diff --git a/.changeset/report-bound-http-port.md b/.changeset/report-bound-http-port.md new file mode 100644 index 000000000..75b45f8a5 --- /dev/null +++ b/.changeset/report-bound-http-port.md @@ -0,0 +1,5 @@ +--- +"@upstash/context7-mcp": patch +--- + +Report the actual assigned HTTP port when `--port 0` requests an ephemeral port. diff --git a/packages/mcp/src/index.ts b/packages/mcp/src/index.ts index 6656dcbce..1d5e4009a 100644 --- a/packages/mcp/src/index.ts +++ b/packages/mcp/src/index.ts @@ -652,8 +652,13 @@ async function main() { }); httpServer.once("listening", () => { + const address = httpServer.address(); + if (!address || typeof address === "string") { + console.error("Failed to determine the bound HTTP port"); + process.exit(1); + } console.error( - `Context7 Documentation MCP Server v${SERVER_VERSION} running on HTTP at http://localhost:${port}/mcp` + `Context7 Documentation MCP Server v${SERVER_VERSION} running on HTTP at http://localhost:${address.port}/mcp` ); }); }; diff --git a/packages/mcp/test/integration.test.ts b/packages/mcp/test/integration.test.ts index cff8bf91c..0b787bf0a 100644 --- a/packages/mcp/test/integration.test.ts +++ b/packages/mcp/test/integration.test.ts @@ -188,6 +188,19 @@ afterAll(() => { stubServer?.close(); }); +test("reports the bound port when port zero requests an ephemeral port", async () => { + const { child, url } = await startHttpChild({ port: 0 }); + try { + expect(new URL(url).port).not.toBe("0"); + + const response = await fetch(new URL("/ping", url)); + expect(response.ok).toBe(true); + await expect(response.json()).resolves.toMatchObject({ status: "ok" }); + } finally { + child.kill(); + } +}); + async function connect(transportKind: "http" | "stdio", era: "modern" | "legacy") { const client = new Client( { name: "test-harness", version: "1.0.0" },