[BUG] Claude-in-Chrome: Browser extension persistently fails to connect from CLI
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?
The Claude-in-Chrome browser extension consistently fails to connect when invoked from Claude Code CLI. Every MCP tool call (tabs_context_mcp, switch_browser, etc.) returns the same error:
Browser extension is not connected. Please ensure the Claude browser extension is installed and running...
The connection never establishes despite extensive troubleshooting across multiple sessions.
Troubleshooting Already Attempted
- Reinstalled/re-enabled the Chrome extension multiple times
- Restarted Chrome multiple times
- Restarted Claude Code CLI multiple times
- Logged out and re-logged into claude.ai on all devices
- Clicked the extension icon / checked for "Connect" button in extension popup
- Tried switch_browser MCP tool to re-initiate connection
- Issue persists across multiple separate CLI sessions over multiple days
Error Message
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.
This exact same message is returned for all MCP browser tools attempted:
- tabs_context_mcp (with createIfEmpty: true)
- switch_browser
Environment
- Claude Code version: 2.1.38
- OS: macOS 26.2 (Build 25C56)
- Architecture: Apple Silicon (arm64)
- Chrome version: 144.0.7559.133
- Node.js: v23.6.0
- Model: claude-opus-4-6
Expected Behavior
tabs_context_mcp should establish a connection to the Chrome extension and return available tab context, allowing browser automation tools to function.
Actual Behavior
All MCP browser tool calls fail immediately with the "Browser extension is not connected" error. No connection is ever established regardless of troubleshooting steps taken.
Additional Context
- The issue has persisted across multiple days and sessions, not a one-time failure
- No additional error details or logs are surfaced beyond the generic connection error message
- It's unclear whether the issue is on the CLI/MCP side or the extension side, as no diagnostic info is provided
- In a previous session, the MCP bridge appeared to reject connection requests due to a user identity mismatch — the authenticated user on the Claude Code CLI side did not match the authenticated user on the Chrome extension / claude.ai side. The user
verified they were logged into the same account on both sides and re-authenticated on all devices, but the issue persisted. This suggests a possible bug in the authentication/session handshake between the CLI and the browser extension bridge, where
stale session tokens or cached identity state may cause a permanent mismatch even after re-login.
What Should Happen?
Claude Code CLI should be able to use the browser.
Error Messages/Logs
Steps to Reproduce
- Install Claude-in-Chrome extension in Chrome
- Log into claude.ai in the browser
- Start a Claude Code CLI session
- Call any mcp__claude-in-chrome__* tool (e.g., tabs_context_mcp with createIfEmpty: true)
- Observe: always returns "Browser extension is not connected" error
Claude Model
Opus
Is this a regression?
Yes, this worked in a previous version
Last Working Version
_No response_
Claude Code Version
v2.1.38
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
Also present in VsCode Extension
21 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Cross-platform confirmation: Same issue on Linux (Ubuntu/Zorin 17.3)
Experiencing the identical
"Invalid token or user mismatch"bridge rejection on Linux with v2.1.38.Environment
/opt/google/chrome/chrome)fcoeoabgfenejglbffodgkkbkcdhcgfn)liran@smartlighthouse.com) confirmed on both CLI (/status) and claude.aiDiagnostic findings
Everything below the bridge is healthy:
| Component | Status |
|-----------|--------|
| Native messaging host manifest | Correct (
~/.config/google-chrome/NativeMessagingHosts/com.anthropic.claude_code_browser_extension.json) || Native host binary | Points to correct version (
~/.local/share/claude/versions/2.1.38) || Chrome spawns native host | Confirmed (PID 2426014, parent = Chrome PID 2425776) |
| Unix socket created |
/tmp/claude-mcp-browser-bridge-liran/2426014.sock— listening || Socket accepts connections | Verified via Python
socket.connect()|| Extension detected by CC |
Extension fcoeoabgfenejglbffodgkkbkcdhcgfn found in chrome Default|The failure is specifically in the WebSocket bridge handshake:
This repeats indefinitely (30+ attempts observed) with exponential backoff capping at 30s intervals. Every retry fetches a fresh OAuth token, connects successfully to the WebSocket, then gets immediately rejected by the bridge.
What was tried (none helped)
Key observation
The bridge uses cloud-based WebSocket pairing (
wss://bridge.claudeusercontent.com), not the local Unix socket. CC's OAuth token is rejected server-side despite being for the correct account. This suggests the issue is in the bridge's token validation logic, not in the local native messaging setup.The debug log (
~/.claude/debug/) does not log actual token values — only that it "Fetches OAuth token" before each attempt. No way to inspect what's being sent vs. what's expected without server-side logs.For some reason
contains a hard-coded version
which seems to cause different kind of troubles. After changing it too
things worked smoother for me.
Additional findings: existing workaround is incomplete when token becomes stale
I hit this same issue (macOS, Claude Code v2.1.41, Chrome extension v1.0.49) and found that the commonly suggested workaround (disable Desktop's native messaging manifest + restart Chrome) is not sufficient when the extension's OAuth token has already gone stale.
Root cause chain
com.anthropic.claude_browser_extension) intercepts the Chrome extension connection before Claude Code's host (com.anthropic.claude_code_browser_extension)accessTokenremains in local storage with a validtokenExpiry, but is actually revoked server-side"Invalid token or user mismatch"— even though it's the same account/login) resolves the token mismatchDebugging evidence
chrome.storage.localshowedmcpConnected: false, validbridgeDeviceId,accessTokenwith unexpiredtokenExpirywss://bridge.claudeusercontent.comsucceeded (connection opened){type: "connect", client_type: "chrome-extension", device_id: ..., oauth_token: ...}returned{"type":"error","error":"Invalid token or user mismatch"}followed by close code 1008sk-ant-oat01-mQoW...vssk-ant-oat01-NQ5W...) despite being the same accountSuggested workaround update
The workaround should include an additional step:
com.anthropic.claude_browser_extension.jsonto.disabled)/login) to refresh the OAuth tokenclaude --chromeAdditional confirmation: macOS, Claude Code v2.1.42
Same
"Invalid token or user mismatch"bridge rejection.Environment:
fcoeoabgfenejglbffodgkkbkcdhcgfn(profile: Default)Root cause found: Claude Desktop native host hijacking
Claude Desktop's manifest (
com.anthropic.claude_browser_extension.json) claims the same extension ID, so Chrome spawns Desktop's host instead of Claude Code's:After disabling Desktop's manifest + Chrome restart + CLI re-login (
/login):Bridge still rejects every attempt:
Retries indefinitely with backoff (10+ attempts observed). The token mismatch persists even after fresh
/loginon the CLI side, confirming this is a server-side issue in the bridge's token validation — not a local configuration problem.Follow-up: The
/logincommand opens Safari (macOS default browser) instead of Chrome for OAuth authentication. This likely contributes to the token mismatch — the CLI gets a token issued through a Safari session, while the bridge expects it to match the Chrome session on claude.ai.This could be a separate issue:
/loginshould either open the auth flow in Chrome specifically (since that's where the extension lives), or the bridge should accept tokens regardless of which browser issued them.RESOLVED — working fix:
/loginopens OAuth in Chrome, not Safari/other)/loginto re-authenticateclaude --chromeThe root cause:
/loginopens the OS default browser for OAuth. If that's not Chrome, the token is issued through a different browser session than where the extension lives, causing the bridge to reject with "Invalid token or user mismatch."Summary of full fix if Claude Desktop is also installed:
com.anthropic.claude_browser_extension.jsonto.disabledin Chrome'sNativeMessagingHostsdirectory)/loginto re-authenticate through Chromeclaude --chromeEnvironment
--chromeflagIssue
Browser extension failed to connect after initial working session. All MCP browser tool calls returned:
/tmp/claude-mcp-browser-bridge-root/Root Cause
The MCP server process (
--claude-in-chrome-mcp) retained stale OAuth tokens after running/loginto re-authenticate.**The MCP server started at session initialization and continued running with old credentials even after the CLI re-authenticated. The native host process (
--chrome-native-host) restarted with Chrome, but the MCP server did not.Solution
Restart the MCP server process after re-authentication:
Root cause found: cloud bridge vs local socket transport
After extensive debugging (binary analysis of Claude Code, process tracing, socket inspection), I found the actual root cause of why the bridge rejects with
"Invalid token or user mismatch":The MCP server (
--claude-in-chrome-mcp) has two transport modes:/tmp/claude-mcp-browser-bridge-<user>/<pid>.sockwss://bridge.claudeusercontent.com(requires valid OAuth token matching on both sides)A GrowthBook feature flag called
tengu_copper_bridgecontrols which transport is used. When set totrue(the default for many users), it uses the cloud bridge — which is where all the token mismatch errors come from.The fix
Edit
~/.claude.json(NOT~/.claude/settings.json) and set the flag tofalse:If
cachedGrowthBookFeaturesalready exists with other keys, just add/changetengu_copper_bridgetofalse.Then restart your session:
Why this works
Setting
tengu_copper_bridge: falseforces the MCP server to use the local Unix socket instead of the cloud WebSocket bridge. This completely bypasses the OAuth token validation that causes the"Invalid token or user mismatch"error. The local socket connects directly to the native host process — no cloud authentication needed.Technical details
W9("tengu_copper_bridge", false)reads fromQR().cachedGrowthBookFeaturesin~/.claude.jsontrue— if the error returns, just set it back tofalseEnvironment where this was confirmed
After applying this fix, all
mcp__claude-in-chrome__*tools work immediately without any OAuth dance, browser restarts, or/loginre-authentication.It looks like this file ~/.claude.json is being overwritten all the time by claude code, when i set tengu_copper_bridge to false, it is set back to true when i start
claude --chrome@AshDevFr Yeah, that's expected — Claude Code re-fetches GrowthBook feature flags from Anthropic's servers on every startup and overwrites
cachedGrowthBookFeaturesin~/.claude.json.Permanent fix: Add a
SessionStarthook that patches it back automatically before the MCP connection attempt. In~/.claude/settings.json:This runs on every session start (new, resume, clear, compact), so the flag is always
falseby the time Chrome tries to connect. No more manual edits.Confirmed: competing native host registrations cause silent failures
Confirmed: competing native host registrations cause silent failures
On systems with both Claude Desktop (Cowork) and Claude Code installed, two native messaging hosts are registered:
com.anthropic.claude_browser_extension(Claude Desktop)com.anthropic.claude_code_browser_extension(Claude Code)The Chrome extension (
fcoeoabgfenejglbffodgkkbkcdhcgfn) looks forcom.anthropic.claude_browser_extension-- not the_code_variant. If Claude Desktop's manifest points to an invalid path (e.g., after uninstall or update), the extension can't start the native host.Fix: Ensure
HKCU\SOFTWARE\Google\Chrome\NativeMessagingHosts\com.anthropic.claude_browser_extensionpoints to Claude Code's manifest at%USERPROFILE%\.claude\chrome\com.anthropic.claude_browser_extension.json.However, this alone won't fix it if
tengu_copper_bridgeistrue-- see #24935 for the complete solution.@Nachx639 thank you very much, it helps me save lot of times
Thanks @olegiv,
I had multiple Browser Profiles in Chrome. I was only able to connect Claude Code in one Profile, the other Profiles did not work and were unable to communicate with claude-code. Your solution via re-login and authenticate, then restart worked perfectly for me.
Specs:
MacOS 26.2
Chrome 145.0.7632.77
Claude Code 2.1.47
Claude Extension 1.0.53
Warp Terminal 145.0.7632.77
I'm having similar problems.
Setup:
Chrome - version 143.0.7499.192 (Official Build) (64-bit)
OS: Manjaro Sway 6.18.7-1-MANJARO
Claude Code v2.1.62, extension v1.0.56
Claude CLI reports the MCP is connected. Hitting reconnect shows all green and that reconnection has been successful, however interactions with the extension fail repeatedly. Restart Claude or Chrome doesn't help, however, the only workaround I've found so far is to tell the Claude extension to log in again. Furthermore, it appears to lose the login consistently (from one day to another, and sometimes intra-day).
Simplest fix is to have claude update any documentation in case of issues with resume (ok 9 times out of 10) then /exit and immediately log back in with the resume code, for example: claude --dangerously-skip-permissions --chrome --resume 957719b4-194a-4f57-90a1-8d269e3xxxx then /chrome then reconnect. The chrome extension should then work. If you have never used resume, it essentially allows you to continue your session without memory loss - very handy for this case!
I have connected. But when I prompt
open https://google.com, it saysbrower not connected<img width="1579" height="240" alt="Image" src="https://github.com/user-attachments/assets/b95e7431-0642-48c5-a84f-79c89db269ee" />
Cross-posting a working fix from #24935: the
sed/ JSON-editing workarounds fail because the chrome MCP runs in-process (not as a child subprocess), so editing~/.claude.jsonhas no effect on the running GrowthBook in-memory state.The reliable workaround is
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1, which prevents GrowthBook from initializing and keepstengu_copper_bridgeat its JSON-cached value (false):Users with both Claude Desktop and Claude Code also need to disable Desktop's native messaging manifest — see full details in #24935.
Same issue here. macOS Sequoia, Claude Code desktop app, Chrome extension v1.0.63. Worked reliably for weeks, broke around 20 March. Extension shows connected in Chrome but tabs_context_mcp always returns not connected. Tried everything — restart Chrome, reconnect extension, switch orgs, create missing native messaging host file. Nothing works. Filed #38845 with full details.
Root cause on the macOS Desktop app: bridge WebSocket TLS chain verification fails in the bundled Electron/Node runtime
Adding a precise, reproducible root-cause from the macOS Desktop app (distinct from the CLI /
tengu_copper_bridgepath discussed earlier in this thread).Environment
Symptom (
~/Library/Logs/Claude/main.log):Retries every 30s indefinitely;
list_connected_browsersand theClaude in Chrometools return "not connected". The local native-messaging host (chrome-native-host) is healthy — theControl ChromeMCP (native-host path) works fine; only the cloud bridge WebSocket is affected.Root cause
bridge.claudeusercontent.comserves a valid public chain:The macOS system trust store verifies this fine (
openssl s_client … -> verify return:1), but the app's bundled Node/BoringSSL runtime cannot build the chain to the cross-signed anchor and fails withUNABLE_TO_GET_ISSUER_CERT. Reproduced with standalone Node v22.22.0 (bothhttpsandundici/fetchfail).Why env-var workarounds do not fix the Desktop app
NODE_EXTRA_CA_CERTS=<macOS system roots PEM>makes standalone Node succeed (server returns HTTP 426 upgrade).launchctl setenvdoes not help: the Electron main process inherits it, yet every Electron helper/utility process has it absent (ps ewwshows noNODE_EXTRA_CA_CERTSon anyClaude Helper). The bridge TLS runs in a helper whose environment Electron sanitizes, so the extra CA never reaches it.--use-system-caalone does not fix it on Node 22.x.Suggested fix
Perform the bridge WebSocket TLS via the OS trust store (Chromium
netverifier), or bundle/propagate the GTS Root R4 / GlobalSign Root CA cross-sign anchor into the helper process that performs the TLS. This was likely triggered by the recent rotation ofbridge.claudeusercontent.comto a Google Trust Services certificate (leafnotBefore2026-05-17).Workaround for affected users: use the
Control ChromeMCP tools (native messaging host path) — unaffected by this bug.