# How the Cypher Query Engine in DeusData's codebase-memory Executes openCypher-Style Queries Against the Code Graph

> Learn how the Cypher query engine executes openCypher-style queries on the code graph. It translates queries to SQLite SQL, enforcing safety limits.

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

---

**The Cypher query engine translates a subset of OpenCypher syntax into read-only SQLite SQL statements, executing them against the cbm_store graph database while enforcing strict safety limits on recursion and variable binding.**

The DeusData/codebase-memory-mcp repository implements a lightweight, read-only Cypher query engine that enables developers to explore code relationships using familiar graph query syntax. Unlike full graph databases, this engine compiles openCypher-style queries into efficient SQL operations against an underlying SQLite store, making it ideal for static analysis of repository structures without external dependencies.

## Architecture of the Cypher Query Engine

The engine resides entirely within the `src/cypher` package and consists of five tightly integrated components that transform query strings into result sets:

- **Lexer** – Tokenizes input strings into identifiers, literals, and operators via the `cbm_lex` functions defined in [`src/cypher/cypher.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/cypher/cypher.c) (lines 145-190).
- **Parser** – A recursive-descent parser constructs an abstract syntax tree (AST) for clauses like MATCH, WHERE, RETURN, OPTIONAL MATCH, and UNION, respecting a nesting depth limit of approximately 5 levels specified in [`src/foundation/recursion_whitelist.h`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/foundation/recursion_whitelist.h).
- **Planner** – Walks the AST to resolve labels, relationship types, and variable bindings, producing a logical plan that maps graph traversals to SQL joins. The planner rejects unsupported write operations (CREATE, DELETE, MERGE) early with explicit error messages (lines 817-839 of [`cypher.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/cypher.c)).
- **Executor** – Renders the logical plan into a safe SQL string and dispatches it to `cbm_store` via `cbm_sql_execute`, streaming rows back as JSON values.
- **Safety Layer** – Sandboxes the translation step to ensure only read-only SQL constructs are generated, with the SQLite authorizer blocking privileged statements like `ATTACH`.

## Lexing and Parsing Pipeline

Query processing begins in [`src/cypher/cypher.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/cypher/cypher.c) where the `cbm_lex` tokenizer breaks the input into a token stream. The parser then builds an AST while enforcing hard limits on query complexity.

The recursive-descent parser specifically monitors nesting depth using constants defined in [`src/foundation/recursion_whitelist.h`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/foundation/recursion_whitelist.h) (lines 7-12). If a query exceeds the configured depth limit or attempts to bind more than **CYP_MAX_VARS** (16) variables, the engine returns an error before planning begins.

## Query Planning and SQL Translation

Once parsed, the AST enters the planning phase where graph patterns convert to relational operations. The planner analyzes node labels and relationship types to generate efficient SQLite join structures that represent graph traversals.

Write operations are explicitly prohibited during this phase. If the planner encounters CREATE, DELETE, or MERGE clauses, it immediately aborts with a clear error message, ensuring the **cbm_store** remains immutable from the query interface.

## Execution Flow and Safety Guarantees

The `execute_cypher_query` function (lines 324-360 of [`cypher.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/cypher.c)) orchestrates the final execution:

1. **Input Validation** – Accepts the Cypher string through the `query_graph` interface.
2. **SQL Generation** – Converts the logical plan into a parameterized SQLite query.
3. **Authorization Check** – The SQLite authorizer validates that no privileged operations (e.g., `ATTACH`, `PRAGMA`) are present, as verified by test cases in [`tests/test_security.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/tests/test_security.c) (lines 293-314).
4. **Result Streaming** – Executes against `cbm_store` and converts SQLite types to JSON for API consumption or tabular output for CLI users.

This read-only architecture guarantees that even compromised query strings cannot modify the underlying code graph.

## Invoking the Engine via query_graph

The engine exposes functionality through the **`query_graph`** tool, available in both the CLI and JSON-RPC API.

**Command Line Usage:**

```sh

# List all functions that call `init` (up to 20 results)

query_graph --query "MATCH (caller)-[:CALLS]->(callee {name: 'init'}) RETURN caller.name, callee.name LIMIT 20"

```

**JSON-RPC API:**

```http
POST /api/query_graph
Content-Type: application/json

{
  "query": "MATCH (n:Function)-[:CALLS]->(m:Function) WHERE n.name =~ '.*parse.*' RETURN n.name, m.name LIMIT 5"
}

```

**Programmatic C Integration:**

```c
const char *cypher = "MATCH (a)-[:IMPORTS]->(b) RETURN a.name, b.name LIMIT 3";
struct cbm_result *res = NULL;
int rc = cypher_execute(store, cypher, &res);
if (rc == 0) {
    // iterate over `res` rows …
}

```

## Summary

- The Cypher query engine in DeusData/codebase-memory-mcp compiles openCypher-style queries into read-only SQLite SQL, executing against the **cbm_store** backend.
- The implementation spans [`src/cypher/cypher.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/cypher/cypher.c) (core engine), [`src/cypher/cypher.h`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/cypher/cypher.h) (public API), and [`src/mcp/mcp.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/mcp/mcp.c) (CLI routing).
- Security is enforced through recursive depth limits, variable count caps (16 max), and SQLite authorizer hooks that block write operations.
- Developers access the engine via the `query_graph` tool or the `cypher_execute()` C function, receiving results as JSON or tabular data.

## Frequently Asked Questions

### Is the Cypher query engine write-capable?

No. The engine is explicitly read-only. The parser rejects CREATE, DELETE, and MERGE clauses during the planning phase, and the SQLite authorizer blocks any SQL that attempts to modify the database schema or data, as demonstrated in [`tests/test_security.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/tests/test_security.c).

### What openCypher features are supported?

The engine supports MATCH, WHERE, RETURN, OPTIONAL MATCH, and UNION clauses. It handles node labels, relationship types, property filters, and limited regular expressions. Complex features like path variables, unwind operations, and subqueries are not implemented in the current version.

### How does the engine prevent recursive query attacks?

The parser enforces a nesting depth limit of approximately 5 levels using the recursion whitelist defined in [`src/foundation/recursion_whitelist.h`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/foundation/recursion_whitelist.h). Additionally, queries are limited to 16 variables (CYP_MAX_VARS), preventing resource exhaustion through deeply nested patterns.

### Why translate Cypher to SQLite instead of using a native graph database?

Translating to SQLite allows the codebase-memory tool to remain self-contained without external database dependencies. The **cbm_store** is a single file that can be versioned, copied, and queried using standard SQL tooling while still presenting a familiar graph interface to developers via the Cypher query engine.