Re-vendor 2026-07-28 schema at spec ead35b59 (SubscriptionsListenResult) (#3006)

This commit is contained in:
Max 2026-06-27 10:15:34 +02:00 • committed by GitHub
commit e942d00b98
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 124 additions and 15 deletions

View file

@ -3220,6 +3220,9 @@
{ {
"$ref": "#/$defs/ReadResourceResult" "$ref": "#/$defs/ReadResourceResult"
}, },
{
"$ref": "#/$defs/SubscriptionsListenResult"
},
{ {
"$ref": "#/$defs/ListPromptsResult" "$ref": "#/$defs/ListPromptsResult"
}, },
@ -3389,6 +3392,36 @@
], ],
"type": "object" "type": "object"
}, },
"SubscriptionsListenResult": {
"description": "The response to a {@link SubscriptionsListenRequestsubscriptions/listen}\nrequest, signalling that the subscription has ended gracefully (for example,\nduring server shutdown). Because the listen stream is long-lived, this result\nis sent only when the server tears the subscription down; an abrupt transport\nclose carries no response. The result body is otherwise empty.",
"properties": {
"_meta": {
"$ref": "#/$defs/SubscriptionsListenResultMeta"
},
"resultType": {
"description": "Indicates the type of the result, which allows the client to determine\nhow to parse the result object.\n\nServers implementing this protocol version MUST include this field.\nFor backward compatibility, when a client receives a result from a\nserver implementing an earlier protocol version (which does not include\n`resultType`), the client MUST treat the absent field as `\"complete\"`.",
"type": "string"
}
},
"required": [
"_meta",
"resultType"
],
"type": "object"
},
"SubscriptionsListenResultMeta": {
"description": "Extends {@link MetaObject} with the subscription-stream identifier carried by a\n{@link SubscriptionsListenResult}. All key naming rules from `MetaObject` apply.",
"properties": {
"io.modelcontextprotocol/subscriptionId": {
"$ref": "#/$defs/RequestId",
"description": "Identifies the subscription stream this response closes, so the client can\ncorrelate it with the originating subscription — mirroring the same key on\nthe stream's notifications. The value is the JSON-RPC ID of the\n`subscriptions/listen` request that opened the stream (and equals this\nresponse's `id`)."
}
},
"required": [
"io.modelcontextprotocol/subscriptionId"
],
"type": "object"
},
"TextContent": { "TextContent": {
"description": "Text provided to or from an LLM.", "description": "Text provided to or from an LLM.",
"properties": { "properties": {

View file

@ -8,7 +8,7 @@
{ {
"protocol_version": "2026-07-28", "protocol_version": "2026-07-28",
"source_path_in_spec_repo": "schema/draft/schema.json", "source_path_in_spec_repo": "schema/draft/schema.json",
"spec_commit": "2852f30e26ca5fb779565741ec042094cb110abd", "spec_commit": "ead35b59b4fda8b32e276810025d8f92bdcec1b6",
"sha256": "ed1ad4ba94aaeb2068b78969ef901b1150f7b2f06cf86472b3032abee1380b6a" "sha256": "e00f675287e8cf078688c26c8a89d283ff2613da3b76d5cd15aff9d189df639c"
} }
] ]

View file

@ -85,7 +85,15 @@ SCHEMA_PATCHES: dict[str, list[tuple[str, Any, Any]]] = {
OPEN_CLASSES: dict[str, frozenset[str]] = { OPEN_CLASSES: dict[str, frozenset[str]] = {
"2025-11-25": frozenset({"Meta", "InputSchema", "OutputSchema", "Result", "GetTaskPayloadResult", "Data"}), "2025-11-25": frozenset({"Meta", "InputSchema", "OutputSchema", "Result", "GetTaskPayloadResult", "Data"}),
"2026-07-28": frozenset( "2026-07-28": frozenset(
{"MetaObject", "NotificationMetaObject", "RequestMetaObject", "InputSchema", "OutputSchema", "Result"} {
"MetaObject",
"NotificationMetaObject",
"RequestMetaObject",
"SubscriptionsListenResultMeta",
"InputSchema",
"OutputSchema",
"Result",
}
), ),
} }

View file

@ -160,6 +160,7 @@ from mcp_types._types import (
SubscriptionsAcknowledgedNotificationParams, SubscriptionsAcknowledgedNotificationParams,
SubscriptionsListenRequest, SubscriptionsListenRequest,
SubscriptionsListenRequestParams, SubscriptionsListenRequestParams,
SubscriptionsListenResult,
Task, Task,
TaskMetadata, TaskMetadata,
TasksCallCapability, TasksCallCapability,
@ -385,6 +386,7 @@ __all__ = [
"ListTasksResult", "ListTasksResult",
"ListToolsResult", "ListToolsResult",
"ReadResourceResult", "ReadResourceResult",
"SubscriptionsListenResult",
# Error data payloads # Error data payloads
"MissingRequiredClientCapabilityErrorData", "MissingRequiredClientCapabilityErrorData",
"UnsupportedProtocolVersionErrorData", "UnsupportedProtocolVersionErrorData",

View file

@ -1063,6 +1063,21 @@ class SubscriptionsAcknowledgedNotification(
params: SubscriptionsAcknowledgedNotificationParams params: SubscriptionsAcknowledgedNotificationParams
class SubscriptionsListenResult(Result):
"""Signals that a `subscriptions/listen` stream has ended gracefully (2026-07-28).
Because the listen stream is long-lived, this result is sent only when the
server tears the subscription down (for example during shutdown); an abrupt
transport close carries no response. The body is otherwise empty: the
`_meta["io.modelcontextprotocol/subscriptionId"]` key is required on the
wire and equals the JSON-RPC id of the originating `subscriptions/listen`
request.
"""
result_type: ResultType = "complete"
"""See `ResultType`. Always serialized; older peers ignore it."""
class ListPromptsRequest(PaginatedRequest[Literal["prompts/list"]]): class ListPromptsRequest(PaginatedRequest[Literal["prompts/list"]]):
"""Sent from the client to request a list of prompts and prompt templates the server has.""" """Sent from the client to request a list of prompts and prompt templates the server has."""
@ -2156,6 +2171,7 @@ ServerResult = (
| ReadResourceResult | ReadResourceResult
| CallToolResult | CallToolResult
| ListToolsResult | ListToolsResult
| SubscriptionsListenResult
| InputRequiredResult | InputRequiredResult
) )
"""Union of every result payload a server can return for a client request. """Union of every result payload a server can return for a client request.

View file

@ -292,7 +292,7 @@ SERVER_RESULTS: Final[Mapping[tuple[str, str], type[BaseModel] | UnionType]] = M
("resources/read", "2026-07-28"): v2026.AnyReadResourceResult, ("resources/read", "2026-07-28"): v2026.AnyReadResourceResult,
("resources/templates/list", "2026-07-28"): v2026.ListResourceTemplatesResult, ("resources/templates/list", "2026-07-28"): v2026.ListResourceTemplatesResult,
("server/discover", "2026-07-28"): v2026.DiscoverResult, ("server/discover", "2026-07-28"): v2026.DiscoverResult,
("subscriptions/listen", "2026-07-28"): v2026.EmptyResult, ("subscriptions/listen", "2026-07-28"): v2026.SubscriptionsListenResult,
("tools/call", "2026-07-28"): v2026.AnyCallToolResult, ("tools/call", "2026-07-28"): v2026.AnyCallToolResult,
("tools/list", "2026-07-28"): v2026.ListToolsResult, ("tools/list", "2026-07-28"): v2026.ListToolsResult,
} }
@ -396,7 +396,7 @@ MONOLITH_RESULTS: Final[Mapping[str, type[types.Result] | UnionType]] = MappingP
# smart-union ties resolve leftmost. Pinned by tests/types/test_methods.py. # smart-union ties resolve leftmost. Pinned by tests/types/test_methods.py.
"sampling/createMessage": types.CreateMessageResult | types.CreateMessageResultWithTools, "sampling/createMessage": types.CreateMessageResult | types.CreateMessageResultWithTools,
"server/discover": types.DiscoverResult, "server/discover": types.DiscoverResult,
"subscriptions/listen": types.EmptyResult, "subscriptions/listen": types.SubscriptionsListenResult,
"tools/call": types.CallToolResult | types.InputRequiredResult, "tools/call": types.CallToolResult | types.InputRequiredResult,
"tools/list": types.ListToolsResult, "tools/list": types.ListToolsResult,
} }

View file

@ -1,7 +1,7 @@
"""Internal wire-shape models for protocol 2026-07-28. Generated; do not edit. """Internal wire-shape models for protocol 2026-07-28. Generated; do not edit.
Regenerate with `scripts/gen_surface_types.py` from `schema/2026-07-28.json` Regenerate with `scripts/gen_surface_types.py` from `schema/2026-07-28.json`
(sha256 `ed1ad4ba94aaeb2068b78969ef901b1150f7b2f06cf86472b3032abee1380b6a`).""" (sha256 `e00f675287e8cf078688c26c8a89d283ff2613da3b76d5cd15aff9d189df639c`)."""
# pyright: reportIncompatibleVariableOverride=false, reportGeneralTypeIssues=false # pyright: reportIncompatibleVariableOverride=false, reportGeneralTypeIssues=false
from __future__ import annotations from __future__ import annotations
@ -909,6 +909,25 @@ class SubscriptionFilter(WireModel):
""" """
class SubscriptionsListenResultMeta(WireModel):
"""
Extends {@link MetaObject} with the subscription-stream identifier carried by a
{@link SubscriptionsListenResult}. All key naming rules from `MetaObject` apply.
"""
model_config = ConfigDict(
extra="allow",
)
io_modelcontextprotocol_subscription_id: Annotated[RequestId, Field(alias="io.modelcontextprotocol/subscriptionId")]
"""
Identifies the subscription stream this response closes, so the client can
correlate it with the originating subscription — mirroring the same key on
the stream's notifications. The value is the JSON-RPC ID of the
`subscriptions/listen` request that opened the stream (and equals this
response's `id`).
"""
class TextResourceContents(WireModel): class TextResourceContents(WireModel):
model_config = ConfigDict( model_config = ConfigDict(
extra="ignore", extra="ignore",
@ -2056,6 +2075,31 @@ class SubscriptionsAcknowledgedNotificationParams(WireModel):
""" """
class SubscriptionsListenResult(WireModel):
"""
The response to a {@link SubscriptionsListenRequestsubscriptions/listen}
request, signalling that the subscription has ended gracefully (for example,
during server shutdown). Because the listen stream is long-lived, this result
is sent only when the server tears the subscription down; an abrupt transport
close carries no response. The result body is otherwise empty.
"""
model_config = ConfigDict(
extra="ignore",
)
meta: Annotated[SubscriptionsListenResultMeta, Field(alias="_meta")]
result_type: Annotated[str, Field(alias="resultType")]
"""
Indicates the type of the result, which allows the client to determine
how to parse the result object.
Servers implementing this protocol version MUST include this field.
For backward compatibility, when a client receives a result from a
server implementing an earlier protocol version (which does not include
`resultType`), the client MUST treat the absent field as `"complete"`.
"""
class TextContent(WireModel): class TextContent(WireModel):
""" """
Text provided to or from an LLM. Text provided to or from an LLM.
@ -3544,6 +3588,7 @@ class ServerResult(
| ListResourcesResult | ListResourcesResult
| ListResourceTemplatesResult | ListResourceTemplatesResult
| ReadResourceResult | ReadResourceResult
| SubscriptionsListenResult
| ListPromptsResult | ListPromptsResult
| GetPromptResult | GetPromptResult
| ListToolsResult | ListToolsResult
@ -3558,6 +3603,7 @@ class ServerResult(
| ListResourcesResult | ListResourcesResult
| ListResourceTemplatesResult | ListResourceTemplatesResult
| ReadResourceResult | ReadResourceResult
| SubscriptionsListenResult
| ListPromptsResult | ListPromptsResult
| GetPromptResult | GetPromptResult
| ListToolsResult | ListToolsResult

View file

@ -182,7 +182,7 @@ class Server(Generic[LifespanResultT]):
| None = None, | None = None,
on_subscriptions_listen: Callable[ on_subscriptions_listen: Callable[
[ServerRequestContext[LifespanResultT], types.SubscriptionsListenRequestParams], [ServerRequestContext[LifespanResultT], types.SubscriptionsListenRequestParams],
Awaitable[types.EmptyResult], Awaitable[types.SubscriptionsListenResult],
] ]
| None = None, | None = None,
on_list_prompts: Callable[ on_list_prompts: Callable[
@ -264,7 +264,7 @@ class Server(Generic[LifespanResultT]):
| None = None, | None = None,
on_subscriptions_listen: Callable[ on_subscriptions_listen: Callable[
[ServerRequestContext[LifespanResultT], types.SubscriptionsListenRequestParams], [ServerRequestContext[LifespanResultT], types.SubscriptionsListenRequestParams],
Awaitable[types.EmptyResult], Awaitable[types.SubscriptionsListenResult],
] ]
| None = None, | None = None,
on_list_prompts: Callable[ on_list_prompts: Callable[
@ -355,7 +355,7 @@ class Server(Generic[LifespanResultT]):
| None = None, | None = None,
on_subscriptions_listen: Callable[ on_subscriptions_listen: Callable[
[ServerRequestContext[LifespanResultT], types.SubscriptionsListenRequestParams], [ServerRequestContext[LifespanResultT], types.SubscriptionsListenRequestParams],
Awaitable[types.EmptyResult], Awaitable[types.SubscriptionsListenResult],
] ]
| None = None, | None = None,
on_list_prompts: Callable[ on_list_prompts: Callable[

View file

@ -268,7 +268,7 @@ EXPECTED_SERVER_RESULTS: dict[tuple[str, str], type[BaseModel] | tuple[type[Base
("resources/read", "2026-07-28"): (v2026.ReadResourceResult, v2026.InputRequiredResult), ("resources/read", "2026-07-28"): (v2026.ReadResourceResult, v2026.InputRequiredResult),
("resources/templates/list", "2026-07-28"): v2026.ListResourceTemplatesResult, ("resources/templates/list", "2026-07-28"): v2026.ListResourceTemplatesResult,
("server/discover", "2026-07-28"): v2026.DiscoverResult, ("server/discover", "2026-07-28"): v2026.DiscoverResult,
("subscriptions/listen", "2026-07-28"): v2026.EmptyResult, ("subscriptions/listen", "2026-07-28"): v2026.SubscriptionsListenResult,
("tools/call", "2026-07-28"): (v2026.CallToolResult, v2026.InputRequiredResult), ("tools/call", "2026-07-28"): (v2026.CallToolResult, v2026.InputRequiredResult),
("tools/list", "2026-07-28"): v2026.ListToolsResult, ("tools/list", "2026-07-28"): v2026.ListToolsResult,
} }
@ -290,9 +290,7 @@ EXPECTED_CLIENT_RESULTS: dict[tuple[str, str], type[BaseModel] | tuple[type[Base
("sampling/createMessage", "2025-11-25"): v2025.CreateMessageResult, ("sampling/createMessage", "2025-11-25"): v2025.CreateMessageResult,
} }
EMPTY_SERVER_RESPONSE_METHODS = frozenset( EMPTY_SERVER_RESPONSE_METHODS = frozenset({"logging/setLevel", "ping", "resources/subscribe", "resources/unsubscribe"})
{"logging/setLevel", "ping", "resources/subscribe", "resources/unsubscribe", "subscriptions/listen"}
)
EMPTY_CLIENT_RESPONSE_METHODS = frozenset({"ping"}) EMPTY_CLIENT_RESPONSE_METHODS = frozenset({"ping"})
# Pre-2026 versions share the 2025-11-25 surface package. # Pre-2026 versions share the 2025-11-25 surface package.
@ -404,7 +402,10 @@ RESULT_BODY_FIXTURES: dict[type[BaseModel] | UnionType, dict[str, Any]] = {
"ttlMs": 0, "ttlMs": 0,
"cacheScope": "private", "cacheScope": "private",
}, },
v2026.EmptyResult: {"resultType": "complete"}, v2026.SubscriptionsListenResult: {
"resultType": "complete",
"_meta": {"io.modelcontextprotocol/subscriptionId": 1},
},
v2026.ListPromptsResult: {"prompts": [], "resultType": "complete", "ttlMs": 0, "cacheScope": "private"}, v2026.ListPromptsResult: {"prompts": [], "resultType": "complete", "ttlMs": 0, "cacheScope": "private"},
v2026.ListResourcesResult: {"resources": [], "resultType": "complete", "ttlMs": 0, "cacheScope": "private"}, v2026.ListResourcesResult: {"resources": [], "resultType": "complete", "ttlMs": 0, "cacheScope": "private"},
v2026.ListResourceTemplatesResult: { v2026.ListResourceTemplatesResult: {
@ -844,7 +845,9 @@ MONOLITH_RESULT_FIXTURES: dict[str, types.Result] = {
ttl_ms=0, ttl_ms=0,
cache_scope="private", cache_scope="private",
), ),
"subscriptions/listen": types.EmptyResult(result_type="complete"), "subscriptions/listen": types.SubscriptionsListenResult.model_validate(
{"_meta": {"io.modelcontextprotocol/subscriptionId": 1}}
),
"tools/call": types.CallToolResult(content=[]), "tools/call": types.CallToolResult(content=[]),
"tools/list": types.ListToolsResult(tools=[], ttl_ms=0, cache_scope="private"), "tools/list": types.ListToolsResult(tools=[], ttl_ms=0, cache_scope="private"),
} }

View file

@ -122,6 +122,7 @@ SKIP: frozenset[str] = frozenset(
"v2026_07_28.RequestedSchema", "v2026_07_28.RequestedSchema",
"v2026_07_28.ResourceRequestParams", "v2026_07_28.ResourceRequestParams",
"v2026_07_28.StringSchema", "v2026_07_28.StringSchema",
"v2026_07_28.SubscriptionsListenResultMeta",
"v2026_07_28.TitledMultiSelectEnumSchema", "v2026_07_28.TitledMultiSelectEnumSchema",
"v2026_07_28.TitledSingleSelectEnumSchema", "v2026_07_28.TitledSingleSelectEnumSchema",
"v2026_07_28.UnsupportedProtocolVersionError", "v2026_07_28.UnsupportedProtocolVersionError",