fix: bump SDK to 1.26.0, add session management to tools_call scenario (#134)

* fix: bump SDK to 1.26.0, add session management to tools_call scenario

SDK 1.26.0 made Protocol.connect() throw if already connected to a
transport. The tools_call scenario was calling server.connect(transport)
on every request with the same Server instance, which now throws.

Fixed by adding proper session management: each initialize request
creates a new Server + Transport pair, and subsequent requests are
routed to the correct transport via the mcp-session-id header.

* fix: return 404 for invalid session IDs in tools_call POST handler

The else branch was returning 400 for both missing-session and
invalid/stale-session cases. The MCP spec requires 404 for invalid
session IDs and 400 only for non-initialization requests without
any session ID.

* refactor: keep tools_call stateless, create fresh server per request

Instead of adding session management, simply create a new Server
instance per request. This preserves the original stateless design
while fixing the SDK 1.26.0 Protocol.connect() restriction.
This commit is contained in:
Paul Carleton 2026-02-05 15:43:21 +00:00 • committed by GitHub
commit 22196ca809
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -9,7 +9,7 @@ import express, { Request, Response } from 'express';
import { ScenarioUrls } from '../../types';
import { createRequestLogger } from '../request-logger';
function createServer(checks: ConformanceCheck[]): express.Application {
function createMcpServer(checks: ConformanceCheck[]): Server {
const server = new Server(
{
name: 'add-numbers-server',
@ -84,6 +84,10 @@ function createServer(checks: ConformanceCheck[]): express.Application {
throw new Error(`Unknown tool: ${request.params.name}`);
});
return server;
}
function createServerApp(checks: ConformanceCheck[]): express.Application {
const app = express();
app.use(express.json());
@ -96,6 +100,8 @@ function createServer(checks: ConformanceCheck[]): express.Application {
);
app.post('/mcp', async (req: Request, res: Response) => {
// Stateless: create a fresh server and transport per request
const server = createMcpServer(checks);
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined
});
@ -116,7 +122,7 @@ export class ToolsCallScenario implements Scenario {
async start(): Promise<ScenarioUrls> {
this.checks = [];
this.app = createServer(this.checks);
this.app = createServerApp(this.checks);
this.httpServer = this.app.listen(0);
const port = this.httpServer.address().port;
return { serverUrl: `http://localhost:${port}/mcp` };