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

> Explore supported and unsupported Cypher query features in codebase-memory-mcp. Understand what's included, from pattern matching and filtering to aggregations and scalar functions, while learning what's excluded.

- Repository: [Martin Vogel/codebase-memory-mcp](https://github.com/DeusData/codebase-memory-mcp)
- Tags: api-reference
- Published: 2026-07-06

---

**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`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/cypher/cypher.c) and [`src/cypher/cypher.h`](https://github.com/DeusData/codebase-memory-mcp/blob/main/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`](https://github.com/DeusData/codebase-memory-mcp/blob/main/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`](https://github.com/DeusData/codebase-memory-mcp/blob/main/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

```cypher
-- Simple node match with label and property filter
MATCH (f:Function {name: "HandleOrder"})
RETURN f.name, f.qualified_name, f.file_path;

```

```cypher
-- 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;

```

```cypher
-- Aggregation with DISTINCT and ORDER BY
MATCH (f:Function)
RETURN COUNT(DISTINCT f.label) AS label_cnt
ORDER BY label_cnt DESC
LIMIT 5;

```

```cypher
-- Using scalar introspection functions
MATCH (f:Function)-[r:CALLS]->(g:Function)
RETURN labels(f), type(r), id(f);

```

```cypher
-- 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;

```

```cypher
-- 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`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/cypher/cypher.c) and [`src/cypher/cypher.h`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/cypher/cypher.h), with validation in [`tests/test_cypher.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/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`](https://github.com/DeusData/codebase-memory-mcp/blob/main/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`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/cypher/cypher.h), while the implementation logic resides in [`src/cypher/cypher.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/cypher/cypher.c). The comprehensive test suite in [`tests/test_cypher.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/tests/test_cypher.c) validates all supported features and confirms rejection of unsupported ones, serving as the authoritative reference for query capabilities.