@@ -319,6 +319,34 @@ def __post_init__(self) -> None:
319319 "support fails initialization with an error rather than proceeding with the session."
320320 ),
321321 ),
322+ "lifecycle:stateless:request-envelope" : Requirement (
323+ source = f"{ SPEC_2026_BASE_URL } /basic/lifecycle#stateless-operation" ,
324+ behavior = (
325+ "At protocol_version 2026-07-28, every request carries io.modelcontextprotocol/protocolVersion, "
326+ "/clientInfo, and /clientCapabilities in params._meta; no initialize handshake occurs."
327+ ),
328+ added_in = "2026-07-28" ,
329+ ),
330+ "lifecycle:stateless:no-initialize" : Requirement (
331+ source = f"{ SPEC_2026_BASE_URL } /basic/lifecycle#stateless-operation" ,
332+ behavior = "A ClientSession pinned to 2026-07-28 rejects initialize() before any frame is sent." ,
333+ added_in = "2026-07-28" ,
334+ ),
335+ "lifecycle:stateless:caller-meta-preserved" : Requirement (
336+ source = f"{ SPEC_2026_BASE_URL } /basic/lifecycle#stateless-operation" ,
337+ behavior = (
338+ "Caller-supplied _meta keys on a request survive the per-request envelope merge: the "
339+ "io.modelcontextprotocol/* keys are added alongside, never overwriting the caller's keys."
340+ ),
341+ added_in = "2026-07-28" ,
342+ ),
343+ "lifecycle:stateless:unpinned-legacy-wire" : Requirement (
344+ source = f"{ SPEC_2026_BASE_URL } /basic/versioning" ,
345+ behavior = (
346+ "An unpinned session that negotiates an earlier protocol version emits no 2026-07-28 "
347+ "vocabulary on any JSON-RPC frame in either direction."
348+ ),
349+ ),
322350 # ═══════════════════════════════════════════════════════════════════════════
323351 # Protocol primitives: cancellation, timeout, progress, errors, _meta
324352 # ═══════════════════════════════════════════════════════════════════════════
@@ -2861,6 +2889,57 @@ def __post_init__(self) -> None:
28612889 removed_in = "2026-07-28" ,
28622890 note = "removed in 2026-07-28 (SEP-2575); the standalone GET endpoint is replaced by subscriptions/listen." ,
28632891 ),
2892+ "hosting:http:protocol-version-rejection-literal" : Requirement (
2893+ source = "sdk" ,
2894+ behavior = (
2895+ "The legacy streamable-HTTP transport's version-rejection body contains the literal substring "
2896+ "'Unsupported protocol version', which other-SDK clients substring-match during negotiation."
2897+ ),
2898+ transports = ("streamable-http" ,),
2899+ note = (
2900+ "Only observable over streamable HTTP: cross-SDK clients sniff this exact substring in the rejection body."
2901+ ),
2902+ ),
2903+ "hosting:http:legacy-no-modern-vocabulary" : Requirement (
2904+ source = f"{ SPEC_2026_BASE_URL } /basic/versioning" ,
2905+ behavior = (
2906+ "A 2025-era streamable-HTTP exchange carries none of the 2026-07-28 wire vocabulary "
2907+ "(resultType, ttlMs, cacheScope, io.modelcontextprotocol/* _meta keys, the 2026-07-28 "
2908+ "version string, or Mcp-Method/Mcp-Name/Mcp-Param-* headers)."
2909+ ),
2910+ transports = ("streamable-http" ,),
2911+ note = (
2912+ "Only observable over streamable HTTP: the assertion records HTTP headers and SSE frames "
2913+ "at the transport seam."
2914+ ),
2915+ ),
2916+ "hosting:http:modern:tools-call-stateless" : Requirement (
2917+ source = f"{ SPEC_2026_BASE_URL } /basic/transports/streamable-http" ,
2918+ behavior = (
2919+ "A 2026-07-28 tools/call POST is served without an initialize handshake and returns a "
2920+ "result body carrying resultType: complete."
2921+ ),
2922+ added_in = "2026-07-28" ,
2923+ transports = ("streamable-http" ,),
2924+ note = (
2925+ "Only observable over streamable HTTP: the modern entry handles a 2026-07-28 POST without "
2926+ "an initialize handshake."
2927+ ),
2928+ ),
2929+ "hosting:http:modern:no-session-id" : Requirement (
2930+ source = f"{ SPEC_2026_BASE_URL } /basic/transports/streamable-http" ,
2931+ behavior = "A 2026-07-28 response never carries an Mcp-Session-Id header." ,
2932+ added_in = "2026-07-28" ,
2933+ transports = ("streamable-http" ,),
2934+ note = "Only observable over streamable HTTP: Mcp-Session-Id is a streamable-HTTP response header." ,
2935+ ),
2936+ "hosting:http:modern:initialize-removed" : Requirement (
2937+ source = f"{ SPEC_2026_BASE_URL } /basic/index" ,
2938+ behavior = "A 2026-07-28 initialize request is answered with METHOD_NOT_FOUND." ,
2939+ added_in = "2026-07-28" ,
2940+ transports = ("streamable-http" ,),
2941+ note = ("Only observable over streamable HTTP: the modern entry's method registry omits initialize." ),
2942+ ),
28642943 # ═══════════════════════════════════════════════════════════════════════════
28652944 # Client transport: streamable HTTP
28662945 # ═══════════════════════════════════════════════════════════════════════════
@@ -3034,6 +3113,28 @@ def __post_init__(self) -> None:
30343113 removed_in = "2026-07-28" ,
30353114 note = "removed in 2026-07-28 (SEP-2567); session DELETE removed with Mcp-Session-Id, no replacement." ,
30363115 ),
3116+ "client-transport:http:body-derived-headers" : Requirement (
3117+ source = f"{ SPEC_2026_BASE_URL } /basic/transports#stateless-request-headers" ,
3118+ behavior = (
3119+ "An envelope-bearing request body yields MCP-Protocol-Version, Mcp-Method, and (for tools/call) "
3120+ "Mcp-Name headers on the outgoing HTTP request; a body without the envelope yields none."
3121+ ),
3122+ added_in = "2026-07-28" ,
3123+ transports = ("streamable-http" ,),
3124+ note = "Only observable over streamable HTTP: headers are derived from the body envelope at the transport seam." ,
3125+ ),
3126+ "client-transport:http:mcp-name-encoding" : Requirement (
3127+ source = f"{ SPEC_2026_BASE_URL } /basic/transports#stateless-request-headers" ,
3128+ behavior = (
3129+ "Mcp-Name header values that are not safe for an HTTP field are wrapped in the =?base64?...?= "
3130+ "sentinel; printable-ASCII values pass verbatim."
3131+ ),
3132+ added_in = "2026-07-28" ,
3133+ transports = ("streamable-http" ,),
3134+ note = (
3135+ "Only observable over streamable HTTP: the Base64-sentinel encoding is the spec's HTTP header-safety rule."
3136+ ),
3137+ ),
30373138 # ═══════════════════════════════════════════════════════════════════════════
30383139 # Client auth
30393140 # ═══════════════════════════════════════════════════════════════════════════
0 commit comments