-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Open
Labels
bugSomething isn't workingSomething isn't working
Description
Describe the bug
When using StreamableHTTPServerTransport with multiple concurrent sessions, calling Server.connect(transport) for a second transport silently breaks the first transport's ability to receive responses. This is because connect() overwrites this._transport without any warning or error.
Related: #1400 describes a similar issue with reconnection ("Server already initialized"). Both stem from the same root cause: Server only supports one transport at a time. This issue documents a different failure mode—silent corruption of existing connections rather than an explicit error.
To Reproduce
- Create a single
Serverinstance - Create
StreamableHTTPServerTransportfor Session A and callserver.connect(transportA) - Session A makes requests successfully
- Create
StreamableHTTPServerTransportfor Session B and callserver.connect(transportB) - Session A now fails with
AbortError: This operation was aborted
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
const server = new Server({ name: 'test', version: '1.0.0' }, { capabilities: { tools: {} } });
// Session A connects
const transportA = new StreamableHTTPServerTransport({ sessionIdGenerator: () => 'session-a' });
await server.connect(transportA); // Works
// Session B connects
const transportB = new StreamableHTTPServerTransport({ sessionIdGenerator: () => 'session-b' });
await server.connect(transportB); // Also "works" - but silently breaks transportA
// Now any request through transportA will failExpected behavior
Either:
Server.connect()should throw an error if already connected to a transport, ORServershould support multiple concurrent transports for HTTP scenarios, OR- Documentation should clearly state that each HTTP session requires its own
Serverinstance
Logs
[MCP] POST tools/call for session A...
[MCP] SSE socket.end for session A...
[MCP] SSE req.aborted for session A...
AbortError: This operation was aborted
Additional context
- SDK Version: 1.25.2
- The root cause is in
Protocol.connect()which simply overwritesthis._transportwithout checking for an existing connection - Workaround: Create a new
Serverinstance for each session, as shown in the SDK'ssseAndStreamableHttpCompatibleServer.jsexample - This is a significant footgun because: no error is thrown at
connect()time, the first session works until the second connects, and error messages don't indicate the root cause
Suggested fix (fail fast):
async connect(transport) {
if (this._transport) {
throw new Error('Server is already connected to a transport. Create a new Server instance for each connection, or call close() first.');
}
this._transport = transport;
// ...
}Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working