claude-code - 💡(How to fix) Fix Claude in Chrome bridge silently fails when both Desktop and CLI native-messaging hosts are registered for the same extension [3 comments, 4 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#54567Fetched 2026-04-30 06:42:08
View on GitHub
Comments
3
Participants
4
Timeline
7
Reactions
0
Timeline (top)
labeled ×4commented ×3

Error Message

Even with the CLI helper as the bridge, mcp__claude-in-chrome__* calls still fail with the same error. The CLI helper does implement case "ping": ... type:"pong" ... and case "get_status": ... type:"status_response", and emits {type:"mcp_connected"} on stdout when an MCP client connects to its Unix socket. But the extension's mcpConnected flag is not getting set. The extension's service worker is heavily minified with console.log calls stripped, so we couldn't get a live error from the SW DevTools console to pin the exact failure.

  1. Schema mismatch: helper does YJ3().safeParse(_) (Zod strict) on incoming Chrome messages — if the schema rejects {type:"ping"} (e.g. requires extra fields), helper sends {type:"error"} instead of {type:"pong"} and the extension's pong-listener (matching only r.type === "pong") times out.
  • Diagnostic: leave at least one console.error in the extension's bridge handshake so users can see the failure mode.

Root Cause

Root cause (architectural)

Fix Action

Fix / Workaround

Workaround that proves the diagnosis (partially)

mv ~/Library/Application\ Support/Google/Chrome/NativeMessagingHosts/com.anthropic.claude_browser_extension.json \
   ~/Library/Application\ Support/Google/Chrome/NativeMessagingHosts/com.anthropic.claude_browser_extension.json.disabled

Then toggle the extension off/on in chrome://extensions/.

Remaining issue (after workaround)

Even with the CLI helper as the bridge, mcp__claude-in-chrome__* calls still fail with the same error.

Code Example

const s = [
  { name: "com.anthropic.claude_browser_extension",      label: "Desktop" },
  { name: "com.anthropic.claude_code_browser_extension", label: "Claude Code" }
];
for (const a of s) try {
  const t = chrome.runtime.connectNative(a.name);
  // ... ping/pong with 10s timeout, breaks on first success ...
}

---

mv ~/Library/Application\ Support/Google/Chrome/NativeMessagingHosts/com.anthropic.claude_browser_extension.json \
   ~/Library/Application\ Support/Google/Chrome/NativeMessagingHosts/com.anthropic.claude_browser_extension.json.disabled
RAW_BUFFERClick to expand / collapse

Environment

  • Claude Code CLI: 2.1.123 (also reproduces on 2.1.122)
  • Claude Desktop: 1.5354.0 (installed but not used)
  • Claude browser extension: 1.0.69 (ID: fcoeoabgfenejglbffodgkkbkcdhcgfn)
  • Google Chrome: 147.0.7727.116
  • macOS: 26.2 (build 25C56)
  • Chrome profile in use: "Profile 1" (extension installed only there, not in Default)

Symptom

Every mcp__claude-in-chrome__* tool call from Claude Code CLI 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...

The user is signed into claude.ai in Chrome with the same account as the CLI, the extension is installed and enabled, the sidepanel chat works, and Chrome was restarted multiple times. /chrome slash command shows "Status: Enabled" and "Extension: Installed". "Reconnect extension" does not fix it.

Root cause (architectural)

The extension's service worker iterates two native-messaging host names in fixed order, taking the first one that returns a pong:

const s = [
  { name: "com.anthropic.claude_browser_extension",      label: "Desktop" },
  { name: "com.anthropic.claude_code_browser_extension", label: "Claude Code" }
];
for (const a of s) try {
  const t = chrome.runtime.connectNative(a.name);
  // ... ping/pong with 10s timeout, breaks on first success ...
}

(Source: Profile 1/Extensions/fcoeoabgfenejglbffodgkkbkcdhcgfn/1.0.69_0/assets/service-worker.ts-tDtlCDd6.js)

Both manifests ship with the same extension ID in allowed_origins:

  • ~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.anthropic.claude_browser_extension.json/Applications/Claude.app/Contents/Helpers/chrome-native-host (Rust binary, ships with Claude Desktop installer)
  • ~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.anthropic.claude_code_browser_extension.json~/.claude/chrome/chrome-native-host (wrapper that execs claude --chrome-native-host)

Because Claude Desktop is installed (even if never opened — the helper binary is just a Rust executable with no GUI dependency), the Desktop host wins the loop. Chrome spawns the Desktop helper, the helper opens its bridge socket at /tmp/claude-mcp-browser-bridge-$USER/<pid>.sock, the extension marks "connected" — but the CLI's claude-in-chrome MCP client cannot complete the upstream handshake against the Desktop helper, so every tool call fails with "Browser extension is not connected."

Evidence

  • lsof confirmed bridge socket owned by /Applications/Claude.app/Contents/Helpers/chrome-native-host, parent = Chrome.
  • Quitting the Claude Desktop GUI does NOT help — Chrome relaunches the Desktop helper binary on demand because the manifest is what's registered, not the app.
  • Socket directory permissions/ownership pass the CLI's validateSocketSecurity check (0700 dir, 0600 socket, user-owned).
  • Both fresh and existing CLI sessions (v2.1.122 and v2.1.123) fail identically.

Workaround that proves the diagnosis (partially)

mv ~/Library/Application\ Support/Google/Chrome/NativeMessagingHosts/com.anthropic.claude_browser_extension.json \
   ~/Library/Application\ Support/Google/Chrome/NativeMessagingHosts/com.anthropic.claude_browser_extension.json.disabled

Then toggle the extension off/on in chrome://extensions/.

After this, Chrome correctly spawns claude --chrome-native-host as the helper (ps -ef confirms). The CLI's helper Unix socket is created, stdio pipes to Chrome are alive, and the helper has been observed running for 4+ minutes.

Remaining issue (after workaround)

Even with the CLI helper as the bridge, mcp__claude-in-chrome__* calls still fail with the same error.

The CLI helper does implement case "ping": ... type:"pong" ... and case "get_status": ... type:"status_response", and emits {type:"mcp_connected"} on stdout when an MCP client connects to its Unix socket. But the extension's mcpConnected flag is not getting set. The extension's service worker is heavily minified with console.log calls stripped, so we couldn't get a live error from the SW DevTools console to pin the exact failure.

Plausible secondary causes:

  1. Schema mismatch: helper does YJ3().safeParse(_) (Zod strict) on incoming Chrome messages — if the schema rejects {type:"ping"} (e.g. requires extra fields), helper sends {type:"error"} instead of {type:"pong"} and the extension's pong-listener (matching only r.type === "pong") times out.
  2. Manifest V3 service-worker idle race around the post-get_status mcp_connected notification.

Suggested fixes

  • Short-term: in the extension's host iteration, don't trust connectNative + ping/pong as proof of bridge health — also wait for the upstream mcp_connected notification (with a short timeout) before committing to a host. If it doesn't arrive, fall through to the next host name.
  • Longer-term: have the Claude Desktop installer either skip the chrome native-messaging manifest when the user opted into Claude Code, or make the Desktop helper detect "no Desktop GUI auth available" and refuse the pong so the loop falls through.
  • Diagnostic: leave at least one console.error in the extension's bridge handshake so users can see the failure mode.

Reproduction

  1. Install Claude Desktop (/Applications/Claude.app/) — but never use it.
  2. Install Claude Code CLI and the Chrome extension; sign into claude.ai with the matching account.
  3. From CLI, run any mcp__claude-in-chrome__* tool. Observe "Browser extension is not connected."
  4. Verify dual manifest registration: ls ~/Library/Application\ Support/Google/Chrome/NativeMessagingHosts/com.anthropic.claude*.

extent analysis

TL;DR

The issue can be resolved by modifying the extension's service worker to wait for the upstream mcp_connected notification before committing to a host, or by having the Claude Desktop installer skip the chrome native-messaging manifest when the user opted into Claude Code.

Guidance

  • Verify that the Claude Desktop helper is being spawned by Chrome by checking the bridge socket ownership using lsof.
  • Try the suggested workaround of disabling the Claude Desktop native-messaging manifest and toggling the extension off/on in chrome://extensions/ to see if it resolves the issue.
  • Investigate the possibility of a schema mismatch between the helper and the extension, and check if the helper is sending an error response instead of a pong.
  • Consider adding a console.error statement in the extension's bridge handshake to diagnose the failure mode.

Example

No code snippet is provided as the issue is more related to the architecture and configuration of the system.

Notes

The issue is complex and has multiple possible causes, including a schema mismatch and a manifest V3 service-worker idle race. Further investigation is needed to determine the root cause and implement a permanent fix.

Recommendation

Apply the suggested workaround of disabling the Claude Desktop native-messaging manifest and toggling the extension off/on in chrome://extensions/, as it has been proven to partially resolve the issue. This will allow the CLI helper to be spawned by Chrome and may provide more insight into the remaining issue.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING