@@ -572,6 +572,13 @@ def __post_init__(self) -> None:
572572 source = "sdk" ,
573573 behavior = "Closing the transport fails all in-flight requests with a connection-closed error." ,
574574 ),
575+ "protocol:error:handler-error-passthrough" : Requirement (
576+ source = "sdk" ,
577+ behavior = (
578+ "An MCPError raised by a request handler is returned to the caller as a JSON-RPC error "
579+ "carrying the handler-chosen code and message verbatim."
580+ ),
581+ ),
575582 "protocol:error:internal-error" : Requirement (
576583 source = f"{ SPEC_BASE_URL } /basic#responses" ,
577584 behavior = (
@@ -635,12 +642,23 @@ def __post_init__(self) -> None:
635642 "extension."
636643 ),
637644 ),
638- "meta:request-to-handler" : Requirement (
645+ "protocol: meta:request-to-handler" : Requirement (
639646 source = f"{ SPEC_BASE_URL } /basic#_meta" ,
640647 behavior = "The _meta object the client attaches to a request is visible to the server handler." ,
641- arm_exclusions = (ArmExclusion (reason = "asserts-legacy-handshake" , spec_version = "2026-07-28" ),),
648+ arm_exclusions = (
649+ ArmExclusion (
650+ reason = "legacy-only-vocabulary" ,
651+ spec_version = "2026-07-28" ,
652+ note = (
653+ "The pass-through itself holds at 2026, but the modern envelope merges the reserved "
654+ "io.modelcontextprotocol/* keys into every request's _meta, so the test's "
655+ "nothing-else-injected equality assertion only holds on the legacy wire; needs an "
656+ "era-aware assertion before re-admission."
657+ ),
658+ ),
659+ ),
642660 ),
643- "meta:result-to-client" : Requirement (
661+ "protocol: meta:result-to-client" : Requirement (
644662 source = f"{ SPEC_BASE_URL } /basic#_meta" ,
645663 behavior = "The _meta object a handler attaches to its result is delivered to the client." ,
646664 ),
@@ -1037,7 +1055,7 @@ def __post_init__(self) -> None:
10371055 # ═══════════════════════════════════════════════════════════════════════════
10381056 # MCPServer: Context helpers (SDK)
10391057 # ═══════════════════════════════════════════════════════════════════════════
1040- "mcpserver:context:logging " : Requirement (
1058+ "mcpserver:context:log-from-handler " : Requirement (
10411059 source = "sdk" ,
10421060 behavior = (
10431061 "The Context logging helpers (debug/info/warning/error) send log message notifications at the "
@@ -1050,7 +1068,7 @@ def __post_init__(self) -> None:
10501068 "Context.report_progress sends a progress notification against the requesting client's progress token."
10511069 ),
10521070 ),
1053- "mcpserver:context:elicit" : Requirement (
1071+ "mcpserver:context:elicit-from-handler " : Requirement (
10541072 source = "sdk" ,
10551073 behavior = (
10561074 "Context.elicit sends a form elicitation built from a typed schema and returns a typed "
@@ -1121,8 +1139,11 @@ def __post_init__(self) -> None:
11211139 behavior = "resources/read returns text contents carrying uri, mimeType, and the text." ,
11221140 ),
11231141 "resources:read:unknown-uri" : Requirement (
1124- source = f"{ SPEC_BASE_URL } /server/resources#error-handling" ,
1125- behavior = "resources/read for an unknown URI returns JSON-RPC error -32002 (resource not found)." ,
1142+ source = f"{ SPEC_2026_BASE_URL } /server/resources#error-handling" ,
1143+ behavior = (
1144+ "resources/read for a URI matching no registered resource returns JSON-RPC error -32602 "
1145+ "(invalid params) with the requested URI in error.data, per SEP-2164."
1146+ ),
11261147 ),
11271148 "resources:subscribe" : Requirement (
11281149 source = f"{ SPEC_BASE_URL } /server/resources#subscriptions" ,
@@ -1228,13 +1249,6 @@ def __post_init__(self) -> None:
12281249 "by resources/read, receiving the parameters extracted from the requested URI."
12291250 ),
12301251 ),
1231- "mcpserver:resource:unknown-uri" : Requirement (
1232- source = f"{ SPEC_BASE_URL } /server/resources#error-handling" ,
1233- behavior = (
1234- "resources/read for a URI matching no registered resource returns JSON-RPC error -32602 "
1235- "(invalid params) with the requested URI in error.data, per SEP-2164."
1236- ),
1237- ),
12381252 # ═══════════════════════════════════════════════════════════════════════════
12391253 # Prompts
12401254 # ═══════════════════════════════════════════════════════════════════════════
@@ -1528,23 +1542,23 @@ def __post_init__(self) -> None:
15281542 "rejects every tool-enabled request before it is sent."
15291543 ),
15301544 ),
1531- "sampling:create-message :audio-content" : Requirement (
1545+ "sampling:create:audio-content" : Requirement (
15321546 source = f"{ SPEC_BASE_URL } /client/sampling#audio-content" ,
15331547 behavior = "Sampling messages can carry audio content: base64 data with a mimeType." ,
15341548 arm_exclusions = (
15351549 ArmExclusion (reason = "server-initiated-request" , transport = "streamable-http-stateless" ),
15361550 ArmExclusion (reason = "server-initiated-request" , spec_version = "2026-07-28" ),
15371551 ),
15381552 ),
1539- "sampling:create-message :image-content" : Requirement (
1553+ "sampling:create:image-content" : Requirement (
15401554 source = f"{ SPEC_BASE_URL } /client/sampling#image-content" ,
15411555 behavior = "Sampling messages can carry image content: base64 data with a mimeType." ,
15421556 arm_exclusions = (
15431557 ArmExclusion (reason = "server-initiated-request" , transport = "streamable-http-stateless" ),
15441558 ArmExclusion (reason = "server-initiated-request" , spec_version = "2026-07-28" ),
15451559 ),
15461560 ),
1547- "sampling:create-message :not-supported" : Requirement (
1561+ "sampling:create:not-supported" : Requirement (
15481562 source = f"{ SPEC_BASE_URL } /client/sampling#capabilities" ,
15491563 behavior = (
15501564 "A sampling request to a client that did not declare the sampling capability fails with an "
@@ -1832,20 +1846,28 @@ def __post_init__(self) -> None:
18321846 ArmExclusion (reason = "server-initiated-request" , spec_version = "2026-07-28" ),
18331847 ),
18341848 ),
1835- "elicitation:url:basic" : Requirement (
1836- source = f"{ SPEC_BASE_URL } /client/elicitation#url-mode-elicitation-requests" ,
1837- behavior = (
1838- "A url-mode elicitation delivers the elicitation id and URL to the client callback exactly as "
1839- "the server sent them."
1840- ),
1849+ "elicitation:url:action:cancel" : Requirement (
1850+ source = f"{ SPEC_BASE_URL } /client/elicitation#response-actions" ,
1851+ behavior = "A URL-mode elicitation answered with cancel returns the action with no content." ,
18411852 arm_exclusions = (
18421853 ArmExclusion (reason = "server-initiated-request" , transport = "streamable-http-stateless" ),
18431854 ArmExclusion (reason = "server-initiated-request" , spec_version = "2026-07-28" ),
18441855 ),
18451856 ),
1846- "elicitation:url:cancel " : Requirement (
1857+ "elicitation:url:action:decline " : Requirement (
18471858 source = f"{ SPEC_BASE_URL } /client/elicitation#response-actions" ,
1848- behavior = "A URL-mode elicitation answered with cancel returns the action with no content." ,
1859+ behavior = "A URL-mode elicitation answered with decline returns the action with no content." ,
1860+ arm_exclusions = (
1861+ ArmExclusion (reason = "server-initiated-request" , transport = "streamable-http-stateless" ),
1862+ ArmExclusion (reason = "server-initiated-request" , spec_version = "2026-07-28" ),
1863+ ),
1864+ ),
1865+ "elicitation:url:basic" : Requirement (
1866+ source = f"{ SPEC_BASE_URL } /client/elicitation#url-mode-elicitation-requests" ,
1867+ behavior = (
1868+ "A url-mode elicitation delivers the elicitation id and URL to the client callback exactly as "
1869+ "the server sent them."
1870+ ),
18491871 arm_exclusions = (
18501872 ArmExclusion (reason = "server-initiated-request" , transport = "streamable-http-stateless" ),
18511873 ArmExclusion (reason = "server-initiated-request" , spec_version = "2026-07-28" ),
@@ -1873,14 +1895,6 @@ def __post_init__(self) -> None:
18731895 removed_in = "2026-07-28" ,
18741896 note = "removed in 2026-07-28 (spec PR #2891); notifications/elicitation/complete removed, no replacement." ,
18751897 ),
1876- "elicitation:url:decline" : Requirement (
1877- source = f"{ SPEC_BASE_URL } /client/elicitation#response-actions" ,
1878- behavior = "A URL-mode elicitation answered with decline returns the action with no content." ,
1879- arm_exclusions = (
1880- ArmExclusion (reason = "server-initiated-request" , transport = "streamable-http-stateless" ),
1881- ArmExclusion (reason = "server-initiated-request" , spec_version = "2026-07-28" ),
1882- ),
1883- ),
18841898 "elicitation:url:not-supported" : Requirement (
18851899 source = f"{ SPEC_BASE_URL } /client/elicitation#error-handling" ,
18861900 behavior = (
@@ -3453,7 +3467,7 @@ def __post_init__(self) -> None:
34533467 transports = ("streamable-http" ,),
34543468 note = "OAuth is HTTP-only." ,
34553469 ),
3456- "client-auth:403- scope-union" : Requirement (
3470+ "client-auth:stepup: scope-union" : Requirement (
34573471 source = f"{ SPEC_BASE_URL } /basic/authorization#step-up-authorization-flow" ,
34583472 behavior = (
34593473 "On a 403 insufficient_scope step-up, the re-authorization request carries the union of the "
@@ -3496,7 +3510,7 @@ def __post_init__(self) -> None:
34963510 ),
34973511 ),
34983512 ),
3499- "client-auth:authorize :offline-access-consent " : Requirement (
3513+ "client-auth:scope :offline-access-gate " : Requirement (
35003514 source = "sdk" ,
35013515 behavior = (
35023516 "When the authorization server's metadata advertises offline_access in scopes_supported and "
@@ -3530,7 +3544,7 @@ def __post_init__(self) -> None:
35303544 transports = ("streamable-http" ,),
35313545 note = "OAuth is HTTP-only." ,
35323546 ),
3533- "client-auth:dcr:registration-error-surfaces " : Requirement (
3547+ "client-auth:dcr:registration-rejected-error " : Requirement (
35343548 source = "sdk" ,
35353549 behavior = (
35363550 "A 400 from the registration endpoint surfaces to the caller as an OAuthRegistrationError "
@@ -3692,7 +3706,7 @@ def __post_init__(self) -> None:
36923706 transports = ("streamable-http" ,),
36933707 note = "OAuth is HTTP-only." ,
36943708 ),
3695- "client-auth:authorization-response: iss-verify " : Requirement (
3709+ "client-auth:iss:mismatch-reject " : Requirement (
36963710 source = f"{ SPEC_2026_BASE_URL } /basic/authorization#authorization-response-validation" ,
36973711 behavior = (
36983712 "The client validates the RFC 9207 iss authorization-response parameter against the "
0 commit comments