Claude-in-Chrome: MCP server ignores working native sockets, fails on WebSocket bridge auth
Environment
- OS: Ubuntu 24.04.4 LTS (Linux 6.8.0-101-generic, x86-64)
- Chrome: 145.0.7632.45
- Claude Code: 2.1.72
- Claude Chrome Extension: 1.0.59 (CWS, ID:
fcoeoabgfenejglbffodgkkbkcdhcgfn) - Auth: Claude AI OAuth (
user:inferencescope,subscriptionType: null)
Description
All claude-in-chrome MCP tools return "Browser extension is not connected" despite the Chrome extension, native messaging host, and local Unix sockets all working correctly.
The MCP server subprocess ignores the working native socket path and exclusively attempts a WebSocket bridge (bridge.claudeusercontent.com), which fails due to missing auth prerequisites (oauthAccount.accountUuid is unset). There is no fallback to native sockets.
Root Cause
The tengu_copper_bridge feature flag is enabled on my account, causing the Chrome MCP server to use the WebSocket bridge instead of native Unix sockets. The bridge authentication fails, and there is no fallback.
Native sockets work perfectly
Confirmed by connecting directly with Node.js:
const net = require('net');
const s = net.createConnection('/tmp/claude-mcp-browser-bridge-user/664422.sock');
s.on('connect', () => {
// send {method: "execute_tool", params: {tool: "tabs_context_mcp", args: {createIfEmpty: true}}}
});
// Result: valid tab context response with real Chrome tabs
MCP server never attempts local sockets
Confirmed via strace -e trace=connect on the MCP subprocess (--claude-in-chrome-mcp):
# Only TCP connections to the bridge server:
connect(13, {AF_INET, sin_port=443, sin_addr="160.79.104.10"}) # bridge.claudeusercontent.com
connect(16, {AF_INET, sin_port=443, sin_addr="34.149.66.137"}) # API/auth
# ZERO connections to /tmp/claude-mcp-browser-bridge-*/*.sock
Bridge auth state is incomplete
oauthAccount.accountUuid: not set (undefined)chromeExtension.pairedDeviceId: not set (undefined)- OAuth scopes:
["user:inference"]only subscriptionType: null
The pairing flow (pairing.html) requires a working bridge connection to be initiated, creating a chicken-and-egg problem — pairing can't happen because the bridge auth fails, and bridge auth fails because pairing hasn't happened.
Code path
In createChromeContext(), the bridge URL is set when tengu_copper_bridge is true:
function zs6() {
if (!ZA("tengu_copper_bridge", false)) return; // flag OFF → undefined → native sockets
return "wss://bridge.claudeusercontent.com"; // flag ON → bridge
}
let A = zs6();
return {
socketPath: Oj$(),
getSocketPaths: dnf, // ← These exist but are IGNORED when bridgeConfig is present
...A && { bridgeConfig: { url: A, getUserId: ..., getOAuthToken: ... } }
};
When bridgeConfig exists, the bridge client is used exclusively. Its ensureConnected() requires connected && authenticated && ws.readyState === OPEN. When auth fails, onToolCallDisconnected() fires with the misleading "Browser extension is not connected" message.
Steps to Reproduce
- Have Claude Code 2.1.72 authenticated via OAuth (
user:inferencescope) - Have Chrome extension 1.0.59 installed and working (native messaging host active, sockets responding)
- Have
tengu_copper_bridgefeature flag enabled (server-side) - Call any
claude-in-chromeMCP tool (e.g.,tabs_context_mcp) - Get error: "Browser extension is not connected"
Expected Behavior
- The MCP server should fall back to native sockets when the bridge connection fails
- Or at minimum, the error message should indicate the actual cause (bridge auth failure) rather than blaming the extension
Suggested Fixes
- Fall back to native sockets when bridge fails — the infrastructure works perfectly
- Check bridge prerequisites before enabling — don't use bridge path if
accountUuidis missing - Better error message — "Bridge authentication failed" instead of "Browser extension is not connected"
- Add env var override — e.g.
CLAUDE_CODE_USE_NATIVE_SOCKET=1to bypass the bridge
Verified Working Infrastructure
| Component | Status |
|-----------|--------|
| Chrome extension installed & enabled | ✅ |
| nativeMessaging permission granted | ✅ |
| Native messaging host config | ✅ |
| Native host processes (v2.1.72) | ✅ Running |
| Unix sockets connectable | ✅ |
| Socket responses (execute_tool) | ✅ Valid tab context |
| Socket directory permissions (0700) | ✅ |
| Socket file permissions (0600) | ✅ |
| Bridge WebSocket connection | ❌ Auth fails |
| Bridge accountUuid | ❌ Not set |
| Bridge device pairing | ❌ Never initiated |
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗