feat(mcp): deepcode mcp serve — expose tools as an MCP server over stdio#113
Merged
Conversation
…stdio
Adds the server side of MCP (DEVELOPMENT_PLAN §3.3): other MCP clients
(Claude Desktop, another DeepCode, etc.) can now call DeepCode's tools.
core (packages/core/src/mcp/serve.ts):
- buildMcpServer({cwd,...}) — wraps the tool registry in an SDK `Server`
with ListTools + CallTool handlers; returned unconnected so any transport
attaches (stdio in prod, in-memory pair in tests).
- serveMcpOverStdio() — connects StdioServerTransport, resolves on peer
disconnect / stdin EOF / abort (closes the transport cleanly on SIGINT).
- mcpServableTools() / MCP_SERVE_EXCLUDE — exposes only STATELESS tools
(Read/Write/Edit/Bash/Grep/Glob/NotebookEdit/TodoWrite/WebFetch/WebSearch);
excludes the 9 host-coupled ones (AskUserQuestion, plan/worktree/Task, Cron*)
that need context an MCP peer can't supply.
cli (apps/cli/src/mcp-cmd.ts):
- `deepcode mcp serve` + `deepcode mcp` help. Banner/readiness go to stderr —
stdout stays the pure JSON-RPC channel. Serve impl is injectable for tests.
- Wired into cli.ts dispatch + --help.
Tests: 6 core (in-memory client↔server: listTools hides excluded tools,
Write→Read round-trip, unknown-tool + tool-error → isError) + 3 CLI (help,
unknown subcommand → exit 2, serve forwards cwd & logs only to stderr).
Verified end-to-end: a real StdioClientTransport spawned `mcp serve`, listed
10 tools, and called Bash successfully.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the server side of MCP —
docs/DEVELOPMENT_PLAN.md§3.3. After this, other MCP clients (Claude Desktop, another DeepCode instance, any MCP-aware tool) can call DeepCode's built-in tools in a project directory. Mirrors Claude Code'sclaude mcp serve.Register it in another client as:
{ "command": "deepcode", "args": ["mcp", "serve"] }What's in here
core —
packages/core/src/mcp/serve.ts(all SDK usage stays in core; the CLI has no third-party deps):buildMcpServer({ cwd, ... })— wraps the tool registry in an@modelcontextprotocol/sdkServerwithListTools+CallToolhandlers. Returned unconnected so any transport attaches — stdio in prod, an in-memory linked pair in tests.serveMcpOverStdio()— connectsStdioServerTransport; resolves on peer disconnect / stdin EOF / abort, and closes the transport cleanly on SIGINT so stdin listeners detach.mcpServableTools()/MCP_SERVE_EXCLUDE— exposes only stateless tools (Read/Write/Edit/Bash/Grep/Glob/NotebookEdit/TodoWrite/WebFetch/WebSearch). Excludes the 9 host-coupled tools (AskUserQuestion, EnterPlanMode/ExitPlanMode, EnterWorktree/ExitWorktree, Task, Cron×3) whoseToolContext(askUser / modeSignal / runSubAgent / live worktree / local scheduler) an MCP peer can't provide.cli —
apps/cli/src/mcp-cmd.ts:deepcode mcp serve+ adeepcode mcphelp screen. The banner + readiness line go to stderr — stdout stays the pure JSON-RPC channel. The serve impl is injectable so tests don't grab the real process stdio.cli.tsdispatch +--help.Tests
serve.test.ts) via a realClientoverInMemoryTransport.createLinkedPair():listToolshides excluded tools + includes core ones, aWrite→Readround-trip actually hits disk, unknown-tool and tool-level errors surface asisError.mcp-cmd.test.ts): help (exit 0), unknown subcommand (exit 2), andserveforwardscwd+ logs only to stderr (stdout asserted empty).StdioClientTransportspawned the builtdeepcode mcp serve, listed all 10 tools, and calledBash(echo hello-mcp→ exit 0).Core suite 558 green (+6), CLI 72 green (+3); full repo suite green via pre-commit.
Notes
🤖 Generated with Claude Code