Server-side 2026-07-28 stateless support: classifier, driver split, server/discover (#2928)
This commit is contained in:
parent
44724284b3
commit
2397319a68
1 changed files with 2256 additions and 1088 deletions
|
|
@ -14,9 +14,14 @@ from inline_snapshot import snapshot
|
|||
|
||||
from mcp.server import Server, ServerRequestContext
|
||||
from mcp.server.transport_security import TransportSecuritySettings
|
||||
from mcp.shared.version import MODERN_PROTOCOL_VERSIONS
|
||||
from mcp.types import (
|
||||
CLIENT_CAPABILITIES_META_KEY,
|
||||
CLIENT_INFO_META_KEY,
|
||||
INVALID_PARAMS,
|
||||
PARSE_ERROR,
|
||||
PROTOCOL_VERSION_META_KEY,
|
||||
UNSUPPORTED_PROTOCOL_VERSION,
|
||||
CallToolRequestParams,
|
||||
CallToolResult,
|
||||
EmptyResult,
|
||||
|
|
@ -155,7 +160,12 @@ async def test_malformed_and_batched_bodies_return_400() -> None:
|
|||
@requirement("hosting:http:protocol-version-400")
|
||||
@requirement("hosting:http:protocol-version-default")
|
||||
async def test_protocol_version_header_is_validated() -> None:
|
||||
"""An unsupported MCP-Protocol-Version header returns 400; an absent header is accepted as the default."""
|
||||
"""An unsupported MCP-Protocol-Version header returns 400; an absent header is accepted as the default.
|
||||
|
||||
An unrecognised header value routes to the modern entry (which owns rejection of unknown
|
||||
versions), and a request without the per-request envelope is rejected at the first ladder
|
||||
rung. Only known initialize-handshake versions and an absent header reach the legacy path.
|
||||
"""
|
||||
async with mounted_app(_server()) as (http, _):
|
||||
session_id = await initialize_via_http(http)
|
||||
|
||||
|
|
@ -172,9 +182,7 @@ async def test_protocol_version_header_is_validated() -> None:
|
|||
)
|
||||
|
||||
assert bad.status_code == 400
|
||||
assert JSONRPCError.model_validate_json(bad.text).error.message.startswith(
|
||||
"Bad Request: Unsupported protocol version: 1991-01-01."
|
||||
)
|
||||
assert JSONRPCError.model_validate_json(bad.text).error.code == INVALID_PARAMS
|
||||
# 202 proves the request was accepted under the assumed default version (2025-03-26).
|
||||
assert defaulted.status_code == 202
|
||||
|
||||
|
|
@ -185,18 +193,27 @@ async def test_unsupported_protocol_version_rejection_body_contains_the_sniffed_
|
|||
|
||||
SDK-defined: other SDKs detect this rejection by substring-matching ``Unsupported protocol
|
||||
version`` in the response body, so the literal must survive any rewording of the surrounding
|
||||
message. Asserted at the wire because the SDK client never surfaces the rejection body.
|
||||
message. The unsupported value must appear in both the header and the envelope so the
|
||||
classifier reaches its version-supported rung rather than reporting a header mismatch first.
|
||||
"""
|
||||
bad = "1991-01-01"
|
||||
meta = {
|
||||
PROTOCOL_VERSION_META_KEY: bad,
|
||||
CLIENT_INFO_META_KEY: {"name": "t", "version": "0"},
|
||||
CLIENT_CAPABILITIES_META_KEY: {},
|
||||
}
|
||||
async with mounted_app(_server()) as (http, _):
|
||||
session_id = await initialize_via_http(http)
|
||||
response = await http.post(
|
||||
"/mcp",
|
||||
json={"jsonrpc": "2.0", "id": 2, "method": "ping"},
|
||||
headers=base_headers(session_id=session_id) | {"mcp-protocol-version": "1991-01-01"},
|
||||
json={"jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {"_meta": meta}},
|
||||
headers=base_headers() | {"mcp-protocol-version": bad},
|
||||
)
|
||||
|
||||
assert response.status_code == 400
|
||||
error = JSONRPCError.model_validate_json(response.text).error
|
||||
assert error.code == UNSUPPORTED_PROTOCOL_VERSION
|
||||
assert "Unsupported protocol version" in response.text
|
||||
assert error.data == {"supported": list(MODERN_PROTOCOL_VERSIONS), "requested": bad}
|
||||
|
||||
|
||||
@requirement("hosting:http:json-response-mode")
|
||||
|
|
|
|||
Loading…
Reference in a new issue