[BUG] Claude in Chrome: handshake fails even after full recovery (CLI 2.1.117, ext 1.0.69)

Resolved 💬 4 comments Opened Apr 24, 2026 by WolfTheDesigner Closed May 5, 2026

Summary

mcp__claude-in-chrome__* tools return "Browser extension is not connected" on every call, despite:

  • Claude Code CLI authenticated to the same org and email as the claude.ai Chrome session (verified via avatar menu + claude auth status)
  • Chrome extension installed, enabled, toggled OFF→ON
  • Chrome fully restarted (osascript quit + open -a)
  • Native messaging host respawned (new PID observed each toggle)
  • Local + Managed Extension Settings for the extension wiped
  • /tmp/claude-mcp-browser-bridge-*/*.sock cleaned
  • Logged out of claude.ai and back in, with matching account confirmed

Same-shape bug as #52559 (filed 2026-04-23). I can confirm the full recovery checklist from the community docs (toggle, storage wipe, Chrome restart, re-login) does not unblock it on CLI 2.1.117.

Environment

| Field | Value |
| --- | --- |
| OS | macOS Darwin 25.4.0 |
| Claude Code CLI | 2.1.117 (native build, ~/.local/share/claude/versions/2.1.117) |
| Browser | Google Chrome (latest stable); Brave also installed |
| Extension | Claude for Chrome 1.0.69_0, ID fcoeoabgfenejglbffodgkkbkcdhcgfn |
| Subscription | paid team plan |

Key observation — MCP says connected, tool says not connected

When probed with claude --chrome -p "..." --output-format=stream-json --verbose, the init event reports:

"mcp_servers":[
  ...,
  {"name":"claude-in-chrome","status":"connected"},
  ...
]

So the MCP server registration succeeds. But the tool invocation itself (mcp__claude-in-chrome__tabs_context_mcp with no args) returns the "not connected" error verbatim. The failure is inside the native-host ↔ extension stdio dialogue, not at the MCP socket layer.

Native host state during failure

Host is alive with stdio PIPE to the Chrome extension AND a listening unix socket — but never receives an accepted client connection:

$ lsof -p <host-pid> | grep -E "sock|PIPE|unix"
2.1.117 <pid> user    0     PIPE ...  ->...   (stdin from extension)
2.1.117 <pid> user    1     PIPE ...  ->...   (stdout to extension)
2.1.117 <pid> user    4u    unix ...  /tmp/claude-mcp-browser-bridge-<user>/<pid>.sock
2.1.117 <pid> user    5     PIPE ...  ->...   (dup of fd 1)

No accepted client socket on the host. Each new claude --chrome -p probe also never opens a connection back to the socket:

$ lsof -U | grep claude-mcp-browser
2.1.117 <host-pid> user 4u unix ...  /tmp/claude-mcp-browser-bridge-<user>/<pid>.sock
# only the listening entry

So either the extension is rejecting the handshake before the host accepts, or the host is rejecting before listening accepts — but the extension → host stdio is definitely live (PIPEs active, otherwise the service worker wouldn't have spawned the host at all).

Steps attempted (none fixed it)

  1. chrome://extensions/ → Claude card → toggle OFF → verify ps aux | grep chrome-native-host is empty → toggle ON → new host spawns → claude --chrome → NOTCONNECTED
  2. osascript -e 'tell application "Google Chrome" to quit'open -a "Google Chrome" → new host spawns → NOTCONNECTED
  3. rm -rf "~/Library/Application Support/Google/Chrome/Default/Local Extension Settings/fcoeoabgfenejglbffodgkkbkcdhcgfn" + Managed Extension Settings + Chrome restart → new host → NOTCONNECTED
  4. Logout of claude.ai web, login back with the CLI account → refresh → NOTCONNECTED
  5. All of the above combined, in the sequence recommended by community docs → NOTCONNECTED

Every probe observes fresh PIDs: 5 consecutive respawned hosts over the session, each with a fresh unix socket. Fresh bridgeSessionId per CLI probe, so the stale-session-lock gotcha can be ruled out.

Secondary finding — Brave manifest auto-regenerates

Not a blocker here, but contributes to making the CLI integration hard to keep stable on a dual-browser macOS install where Claude.app is also present:

~/Library/Application Support/BraveSoftware/Brave-Browser/NativeMessagingHosts/
 com.anthropic.claude_browser_extension.json    (re-appears whenever Claude.app launches)

Any launch of /Applications/Claude.app regenerates that manifest in Brave (and Chrome) even if the user previously renamed it to .disabled. If Claude.app is also installed, the desktop native-messaging wrapper can intercept the extension from the wrong binary; users have to chase the manifest and rename it again. Making the manifest write idempotent against a .disabled sibling, or honouring a .claude-no-regen marker, would help.

What would help diagnose further

The extension service worker's DevTools console would almost certainly show the actual rejection cause. Could the extension surface the handshake-refusal reason in the extension popup or in chrome.runtime.lastError? Right now the user-facing error message is fully generic and points at the three things that are demonstrably already correct (installed, enabled, logged into matching account).

Related issues

  • #52559 — same-shape symptom, filed 2026-04-23
  • #47202 — --chrome flag: MCP client never connects to Chrome native host socket
  • #42344 — Chrome extension MCP tools report 'not connected' despite successful pairing (macOS, v2.1.90)
  • #40758, #38845, #36910 — earlier broken-handshake reports on 1.0.63

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗