Supported and Unsupported Cypher Query Features in codebase-memory-mcp

Codebase-memory-mcp supports a read-only subset of OpenCypher including pattern matching, filtering, aggregations, and scalar functions, while explicitly rejecting all write operations, stored procedures, and list indexing.

The codebase-memory-mcp project embeds a lightweight Cypher execution engine that translates graph queries into SQL for its internal cbm_store database. Understanding which cypher query features are supported and unsupported in codebase-memory-mcp is essential for writing effective AI-agent search queries against codebases.

Architecture Overview

The Cypher engine is implemented in src/cypher/cypher.c and src/cypher/cypher.h and operates through three distinct layers:

  1. Lexer (cbm_lex) – Tokenizes the query string.
  2. Parser (cbm_cypher_parse) – Builds an AST from the token stream using recursive descent parsing.
  3. Executor (cbm_cypher_execute) – Walks the AST and generates SQL against the SQLite-backed store.

This design deliberately enforces read-only semantics, making it suitable for code analysis while preventing accidental graph mutation.

Supported Cypher Query Features

Pattern Matching and Traversal

The engine handles fundamental graph patterns through specific parser functions in src/cypher/cypher.c:

  • Node patterns – MATCH (n:Label) with optional inline property maps ({key: "value"}) are parsed by parse_node (lines 445–495).
  • Relationship direction – Directed (-[:TYPE]->, <-[:TYPE]-) and undirected (-[:TYPE]-) relationships are handled by parse_rel (lines 506–540), storing direction as "outbound", "inbound", or "any".
  • Multiple edge types – Disjunction patterns like [:CALLS|HTTP_CALLS] are supported via parse_rel_types (lines 624–679).
  • Variable-length hops – Syntax like *, *1..3, and *..5 is parsed by parse_hop_range (lines 998–1022), though the executor enforces a configurable maximum depth (default 10) via cbm_cypher_max_depth.

Filtering and Conditions

The WHERE clause supports a rich set of predicates parsed by parse_condition_expr (lines 1110–1260):

  • Comparison operators, regex matching, and string tests: CONTAINS, STARTS WITH, ENDS WITH
  • Membership tests: IN
  • Null checks: IS NULL and IS NOT NULL
  • Label existence tests: n:Label translates to a HAS_LABEL condition (lines 2815–2820)
  • Logical operators: AND, OR, XOR, and NOT built as binary expression trees (lines 1250–1590)
  • Edge existence: EXISTS { ... } for single-hop tests via parse_exists_predicate (lines 1760–1790)

Return Clauses and Aggregation

The RETURN and WITH clauses support complex projections via parse_return_item (lines 1500–1580):

  • Aggregations – COUNT, SUM, AVG, MIN, MAX, and COLLECT including COUNT(DISTINCT ...) are recognized by is_aggregate_tok (lines 1893–1896).
  • Result modifiers – DISTINCT, AS alias, ORDER BY, SKIP, and LIMIT are fully supported. parse_order_by_clause handles sorting (lines 1690–1700).
  • UNION – Both UNION and UNION ALL are supported through linked result sets (union_next).

Functions and Expressions

Built-in functions are strictly whitelisted:

  • String functions – toLower, toUpper, toString are handled by parse_string_func_item (lines 1595–1605).
  • Scalar introspection – labels(n), type(r), id(n), keys(n), and properties(n) are recognized by is_named_func_call (lines 1677–1680).
  • Multi-argument functions – coalesce, substring, replace, left, and right are parsed by parse_multiarg_func_item (lines 1705–1725).
  • CASE expressions – Full CASE WHEN ... THEN ... [ELSE ...] END support via parse_case_expr (lines 1625–1650).
  • Edge property access – r.property syntax in both WHERE and RETURN contexts via parse_var_dot_prop.

Advanced Structures

  • UNWIND – Simple literal lists are supported through unwind_expr and unwind_alias fields.
  • Edge property projection – Accessing relationship properties in return lists is validated in the executor (see tests around line 3090).

Unsupported Cypher Query Features

Write and Administrative Operations

All graph mutation clauses are explicitly rejected by unsupported_clause_error (lines 803–834) with clear error messages:

  • Data creation: CREATE, MERGE
  • Data deletion: DELETE, DETACH DELETE
  • Property updates: SET, REMOVE
  • Schema changes: DROP, CONSTRAINT declarations
  • Procedural calls: CALL, YIELD, FOREACH

These tokens are defined in src/cypher/cypher.h (lines 69–99) but mapped to immediate failures in the parser.

Data Structure Limitations

  • List indexing and slicing – Syntax like r[0] or r[1..3] is detected but rejected with an "unsupported expression" error.
  • Complex UNWIND – Only simple literal lists are supported; dynamic list expressions fail.

Extension Points

  • User-defined functions – Any bare identifier followed by ( that is not a recognized built-in causes parse_return_item to fail explicitly (lines 1525–1535).
  • Subqueries – Advanced features like SKIP inside sub-queries or complex nested patterns are not present in the grammar and trigger "unexpected token" errors.

Practical Query Examples

-- Simple node match with label and property filter
MATCH (f:Function {name: "HandleOrder"})
RETURN f.name, f.qualified_name, f.file_path;
-- Relationship traversal with variable-length hops (capped at depth 10)
MATCH (f:Function)-[:CALLS*1..3]->(g:Function)
WHERE f.name = "HandleOrder"
RETURN g.name;
-- Aggregation with DISTINCT and ORDER BY
MATCH (f:Function)
RETURN COUNT(DISTINCT f.label) AS label_cnt
ORDER BY label_cnt DESC
LIMIT 5;
-- Using scalar introspection functions
MATCH (f:Function)-[r:CALLS]->(g:Function)
RETURN labels(f), type(r), id(f);
-- Edge property filter and projection
MATCH (a:Function)-[r:HTTP_CALLS]->(b:Function)
WHERE r.confidence > 0.8 AND r.url_path CONTAINS "/api"
RETURN a.name, b.name, r.url_path, r.confidence;
-- This write clause will error (unsupported)
CREATE (n:Function {name: "NewFn"});

Summary

  • Read-only enforcement: The engine explicitly rejects CREATE, DELETE, MERGE, SET, and all other write clauses at the parser level.
  • Rich read support: Comprehensive pattern matching, filtering, aggregation, and built-in function support for code analysis workloads.
  • Explicit failures: Unsupported syntax generates clear error messages rather than silent failures, aiding debugging.
  • Depth limitation: Variable-length traversals are capped at 10 hops by default to prevent runaway queries.
  • Source locations: Core implementation resides in src/cypher/cypher.c and src/cypher/cypher.h, with validation in tests/test_cypher.c.

Frequently Asked Questions

Does codebase-memory-mcp support CREATE or DELETE operations?

No. All write operations including CREATE, DELETE, MERGE, SET, REMOVE, and DETACH DELETE are explicitly rejected by the parser. The function unsupported_clause_error in src/cypher/cypher.c (lines 803–834) maps these tokens to clear error messages, ensuring the graph remains read-only for safe code analysis.

What is the maximum traversal depth for variable-length relationships?

The engine caps variable-length hops at depth 10 by default. While parse_hop_range (lines 998–1022) parses syntax like *1..3, the executor respects cbm_cypher_max_depth to prevent excessive traversal. Attempts to exceed this limit result in trimmed results or appropriate warnings depending on the query context.

Can I use custom functions or list indexing in RETURN clauses?

No. Only built-in functions recognized by is_named_func_call and is_aggregate_tok are supported. User-defined functions and list indexing syntax like r[0] or r[1..3] trigger explicit errors in parse_return_item (lines 1525–1535) with the message "unsupported expression" rather than failing silently.

Where can I find the complete list of supported tokens and features?

The token definitions and AST structures are declared in src/cypher/cypher.h, while the implementation logic resides in src/cypher/cypher.c. The comprehensive test suite in tests/test_cypher.c validates all supported features and confirms rejection of unsupported ones, serving as the authoritative reference for query capabilities.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →