Skip to content

Commit ee29c34

Browse files
committed
Fixed test failures induced by MCP SDK update (added session id generator to Streamable test server). Cleanup up some port usage to avoid potential issues (always use port 0 for servers). Added stdout/stderr to cli status assertion failures to make CLI test failures easier to debug from test output.
1 parent f977257 commit ee29c34

3 files changed

Lines changed: 41 additions & 20 deletions

File tree

cli/__tests__/helpers/assertions.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,30 @@
11
import { expect } from "vitest";
22
import type { CliResult } from "./cli-runner.js";
33

4+
function formatCliOutput(result: CliResult): string {
5+
const out = result.stdout?.trim() || "(empty)";
6+
const err = result.stderr?.trim() || "(empty)";
7+
return `stdout: ${out}\nstderr: ${err}`;
8+
}
9+
410
/**
511
* Assert that CLI command succeeded (exit code 0)
612
*/
713
export function expectCliSuccess(result: CliResult) {
8-
expect(result.exitCode).toBe(0);
14+
expect(
15+
result.exitCode,
16+
`CLI exited with code ${result.exitCode}. ${formatCliOutput(result)}`,
17+
).toBe(0);
918
}
1019

1120
/**
1221
* Assert that CLI command failed (non-zero exit code)
1322
*/
1423
export function expectCliFailure(result: CliResult) {
15-
expect(result.exitCode).not.toBe(0);
24+
expect(
25+
result.exitCode,
26+
`CLI unexpectedly exited with code ${result.exitCode}. ${formatCliOutput(result)}`,
27+
).not.toBe(0);
1628
}
1729

1830
/**

cli/__tests__/helpers/fixtures.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import fs from "fs";
2-
import path from "path";
3-
import os from "os";
4-
import crypto from "crypto";
1+
import * as fs from "fs";
2+
import * as path from "path";
3+
import * as os from "os";
4+
import * as crypto from "crypto";
55
import { getTestMcpServerCommand } from "./test-server-stdio.js";
66

77
/**

cli/__tests__/helpers/test-server-http.ts

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type { Request, Response } from "express";
66
import express from "express";
77
import { createServer as createHttpServer, Server as HttpServer } from "http";
88
import { createServer as createNetServer } from "net";
9+
import { randomUUID } from "crypto";
910
import * as z from "zod/v4";
1011
import type { ServerConfig } from "./test-fixtures.js";
1112

@@ -187,22 +188,24 @@ export class TestServerHttp {
187188
}
188189

189190
/**
190-
* Start the server with the specified transport
191+
* Start the server with the specified transport.
192+
* When requestedPort is omitted, uses port 0 so the OS assigns a unique port (avoids EADDRINUSE when tests run in parallel).
191193
*/
192194
async start(
193195
transport: "http" | "sse",
194196
requestedPort?: number,
195197
): Promise<number> {
196-
const port = requestedPort
197-
? await findAvailablePort(requestedPort)
198-
: await findAvailablePort(transport === "http" ? 3001 : 3000);
199-
200-
this.url = `http://localhost:${port}`;
198+
const port =
199+
requestedPort !== undefined ? await findAvailablePort(requestedPort) : 0;
201200

202201
if (transport === "http") {
203-
return this.startHttp(port);
202+
const actualPort = await this.startHttp(port);
203+
this.url = `http://localhost:${actualPort}`;
204+
return actualPort;
204205
} else {
205-
return this.startSse(port);
206+
const actualPort = await this.startSse(port);
207+
this.url = `http://localhost:${actualPort}`;
208+
return actualPort;
206209
}
207210
}
208211

@@ -213,8 +216,10 @@ export class TestServerHttp {
213216
// Create HTTP server
214217
this.httpServer = createHttpServer(app);
215218

216-
// Create StreamableHTTP transport
217-
this.transport = new StreamableHTTPServerTransport({});
219+
// Create StreamableHTTP transport (stateful so it can handle multiple requests per session)
220+
this.transport = new StreamableHTTPServerTransport({
221+
sessionIdGenerator: () => randomUUID(),
222+
});
218223

219224
// Set up Express route to handle MCP requests
220225
app.post("/mcp", async (req: Request, res: Response) => {
@@ -292,10 +297,12 @@ export class TestServerHttp {
292297
// Connect transport to server
293298
await this.mcpServer.connect(this.transport);
294299

295-
// Start listening
300+
// Start listening (port 0 = OS assigns a unique port)
296301
return new Promise((resolve, reject) => {
297302
this.httpServer!.listen(port, () => {
298-
resolve(port);
303+
const assignedPort = (this.httpServer!.address() as { port: number })
304+
?.port;
305+
resolve(assignedPort ?? port);
299306
});
300307
this.httpServer!.on("error", reject);
301308
});
@@ -371,10 +378,12 @@ export class TestServerHttp {
371378
// Note: SSE transport is created per request, so we don't store a single instance
372379
this.transport = undefined;
373380

374-
// Start listening
381+
// Start listening (port 0 = OS assigns a unique port)
375382
return new Promise((resolve, reject) => {
376383
this.httpServer!.listen(port, () => {
377-
resolve(port);
384+
const assignedPort = (this.httpServer!.address() as { port: number })
385+
?.port;
386+
resolve(assignedPort ?? port);
378387
});
379388
this.httpServer!.on("error", reject);
380389
});

0 commit comments

Comments
 (0)