diff --git a/.github/actions/conformance/client.py b/.github/actions/conformance/client.py index 0784ef190d..18e59a8ac6 100644 --- a/.github/actions/conformance/client.py +++ b/.github/actions/conformance/client.py @@ -11,16 +11,18 @@ --spec-version is omitted the harness picks per-scenario (LATEST_SPEC_VERSION for active scenarios, DRAFT_PROTOCOL_VERSION for draft-only ones). - Server URL as last CLI argument (sys.argv[1]) - - Must exit 0 within 30 seconds + - Must exit 0 within the harness --timeout (CI passes 60s; the default is 30s) Scenarios: initialize - Connect, initialize, list tools, close tools_call - Connect, call add_numbers(a=5, b=3), close sse-retry - Connect, call test_reconnection, close json-schema-ref-no-deref - Connect, list tools (no $ref deref) + json-schema-2020-12-preservation - List tools, echo the focal inputSchema back verbatim request-metadata - Connect with all callbacks; client stamps _meta http-standard-headers - Connect, call a tool (Mcp-* headers checked) http-invalid-tool-headers - List tools, call every surfaced tool (x-mcp-header filter) + http-custom-headers - Replay the harness's toolCalls (x-mcp-header -> Mcp-Param-*) elicitation-sep1034-client-defaults - Elicitation with default accept callback sep-2322-client-request-state - Drive the MRTR auto-loop (SEP-2322) auth/client-credentials-jwt - Client credentials with private_key_jwt @@ -252,6 +254,21 @@ async def run_json_schema_ref_no_deref(server_url: str) -> None: await client.list_tools() +@register("json-schema-2020-12-preservation") +async def run_json_schema_2020_12_preservation(server_url: str) -> None: + """List tools, then echo the focal tool's inputSchema back verbatim (SEP-1613 / SEP-2106). + + The harness diffs what the client round-trips through `json_schema_echo` against its + fixture to detect 2020-12 keywords ($schema, $defs, $anchor, additionalProperties, + allOf/anyOf, if/then/else) being stripped while parsing tools/list. Unlike + json-schema-ref-no-deref, this mock is version-aware, so client_mode() applies. + """ + async with Client(server_url, mode=client_mode()) as client: + listed = await client.list_tools() + focal = next(tool for tool in listed.tools if tool.name == "json_schema_2020_12_tool") + await client.call_tool("json_schema_echo", {"schema": focal.input_schema}) + + @register("tools_call") async def run_tools_call(server_url: str) -> None: """Connect, list tools, call add_numbers(a=5, b=3), close.""" diff --git a/.github/workflows/conformance.yml b/.github/workflows/conformance.yml index c7e5097a72..0222296888 100644 --- a/.github/workflows/conformance.yml +++ b/.github/workflows/conformance.yml @@ -17,7 +17,7 @@ env: # Pinned conformance harness package spec (passed verbatim to `npx --yes`). # Bump deliberately and reconcile both # .github/actions/conformance/expected-failures*.yml files in the same change. - CONFORMANCE_PKG: "@modelcontextprotocol/conformance@0.2.0-alpha.10" + CONFORMANCE_PKG: "@modelcontextprotocol/conformance@0.2.0-alpha.11" jobs: server-conformance: