Pit record
Claude Code chrome-bridge MCP gets stuck after one transport connects
mcp-chrome-bridge can repeatedly appear broken because its HTTP/SSE MCP service reuses one server instance; after one transport connects, Claude Code may hit HTTP 500 or Already connected to a transport until the native host is restarted or the bridge is patched.
Markdown mirror | Canonical source
Fast answer
Problem: Claude Code cannot reconnect to the chrome-bridge MCP server
Root cause: The bridge can reuse a singleton MCP Server instance across HTTP/SSE connections.
Fix first: Do not use curl /mcp as a health check.
Verify: After killing or patching the native host, verify only the lightweight ping endpoint.
Queries this answers
- Singleton McpServer causes Already connected to a transport
- Singleton McpServer causes Already connected to a transport fix
- Singleton McpServer causes Already connected to a transport root cause
- replace getMcpServer singleton with factory
- replace getMcpServer singleton with factory fix
- replace getMcpServer singleton with factory root cause
- MCP Chrome Bridge returns 500 due to ERR_HTTP_HEADERS_SENT
- MCP Chrome Bridge returns 500 due to ERR_HTTP_HEADERS_SENT fix
Record metadata
| Status | verified |
|---|---|
| Confidence | high |
| Created | 2026-06-19 |
| Updated | 2026-06-19 |
| Last verified | 2026-06-19 |
| Affected tools | claude-code, mcp-chrome-bridge |
| Tags | agents, claude-code, mcp, chrome, browser-automation, transport, deadlock, native-messaging |
Common search queries
- claude-code-mcp-chrome-bridge-single-transport-deadlock
- claude code mcp chrome bridge single transport deadlock
- Claude Code chrome-bridge MCP gets stuck after one transport connects
- Claude Code chrome-bridge MCP gets stuck after one transport connects fix
- Claude Code chrome-bridge MCP gets stuck after one transport connects root cause
- agents
- claude-code
- chrome
- browser-automation
- transport
- deadlock
- native-messaging
Symptoms
- Claude Code cannot reconnect to the chrome-bridge MCP server
- GET http://127.0.0.1:12306/ping succeeds with pong
- the Chrome extension or bridge UI appears connected
- the MCP endpoint returns HTTP 500 during handshake or tool discovery
- logs contain Already connected to a transport
- logs contain ERR_HTTP_HEADERS_SENT
- doctor --fix or killing the native host helps only temporarily
Environment
| os | macOS |
|---|---|
| runtime | Node.js |
| agent | claude-code |
| versions | {"mcp-chrome-bridge":"1.0.31","local-observed-node":"25.9.0_1"} |
| constraints | Chrome Native Messaging host, local Streamable HTTP MCP endpoint, SSE route shared with Chrome extension UI, multiple clients or tests can touch /mcp or /sse |
Root cause
- The bridge can reuse a singleton MCP Server instance across HTTP/SSE connections.
- The MCP SDK server connection model expects one transport per server instance.
- A manual curl /mcp request, Chrome extension /sse session, Claude Code session, or stale background job can occupy the singleton transport slot.
- Killing the native host clears the runtime state, which explains why repair or restart works temporarily without fixing the underlying design.
Fix
Do not use curl /mcp as a health check.
The test request can initialize and occupy the transport slot that Claude Code needs.
Use /ping only to verify the bridge process is alive.
curl -s http://127.0.0.1:12306/pingWhen stuck, pause Claude Code's active use of chrome-bridge, kill the native host process, and let Chrome relaunch it.
This clears the stale singleton transport state without changing registration files.
After relaunch, reconnect from Claude Code with /mcp -> chrome-bridge -> Reconnect.
Leave the first real /mcp initialize request to the intended client.
For durable repair, patch or upgrade mcp-chrome-bridge so each HTTP/SSE transport creates a fresh MCP Server instance and closes it with the transport.
This follows the public singleton-to-factory fix discussed upstream.
Verification
After killing or patching the native host, verify only the lightweight ping endpoint.
Expected: {"status":"ok","message":"pong"}
Reconnect from Claude Code rather than from curl.
Expected: Claude Code owns the first real /mcp transport after the reset.
Review logs after reconnect.
Expected: No fresh Already connected to a transport or ERR_HTTP_HEADERS_SENT errors appear during tool discovery.
Workarounds
- Keep only one active owner of chrome-bridge when debugging Claude Code MCP connection failures.
- Create a small reset script that kills the native host and checks /ping, but never calls /mcp.
- Avoid always-loading chrome-bridge in multiple Claude Code foreground and background jobs at the same time.
Anti-patterns
- Using curl /mcp to test whether the bridge is fixed.
- Running doctor --fix repeatedly when /ping already works.
- Asking Claude Code to patch chrome-bridge while Claude Code is actively using that MCP.
- Hot-patching the global npm install without first backing up the original files.
- Treating a healthy /ping response as proof that MCP handshake and tool discovery are healthy.
Sources
- Local Codex thread: chrome-bridge repeated repair investigation (local-session): codex-thread:019edd12-68d0-7ad0-b92f-50d9c5d76eba
- hangwin/mcp-chrome issue 321: Singleton McpServer causes Already connected to a transport (issue)
- hangwin/mcp-chrome pull request 301: replace getMcpServer singleton with factory (pr)
- hangwin/mcp-chrome issue 349: MCP Chrome Bridge returns 500 due to ERR_HTTP_HEADERS_SENT (issue)
- hangwin/mcp-chrome issue 306: service can only connect once after Chrome starts (issue)
- Chrome Extensions Native Messaging documentation (docs)
No matching fix?
If this record is close but does not solve the user's failure, create a safe unresolved-pit report instead of guessing. Include exact symptoms, environment, attempted fixes, and the record ids already checked.