Claude Desktop ↔ Claude Code MCP Bridge
A bidirectional MCP bridge that lets Claude Desktop and Claude Code collaborate on a build with no human in the execution loop.
README
Claude Desktop ↔ Claude Code MCP Bridge
What this is
A bidirectional MCP bridge that lets Claude Desktop
and Claude Code collaborate on a build with no human in the execution loop. Desktop
writes a plan; Code picks it up, implements it, streams progress, and submits a completion
summary; Desktop approves or rejects (with a reason); Code revises on rejection or finalizes
on approval. The two sides never talk directly — they communicate through a shared SQLite
database and a small set of markdown files under ~/.claude-bridge/. Two stdio FastMCP
servers expose the tools each side calls.
~/.claude-bridge/
├── bridge.db # SQLite: projects, updates, completions, approvals
├── plans/ # Desktop writes <project_id>.md here
└── status/ # Code writes <project_id>_status.md here
claude_desktop_mcp/
├── desktop_server.py # FastMCP server registered with Claude Desktop
├── code_server.py # FastMCP server registered with Claude Code (CLI)
├── db.py # All SQLite schema + access (async, aiosqlite)
├── models.py # Shared Pydantic v2 models (rows + tool inputs)
├── config.py # Paths, server names, status constants
└── requirements.txt
Both servers import from db.py and models.py; no DB logic is duplicated between them.
Install
A dedicated virtual environment is strongly recommended — both servers are spawned by the host app (Claude Desktop / Claude Code), and a venv with a concrete interpreter path is the most reliable target (especially on Windows, where the Microsoft Store "App execution alias" Python can fail when launched by a packaged app).
# from the project directory
python -m venv .venv
# Windows
.venv\Scripts\python.exe -m pip install -r requirements.txt
# macOS / Linux
.venv/bin/python -m pip install -r requirements.txt
The interpreter to reference in the config snippets is then:
- Windows:
<project>\.venv\Scripts\python.exe - macOS / Linux:
<project>/.venv/bin/python
(You can skip the venv and pip install -r requirements.txt into any Python 3.11+, but then
make sure the command in the configs points at that interpreter.)
Requires Python 3.11+. Dependencies: mcp[cli], fastmcp, aiosqlite, aiofiles,
pydantic>=2.0.
Initialize the shared state directory and database (also runs automatically on the first tool call):
# Windows
.venv\Scripts\python.exe db.py
# macOS / Linux
.venv/bin/python db.py
This creates ~/.claude-bridge/ with plans/, status/, and bridge.db.
How to register
Both servers run over stdio and are launched by the host (Desktop / Code) via its MCP config. Use the ready-made snippets in this folder:
claude_desktop_config.snippet.json→ Claude Desktopclaude_code_config.snippet.json→ Claude Code
Claude Desktop
Add the claude_bridge_desktop entry to your claude_desktop_config.json:
{
"mcpServers": {
"claude_bridge_desktop": {
"command": "C:\\Users\\quack\\documents\\projects\\claude_desktop_mcp\\.venv\\Scripts\\python.exe",
"args": ["C:\\Users\\quack\\documents\\projects\\claude_desktop_mcp\\desktop_server.py"],
"env": {}
}
}
}
Config file location:
| OS | Path |
|---|---|
| Windows (standard installer) | %APPDATA%\Claude\claude_desktop_config.json (e.g. C:\Users\<you>\AppData\Roaming\Claude\claude_desktop_config.json) |
| Windows (Microsoft Store / packaged install) | %LOCALAPPDATA%\Packages\Claude_<id>\LocalCache\Roaming\Claude\claude_desktop_config.json (e.g. ...\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\Claude\...) |
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Linux | ~/.config/Claude/claude_desktop_config.json |
If Claude Desktop was installed from the Microsoft Store, it uses a virtualized Roaming folder under
%LOCALAPPDATA%\Packages\Claude_<id>\LocalCache\Roaming\Claude— editing the standard%APPDATA%\Claudepath will have no effect. Merge into the existing file (it may already contain othermcpServers); don't overwrite it.
Restart (fully quit and reopen) Claude Desktop after editing — the config is read at launch.
Claude Code (CLI)
The simplest way is the CLI, which writes the right config for you:
claude mcp add claude_bridge_code --scope user -- "C:\Users\quack\documents\projects\claude_desktop_mcp\.venv\Scripts\python.exe" "C:\Users\quack\documents\projects\claude_desktop_mcp\code_server.py"
--scope user makes the bridge available in every project. Restart Claude Code (or start a
new session) afterward so it loads the server.
Or add the claude_bridge_code entry manually to the appropriate MCP config (e.g.
.mcp.json in your project root, or your user-level Claude Code config):
{
"mcpServers": {
"claude_bridge_code": {
"command": "C:\\Users\\quack\\documents\\projects\\claude_desktop_mcp\\.venv\\Scripts\\python.exe",
"args": ["C:\\Users\\quack\\documents\\projects\\claude_desktop_mcp\\code_server.py"],
"env": {}
}
}
}
Path note: the
commandpoints at the project's venv interpreter (.venv\Scripts\python.exeon Windows,.venv/bin/pythonon macOS/Linux) — the one you installed the dependencies into. Avoid the bare Microsoft Storepython.exealias here; packaged host apps may fail to launch it. JSON requires escaped backslashes (\\) in Windows paths.
Tool argument shape
Important: every tool whose table lists parameters takes a single object argument named
params— the tool input is one Pydantic model, so the JSON the MCP client sends is{"params": { ... }}, not flat top-level fields. Tools that take no parameters (bridge_get_approval_queue,bridge_list_projects,bridge_get_pending_plan) are called with{}.
For example, bridge_send_plan is invoked as:
{ "params": { "title": "Add CSV export", "plan_markdown": "# Goal\n..." } }
In practice you just tell Claude what to do ("send this plan to Code") and it fills in the
params object; the shape above is what travels over the wire.
Typical workflow
The examples below show each tool with its params payload.
- Desktop registers a plan. In Claude Desktop, call
bridge_send_plan:bridge_send_plan params={"title": "Add CSV export", "plan_markdown": "# Goal\n..."} → { "project_id": "ab12cd34ef56", "status": "pending", "plan_path": "...", ... } - Code picks it up. In Claude Code:
bridge_get_pending_plan (no params) → returns project_id, title, full plan markdown bridge_claim_project params={"project_id": "ab12cd34ef56"} → status: in_progress - Code streams progress while implementing:
bridge_send_update params={"project_id": "ab12cd34ef56", "message": "Wrote exporter module"} bridge_send_update params={"project_id": "ab12cd34ef56", "message": "Added tests"} - Code submits completion:
bridge_send_completion params={ "project_id": "ab12cd34ef56", "files_created": ["export.py", "test_export.py"], "files_modified": ["cli.py"], "summary": "CSV export end to end", "caveats": null} → status: awaiting_approval - Desktop reviews:
bridge_get_approval_queue (no params) → project + completion summary bridge_get_project_updates params={"project_id": "ab12cd34ef56"} - Desktop decides:
bridge_approve params={"project_id": "ab12cd34ef56"} → status: approved # or bridge_reject params={"project_id": "ab12cd34ef56", "reason": "Handle empty rows"} → status: rejected - Code learns the outcome by polling:
bridge_get_approval_status params={"project_id": "ab12cd34ef56"}- Approved → the project is finalized to
complete. - Rejected → the response includes the rejection
reason. Code callsbridge_reset_for_revisionwithparams={"project_id": "ab12cd34ef56"}(status →in_progress), revises, and submits a new completion. The loop repeats until approved.
- Approved → the project is finalized to
Status lifecycle
pending → in_progress → awaiting_approval → approved → complete
▲ │
└──────── rejected ◄───────────┘ (bridge_reset_for_revision)
Each tool validates the current status before transitioning and returns a clear
ERROR: ... string if the transition is invalid.
Tool reference
Desktop server (claude_bridge_desktop)
| Tool | Purpose |
|---|---|
bridge_send_plan |
Register a new project + plan (writes plans/<id>.md) |
bridge_get_approval_queue |
List projects awaiting approval, with completion summaries |
bridge_get_project_updates |
All progress updates for a project |
bridge_approve |
Approve completed work |
bridge_reject |
Reject with a reason; sends work back |
bridge_get_project_status |
Full project state (status, updates, completion, decision) |
bridge_list_projects |
All projects, newest first |
Code server (claude_bridge_code)
| Tool | Purpose |
|---|---|
bridge_get_pending_plan |
Retrieve the oldest pending plan + markdown |
bridge_claim_project |
Mark a pending project in_progress |
bridge_send_update |
Append a progress message (also writes status/<id>_status.md) |
bridge_send_completion |
Submit finished-work summary → awaiting_approval |
bridge_get_approval_status |
Poll for approval/rejection (finalizes approved → complete) |
bridge_reset_for_revision |
Re-enter in_progress after a rejection |
State directory
~/.claude-bridge/ (on Windows, C:\Users\<you>\.claude-bridge\):
bridge.db— SQLite with four tables:projects,updates,completions,approvals. Foreign keys linkupdates/completions/approvalsback toprojects.plans/<project_id>.md— the exact plan markdown Desktop submitted.status/<project_id>_status.md— a running log: one timestamped line per progress update, plus a structured## Completionblock each time Code submits a completion.
You can safely inspect these files by hand. To reset everything, delete bridge.db and the
contents of plans/ and status/, then run python db.py again.
HTTP API Server
A lightweight FastAPI server (api_server.py) exposes the bridge database over http://localhost:7823. A browser-based dashboard artifact in Claude Desktop can poll it for live project status without any MCP or stdio involvement.
How to start
Option A — visible terminal:
start_api.bat
Option B — hidden background process:
Double-click start_api.vbs (no terminal window appears). It also runs automatically on login via the Windows startup folder.
Endpoints
| Method | Path | Description |
|---|---|---|
GET |
/health |
Server health + DB path |
GET |
/projects |
All projects, newest first |
GET |
/projects/{id} |
Full project detail: project + updates + completion + approval |
POST |
/projects/{id}/approve |
Approve a project (must be awaiting_approval) |
POST |
/projects/{id}/reject |
Reject a project; body: {"reason": "..."} |
Example curl calls
curl http://localhost:7823/health
curl http://localhost:7823/projects
curl http://localhost:7823/projects/abc123def456
curl -X POST http://localhost:7823/projects/abc123def456/approve
curl -X POST http://localhost:7823/projects/abc123def456/reject -H "Content-Type: application/json" -d "{\"reason\": \"needs better error handling\"}"
Auto-start on login
start_api.vbs is copied to %APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\ so the API server starts automatically every time you log in alongside the bridge loop. To disable, delete start_api.vbs from that folder.
Running the Persistent Loop
The bridge loop keeps Claude Code running in the background so Claude Desktop can push plans at any time and Code picks them up automatically — no manual intervention needed on the Code side.
Files
| File | Purpose |
|---|---|
run_loop.bat |
Activates the venv, launches Claude Code with the bridge prompt, and auto-restarts on exit |
start_bridge.vbs |
Launches run_loop.bat as a hidden background window (no terminal stays open) |
stop_bridge.bat |
Kills the running Claude Code process |
bridge_status.bat |
Shows running Claude processes and the last 10 lines of loop.log |
How to start
Option A — visible terminal (useful for debugging):
run_loop.bat
Option B — hidden background process:
Double-click start_bridge.vbs (or invoke it via wscript.exe start_bridge.vbs). No terminal window appears.
How to stop
Run stop_bridge.bat or:
taskkill /F /IM claude.exe /T
How to check status
Run bridge_status.bat — it lists active claude.exe processes and prints the last 10 lines of the log file.
Startup registration
start_bridge.vbs is copied into %APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\ so the loop starts automatically every time you log in. To disable autostart, delete start_bridge.vbs from that folder.
Log file
Every time the loop restarts, a timestamped line is appended to:
C:\Users\quack\.claude-bridge\loop.log
This lets you see how often Claude Code was restarted and when each session began.
Troubleshooting
ERROR: cannot <action> project in status '<x>'; expected '<y>'.— A status transition was attempted out of order (e.g. completing a project that was never claimed, or approving one that isn'tawaiting_approval). Check the current state withbridge_get_project_status/bridge_list_projectsand follow the lifecycle above.ERROR: project not found: <id>— Wrong/typo'dproject_id. Usebridge_list_projectsto find the correct id.ERROR: a non-empty 'reason' is required to reject a project.—bridge_rejectneeds areason; supply one.ERROR: plan file missing for project <id>: <path>— Theplans/<id>.mdfile was deleted out from under the DB. Re-send the plan withbridge_send_plan(creates a new project) or restore the file.- Database is locked. SQLite serializes writers; the bridge uses short-lived async
connections so this is rare. If it happens, ensure you don't have an external tool holding
a long transaction on
bridge.db, then retry — the offending tool will simply return anERROR: ...string and can be called again. - Server not found / tools don't appear. Confirm the
commandpath points at the interpreter where dependencies are installed (pip show mcp), that theargspath to the*_server.pyfile is correct and absolute, and that you restarted the host (Desktop) or re-ranclaude mcp add(Code). On Windows, JSON requires escaped backslashes (\\) in paths. - Nothing happens after
bridge_send_plan. Code only acts when you ask it to callbridge_get_pending_plan(and the rest). The bridge is pull-based polling, not a push notification system.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。