Merge pull request #1067 from BobDickinson/cli-test-update

Fixed test failures induced by MCP SDK update
This commit is contained in:
Cliff Hall 2026-02-05 19:44:21 -05:00 • committed by GitHub
commit 98f058765d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 41 additions and 20 deletions

View file

@ -1,18 +1,30 @@
import { expect } from "vitest";
import type { CliResult } from "./cli-runner.js";
function formatCliOutput(result: CliResult): string {
const out = result.stdout?.trim() || "(empty)";
const err = result.stderr?.trim() || "(empty)";
return `stdout: ${out}\nstderr: ${err}`;
}
/**
* Assert that CLI command succeeded (exit code 0)
*/
export function expectCliSuccess(result: CliResult) {
expect(result.exitCode).toBe(0);
expect(
result.exitCode,
`CLI exited with code ${result.exitCode}. ${formatCliOutput(result)}`,
).toBe(0);
}
/**
* Assert that CLI command failed (non-zero exit code)
*/
export function expectCliFailure(result: CliResult) {
expect(result.exitCode).not.toBe(0);
expect(
result.exitCode,
`CLI unexpectedly exited with code ${result.exitCode}. ${formatCliOutput(result)}`,
).not.toBe(0);
}
/**

View file

@ -1,7 +1,7 @@
import fs from "fs";
import path from "path";
import os from "os";
import crypto from "crypto";
import * as fs from "fs";
import * as path from "path";
import * as os from "os";
import * as crypto from "crypto";
import { getTestMcpServerCommand } from "./test-server-stdio.js";
/**

View file

@ -6,6 +6,7 @@ import type { Request, Response } from "express";
import express from "express";
import { createServer as createHttpServer, Server as HttpServer } from "http";
import { createServer as createNetServer } from "net";
import { randomUUID } from "crypto";
import * as z from "zod/v4";
import type { ServerConfig } from "./test-fixtures.js";
@ -187,22 +188,24 @@ export class TestServerHttp {
}
/**
* Start the server with the specified transport
* Start the server with the specified transport.
* When requestedPort is omitted, uses port 0 so the OS assigns a unique port (avoids EADDRINUSE when tests run in parallel).
*/
async start(
transport: "http" | "sse",
requestedPort?: number,
): Promise<number> {
const port = requestedPort
? await findAvailablePort(requestedPort)
: await findAvailablePort(transport === "http" ? 3001 : 3000);
this.url = `http://localhost:${port}`;
const port =
requestedPort !== undefined ? await findAvailablePort(requestedPort) : 0;
if (transport === "http") {
return this.startHttp(port);
const actualPort = await this.startHttp(port);
this.url = `http://localhost:${actualPort}`;
return actualPort;
} else {
return this.startSse(port);
const actualPort = await this.startSse(port);
this.url = `http://localhost:${actualPort}`;
return actualPort;
}
}
@ -213,8 +216,10 @@ export class TestServerHttp {
// Create HTTP server
this.httpServer = createHttpServer(app);
// Create StreamableHTTP transport
this.transport = new StreamableHTTPServerTransport({});
// Create StreamableHTTP transport (stateful so it can handle multiple requests per session)
this.transport = new StreamableHTTPServerTransport({
sessionIdGenerator: () => randomUUID(),
});
// Set up Express route to handle MCP requests
app.post("/mcp", async (req: Request, res: Response) => {
@ -292,10 +297,12 @@ export class TestServerHttp {
// Connect transport to server
await this.mcpServer.connect(this.transport);
// Start listening
// Start listening (port 0 = OS assigns a unique port)
return new Promise((resolve, reject) => {
this.httpServer!.listen(port, () => {
resolve(port);
const assignedPort = (this.httpServer!.address() as { port: number })
?.port;
resolve(assignedPort ?? port);
});
this.httpServer!.on("error", reject);
});
@ -371,10 +378,12 @@ export class TestServerHttp {
// Note: SSE transport is created per request, so we don't store a single instance
this.transport = undefined;
// Start listening
// Start listening (port 0 = OS assigns a unique port)
return new Promise((resolve, reject) => {
this.httpServer!.listen(port, () => {
resolve(port);
const assignedPort = (this.httpServer!.address() as { port: number })
?.port;
resolve(assignedPort ?? port);
});
this.httpServer!.on("error", reject);
});