Skip to content

bug(server): connect() silently overwrites transport, breaking concurrent HTTP sessions #1405

@josh-fisher

Description

@josh-fisher

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

  1. Create a single Server instance
  2. Create StreamableHTTPServerTransport for Session A and call server.connect(transportA)
  3. Session A makes requests successfully
  4. Create StreamableHTTPServerTransport for Session B and call server.connect(transportB)
  5. 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 fail

Expected behavior
Either:

  1. Server.connect() should throw an error if already connected to a transport, OR
  2. Server should support multiple concurrent transports for HTTP scenarios, OR
  3. Documentation should clearly state that each HTTP session requires its own Server instance

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 overwrites this._transport without checking for an existing connection
  • Workaround: Create a new Server instance for each session, as shown in the SDK's sseAndStreamableHttpCompatibleServer.js example
  • 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

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions