[BUG] Claude in Chrome extension v1.0.70 + Claude Desktop 1.6608.2: protocol-level handshake silent failure breaks Claude Code browser MCP
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Claude in Chrome extension v1.0.70 + Claude Desktop 1.6608.2: protocol-level handshake silent failure breaks Claude Code browser MCP
Labels: bug,claude-in-chrome
Summary
mcp__claude-in-chrome__* tools in Claude Code consistently return the static error "Browser extension is not connected" despite the extension being installed, enabled, logged into the same claude.ai account as Claude Code, and showing connected status in its own side panel. The wire-level plumbing is correct end-to-end; the failure is at the protocol handshake layer between the extension and the Code-side native messaging host.
This worked from 2026-05-06 (extension install) through 2026-05-12, then broke when the desktop Claude app rewrote its native-messaging manifest. Operator-side workarounds confirmed non-durable.
Environment
| Component | Version |
|---|---|
| OS | Windows 11 Home 10.0.26200 |
| Chrome | stable (toolbar shows pinned extension support, Manifest V3) |
| Claude Desktop app | 1.6608.2 (MSIX package Claude_pzs8sxrjxfjjc) |
| Claude Code CLI | 2.1.139 |
| Claude in Chrome extension | 1.0.70 (Beta) |
| Extension ID | fcoeoabgfenejglbffodgkkbkcdhcgfn |
Symptom
Any invocation of mcp__claude-in-chrome__tabs_context_mcp (or other browser-MCP tools) from a Claude Code session returns:
Browser extension is not connected. Please ensure the Claude browser extension is installed and running (https://claude.ai/chrome), and that you are logged into claude.ai with the same account as Claude Code. If this is your first time connecting to Chrome, you may need to restart Chrome for the installation to take effect.
The error string is static and emitted locally by the Code-side MCP plugin without ever attempting (or before completing) the bridge handshake. The extension is in fact installed, enabled, signed in to the same account, and Chrome had been restarted multiple times during diagnosis.
Architecture (as observed on Windows)
Two native messaging hosts are registered in HKCU\Software\Google\Chrome\NativeMessagingHosts:
| Host name | Manifest path | Binary |
|---|---|---|
| com.anthropic.claude_browser_extension | %LOCALAPPDATA%\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\Claude\ChromeNativeHost\com.anthropic.claude_browser_extension.json | chrome-native-host.exe (desktop app) |
| com.anthropic.claude_code_browser_extension | %APPDATA%\Claude Code\ChromeNativeHost\com.anthropic.claude_code_browser_extension.json | claude.exe --chrome-native-host (Code) |
The single extension ID fcoeoabgfenejglbffodgkkbkcdhcgfn is whitelisted in both manifests' allowed_origins. Code's side additionally exposes a named pipe \\.\pipe\claude-mcp-browser-bridge-speed that the spawned bridge process and any active Claude Code session bind to.
Timeline (proved by file mtimes + registry timestamps)
| Date (UTC) | Event |
|---|---|
| 2026-03-12 12:18 | Claude desktop app installed; native-messaging host registered |
| 2026-03-24 18:23 | Claude Code installed; Code native-messaging host registered |
| 2026-05-06 21:10 | Extension v1.0.70 installed in Chrome |
| 2026-05-06 → 2026-05-12 | Working window — Claude Code's mcp__claude-in-chrome__* tools functioned normally |
| 2026-05-12 15:53 | Desktop app's com.anthropic.claude_browser_extension.json rewritten by the desktop app (file mtime), adding chrome-extension://fcoeoabgfenejglbffodgkkbkcdhcgfn/ to its allowed_origins |
| 2026-05-12 onward | All mcp__claude-in-chrome__* calls return "not connected" |
Hypothesis at first inspection: the May 12 manifest rewrite caused the extension's connectNative to bind to the desktop host first and never fall through to Code's host. That hypothesis was tested and falsified — see "Diagnostics tried" below.
Diagnostics tried (each independently insufficient)
1. Manifest surgery on desktop's allowed_origins
Removed chrome-extension://fcoeoabgfenejglbffodgkkbkcdhcgfn/ from desktop's com.anthropic.claude_browser_extension.json allowed_origins. The file edit succeeded, JSON stayed valid. Effect: nothing — Chrome had already cached the manifest.
2. Toggle extension off → on
Reset the extension's service worker. Effect: Chrome re-read the manifest, the desktop-side connectNative was rejected, and Chrome spawned claude.exe --chrome-native-host (Code's bridge) instead. Bridge process alive, named pipe up. But still tabs_context_mcp returns "not connected".
3. Full Chrome restart (close all windows, kill remaining chrome.exe, relaunch)
Clean cache, fresh extension service worker. Same result — bridge spawned, "not connected".
4. Direct pipe handshake test (PowerShell)
$pipe = [System.IO.Pipes.NamedPipeClientStream]::new('.', 'claude-mcp-browser-bridge-speed', 'InOut', 'None')
$pipe.Connect(2000)
# IsConnected=True, CanRead=True, CanWrite=True
$sw = [System.IO.StreamWriter]::new($pipe); $sw.WriteLine('{"type":"ping"}'); $sw.Flush()
Bridge process accepts the connection, consumes the bytes, doubles its CPU (0.48s → 0.97s), spawns 8 new worker threads, but sends no reply (expected — wrong protocol). The bridge is alive, healthy, and a functioning pipe server.
5. DevTools service-worker console probe
In the extension's service-worker DevTools, executed:
chrome.runtime.connectNative('com.anthropic.claude_code_browser_extension')
Result: returned a Port object, then immediately Unchecked runtime.lastError: Native host has exited. The error fires because the bridge enforces a singleton on the named pipe — Chrome's existing connection from the extension's initial connectNative still owns the pipe, so the second spawn exits immediately. The first spawn (at Chrome startup) is the canonical bridge process and survives.
6. Chat panel interaction does NOT route through Code's bridge
With the side panel open and the bridge process PID known, asked the user to type and send a message in the chat panel. Observed bridge process CPU: 0.45s → 0.48s (a 30ms delta over a full chat interaction). Compare to single external pipe poke: 0.48s → 0.97s (+500ms). The extension is not sending any payload bytes to Code's native messaging port even during full chat-panel use. The chat panel's traffic goes elsewhere (presumably HTTPS to claude.ai).
7. Fresh Claude Code session with --chrome flag
claude --chrome --dangerously-skip-permissions -p "Call mcp__claude-in-chrome__tabs_context_mcp once..."
Returns the same "Browser extension is not connected" error. Confirms the failure is not stale state in any long-running Code session.
8. Extension uninstall + reinstall via Chrome Web Store
Removed and reinstalled (still v1.0.70). Logged back into the same account. No change — same error. Confirms the failure is in the extension's code paths, not in stored state (IndexedDB, Local Storage, service worker registration).
9. Manifest edit does not survive desktop-app restart
The desktop app rewrites com.anthropic.claude_browser_extension.json on every startup, re-adding the shared extension ID to allowed_origins. Confirmed by mtime delta after a desktop relaunch: original edit at 01:08, post-restart mtime at 01:33, content with extension ID re-added. Operator-side mitigation is fundamentally non-durable.
Root cause (best evidence-supported hypothesis)
Both endpoints — the extension service worker and the Code-side bridge process — are wired up correctly at the OS level. Each is waiting for the other to initiate the protocol-level handshake. Neither does. The stream stays open and silent indefinitely.
Evidence pattern:
- Extension successfully opens a Chrome Native Messaging Port to Code's host (
connectNativereturns a Port; nolastError). - Code's bridge process consumes ~0.4s of CPU on startup (accept-loop setup) and then stays idle indefinitely — no application-level bytes arrive on stdin.
- Bridge IS responsive when poked externally (CPU+threads jump on first pipe access from a non-Code client), so the process isn't stuck.
- Chat panel use generates HTTPS traffic to claude.ai but no bytes through the native messaging port to Code's bridge.
Possible causes inside the extension code:
- The extension may now check for desktop-host-style protocol responses and treat the Code host as "not the right server", silently abandoning the port.
- The Code-side bridge may expect an extension-initiated
hello/initmessage that the extension only sends when bound to the desktop host. - The May 12 desktop-app update may have updated a shared client library version that the Code bridge wasn't updated for.
We don't have extension or bridge source visibility to narrow further.
Suggested fix directions
In order of suspected blast radius:
- Restore the May 6–12 working behavior in the extension: when
connectNativeis called againstcom.anthropic.claude_code_browser_extension, send the same hello/init message that worked in the May 6–12 window. Independently of which native host the extension thinks it's "primarily" talking to. - Have the Code-side bridge send an unsolicited hello on accept so the extension can see "this is a Code host" without needing to initiate.
- Decouple the two products' native hosts. Use distinct extension IDs (one extension per product, no shared whitelisting), or include a routing discriminator in the native-host name. Currently a desktop-app update silently steals the extension's primary native messaging port from Claude Code, with no operator-visible signal and no fall-through.
- Make the operator-side workaround durable. If a future extension version is going to be the right place to fix this, also stop the desktop app from rewriting its native-messaging manifest on every startup so operators can hold an intentional
allowed_originsconfiguration in place between extension fixes.
Repro
- Install Claude Desktop ≥ 1.6608.2 and Claude Code ≥ 2.1.139 on a Windows 11 machine.
- Install the "Claude in Chrome (Beta)" extension v1.0.70 from claude.ai/chrome.
- Launch Chrome. Open a
claudeCLI session and invoke anymcp__claude-in-chrome__*tool. Observe "Browser extension is not connected" error. - (Optional verification) Inspect the bridge process (
claude.exe --chrome-native-host) over a 5-minute window during chat-panel use. CPU usage will not exceed ~0.5s — confirming no application-level traffic flows through Code's native messaging port.
Diagnostic artifacts
- Process ancestry of the spawned bridge:
chrome.exe → cmd.exe → chrome-native-host.bat → claude.exe --chrome-native-host(correct path). - Active named pipes during diagnosis:
chrome.nativeMessaging.in/out.<session>(Chrome ↔ bridge) andclaude-mcp-browser-bridge-speed(bridge ↔ Code session). - DevTools service-worker console: empty after fresh reload — extension is built with logging stripped in production, so no extension-side trace available.
What Should Happen?
Claude in Chrome extension v1.0.70 + Claude Desktop 1.6608.2: protocol-level handshake silent failure breaks Claude Code browser MCP
Labels: bug,claude-in-chrome
Summary
mcp__claude-in-chrome__* tools in Claude Code consistently return the static error "Browser extension is not connected" despite the extension being installed, enabled, logged into the same claude.ai account as Claude Code, and showing connected status in its own side panel. The wire-level plumbing is correct end-to-end; the failure is at the protocol handshake layer between the extension and the Code-side native messaging host.
This worked from 2026-05-06 (extension install) through 2026-05-12, then broke when the desktop Claude app rewrote its native-messaging manifest. Operator-side workarounds confirmed non-durable.
Environment
| Component | Version |
|---|---|
| OS | Windows 11 Home 10.0.26200 |
| Chrome | stable (toolbar shows pinned extension support, Manifest V3) |
| Claude Desktop app | 1.6608.2 (MSIX package Claude_pzs8sxrjxfjjc) |
| Claude Code CLI | 2.1.139 |
| Claude in Chrome extension | 1.0.70 (Beta) |
| Extension ID | fcoeoabgfenejglbffodgkkbkcdhcgfn |
Symptom
Any invocation of mcp__claude-in-chrome__tabs_context_mcp (or other browser-MCP tools) from a Claude Code session returns:
Browser extension is not connected. Please ensure the Claude browser extension is installed and running (https://claude.ai/chrome), and that you are logged into claude.ai with the same account as Claude Code. If this is your first time connecting to Chrome, you may need to restart Chrome for the installation to take effect.
The error string is static and emitted locally by the Code-side MCP plugin without ever attempting (or before completing) the bridge handshake. The extension is in fact installed, enabled, signed in to the same account, and Chrome had been restarted multiple times during diagnosis.
Architecture (as observed on Windows)
Two native messaging hosts are registered in HKCU\Software\Google\Chrome\NativeMessagingHosts:
| Host name | Manifest path | Binary |
|---|---|---|
| com.anthropic.claude_browser_extension | %LOCALAPPDATA%\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\Claude\ChromeNativeHost\com.anthropic.claude_browser_extension.json | chrome-native-host.exe (desktop app) |
| com.anthropic.claude_code_browser_extension | %APPDATA%\Claude Code\ChromeNativeHost\com.anthropic.claude_code_browser_extension.json | claude.exe --chrome-native-host (Code) |
The single extension ID fcoeoabgfenejglbffodgkkbkcdhcgfn is whitelisted in both manifests' allowed_origins. Code's side additionally exposes a named pipe \\.\pipe\claude-mcp-browser-bridge-speed that the spawned bridge process and any active Claude Code session bind to.
Timeline (proved by file mtimes + registry timestamps)
| Date (UTC) | Event |
|---|---|
| 2026-03-12 12:18 | Claude desktop app installed; native-messaging host registered |
| 2026-03-24 18:23 | Claude Code installed; Code native-messaging host registered |
| 2026-05-06 21:10 | Extension v1.0.70 installed in Chrome |
| 2026-05-06 → 2026-05-12 | Working window — Claude Code's mcp__claude-in-chrome__* tools functioned normally |
| 2026-05-12 15:53 | Desktop app's com.anthropic.claude_browser_extension.json rewritten by the desktop app (file mtime), adding chrome-extension://fcoeoabgfenejglbffodgkkbkcdhcgfn/ to its allowed_origins |
| 2026-05-12 onward | All mcp__claude-in-chrome__* calls return "not connected" |
Hypothesis at first inspection: the May 12 manifest rewrite caused the extension's connectNative to bind to the desktop host first and never fall through to Code's host. That hypothesis was tested and falsified — see "Diagnostics tried" below.
Diagnostics tried (each independently insufficient)
1. Manifest surgery on desktop's allowed_origins
Removed chrome-extension://fcoeoabgfenejglbffodgkkbkcdhcgfn/ from desktop's com.anthropic.claude_browser_extension.json allowed_origins. The file edit succeeded, JSON stayed valid. Effect: nothing — Chrome had already cached the manifest.
2. Toggle extension off → on
Reset the extension's service worker. Effect: Chrome re-read the manifest, the desktop-side connectNative was rejected, and Chrome spawned claude.exe --chrome-native-host (Code's bridge) instead. Bridge process alive, named pipe up. But still tabs_context_mcp returns "not connected".
3. Full Chrome restart (close all windows, kill remaining chrome.exe, relaunch)
Clean cache, fresh extension service worker. Same result — bridge spawned, "not connected".
4. Direct pipe handshake test (PowerShell)
$pipe = [System.IO.Pipes.NamedPipeClientStream]::new('.', 'claude-mcp-browser-bridge-speed', 'InOut', 'None')
$pipe.Connect(2000)
# IsConnected=True, CanRead=True, CanWrite=True
$sw = [System.IO.StreamWriter]::new($pipe); $sw.WriteLine('{"type":"ping"}'); $sw.Flush()
Bridge process accepts the connection, consumes the bytes, doubles its CPU (0.48s → 0.97s), spawns 8 new worker threads, but sends no reply (expected — wrong protocol). The bridge is alive, healthy, and a functioning pipe server.
5. DevTools service-worker console probe
In the extension's service-worker DevTools, executed:
chrome.runtime.connectNative('com.anthropic.claude_code_browser_extension')
Result: returned a Port object, then immediately Unchecked runtime.lastError: Native host has exited. The error fires because the bridge enforces a singleton on the named pipe — Chrome's existing connection from the extension's initial connectNative still owns the pipe, so the second spawn exits immediately. The first spawn (at Chrome startup) is the canonical bridge process and survives.
6. Chat panel interaction does NOT route through Code's bridge
With the side panel open and the bridge process PID known, asked the user to type and send a message in the chat panel. Observed bridge process CPU: 0.45s → 0.48s (a 30ms delta over a full chat interaction). Compare to single external pipe poke: 0.48s → 0.97s (+500ms). The extension is not sending any payload bytes to Code's native messaging port even during full chat-panel use. The chat panel's traffic goes elsewhere (presumably HTTPS to claude.ai).
7. Fresh Claude Code session with --chrome flag
claude --chrome --dangerously-skip-permissions -p "Call mcp__claude-in-chrome__tabs_context_mcp once..."
Returns the same "Browser extension is not connected" error. Confirms the failure is not stale state in any long-running Code session.
8. Extension uninstall + reinstall via Chrome Web Store
Removed and reinstalled (still v1.0.70). Logged back into the same account. No change — same error. Confirms the failure is in the extension's code paths, not in stored state (IndexedDB, Local Storage, service worker registration).
9. Manifest edit does not survive desktop-app restart
The desktop app rewrites com.anthropic.claude_browser_extension.json on every startup, re-adding the shared extension ID to allowed_origins. Confirmed by mtime delta after a desktop relaunch: original edit at 01:08, post-restart mtime at 01:33, content with extension ID re-added. Operator-side mitigation is fundamentally non-durable.
Root cause (best evidence-supported hypothesis)
Both endpoints — the extension service worker and the Code-side bridge process — are wired up correctly at the OS level. Each is waiting for the other to initiate the protocol-level handshake. Neither does. The stream stays open and silent indefinitely.
Evidence pattern:
- Extension successfully opens a Chrome Native Messaging Port to Code's host (
connectNativereturns a Port; nolastError). - Code's bridge process consumes ~0.4s of CPU on startup (accept-loop setup) and then stays idle indefinitely — no application-level bytes arrive on stdin.
- Bridge IS responsive when poked externally (CPU+threads jump on first pipe access from a non-Code client), so the process isn't stuck.
- Chat panel use generates HTTPS traffic to claude.ai but no bytes through the native messaging port to Code's bridge.
Possible causes inside the extension code:
- The extension may now check for desktop-host-style protocol responses and treat the Code host as "not the right server", silently abandoning the port.
- The Code-side bridge may expect an extension-initiated
hello/initmessage that the extension only sends when bound to the desktop host. - The May 12 desktop-app update may have updated a shared client library version that the Code bridge wasn't updated for.
We don't have extension or bridge source visibility to narrow further.
Suggested fix directions
In order of suspected blast radius:
- Restore the May 6–12 working behavior in the extension: when
connectNativeis called againstcom.anthropic.claude_code_browser_extension, send the same hello/init message that worked in the May 6–12 window. Independently of which native host the extension thinks it's "primarily" talking to. - Have the Code-side bridge send an unsolicited hello on accept so the extension can see "this is a Code host" without needing to initiate.
- Decouple the two products' native hosts. Use distinct extension IDs (one extension per product, no shared whitelisting), or include a routing discriminator in the native-host name. Currently a desktop-app update silently steals the extension's primary native messaging port from Claude Code, with no operator-visible signal and no fall-through.
- Make the operator-side workaround durable. If a future extension version is going to be the right place to fix this, also stop the desktop app from rewriting its native-messaging manifest on every startup so operators can hold an intentional
allowed_originsconfiguration in place between extension fixes.
Repro
- Install Claude Desktop ≥ 1.6608.2 and Claude Code ≥ 2.1.139 on a Windows 11 machine.
- Install the "Claude in Chrome (Beta)" extension v1.0.70 from claude.ai/chrome.
- Launch Chrome. Open a
claudeCLI session and invoke anymcp__claude-in-chrome__*tool. Observe "Browser extension is not connected" error. - (Optional verification) Inspect the bridge process (
claude.exe --chrome-native-host) over a 5-minute window during chat-panel use. CPU usage will not exceed ~0.5s — confirming no application-level traffic flows through Code's native messaging port.
Diagnostic artifacts
- Process ancestry of the spawned bridge:
chrome.exe → cmd.exe → chrome-native-host.bat → claude.exe --chrome-native-host(correct path). - Active named pipes during diagnosis:
chrome.nativeMessaging.in/out.<session>(Chrome ↔ bridge) andclaude-mcp-browser-bridge-speed(bridge ↔ Code session). - DevTools service-worker console: empty after fresh reload — extension is built with logging stripped in production, so no extension-side trace available.
Error Messages/Logs
Steps to Reproduce
Steps to Reproduce (replace the placeholder example):
- On a Windows 11 machine, install Claude Desktop ≥ 1.6608.2 (MSIX) and Claude Code ≥ 2.1.139.
- Install the "Claude in Chrome (Beta)" extension v1.0.70 from https://claude.ai/chrome.
- Restart Chrome after install. Log into claude.ai with the same account Claude Code is authenticated against.
- In a terminal, run
claudeto start a session (orclaude --chrome --dangerously-skip-permissions -p "..."for a headless
test).
- Invoke any browser MCP tool, e.g.
mcp__claude-in-chrome__tabs_context_mcp.
Expected: tool returns tab context for the active Chrome window.
Actual: tool returns the static error "Browser extension is not connected" (full text in "What's Wrong?" above).
Verification that the bridge is alive but no traffic flows: inspect the bridge process claude.exe --chrome-native-host CPU
during chat-panel use — stays ~0.5s. External pipe poke via PowerShell NamedPipeClientStream against
\\.\pipe\claude-mcp-browser-bridge-<user> causes immediate CPU and thread growth, confirming the bridge is responsive and the
extension is simply not sending bytes.
Claude Model: claude-opus-4-7 (Claude Opus 4.7).
Is this a regression?: keep "Yes, this worked in a previous version" ✅.
Last Working Version: 1.0.70 — same extension version. The regression isn't caused by an extension upgrade; it's caused by the
Claude Desktop app v1.6608.2 (2026-05-12) rewriting its native-messaging manifest to claim the shared extension ID. Worth
adding a note: "Extension 1.0.70 worked normally between 2026-05-06 install and 2026-05-12, when Claude Desktop 1.6608.2
rewrote its native-messaging manifest's allowed_origins. No extension version change was involved.
Claude Model
None
Is this a regression?
Yes, this worked in a previous version
Last Working Version
_No response_
Claude Code Version
2.1.139
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
_No response_
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗