Skip to content

Commit 68e4eb2

Browse files
committed
Tighten requirements-catalog divergence notes to match current SDK behaviour
- resources:annotations: drop the stale lastModified divergence; the model now carries the field and it round-trips. - lifecycle:capability:client-not-declared: narrow to the one remaining gap (the deprecated send_roots_list_changed path); the handler half is correct by construction. - lifecycle:pre-initialization-ordering: mark removed_in=2026-07-28; the initialize handshake is gone in the new spec. - client-transport:http:session-404-reinitialize: reword as an intentional cross-SDK choice (404 surfaced to caller), not a missed MUST. - test_resources: drop the now-redundant lastModified xfail.
1 parent e942d00 commit 68e4eb2

2 files changed

Lines changed: 13 additions & 16 deletions

File tree

tests/interaction/_requirements.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -178,13 +178,15 @@ def __post_init__(self) -> None:
178178
),
179179
divergence=Divergence(
180180
note=(
181-
"The client does not check its own declared capabilities before sending notifications or "
182-
"serving callbacks; nothing prevents a caller from violating the spec's MUST."
181+
"The handler half is correct by construction -- the client derives its declared "
182+
"capabilities from the callbacks registered at construction, so it cannot serve a "
183+
"capability it did not declare. Only the deprecated send_roots_list_changed notification "
184+
"is ungated: a caller can send it without having registered a roots callback."
183185
),
184186
),
185187
deferred=(
186-
"Not implemented in the SDK: the client does not check its own declared capabilities before "
187-
"sending notifications or serving callbacks."
188+
"Not implemented in the SDK: the deprecated send_roots_list_changed notification is not "
189+
"gated on a declared roots capability."
188190
),
189191
),
190192
"lifecycle:capability:server-not-advertised": Requirement(
@@ -300,6 +302,8 @@ def __post_init__(self) -> None:
300302
"Before initialization completes, the client sends no requests other than pings, and the "
301303
"server sends no requests other than pings and logging."
302304
),
305+
removed_in="2026-07-28",
306+
note="initialize handshake removed at 2026-07-28; per-request _meta envelope replaces it.",
303307
divergence=Divergence(
304308
note=(
305309
"The server's send methods (create_message / elicit_form / list_roots) do not check "
@@ -1071,12 +1075,6 @@ def __post_init__(self) -> None:
10711075
"resources:annotations": Requirement(
10721076
source=f"{SPEC_BASE_URL}/server/resources#annotations",
10731077
behavior="Resource annotations supplied by the server round-trip to the client in the list result.",
1074-
divergence=Divergence(
1075-
note=(
1076-
"The SDK Annotations model is missing the schema's lastModified field; MCPModel uses the "
1077-
"pydantic default extra='ignore', so the value is silently dropped on parse."
1078-
),
1079-
),
10801078
),
10811079
"resources:capability:declared": Requirement(
10821080
source=f"{SPEC_BASE_URL}/server/resources#capabilities",
@@ -3163,8 +3161,9 @@ def __post_init__(self) -> None:
31633161
transports=("streamable-http",),
31643162
divergence=Divergence(
31653163
note=(
3166-
"The client surfaces the 404 as an error to the caller instead of re-initializing a new "
3167-
"session; the spec's MUST is not satisfied."
3164+
"The 404 is intentionally surfaced to the caller; this matches the TypeScript, C#, and "
3165+
"Go SDKs. The 2025-11-25 MUST was removed in the 2026 spec (SEP-2567), and the transport "
3166+
"layer cannot safely re-initialize without replaying the caller's request."
31683167
),
31693168
),
31703169
deferred=(

tests/interaction/lowlevel/test_resources.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,8 @@
3939
async def test_list_resources_returns_registered_resources(connect: Connect) -> None:
4040
"""Listed resources reach the client with their URIs, names, and optional descriptive fields intact.
4141
42-
The fully-populated entry includes annotations, so the snapshot also proves they round-trip.
43-
The SDK's Annotations model omits the schema's lastModified field (see the divergence on
44-
resources:annotations); the input is built via model_validate with lastModified set so the
45-
snapshot pins the drop and will fail once the SDK adds the field.
42+
The fully-populated entry includes annotations (audience, priority, last_modified), so the
43+
snapshot also proves they round-trip.
4644
"""
4745

4846
async def list_resources(

0 commit comments

Comments
 (0)