Skip to content

Commit 92d6805

Browse files
DvirDukhanclaude
andcommitted
feat(mcp): scaffold api/mcp module with FastMCP server and cgraph-mcp entry point
Add the bare MCP server module (api/mcp/) using the official FastMCP SDK, wire the cgraph-mcp console script in pyproject.toml, and include a protocol smoke test that spawns the server over stdio and verifies list_tools returns an empty tool set. Also copies the MCP design docs into docs/. Closes #648 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent b066064 commit 92d6805

8 files changed

Lines changed: 550 additions & 0 deletions

File tree

api/mcp/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
"""MCP server module for code-graph.
2+
3+
Exposes the code-graph indexer and graph queries as MCP tools so AI coding
4+
agents (Claude Code, Cursor, Copilot, Roo/Cline) can drive the indexer over
5+
the standard Model Context Protocol stdio transport.
6+
7+
Entry point: ``cgraph-mcp`` (defined in ``pyproject.toml``).
8+
"""

api/mcp/server.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""FastMCP server for code-graph.
2+
3+
This is the scaffold (T1). It instantiates a single FastMCP app, exposes it
4+
as ``app`` for tests and embedders, and registers a ``main()`` entry point
5+
that runs the server over stdio. Tools are registered in later tickets
6+
(T4-T8, T11) by importing this module's ``app`` and decorating functions
7+
with ``@app.tool(...)``.
8+
"""
9+
10+
from __future__ import annotations
11+
12+
from mcp.server.fastmcp import FastMCP
13+
14+
app: FastMCP = FastMCP("code-graph")
15+
16+
17+
def main() -> None:
18+
"""Run the MCP server over stdio.
19+
20+
Console-script entry point for ``cgraph-mcp``.
21+
"""
22+
app.run()
23+
24+
25+
if __name__ == "__main__":
26+
main()

docs/MCP_SERVER_DESIGN.md

Lines changed: 321 additions & 0 deletions
Large diffs are not rendered by default.

docs/code-graph-mcp-v4.docx

23.6 KB
Binary file not shown.

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@ dependencies = [
2323
"javatools>=1.6.0,<2.0.0",
2424
"pygit2>=1.17.0,<2.0.0",
2525
"typer>=0.24.0,<1.0.0",
26+
"mcp>=1.0.0,<2.0.0",
2627
]
2728

2829
[project.scripts]
2930
cgraph = "api.cli:app"
31+
cgraph-mcp = "api.mcp.server:main"
3032

3133
[project.optional-dependencies]
3234
test = [

tests/mcp/__init__.py

Whitespace-only changes.

tests/mcp/test_scaffold.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
"""Scaffold smoke tests for the cgraph-mcp server (T1).
2+
3+
These tests prove the bare module is wired correctly:
4+
5+
1. The FastMCP ``app`` instance is importable.
6+
2. The ``cgraph-mcp`` console script spawns a working stdio MCP server.
7+
3. A client can complete the MCP handshake and ``list_tools`` returns 0
8+
tools (no tools are registered yet — they land in T4-T8, T11).
9+
10+
When tool tickets land they should ADD tests, not modify these — these
11+
guard the scaffold itself.
12+
"""
13+
14+
from __future__ import annotations
15+
16+
import shutil
17+
18+
import pytest
19+
from mcp import ClientSession, StdioServerParameters
20+
from mcp.client.stdio import stdio_client
21+
22+
23+
def test_app_is_importable() -> None:
24+
"""The FastMCP instance can be imported and is named ``code-graph``."""
25+
from api.mcp.server import app
26+
27+
assert app is not None
28+
assert app.name == "code-graph"
29+
30+
31+
def test_main_entry_point_exists() -> None:
32+
"""``main()`` is exposed for the console script."""
33+
from api.mcp import server
34+
35+
assert callable(server.main)
36+
37+
38+
@pytest.mark.anyio
39+
async def test_stdio_server_lists_zero_tools() -> None:
40+
"""Spawn ``cgraph-mcp`` over stdio and verify the protocol handshake.
41+
42+
The scaffold registers no tools, so ``list_tools`` must return an
43+
empty list. Tool tickets (T4-T8, T11) extend this expectation.
44+
"""
45+
cgraph_mcp = shutil.which("cgraph-mcp")
46+
assert cgraph_mcp is not None, (
47+
"cgraph-mcp not on PATH; run `uv pip install -e .` first"
48+
)
49+
50+
params = StdioServerParameters(command=cgraph_mcp, args=[])
51+
async with stdio_client(params) as (read, write):
52+
async with ClientSession(read, write) as session:
53+
await session.initialize()
54+
result = await session.list_tools()
55+
assert result.tools == []

uv.lock

Lines changed: 138 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)