Skip to content

Commit a4aa220

Browse files
authored
Merge branch 'main' into fix/enum-anyof-ref-resolution
2 parents 442638f + 0c0e15d commit a4aa220

26 files changed

Lines changed: 2237 additions & 226 deletions

.github/dependabot.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "github-actions"
4+
directory: "/"
5+
schedule:
6+
interval: "weekly"

.github/workflows/claude.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
github.event_name == 'pull_request_review_comment' ||
3434
github.event_name == 'pull_request_review'
3535
id: pr
36-
uses: actions/github-script@v7
36+
uses: actions/github-script@v8
3737
with:
3838
script: |
3939
let prNumber;

.github/workflows/cli_tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
- uses: actions/checkout@v4
1919

2020
- name: Set up Node.js
21-
uses: actions/setup-node@v4
21+
uses: actions/setup-node@v6
2222
with:
2323
node-version-file: package.json
2424
cache: npm

.github/workflows/e2e_tests.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
2121
- uses: actions/checkout@v4
2222

23-
- uses: actions/setup-node@v4
23+
- uses: actions/setup-node@v6
2424
id: setup_node
2525
with:
2626
node-version-file: package.json
@@ -29,7 +29,7 @@ jobs:
2929
# Cache Playwright browsers
3030
- name: Cache Playwright browsers
3131
id: cache-playwright
32-
uses: actions/cache@v4
32+
uses: actions/cache@v5
3333
with:
3434
path: ~/.cache/ms-playwright # The default Playwright cache path
3535
key: ${{ runner.os }}-playwright-${{ hashFiles('package-lock.json') }} # Cache key based on OS and package-lock.json
@@ -51,7 +51,7 @@ jobs:
5151
run: npm run test:e2e
5252

5353
- name: Upload Playwright Report and Screenshots
54-
uses: actions/upload-artifact@v4
54+
uses: actions/upload-artifact@v6
5555
if: steps.playwright-tests.conclusion != 'skipped'
5656
with:
5757
name: playwright-report

.github/workflows/main.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
- name: Check formatting
1818
run: npx prettier --check .
1919

20-
- uses: actions/setup-node@v4
20+
- uses: actions/setup-node@v6
2121
with:
2222
node-version-file: package.json
2323
cache: npm
@@ -51,7 +51,7 @@ jobs:
5151

5252
steps:
5353
- uses: actions/checkout@v4
54-
- uses: actions/setup-node@v4
54+
- uses: actions/setup-node@v6
5555
with:
5656
node-version-file: package.json
5757
cache: npm
@@ -109,7 +109,7 @@ jobs:
109109
labels: ${{ steps.meta.outputs.labels }}
110110

111111
- name: Generate artifact attestation
112-
uses: actions/attest-build-provenance@v2
112+
uses: actions/attest-build-provenance@v3
113113
with:
114114
subject-name: ghcr.io/${{ github.repository }}
115115
subject-digest: ${{ steps.push.outputs.digest }}

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
});

cli/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@modelcontextprotocol/inspector-cli",
3-
"version": "0.19.0",
3+
"version": "0.20.0",
44
"description": "CLI for the Model Context Protocol inspector",
55
"license": "SEE LICENSE IN LICENSE",
66
"author": "Model Context Protocol a Series of LF Projects, LLC.",
@@ -25,7 +25,7 @@
2525
"test:cli-metadata": "vitest run metadata.test.ts"
2626
},
2727
"devDependencies": {
28-
"@types/express": "^5.0.6",
28+
"@types/express": "^5.0.0",
2929
"tsx": "^4.7.0",
3030
"vitest": "^4.0.17"
3131
},

client/jest.config.cjs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,15 @@ module.exports = {
1313
tsconfig: "tsconfig.jest.json",
1414
},
1515
],
16+
"^.+\\.m?js$": [
17+
"ts-jest",
18+
{
19+
tsconfig: "tsconfig.jest.json",
20+
},
21+
],
1622
},
1723
extensionsToTreatAsEsm: [".ts", ".tsx"],
24+
transformIgnorePatterns: ["node_modules/(?!(@modelcontextprotocol)/)"],
1825
testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
1926
// Exclude directories and files that don't need to be tested
2027
testPathIgnorePatterns: [

0 commit comments

Comments
 (0)