Skip to content

feat(mcp): ship cypher-mcp, an MCP server for the front-end#10

Merged
protosphinx merged 1 commit into
mainfrom
feat/mcp-server
May 2, 2026
Merged

feat(mcp): ship cypher-mcp, an MCP server for the front-end#10
protosphinx merged 1 commit into
mainfrom
feat/mcp-server

Conversation

@protosphinx
Copy link
Copy Markdown
Member

@protosphinx protosphinx commented May 2, 2026

Summary

Ships an MCP (Model Context Protocol) server so any MCP-compatible agent — Claude Code, Cursor, Windsurf, Continue — can drive the cypher-rs front-end as tools, without writing a custom adapter.

What landed

  • New `cypher-mcp` binary and `pub mod mcp` (cfg-gated). Layered to keep the library lean: the protocol code lives behind a new `mcp` Cargo feature with one optional dep (`serde_json`). Default builds and existing library consumers' dep trees are unchanged. The `[[bin]] cypher-mcp` entry sets `required-features = ["mcp"]`.
  • Eight tools, all taking a `query` string:
    • `cypher_parse` - AST debug-print + clause count
    • `cypher_validate` - quick yes/no around parse + analyze
    • `cypher_analyze` - bindings + every issue (severity / code / message)
    • `cypher_plan` - tree-pretty-printed plan (optional `optimize: true`)
    • `cypher_optimize` - plan before / after the optimizer (with a `changed` flag)
    • `cypher_explain` - headline tool: full pipeline in one call
    • `cypher_cost` - `Estimate { cardinality, cost }` from `CardinalityCostModel`
    • `cypher_columns` - output / required input columns of the optimized plan
  • Protocol envelope: MCP `2024-11-05`. `initialize` / `tools/list` / `tools/call` / `ping` implemented, `notifications/initialized` silently swallowed, unknown methods return JSON-RPC `-32601`, tool-level failures come back as `isError: true` content (what MCP clients expect) instead of JSON-RPC errors.
  • CI gates updated: the test/clippy steps now run with `--all-features` so they actually exercise the new code. Added a separate `cargo build --lib` step that builds the default-feature library config to catch accidental dep leakage from `mcp` into what downstream consumers would see.
  • Docs: README gains an "MCP Server" section between the library Usage example and "What separation buys you" with build / register / tool-table / sample prompts. CHANGELOG logs the new surface under `[Unreleased]`.

Verification

  • `cargo test --all-features` - 20 new MCP tests pass; all existing test suites still pass (parse 18, sema 14, plan 16, optimize 12, cost 11, prune 12, grammar 14, map_literals 10, doc-tests 1).
  • `cargo clippy --all-targets --all-features -- -D warnings` - clean.
  • `cargo fmt --check` - clean.
  • `cargo build --lib` (no features) - still builds without `serde_json`.
  • External 22-case Python harness against the release binary: full MCP handshake, every tool's happy + sad paths, error paths (malformed JSON, unknown method, unknown tool, missing arg). All pass.
  • `claude mcp add --scope user cypher-rs ./target/release/cypher-mcp` - `✓ Connected`.

Test plan

  • Reviewer: `cargo build --release --features mcp --bin cypher-mcp`
  • `claude mcp add --scope user cypher-rs "$(pwd)/target/release/cypher-mcp"`
  • `claude mcp list` shows `cypher-rs: ✓ Connected`
  • Open Claude Code in any directory and say "use cypher-rs to validate \`MATCH (u:User) RETURN u.name\`" - get back `valid: true`
  • Try a malformed query and get back `valid: false` with a parse error
  • Try `cypher_explain` with a multi-clause query and confirm every pipeline stage shows up

Adds a stdio MCP (Model Context Protocol) server that exposes the
parse / analyze / plan / optimize / cost / columns pipeline as
tools, so any MCP client (Claude Code, Cursor, Windsurf, Continue,
…) can drive the front-end without writing a custom adapter.

Layered to keep the library lean:
- New optional dep `serde_json` and a new `mcp` Cargo feature gate
  the protocol code; default builds and library consumers' dep
  trees are untouched.
- `pub mod mcp` (cfg-gated) holds the protocol envelope and tool
  dispatch.
- `src/bin/cypher-mcp.rs` is a thin stdio loop that delegates to
  `mcp::handle_request`.
- `[[bin]] cypher-mcp` declares `required-features = ["mcp"]`, so
  the binary only exists when the feature is on.

Eight tools, every one taking a `query` string:
- `cypher_parse` - AST debug-print + clause count.
- `cypher_validate` - quick yes/no around parse + analyze, returns
  errors with severity / code / message.
- `cypher_analyze` - bindings + every issue from the analyzer.
- `cypher_plan` - tree-pretty-printed plan; optional `optimize`
  flag applies the rewriter first.
- `cypher_optimize` - before / after the optimizer runs to
  fixpoint, plus a `changed` flag.
- `cypher_explain` - the headline tool: every pipeline stage in one
  response (parse, analyze, plan, optimized_plan, cost, output and
  required input columns).
- `cypher_cost` - `Estimate { cardinality, cost }` from the default
  `CardinalityCostModel`.
- `cypher_columns` - `output_columns` and `required_input_columns`
  for the optimized plan.

Protocol envelope implements MCP `2024-11-05`: `initialize`,
`tools/list`, `tools/call`, `ping`, with `notifications/initialized`
silently swallowed and unknown methods returning JSON-RPC -32601.
Tool-level failures come back as `isError: true` content (what MCP
clients expect), not JSON-RPC errors.

20 integration tests in `tests/mcp.rs` (cfg-gated on the feature)
cover protocol envelope, four error paths, and every tool's happy +
sad path. CI updated to `cargo test --all-features` and
`cargo clippy --all-features` so the gates actually exercise the
new code; a separate `cargo build --lib` step keeps the
default-feature library config honest (catches accidental dep
leakage from `mcp` into what downstream consumers see).

Verified end-to-end against the release binary with a 22-case
external Python harness (full MCP handshake, all 8 tools' happy +
sad paths). `claude mcp list` reports cypher-rs as Connected after
`claude mcp add`.

README gains an "MCP Server" section between the library Usage
example and "What separation buys you" with build / register /
tool-table / sample-prompt material; CHANGELOG logs the new
surface under [Unreleased].

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@protosphinx protosphinx merged commit 082a592 into main May 2, 2026
4 checks passed
@protosphinx protosphinx deleted the feat/mcp-server branch May 2, 2026 07:14
protosphinx added a commit that referenced this pull request May 2, 2026
Adds a stdio MCP (Model Context Protocol) server that exposes the
parse / analyze / plan / optimize / cost / columns pipeline as
tools, so any MCP client (Claude Code, Cursor, Windsurf, Continue,
…) can drive the front-end without writing a custom adapter.

Layered to keep the library lean:
- New optional dep `serde_json` and a new `mcp` Cargo feature gate
  the protocol code; default builds and library consumers' dep
  trees are untouched.
- `pub mod mcp` (cfg-gated) holds the protocol envelope and tool
  dispatch.
- `src/bin/cypher-mcp.rs` is a thin stdio loop that delegates to
  `mcp::handle_request`.
- `[[bin]] cypher-mcp` declares `required-features = ["mcp"]`, so
  the binary only exists when the feature is on.

Eight tools, every one taking a `query` string:
- `cypher_parse` - AST debug-print + clause count.
- `cypher_validate` - quick yes/no around parse + analyze, returns
  errors with severity / code / message.
- `cypher_analyze` - bindings + every issue from the analyzer.
- `cypher_plan` - tree-pretty-printed plan; optional `optimize`
  flag applies the rewriter first.
- `cypher_optimize` - before / after the optimizer runs to
  fixpoint, plus a `changed` flag.
- `cypher_explain` - the headline tool: every pipeline stage in one
  response (parse, analyze, plan, optimized_plan, cost, output and
  required input columns).
- `cypher_cost` - `Estimate { cardinality, cost }` from the default
  `CardinalityCostModel`.
- `cypher_columns` - `output_columns` and `required_input_columns`
  for the optimized plan.

Protocol envelope implements MCP `2024-11-05`: `initialize`,
`tools/list`, `tools/call`, `ping`, with `notifications/initialized`
silently swallowed and unknown methods returning JSON-RPC -32601.
Tool-level failures come back as `isError: true` content (what MCP
clients expect), not JSON-RPC errors.

20 integration tests in `tests/mcp.rs` (cfg-gated on the feature)
cover protocol envelope, four error paths, and every tool's happy +
sad path. CI updated to `cargo test --all-features` and
`cargo clippy --all-features` so the gates actually exercise the
new code; a separate `cargo build --lib` step keeps the
default-feature library config honest (catches accidental dep
leakage from `mcp` into what downstream consumers see).

Verified end-to-end against the release binary with a 22-case
external Python harness (full MCP handshake, all 8 tools' happy +
sad paths). `claude mcp list` reports cypher-rs as Connected after
`claude mcp add`.

README gains an "MCP Server" section between the library Usage
example and "What separation buys you" with build / register /
tool-table / sample-prompt material; CHANGELOG logs the new
surface under [Unreleased].
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant