-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Open
Labels
P2Moderate issues affecting some users, edge cases, potentially valuable featureModerate issues affecting some users, edge cases, potentially valuable featurebugSomething isn't workingSomething isn't workingready for workEnough information for someone to start working onEnough information for someone to start working on
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
P2Moderate issues affecting some users, edge cases, potentially valuable featureModerate issues affecting some users, edge cases, potentially valuable featurebugSomething isn't workingSomething isn't workingready for workEnough information for someone to start working onEnough information for someone to start working on