forked from modelcontextprotocol/python-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_protocol_versions.py
More file actions
102 lines (81 loc) · 4.56 KB
/
Copy pathtest_protocol_versions.py
File metadata and controls
102 lines (81 loc) · 4.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
"""`docs/protocol-versions.md`: every claim the page makes, proved against the real SDK."""
import re
import pytest
from mcp_types import SERVER_INFO_META_KEY, DiscoverResult, Implementation, ServerCapabilities
from docs_src.protocol_versions import tutorial001, tutorial002, tutorial003, tutorial004
from mcp import Client
# See test_index.py for why this is a per-module mark and not a conftest hook.
pytestmark = [pytest.mark.anyio, pytest.mark.filterwarnings("error::mcp.MCPDeprecationWarning")]
async def test_auto_lands_on_the_modern_version() -> None:
"""tutorial001: the default `mode="auto"` probes `server/discover` and adopts the result."""
async with Client(tutorial001.mcp) as client:
assert client.protocol_version == "2026-07-28"
assert client.server_info is not None
assert client.server_info.name == "Bookshop"
assert client.session.discover_result is not None
assert client.session.initialize_result is None
async def test_legacy_forces_the_initialize_handshake() -> None:
"""tutorial002: `mode="legacy"` runs `initialize` against the very same server."""
async with Client(tutorial002.mcp, mode="legacy") as client:
assert client.protocol_version == "2025-11-25"
assert client.server_info is not None
assert client.server_info.name == "Bookshop"
assert client.session.initialize_result is not None
assert client.session.discover_result is None
async def test_version_pin_sends_nothing_and_knows_nothing() -> None:
"""tutorial003: a pin adopts the version locally; `server_info` is None and capabilities are blank."""
async with Client(tutorial003.mcp, mode="2026-07-28") as client:
assert client.protocol_version == "2026-07-28"
# The `!!! check` fence is the literal `print(client.server_info)` output: None.
assert client.server_info is None
assert client.server_capabilities == ServerCapabilities()
result = await client.call_tool("search_books", {"query": "dune"})
assert result.structured_content == {"result": "Found 3 books matching 'dune'."}
def test_handshake_era_version_is_not_a_valid_pin() -> None:
"""A pre-2026 version string is rejected at construction with the exact error the page shows."""
with pytest.raises(
ValueError,
match=re.escape(
"mode must be 'legacy', 'auto', or one of ['2026-07-28']; "
"got '2025-06-18' ('2025-06-18' is a handshake-era version; use mode='legacy')"
),
):
Client(tutorial003.mcp, mode="2025-06-18")
async def test_prior_discover_round_trips() -> None:
"""tutorial004: save `discover_result`, reconnect with it, and the identity comes back."""
async with Client(tutorial004.mcp) as client:
saved = client.session.discover_result
assert saved is not None
assert saved.supported_versions == ["2026-07-28"]
async with Client(tutorial004.mcp, mode="2026-07-28", prior_discover=saved) as client:
assert client.protocol_version == "2026-07-28"
assert client.server_info is not None
assert client.server_info.name == "Bookshop"
assert client.server_capabilities.tools is not None
async def test_discover_result_survives_json() -> None:
"""`DiscoverResult` is a Pydantic model: dump it to JSON, validate it back, reconnect with it."""
async with Client(tutorial004.mcp) as client:
saved = client.session.discover_result
assert saved is not None
restored = DiscoverResult.model_validate_json(saved.model_dump_json())
assert restored == saved
async with Client(tutorial004.mcp, mode="2026-07-28", prior_discover=restored) as client:
assert client.server_info is not None
assert client.server_info.name == "Bookshop"
async def test_prior_discover_is_ignored_unless_mode_is_a_pin() -> None:
"""The `!!! tip`: under `auto` the client probes anyway; under `legacy` it never discovers."""
stale = DiscoverResult(
supported_versions=["2026-07-28"],
capabilities=ServerCapabilities(),
_meta={
SERVER_INFO_META_KEY: Implementation(name="Stale", version="0.0.0").model_dump(
by_alias=True, mode="json", exclude_none=True
)
},
)
async with Client(tutorial004.mcp, prior_discover=stale) as client:
assert client.server_info is not None
assert client.server_info.name == "Bookshop"
async with Client(tutorial004.mcp, mode="legacy", prior_discover=stale) as client:
assert client.session.discover_result is None
assert client.protocol_version == "2025-11-25"