VSCode Chrome integration silently fails: 3 distinct bugs
Summary
Chrome browser integration in the Claude Code VSCode extension silently fails to attach the mcp__claude-in-chrome__* tools to the running CLI session. The webview shows browser context (<browser tabId="undefined"> in the prompt) and the model receives the browser_instruction prose, but the tools never appear in the deferred-tool pool, so the model is told it has chrome capabilities it does not actually have.
Investigation surfaced three distinct, independent bugs that together produce this failure. Bugs 1 and 2 are reproducible and orthogonal to my machine; bug 3 is the proximate cause I could not work around from outside the CLI binary.
Environment
- macOS 26.5 (arm64)
- Claude Code CLI: was 2.1.148, updated to 2.1.154 mid-debug
- VSCode extension: auto-updated 2.1.153 → 2.1.154 during the session
- Chrome 148.0.7778.179
- Claude Code Browser Extension:
fcoeoabgfenejglbffodgkkbkcdhcgfnv1.0.74 - Standalone Claude.app desktop also installed (whose chrome integration triggered bug 1)
---
Bug 1: Chrome extension prefers the wrong native-messaging host
The browser extension at fcoeoabgfenejglbffodgkkbkcdhcgfn iterates host candidates in this exact order (from assets/service-worker.ts-*.js):
const a = [
{name: "com.anthropic.claude_browser_extension", label: "Desktop"},
{name: "com.anthropic.claude_code_browser_extension", label: "Claude Code"}
];
for (const s of a) {
const t = chrome.runtime.connectNative(s.name);
// ping-pong handshake with 10s timeout
if (handshakeSucceeded) return; // ← Desktop wins unconditionally
}
Both manifests live in ~/Library/Application Support/Google/Chrome/NativeMessagingHosts/ whenever both Claude.app desktop and Claude Code are installed. The Desktop manifest's chrome-native-host binary responds to the ping even when Claude.app itself isn't running — Chrome just spawns the helper fresh. So the Claude Code variant is never reached, and VSCode's bridge never receives messages from the extension.
Repro: Install both Claude.app desktop and Claude Code. Confirm /Applications/Claude.app/Contents/Helpers/chrome-native-host gets spawned by Chrome instead of ~/.claude/chrome/chrome-native-host.
Workaround I applied: Renamed com.anthropic.claude_browser_extension.json to .disabled, forcing the fallback. Trade-off: breaks Claude.app desktop's chrome integration.
Suggested fix: Reverse the preference order (Claude Code first), or have each variant identify itself in the pong so the extension picks the one matching its packaging.
---
Bug 2: claude update does not regenerate the chrome-native-host wrapper
The wrapper at ~/.claude/chrome/chrome-native-host hardcodes a specific binary path:
#!/bin/sh
# Chrome native host wrapper script
# Generated by Claude Code - do not edit manually
exec "/Users/tmalahieude/.local/share/claude/versions/2.1.148" --chrome-native-host
When the VSCode extension auto-updates to a newer Claude Code version (e.g. 2.1.154) and spawns claude --claude-in-chrome-mcp from that newer binary, the bridge end (still v2.1.148) and the MCP-server end are mismatched. Running claude update to bump the standalone CLI from 2.1.148 → 2.1.154 installed the new binary but did not rewrite the wrapper — it still pointed at the now-stale 2.1.148. The script's own comment claims "do not edit manually", implying it expects to be regenerated by the updater.
Repro: Install Claude Code, set up chrome integration so the wrapper is generated. Run claude update. Observe wrapper still points at the old version.
Workaround I applied: Manually edited the wrapper to point at 2.1.154.
Suggested fix: Either have claude update rewrite the wrapper, or change the wrapper to dereference a version-agnostic symlink like ~/.local/bin/claude.
---
Bug 3 (root cause — the one I couldn't work around): setMcpServers silently no-ops mid-session
After fixing bugs 1 and 2, the infrastructure is correct end-to-end:
- Chrome native messaging now routes to
~/.claude/chrome/chrome-native-host→ spawnsclaude --chrome-native-hostv2.1.154 (bridge process, listening on/tmp/claude-mcp-browser-bridge-$USER/<pid>.sock) - VSCode spawns
claude --claude-in-chrome-mcpv2.1.154 (MCP child) - Versions match; both processes are alive and healthy
- The MCP child responds correctly when probed directly with a JSON-RPC
initialize/tools/list— it exposes the full set ofmcp__claude-in-chrome__*tools
The remaining problem is in the SDK call that connects the MCP child to the running CLI session.
When the user sends a message with @browser, the webview emits ensure_chrome_mcp_enabled. The extension log confirms it received and dispatched the request:
2026-05-28 20:07:24.598 [info] Received message from webview: {"type":"request","channelId":"alnydhsauyw","requestId":"b487mxh6ej","request":{"type":"ensure_chrome_mcp_enabled"}}
This is supposed to call query.setMcpServers({...existing, "claude-in-chrome": <stdio config>}) on the SDK. Expected: the CLI registers the new MCP server, discovers its tools, and includes them in the deferred-tool pool on the next turn.
Actual: no response, no error, no state push ever follows. Searching the entire log for the request ID b487mxh6ej: only the inbound line. Searching for MCP server "claude-in-chrome": zero matches (compare to normal MCP server connections, e.g. MCP server "linear": Successfully connected ...). The CLI's Dynamic tool loading: N/156 deferred tools included line on the next turn shows N unchanged, total denominator unchanged — the chrome MCP server's tools never join the pool.
Repro:
- Install Claude Code in VSCode on macOS with a working chrome integration setup (bugs 1 and 2 fixed).
- Open Claude Code, send a message with
@browserautocomplete chip. - Tail
~/Library/Application Support/Code/logs/.../anthropic.claude-code/Anthropic.claude-code.Claude VSCode.log.
Observe:
ensure_chrome_mcp_enabledrequest receivedChrome MCP: Successfully connected to serverfor the extension-side client- No corresponding
setMcpServersresponse orMCP server "claude-in-chrome": ...line Dynamic tool loading: N/X deferred tools included— X is the same as before the @browser send, no new tools added
The model is then prompted with the browser_instruction block (telling it mcp__claude-in-chrome__* tools are available) but none of those tools actually exist in its tool list. It responds with confusion or ToolSearchTool: keyword search for "claude-in-chrome", found 0 matches.
Note: The same path does work occasionally — e.g. one of my sessions earlier today (0c33075e-bf8f-4845-b078-5a63a559a574) attached chrome successfully on first send, with Dynamic tool loading: 17/160 deferred tools included afterward. I could not identify what made that session succeed; subsequent attempts in fresh sessions, resumed sessions, after VSCode reloads, and after full VSCode + Chrome restarts all failed.
---
Logs / artifacts available
Happy to provide:
- Full
Anthropic.claude-code.Claude VSCode.logfrom the failing day (~19,800 lines) - Process tree showing all bridge and MCP child processes during failures
- The chrome extension's service-worker bundle showing the preference order
This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗