From 70cd4f05acdbe946c8dd4eca61c517c042025ea1 Mon Sep 17 00:00:00 2001 From: cliffhall Date: Mon, 14 Sep 2026 00:59:23 -0400 Subject: [PATCH] test: discriminate --protocol-era wiring against a modern-only server (#2208) The legacy and auto e2e cases both connect to the legacy stdio fixture whether or not the flag reaches negotiation, since auto falls back. Run initialize against an HTTP test server that rejects the legacy handshake: the default must fail, and --protocol-era modern must connect and report the 2026-07-28 protocol version. Deleting the serverOptions assignment in cli.ts now fails this case (Copilot review, PR #2372). Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01SZ4rrvH6xaCfrst75gJh7x Signed-off-by: cliffhall --- .../__tests__/programmatic-ergonomics.test.ts | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/clients/cli/__tests__/programmatic-ergonomics.test.ts b/clients/cli/__tests__/programmatic-ergonomics.test.ts index 1cef354d..8459644e 100644 --- a/clients/cli/__tests__/programmatic-ergonomics.test.ts +++ b/clients/cli/__tests__/programmatic-ergonomics.test.ts @@ -1,8 +1,16 @@ import { describe, it, expect } from "vitest"; -import { getTestMcpServerCommand } from "@modelcontextprotocol/inspector-test-server"; +import { + createEchoTool, + createTestServerHttp, + createTestServerInfo, + getTestMcpServerCommand, +} from "@modelcontextprotocol/inspector-test-server"; import { runCli } from "./helpers/cli-runner.js"; import { DEFAULT_CONNECT_TIMEOUT_MS, withConnectTimeout } from "../src/cli.js"; -import type { InspectorServerSettings } from "@inspector/core/mcp/types.js"; +import { + MODERN_PROTOCOL_VERSION, + type InspectorServerSettings, +} from "@inspector/core/mcp/types.js"; import { expectCliFailure, expectCliSuccess, @@ -228,6 +236,38 @@ describe("CLI --stored-auth-only wiring", () => { }); describe("--protocol-era", () => { + // The discriminating case: `legacy` and `auto` both connect to a legacy + // fixture whether or not the flag is wired, since `auto` falls back. A + // modern-only server rejects the default legacy handshake, so only a flag + // that actually reaches negotiation turns the failure into a modern session. + it("negotiates the modern era against a modern-only server", async () => { + const server = createTestServerHttp({ + serverInfo: createTestServerInfo(), + tools: [createEchoTool()], + modern: { legacy: "reject" }, + }); + try { + await server.start(); + const adHoc = [server.url, "--transport", "http"]; + + const withoutFlag = await runCli([...adHoc, "--method", "initialize"]); + expectCliFailure(withoutFlag); + + const withFlag = await runCli([ + ...adHoc, + "--protocol-era", + "modern", + "--method", + "initialize", + ]); + expectCliSuccess(withFlag); + const json = JSON.parse(withFlag.stdout) as { protocolVersion: string }; + expect(json.protocolVersion).toBe(MODERN_PROTOCOL_VERSION); + } finally { + await server.stop(); + } + }); + it.each(["legacy", "auto"])( "accepts %s on an ad-hoc target and connects", async (era) => {