Files
Max Isbey 1b74b06753 Tighten comments and docstrings repo-wide
Cut comment and docstring volume roughly in half across src, tests,
examples, and docs_src: removed comments that restate the adjacent code,
leftover development narration, section banners, and self-evident
Args/Returns blocks, and compressed the remaining docstrings to a
Google-style summary line plus only the detail that earns its place.

Kept (and tightened) the load-bearing content: Raises sections,
deprecation and version-availability notes, spec/RFC/issue references,
why-comments for non-obvious decisions, and all coverage pragmas. The
generated mcp_types.v* wire modules are untouched.
2026-06-29 15:10:27 +00:00

108 lines
4.6 KiB
Python

"""`docs/advanced/multi-round-trip.md`: every claim the page makes, proved against the real SDK."""
import pytest
from inline_snapshot import snapshot
from mcp_types import (
INTERNAL_ERROR,
INVALID_REQUEST,
CallToolResult,
CreateMessageRequest,
CreateMessageRequestParams,
ElicitRequest,
ElicitRequestFormParams,
ElicitResult,
InputRequiredResult,
TextContent,
)
from docs_src.mrtr import tutorial001, tutorial002, tutorial003
from mcp import Client, MCPError
# 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_first_call_returns_an_input_required_result() -> None:
async with Client(tutorial001.server) as client:
result = await client.session.call_tool("provision", {"name": "orders"}, allow_input_required=True)
assert result == snapshot(
InputRequiredResult(
result_type="input_required",
input_requests={
"region": ElicitRequest(
method="elicitation/create",
params=ElicitRequestFormParams(
mode="form",
message="Which region should the database live in?",
requested_schema={
"type": "object",
"properties": {"region": {"type": "string"}},
"required": ["region"],
},
),
)
},
request_state="provision-v1",
)
)
async def test_the_auto_loop_drives_the_call_to_completion() -> None:
async with Client(tutorial001.server, elicitation_callback=tutorial003.handle_elicitation) as client:
result = await client.call_tool("provision", {"name": "orders"})
assert result == snapshot(
CallToolResult(content=[TextContent(type="text", text="Provisioned 'orders' in eu-west-1.")])
)
async def test_the_auto_loop_without_a_callback_raises_mcp_error() -> None:
"""The page's `!!! check`: no `elicitation_callback` means the SDK's stand-in answers with an error."""
async with Client(tutorial001.server) as client:
with pytest.raises(MCPError) as exc:
await client.call_tool("provision", {"name": "orders"})
assert exc.value.error.code == INVALID_REQUEST
assert exc.value.error.message == "Elicitation not supported"
async def test_retry_with_input_responses_and_request_state_completes_the_call() -> None:
"""tutorial001: the retry carries `input_responses` keyed like `input_requests` plus the echoed token."""
async with Client(tutorial001.server) as client:
result = await client.call_tool(
"provision",
{"name": "orders"},
input_responses={"region": ElicitResult(action="accept", content={"region": "eu-west-1"})},
request_state="provision-v1",
)
assert result == snapshot(
CallToolResult(content=[TextContent(type="text", text="Provisioned 'orders' in eu-west-1.")])
)
async def test_the_manual_loop_drives_the_call_to_completion() -> None:
async with Client(tutorial001.server) as client:
result = await tutorial002.provision(client, "billing")
assert result == snapshot(
CallToolResult(content=[TextContent(type="text", text="Provisioned 'billing' in eu-west-1.")])
)
async def test_the_in_memory_client_negotiates_2026_07_28() -> None:
"""`InputRequiredResult` only exists at 2026-07-28; `Client(server)` lands there without being asked."""
async with Client(tutorial001.server) as client:
assert client.protocol_version == "2026-07-28"
async def test_a_pre_2026_session_has_nowhere_to_put_the_result() -> None:
"""The page's `!!! warning`: on a legacy session the runner cannot serialize an `InputRequiredResult`."""
async with Client(tutorial001.server, mode="legacy") as client:
with pytest.raises(MCPError) as exc:
await client.call_tool("provision", {"name": "orders"})
assert exc.value.error.code == INTERNAL_ERROR
assert exc.value.error.message == "Handler returned an invalid result"
def test_fulfil_refuses_a_request_it_cannot_answer() -> None:
request = CreateMessageRequest(params=CreateMessageRequestParams(messages=[], max_tokens=64))
with pytest.raises(NotImplementedError, match="sampling/createMessage"):
tutorial002.fulfil(request)