@@ -15,13 +15,28 @@ permissions:
1515
1616env :
1717 # Pinned conformance harness package spec (passed verbatim to `npx --yes`).
18- # Bump deliberately and reconcile both
18+ # Bump deliberately and reconcile the three
1919 # .github/actions/conformance/expected-failures*.yml files in the same change.
2020 CONFORMANCE_PKG : " @modelcontextprotocol/conformance@0.2.0-alpha.11"
2121
22+ # Each job runs three `--suite all` legs, one per baseline file. The two
23+ # `--spec-version <rev>` legs run every scenario the pinned harness marks
24+ # applicable at that spec revision, at that revision's wire (stateful
25+ # handshake for 2025-11-25, stateless per-request _meta for 2026-07-28). Each
26+ # is a superset of the frozen requirement set that `conformance tier-check`
27+ # scores for that revision (`npx $CONFORMANCE_PKG list --requirements <rev>`
28+ # prints it), so an expected-failures.<rev>.yml entry for a scenario in that
29+ # set means tier-check reports the SDK below 100% for <rev>. The bare leg runs
30+ # every shipped scenario at whichever wire the harness defaults it to; it is
31+ # the only leg that reaches extension-tagged scenarios (tasks-*, auth/dpop*,
32+ # ...), which never match a --spec-version filter. For everything else it
33+ # overlaps one of the pinned legs, so a failure it also sees needs its own
34+ # expected-failures.yml entry besides the pinned file's.
35+
2236jobs :
2337 server-conformance :
2438 runs-on : ubuntu-latest
39+ timeout-minutes : 15
2540 steps :
2641 - uses : actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
2742 with :
@@ -34,45 +49,31 @@ jobs:
3449 with :
3550 node-version : 24
3651 - run : uv sync --frozen --all-extras --package mcp-everything-server
37- - name : Run server conformance (active suite)
38- run : >-
39- ./.github/actions/conformance/run-server.sh
40- --suite active
41- --expected-failures ./.github/actions/conformance/expected-failures.yml
42- --output-dir conformance-results/server-active
43- - name : Run server conformance (draft suite)
52+ - name : Run server conformance (all suite, 2025-11-25 wire)
4453 run : >-
4554 ./.github/actions/conformance/run-server.sh
46- --suite draft
47- --expected-failures ./.github/actions/conformance/expected-failures.yml
48- --output-dir conformance-results/server-draft
49- - name : Run server conformance (2026-07-28 wire, all suite)
55+ --suite all
56+ --spec-version 2025-11-25
57+ --expected-failures ./.github/actions/conformance/expected-failures.2025-11-25.yml
58+ --output-dir conformance-results/server-2025-11-25
59+ - name : Run server conformance (all suite, 2026-07-28 wire)
5060 run : >-
5161 ./.github/actions/conformance/run-server.sh
5262 --suite all
5363 --spec-version 2026-07-28
5464 --expected-failures ./.github/actions/conformance/expected-failures.2026-07-28.yml
5565 --output-dir conformance-results/server-2026-07-28
56- - name : Run server conformance (all suite, extension scenarios)
57- # A bare `--suite all` (no --spec-version) selects every scenario
58- # shipped with the pinned harness — including the extension-tagged
59- # tasks-* scenarios and pending-listed ones like server-sse-polling,
60- # which no other leg reaches (extension scenarios never match a
61- # --spec-version filter, and the pending list keeps them out of the
62- # active suite). Running the full set keeps unimplemented surfaces
63- # visible as baselined known failures in expected-failures.yml instead
64- # of silent exclusions, and stays robust to scenarios moving between
65- # harness suite lists across pin bumps. `--suite pending` would cover
66- # the same union slightly faster; the full set is preferred for the
67- # self-contained run and for parity with typescript-sdk's CI.
66+ - name : Run server conformance (all suite, default wire)
6867 run : >-
6968 ./.github/actions/conformance/run-server.sh
7069 --suite all
7170 --expected-failures ./.github/actions/conformance/expected-failures.yml
7271 --output-dir conformance-results/server-all
7372 - name : Upload conformance results
7473 # The log has only summary counts; per-check data is in checks.json.
75- if : failure()
74+ # always(), not !cancelled(): a timeout-minutes kill is a cancellation,
75+ # and that is when the partial results matter most.
76+ if : always()
7677 uses : actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
7778 with :
7879 name : server-conformance-results
8182
8283 client-conformance :
8384 runs-on : ubuntu-latest
85+ timeout-minutes : 15
8486 steps :
8587 - uses : actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
8688 with :
@@ -97,20 +99,21 @@ jobs:
9799 - run : uv sync --frozen --all-extras --package mcp --compile-bytecode
98100 - name : Pre-compile bytecode (editable sources)
99101 run : uv run --frozen python -m compileall -q src .github/actions/conformance
100- - name : Run client conformance ( all suite)
101- # The harness runs all scenarios via unbounded Promise.all; with 40
102- # scenarios on a 2-core runner the slowest one (sse-retry, which has a
103- # real-time SSE reconnect wait) needs more than the 30s default budget.
104- # `.venv/bin/python` (not `uv run`) avoids lockfile re-checks in ~40
105- # concurrent spawns; run- client.sh re-runs unexpected failures solo.
102+ # The harness runs a leg's scenarios via unbounded Promise. all; under
103+ # that concurrency the slowest one (sse-retry, which has a real-time SSE
104+ # reconnect wait) needs more than the 30s default budget.
105+ # `.venv/bin/python` (not `uv run`) avoids lockfile re-checks in ~40
106+ # concurrent spawns; run-client.sh re-runs unexpected failures solo.
107+ - name : Run client conformance (all suite, 2025-11-25 wire)
106108 run : >-
107109 ./.github/actions/conformance/run-client.sh
108110 --command '.venv/bin/python .github/actions/conformance/client.py'
109111 --suite all
110112 --timeout 60000
111- --expected-failures ./.github/actions/conformance/expected-failures.yml
112- --output-dir conformance-results/client-all
113- - name : Run client conformance (2026-07-28 wire, all suite)
113+ --spec-version 2025-11-25
114+ --expected-failures ./.github/actions/conformance/expected-failures.2025-11-25.yml
115+ --output-dir conformance-results/client-2025-11-25
116+ - name : Run client conformance (all suite, 2026-07-28 wire)
114117 run : >-
115118 ./.github/actions/conformance/run-client.sh
116119 --command '.venv/bin/python .github/actions/conformance/client.py'
@@ -119,10 +122,19 @@ jobs:
119122 --spec-version 2026-07-28
120123 --expected-failures ./.github/actions/conformance/expected-failures.2026-07-28.yml
121124 --output-dir conformance-results/client-2026-07-28
125+ - name : Run client conformance (all suite, default wire)
126+ run : >-
127+ ./.github/actions/conformance/run-client.sh
128+ --command '.venv/bin/python .github/actions/conformance/client.py'
129+ --suite all
130+ --timeout 60000
131+ --expected-failures ./.github/actions/conformance/expected-failures.yml
132+ --output-dir conformance-results/client-all
122133 - name : Upload conformance results
123134 # The log has only summary counts; per-check data is in checks.json.
124- # Also on FLAKE_RESCUED: rescued-flake evidence is otherwise discarded.
125- if : failure() || hashFiles('conformance-results/**/FLAKE_RESCUED') != ''
135+ # always(), not !cancelled(): a timeout-minutes kill is a cancellation,
136+ # and that is when the partial results matter most.
137+ if : always()
126138 uses : actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
127139 with :
128140 name : client-conformance-results
0 commit comments