claude-vscode-ide-bridge-mcp
v0.2.0
Published
Standalone MCP server that bridges to VS Code's Claude Code extension IDE tools (getDiagnostics and friends) when auto-discovery fails, e.g. from the extension panel.
Readme
claude-vscode-ide-bridge-mcp
⚠️ Undocumented internal protocol. This package speaks VS Code's Claude Code extension's internal WebSocket/JSON-RPC IDE server protocol, which is not a public, versioned API. It can break on any future Claude Code extension update with no compatibility guarantee. If it stops working, that is expected risk, not a bug in the usual sense — check the Caveats section below before filing an issue.
A standalone MCP (Model Context Protocol) server, installable once globally,
that bridges to VS Code's Claude Code extension's own IDE tools
(getDiagnostics and 11 others) when Claude Code's normal auto-discovery of
those tools fails — most commonly when running as the VS Code extension
panel rather than the integrated terminal.
The problem
Claude Code's VS Code extension embeds its own MCP server (the ide
namespace — tools like mcp__ide__getDiagnostics) that calls VS Code's real
vscode.languages.getDiagnostics() API inside the extension host, exposed
over a local, authenticated WebSocket. The CLI normally auto-discovers this
server via the ENABLE_IDE_INTEGRATION and CLAUDE_CODE_SSE_PORT
environment variables, which VS Code injects into integrated-terminal
sessions.
When Claude Code instead runs as the VS Code extension panel, it does not
receive those environment variables, so auto-discovery never happens and the
ide tools silently disappear from the tool list — even though the
extension's IDE server is live, reachable, and has written a lock file to
~/.claude/ide/<port>.lock. The exact same tools work fine from the
integrated terminal in the same window.
Root-caused in anthropics/claude-code#40766; the workaround this package builds on was originally proposed by GitHub user npapadacis in a comment on that issue.
How this works
Rather than relying on auto-discovery, this package:
- Reads
~/.claude/ide/*.lock, matching each lock file'sworkspaceFoldersagainst the current working directory to find the right one. - Opens a WebSocket to
ws://127.0.0.1:<port>(the port is the lock file's name) with headerx-claude-code-ide-authorization: <authToken>(the token is the lock file'sauthToken). - Speaks the IDE server's JSON-RPC protocol directly:
initialize→notifications/initialized→tools/call. - Wraps that in an MCP server of its own, so it can be registered like any other MCP server and used from any project.
This generalizes a project-scoped, single-tool version of the same technique,
kept for provenance at
docs/vscode-problems-mcp-HANDOFF.md.
Requirements
- Node.js ≥ 20
- VS Code, open on the target workspace, with the Claude Code extension active (so a live lock file exists)
Install
npm install -g claude-vscode-ide-bridge-mcpRegister as an MCP server
Add it to a project's .mcp.json, or your user-level ~/.claude.json:
{
"mcpServers": {
"vscode-ide-bridge": {
"command": "claude-vscode-ide-bridge"
}
}
}MCP server configuration is only read at session start, so after adding this, start a new Claude Code session — reloading or restarting an already-running session is not enough.
Tool list
All 12 tools exposed by VS Code's Claude Code extension IDE server are implemented as proxies. Only the read-only ones are enabled by default; the rest mutate editor state or execute code, and must be opted into explicitly.
| Tool | Default | What it does |
| --------------------- | ------- | ----------------------------------------------------------------- |
| getDiagnostics | enabled | Get language diagnostics (errors/warnings), formatted compactly |
| getOpenEditors | enabled | Get info about currently open editors |
| getWorkspaceFolders | enabled | Get all workspace folders open in VS Code |
| getCurrentSelection | enabled | Get the current text selection in the active editor |
| getLatestSelection | enabled | Get the most recent text selection, even if not the active editor |
| checkDocumentDirty | enabled | Check whether a document has unsaved changes |
| openDiff | opt-in | Open a diff view between an old and new file |
| closeAllDiffTabs | opt-in | Close all diff tabs |
| close_tab | opt-in | Close a specific tab by name |
| openFile | opt-in | Open a file, optionally selecting a range |
| saveDocument | opt-in | Save a document with unsaved changes |
| executeCode | opt-in | Execute Python in the current file's Jupyter kernel |
Enabling more tools
Set environment variables on the MCP server's env block:
{
"mcpServers": {
"vscode-ide-bridge": {
"command": "claude-vscode-ide-bridge",
"env": {
"IDE_BRIDGE_ENABLE_TOOLS": "openFile,saveDocument,openDiff"
}
}
}
}IDE_BRIDGE_ENABLE_TOOLS— comma-separated tool names to add to the default read-only set, or the literal valueallto enable everything except the code-execution tools (see below).IDE_BRIDGE_DISABLE_TOOLS— comma-separated tool names to remove, evaluated afterIDE_BRIDGE_ENABLE_TOOLS— use this to narrow even the default set if you want to be more conservative.
Unknown tool names in either variable are ignored (not fatal) and logged as a warning on startup.
executeCode is a separate trust tier
executeCode runs arbitrary Python in a live Jupyter kernel — full code
execution with your user's privileges, outside any shell allowlist or sandbox.
Because of that it is not granted by IDE_BRIDGE_ENABLE_TOOLS=all, and
naming it in IDE_BRIDGE_ENABLE_TOOLS alone is not enough (you'll get a
warning and it stays disabled). It is enabled only by a dedicated opt-in:
{
"mcpServers": {
"vscode-ide-bridge": {
"command": "claude-vscode-ide-bridge",
"env": {
"IDE_BRIDGE_ENABLE_TOOLS": "all",
"IDE_BRIDGE_ALLOW_CODE_EXECUTION": "1"
}
}
}
}Only set IDE_BRIDGE_ALLOW_CODE_EXECUTION if you understand and accept that
the agent can then run arbitrary code.
Other configuration
IDE_BRIDGE_TIMEOUT_MS— per-call timeout in milliseconds (default15000).IDE_BRIDGE_IDE_DIR— override the lock-file directory (default~/.claude/ide); mainly useful for testing.
CLI flags
Running the installed binary directly (outside of an MCP session) supports:
--check— report whether a matching lock file is found for the current directory, without starting the server.--list-tools— print all 12 tools and whether each is enabled for the current environment.--version,--help
Troubleshooting
- "No running VS Code IDE server found" — no lock file matched the
current directory. Confirm VS Code is open on this exact workspace folder
with the Claude Code extension active, then try
claude-vscode-ide-bridge --check. - Connection refused / "IDE connection closed unexpectedly" — the lock file is stale (VS Code was closed or reloaded since it was written). Reopen the workspace and retry.
- "IDE rejected initialize" / auth errors — the extension's session token rotated (e.g. after a VS Code restart) since the lock file was written. Restart the MCP server connection.
- Tool not found after enabling it — check for typos in
IDE_BRIDGE_ENABLE_TOOLS; noteclose_tabis snake_case, unlike every other tool name.
Security
This bridge re-exposes IDE tools to the agent, so it treats the agent as untrusted and constrains what those tools can reach:
- Workspace path confinement. Every path-bearing argument (
filePath,uri,old_file_path,new_file_path) is resolved and checked against the matched lock file'sworkspaceFoldersbefore the call is forwarded. A path that resolves outside the workspace — an absolute path like/etc/passwd, or a../escape — is refused and never reaches VS Code. This is a lexical check (it collapses..but does not resolve symlinks), so a symlink that already lives inside the workspace and points outside it is not caught. executeCodeis gated behind its own opt-in and is never included inall(see above).- Mutating calls are audited. Every state-changing call (
openFile,saveDocument,openDiff,close_tab,closeAllDiffTabs,executeCode) writes a one-line record to stderr with a timestamp, the tool name, and the target path(s). The auth token is never logged.
What the bridge does not constrain:
- Editor read surface. The default-enabled read tools (
getOpenEditors,getCurrentSelection,getLatestSelection) return whatever is currently open or selected in the VS Code window, which can include files from other projects or sensitive files you happen to have open.getLatestSelectiondeliberately returns the most recent selection even from a no-longer-active editor. If that is a concern, disable those tools withIDE_BRIDGE_DISABLE_TOOLS.
Caveats
- This speaks an undocumented internal protocol (see the warning at the top) with no compatibility guarantee.
- The 12-tool list and their input shapes were captured by decompiling a
specific build of the
anthropic.claude-codeVS Code extension and, forgetDiagnostics, verified against a live session. They could drift on a future extension release. executeCoderuns arbitrary code in a Jupyter kernel; only enable it if you understand and accept that.
Attribution
- Root cause and the original workaround: GitHub user npapadacis, in a comment on anthropics/claude-code#40766.
- This package generalizes the single-tool, project-scoped shim documented at
docs/vscode-problems-mcp-HANDOFF.mdinto a tested, globally-installable package covering the full tool set.
Development
npm install
npm run test
npm run lint
npm run typecheck
npm run buildSee CONTRIBUTING.md for what the automated test suite
can and can't cover, and for the manual end-to-end verification steps.
