docs: stop presenting the in-memory client as the way to connect (#3443)
This commit is contained in:
parent
0c9136841f
commit
7bb486a10f
1 changed files with 803 additions and 598 deletions
|
|
@ -1,11 +1,16 @@
|
|||
"""`docs/protocol-versions.md`: every claim the page makes, proved against the real SDK."""
|
||||
"""`docs/protocol-versions.md`: every claim the page makes, proved against the real SDK.
|
||||
|
||||
The page's snippets are URL clients for the Bookshop `server.py` from The Client page
|
||||
(`docs_src/client/tutorial001.py`). These tests open the same connections in-process
|
||||
against that server object, so each `mode=` is exercised without a port.
|
||||
"""
|
||||
|
||||
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 docs_src.client import tutorial001 as bookshop
|
||||
from mcp import Client
|
||||
|
||||
# See test_index.py for why this is a per-module mark and not a conftest hook.
|
||||
|
|
@ -13,8 +18,9 @@ pytestmark = [pytest.mark.anyio, pytest.mark.filterwarnings("error::mcp.MCPDepre
|
|||
|
||||
|
||||
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:
|
||||
"""tutorial001's connection, in-process: the default `mode="auto"` probes `server/discover`
|
||||
and adopts the result, so the page's `2026-07-28` output block is what it prints."""
|
||||
async with Client(bookshop.mcp) as client:
|
||||
assert client.protocol_version == "2026-07-28"
|
||||
assert client.server_info is not None
|
||||
assert client.server_info.name == "Bookshop"
|
||||
|
|
@ -23,8 +29,9 @@ async def test_auto_lands_on_the_modern_version() -> 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:
|
||||
"""tutorial002's connection, in-process: `mode="legacy"` runs `initialize` against the very
|
||||
same server and lands on the newest handshake-era version."""
|
||||
async with Client(bookshop.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"
|
||||
|
|
@ -33,14 +40,16 @@ async def test_legacy_forces_the_initialize_handshake() -> 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:
|
||||
"""tutorial003's connection, in-process: a pin adopts the version locally, so `server_info`
|
||||
is None and every capability is blank, yet a tool call still round-trips."""
|
||||
async with Client(bookshop.mcp, mode="2026-07-28") as client:
|
||||
assert client.protocol_version == "2026-07-28"
|
||||
assert client.session.initialize_result is None
|
||||
# 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'."}
|
||||
assert result.structured_content == {"result": "Found 3 books matching 'dune' (showing up to 10)."}
|
||||
|
||||
|
||||
def test_handshake_era_version_is_not_a_valid_pin() -> None:
|
||||
|
|
@ -52,18 +61,20 @@ def test_handshake_era_version_is_not_a_valid_pin() -> None:
|
|||
"got '2025-06-18' ('2025-06-18' is a handshake-era version; use mode='legacy')"
|
||||
),
|
||||
):
|
||||
Client(tutorial003.mcp, mode="2025-06-18")
|
||||
Client(bookshop.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:
|
||||
"""tutorial004's flow, driven in-process against the Bookshop server: save `discover_result`,
|
||||
reconnect pinned with it, and the identity comes back without any negotiation."""
|
||||
async with Client(bookshop.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:
|
||||
async with Client(bookshop.mcp, mode="2026-07-28", prior_discover=saved) as client:
|
||||
assert client.protocol_version == "2026-07-28"
|
||||
assert client.session.discover_result is saved
|
||||
assert client.server_info is not None
|
||||
assert client.server_info.name == "Bookshop"
|
||||
assert client.server_capabilities.tools is not None
|
||||
|
|
@ -71,14 +82,14 @@ async def test_prior_discover_round_trips() -> 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:
|
||||
async with Client(bookshop.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:
|
||||
async with Client(bookshop.mcp, mode="2026-07-28", prior_discover=restored) as client:
|
||||
assert client.server_info is not None
|
||||
assert client.server_info.name == "Bookshop"
|
||||
|
||||
|
|
@ -94,9 +105,9 @@ async def test_prior_discover_is_ignored_unless_mode_is_a_pin() -> None:
|
|||
)
|
||||
},
|
||||
)
|
||||
async with Client(tutorial004.mcp, prior_discover=stale) as client:
|
||||
async with Client(bookshop.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:
|
||||
async with Client(bookshop.mcp, mode="legacy", prior_discover=stale) as client:
|
||||
assert client.session.discover_result is None
|
||||
assert client.protocol_version == "2025-11-25"
|
||||
|
|
|
|||
Loading…
Reference in a new issue