From 17774ca7e49ead67ad75ef3776fb9b4e2ace21a0 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Thu, 18 Jun 2026 16:12:40 +0000 Subject: [PATCH] test(conformance): arm everythingServer to publish list_changed via handler.notify; burn down server-stateless SHOULD WARNINGs Adds test_trigger_tool_change and test_trigger_prompt_change diagnostic tools that publish onto the createMcpHandler bus via modernHandler.notify.{tools,prompts}Changed(). The server-stateless scenario opens a subscriptions/listen stream then calls these triggers and asserts the corresponding list_changed notification arrives; the listen router stamps the subscription id and applies the per-stream filter, so the same triggers also feed the ack-first, tags-subscription-id and honors-notification-filter checks. sep-2575-server-sends-{tools,prompts}-list-changed-on-subscription move WARNING -> SUCCESS (server-stateless: 24+2W -> 26/0/0W on both draft and 2026 legs). Removes the placeholder server-stateless entry from both expected-failures baselines. --- .../expected-failures.2026-07-28.yaml | 4 -- test/conformance/expected-failures.yaml | 8 ---- test/conformance/src/everythingServer.ts | 37 +++++++++++++++++++ 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/test/conformance/expected-failures.2026-07-28.yaml b/test/conformance/expected-failures.2026-07-28.yaml index e23ffbe1b3..5c30ea0ade 100644 --- a/test/conformance/expected-failures.2026-07-28.yaml +++ b/test/conformance/expected-failures.2026-07-28.yaml @@ -67,10 +67,6 @@ client: server: # --- Carried-forward scenarios (also run by the 2025 legs) --- - # WARNING-only: see the matching entry in expected-failures.yaml — the - # sep-2575 list_changed-on-listen SHOULD checks; fixture armed in a - # follow-up change. - - server-stateless # Pre-existing fixture/baseline bug: the fixture tool's schema is a plain # Zod object with none of the JSON Schema 2020-12 keywords the scenario # checks; it fails identically at 2025 in `--suite all` (not a 2026-path diff --git a/test/conformance/expected-failures.yaml b/test/conformance/expected-failures.yaml index 3b76bd94bf..c5ab22325a 100644 --- a/test/conformance/expected-failures.yaml +++ b/test/conformance/expected-failures.yaml @@ -49,14 +49,6 @@ client: server: # --- Draft-spec scenarios (in `--suite draft`; the default `active` suite is green) --- - # WARNING-only: with the listChanged capability now advertised in - # server/discover, server-stateless runs three additional SHOULD-level - # checks (sep-2575-server-sends-{tools,prompts,resources}-list-changed-on- - # subscription) that the conformance fixture cannot yet satisfy because it - # is not wired to publish list_changed events to listen streams. The - # fixture is armed in a follow-up change, after which this entry burns - # down. - - server-stateless # SEP-2243 (HTTP header standardization): the reject cells the SDK does # answer now use -32001 (HeaderMismatch), but missing-header enforcement # (Mcp-Method, Mcp-Name) and the Mcp-Name cross-check are not implemented, diff --git a/test/conformance/src/everythingServer.ts b/test/conformance/src/everythingServer.ts index 535b4e1221..5429e3be57 100644 --- a/test/conformance/src/everythingServer.ts +++ b/test/conformance/src/everythingServer.ts @@ -967,6 +967,43 @@ function createMcpServer() { } ); + // ===== SUBSCRIPTION/LISTEN DIAGNOSTIC TRIGGERS (SEP-2575) ===== + // + // The `server-stateless` conformance scenario opens a `subscriptions/listen` + // stream (served by `createMcpHandler`'s built-in listen router), then calls + // one of these triggers and asserts the corresponding `*/list_changed` + // notification arrives on the open stream. The trigger publishes the change + // event onto the handler's bus via the `handler.notify.*` sugar — the + // listen router stamps the subscription id and applies the per-stream + // filter, so the same trigger also exercises the ack-first and + // honors-notification-filter checks. The 2026-07-28 path is per-request + // (each call gets a fresh `McpServer`), so there is no list to mutate; the + // event itself is what the SHOULD requirement measures. + + mcpServer.registerTool( + 'test_trigger_tool_change', + { + description: 'Listen diagnostic (SEP-2575): publishes a tools/list_changed event onto the handler bus', + inputSchema: z.object({}) + }, + async (): Promise => { + modernHandler.notify.toolsChanged(); + return { content: [{ type: 'text', text: 'tools_list_changed published' }] }; + } + ); + + mcpServer.registerTool( + 'test_trigger_prompt_change', + { + description: 'Listen diagnostic (SEP-2575): publishes a prompts/list_changed event onto the handler bus', + inputSchema: z.object({}) + }, + async (): Promise => { + modernHandler.notify.promptsChanged(); + return { content: [{ type: 'text', text: 'prompts_list_changed published' }] }; + } + ); + // ===== RESOURCES ===== // Static text resource