Cypher Query Features Supported in the openCypher Subset of codebase-memory-mcp
The codebase-memory-mcp repository implements a read-only openCypher subset that supports MATCH, OPTIONAL MATCH, WHERE, RETURN, WITH, ORDER BY, SKIP, and LIMIT, along with label alternation, variable-length paths, logical operators, comparison predicates, scalar functions, and aggregations, while explicitly rejecting all write operations like CREATE, DELETE, SET, and MERGE.
The codebase-memory-mcp project provides a Cypher-to-SQLite translation layer that exposes a carefully curated openCypher subset for querying codebases. This implementation focuses exclusively on read-only graph traversal and projection, translating Cypher statements into SQLite queries while strictly prohibiting any data modification or schema changes.
Core Query Clauses
MATCH Pattern Syntax
The parser in src/cypher/cypher.c handles node patterns (var:Label {props}) and relationship patterns -[var:TYPE*min..max]-> through recursive-descent parsing. Supported pattern elements include:
- Node labels: Single labels
(n:Service)or alternation(n:A|B|C)parsed inparse_node - Relationship direction:
<,>, or any direction - Variable-length hops:
*min..max,*, or*..maxprocessed inparse_hop_range(lines 998-1012) - Property filters: Inline property maps
(n {name: "value"})
OPTIONAL MATCH
The TOK_OPTIONAL token is recognized and processed in the query planner, compiling optional patterns to left-outer joins. This allows queries to return results even when the optional pattern matches no data.
WHERE Clause Filtering
The WHERE clause supports a full logical expression grammar including:
- Logical operators:
AND,OR,XOR,NOTwith parentheses for precedence - Comparison operators:
=,<>,=~,>,<,>=,<= - String predicates:
CONTAINS,STARTS WITH,ENDS WITH - Collection operators:
INfor list membership - Null handling:
IS NULLandIS NOT NULL - Label tests:
n:Labelsyntax for runtime label checking - Existence: Single-hop
EXISTS { (v)-[:TYPE]->() }predicates
Projection and Aggregation
RETURN and WITH Clauses
Both clauses support:
- Column aliasing:
RETURN n.name AS serviceName - DISTINCT:
RETURN DISTINCT n.language - Property access:
n.propandr.prop - Wildcard:
RETURN *(expanded to all bound variables)
Aggregation Functions
All standard openCypher aggregations are supported with DISTINCT modifiers:
COUNT,SUM,AVG,MIN,MAX,COLLECT- Usage:
COUNT(DISTINCT n.id),COLLECT(r.name)
Scalar and Multi-Argument Functions
Single-argument functions:
- String:
toLower,toUpper,toString,trim,ltrim,rtrim,reverse - Numeric:
toInteger,toFloat,size,length - Graph:
labels,type,id,keys,properties - Boolean:
toBoolean
Multi-argument functions:
coalesce:coalesce(n.doc, "undocumented")substring:substring(n.name, 0, 3)replace,left,right
CASE Expressions
Full conditional logic is supported:
CASE
WHEN n.isPublic THEN "public"
ELSE "private"
END
Ordering and Pagination
- ORDER BY: Supports
ASC(default) andDESCordering on columns, aggregations, or function results - SKIP: Integer offset for pagination
- LIMIT: Maximum result count
These translate directly to SQLite OFFSET and LIMIT clauses.
Explicitly Unsupported Write Operations
The centralized unsupported_clause_error function (lines 808-831 in src/cypher/cypher.c) explicitly rejects all graph-modifying operations:
- Data modification:
CREATE,DELETE,DETACH DELETE,SET,REMOVE,MERGE - Control flow:
FOREACH - Schema operations:
DROP,CONSTRAINT,INDEX - Procedures:
CALL,YIELD - Variants:
MANDATORY MATCH
While tokens like TOK_UNION and TOK_UNWIND exist in the lexer, they are not implemented in the query planner and will raise parse errors.
Code Examples
Variable-length path with filtering
MATCH (a:Service)-[r:CALLS*1..3]->(b:Service)
WHERE a.name CONTAINS "auth" AND b.language = "go"
RETURN a.name AS caller, b.name AS callee, COUNT(r) AS hops
ORDER BY hops DESC
LIMIT 10
Optional match with label alternation
MATCH (c:Component)
OPTIONAL MATCH (c)-[:USES|DEPENDS_ON]->(d)
RETURN c.id, d.id AS dependentId
Scalar functions and CASE
MATCH (f:Function)
WHERE toLower(f.name) STARTS WITH "get"
RETURN f.name,
substring(f.name, 0, 3) AS prefix,
coalesce(f.doc, "undocumented") AS documentation,
CASE WHEN f.isPublic THEN "public" ELSE "private" END AS visibility
ORDER BY f.name ASC
Summary
- Supported: Read-only traversal via
MATCHandOPTIONAL MATCHwith variable-length paths, label alternation, and complexWHEREfiltering - Supported: Rich projection with
RETURN/WITH, including aggregation, scalar functions, andCASEexpressions - Supported: Result ordering and pagination via
ORDER BY,SKIP, andLIMIT - Unsupported: All write operations (
CREATE,DELETE,SET,MERGE, etc.) and schema modifications - Implementation: Parsed in
src/cypher/cypher.cwith function declarations insrc/cypher/cypher.h
Frequently Asked Questions
Does codebase-memory-mcp support CREATE or DELETE clauses?
No. The engine explicitly rejects CREATE, DELETE, DETACH DELETE, SET, REMOVE, and MERGE clauses through the unsupported_clause_error handler in src/cypher/cypher.c. The implementation is strictly read-only for safety and simplicity.
What aggregation functions are available in the openCypher subset?
The subset supports COUNT, SUM, AVG, MIN, MAX, and COLLECT, each accepting an optional DISTINCT modifier. These are parsed in the RETURN and WITH clause handlers and translated to SQLite aggregation functions.
Can I use variable-length path patterns in MATCH clauses?
Yes. The parser supports variable-length hops using *min..max syntax (e.g., -[r:CALLS*1..3]->), handled by the parse_hop_range function. You can also use unbounded ranges like * or *..5.
Is the UNION clause supported for combining queries?
No. While the lexer defines a TOK_UNION token, the query planner does not implement UNION or UNION ALL. Attempting to use these constructs will result in a parse error indicating the feature is not supported.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →