Description
When connecting to the HTTP MCP endpoint at http://127.0.0.1:12306/mcp, the first session initializes successfully, but all subsequent sessions fail with:
{"statusCode":500,"error":"Internal Server Error","message":"Already connected to a transport. Call close() before connecting to a new transport, or use a separate Protocol instance per connection."}
This affects both the StreamableHTTP (POST /mcp) and SSE (GET /sse) transports. The stdio transport (mcp-server-stdio.js) is unaffected because Claude Desktop spawns a fresh process per connection.
Environment
[email protected] (latest as of March 2026)
- macOS, Node.js v25.8.2
- Clients tested: Claude Desktop (Cowork/Opus sessions),
curl
Root Cause
In dist/mcp/mcp-server.js, getMcpServer() uses a singleton pattern — it creates one Server instance and returns it for every connection:
exports.mcpServer = null;
const getMcpServer = () => {
if (exports.mcpServer) {
return exports.mcpServer; // ← returns the already-connected instance
}
exports.mcpServer = new index_js_1.Server({ ... });
setupTools(exports.mcpServer);
return exports.mcpServer;
};
The MCP SDK's Server.connect(transport) throws if the instance is already connected to a transport. Since the HTTP server runs in a single process, the singleton gets connected on the first request and then rejects all subsequent connections.
Fix
Replace the singleton cache with a factory that creates a new Server instance per connection:
const getMcpServer = () => {
const server = new index_js_1.Server({
name: 'ChromeMcpServer',
version: '1.0.0',
}, {
capabilities: { tools: {} },
});
(0, register_tools_1.setupTools)(server);
exports.mcpServer = server; // backward compat for stdio path
return server;
};
This is safe because:
- Each HTTP transport needs its own
Server instance (per MCP SDK design)
setupTools() is stateless — it just registers tool handlers
- The stdio path (
mcp-server-stdio.js) still works because it runs in its own process
Related Issues
This is likely the root cause behind #182 and #173, where users report Claude CLI / Claude Code failing to connect to the running HTTP server.
Steps to Reproduce
- Start the bridge server (via Chrome extension)
curl -s -X POST http://127.0.0.1:12306/mcp -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" -d '{"jsonrpc":"2.0","method":"initialize","id":1,"params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test1","version":"1.0"}}}' → ✅ succeeds
- Run the same curl again → ❌
"Already connected to a transport"
After applying the fix above, all three consecutive connections succeed with unique session IDs.
Description
When connecting to the HTTP MCP endpoint at
http://127.0.0.1:12306/mcp, the first session initializes successfully, but all subsequent sessions fail with:This affects both the StreamableHTTP (
POST /mcp) and SSE (GET /sse) transports. The stdio transport (mcp-server-stdio.js) is unaffected because Claude Desktop spawns a fresh process per connection.Environment
[email protected](latest as of March 2026)curlRoot Cause
In
dist/mcp/mcp-server.js,getMcpServer()uses a singleton pattern — it creates oneServerinstance and returns it for every connection:The MCP SDK's
Server.connect(transport)throws if the instance is already connected to a transport. Since the HTTP server runs in a single process, the singleton gets connected on the first request and then rejects all subsequent connections.Fix
Replace the singleton cache with a factory that creates a new
Serverinstance per connection:This is safe because:
Serverinstance (per MCP SDK design)setupTools()is stateless — it just registers tool handlersmcp-server-stdio.js) still works because it runs in its own processRelated Issues
This is likely the root cause behind #182 and #173, where users report Claude CLI / Claude Code failing to connect to the running HTTP server.
Steps to Reproduce
curl -s -X POST http://127.0.0.1:12306/mcp -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" -d '{"jsonrpc":"2.0","method":"initialize","id":1,"params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test1","version":"1.0"}}}'→ ✅ succeeds"Already connected to a transport"After applying the fix above, all three consecutive connections succeed with unique session IDs.