Skip to content

Commit e1bf53f

Browse files
committed
Clarify protocol-version docstrings and tighten new tests
- _SERVER_REQUEST_METHODS documents the SDK union, not the spec union (the 2025-11-25 tasks methods are deliberately absent) - protocol_version docstrings no longer claim 'always None' in stateless mode: a client that sends initialize anyway still commits the version - the priming-event test asserts the store saw traffic, so the final all() cannot pass vacuously - add missing test docstrings
1 parent b978383 commit e1bf53f

6 files changed

Lines changed: 16 additions & 10 deletions

File tree

src/mcp/client/session.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,10 @@ async def _default_logging_callback(
9898
_SERVER_REQUEST_METHODS: frozenset[str] = frozenset(
9999
cast(type[BaseModel], arm).model_fields["method"].default for arm in get_args(types.ServerRequest)
100100
)
101-
"""Method names in the spec `ServerRequest` union, derived from the
102-
discriminator literal on each arm. Requests for any other method are answered
103-
with METHOD_NOT_FOUND instead of failing union validation."""
101+
"""Method names in the SDK's `ServerRequest` union, derived from the
102+
discriminator literal on each arm. Requests for any other method — including
103+
spec methods this SDK deliberately doesn't model, like `tasks/*` — are
104+
answered with METHOD_NOT_FOUND instead of failing union validation."""
104105

105106

106107
class ClientSession(

src/mcp/server/connection.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,9 @@ class Connection:
8484

8585
protocol_version: str | None
8686
"""The protocol version negotiated during `initialize`; `None` before
87-
initialization, and always `None` on stateless connections (no handshake
88-
reaches them). Handlers read this as `ServerSession.protocol_version`."""
87+
initialization. Stateless connections don't require the handshake, so this
88+
normally stays `None` there (a client that sends `initialize` anyway still
89+
commits it). Handlers read this as `ServerSession.protocol_version`."""
8990

9091
initialized: anyio.Event
9192
"""Set when `notifications/initialized` arrives (matches TS `oninitialized`);

src/mcp/server/session.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ def client_params(self) -> types.InitializeRequestParams | None:
5454
def protocol_version(self) -> str | None:
5555
"""The protocol version negotiated during `initialize`.
5656
57-
`None` before initialization completes, and always `None` on stateless
58-
connections (no handshake reaches them; on streamable HTTP the
59-
per-request version is the `MCP-Protocol-Version` header, available
60-
via `ctx.request.headers`).
57+
`None` before initialization completes. Stateless connections don't
58+
require the handshake, so this is normally `None` there (on streamable
59+
HTTP the per-request version is the `MCP-Protocol-Version` header,
60+
available via `ctx.request.headers`).
6161
"""
6262
return self._connection.protocol_version
6363

tests/server/test_session.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ def _init_params(protocol_version: str) -> dict[str, Any]:
185185

186186
@pytest.mark.anyio
187187
async def test_protocol_version_is_none_before_initialize():
188+
"""No negotiated version is readable before the initialize handshake."""
188189
async with connected_runner(_runner_server([]), initialized=False) as (_client, runner):
189190
assert runner.session.protocol_version is None
190191

tests/shared/test_streamable_http.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1771,7 +1771,9 @@ async def test_initialize_with_unknown_protocol_version_gets_no_priming_event(
17711771
)
17721772
assert response.status_code == 200
17731773

1774-
# Priming events are stored with a None payload; none may exist for this client.
1774+
# The store must have seen traffic (the initialize response), but no
1775+
# priming event — priming events are stored with a None payload.
1776+
assert event_store._events
17751777
assert all(message is not None for _, _, message in event_store._events)
17761778

17771779

tests/shared/test_version.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
],
2525
)
2626
def test_is_version_at_least_ordering(version: str, minimum: str, expected: bool) -> None:
27+
"""Known revisions order by registry position: equal, newer, and older pairs."""
2728
assert is_version_at_least(version, minimum) is expected
2829

2930

0 commit comments

Comments
 (0)