Split protocol types into a standalone mcp-types package (#2973)

This commit is contained in:
Marcelo Trylesinski 2026-06-25 19:18:38 +02:00 • committed by GitHub
commit 0ee7f1b293
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 1040 additions and 867 deletions

16
src/mcp-types/README.md Normal file
View file

@ -0,0 +1,16 @@
# MCP Types
The wire types for the [Model Context Protocol](https://modelcontextprotocol.io).
This package holds the protocol message models, JSON-RPC envelope types, per-version
surface validators, and the protocol-version registry. Its only runtime dependencies are
`pydantic` and `typing-extensions`, so it can be installed on its own when you need to
(de)serialize MCP traffic without pulling in the full `mcp` SDK.
```python
from mcp_types import Tool, CallToolRequest
from mcp_types.version import LATEST_PROTOCOL_VERSION
```
The `mcp` package re-exports these names, so existing `from mcp import Tool` imports
keep working.

View file

@ -0,0 +1,446 @@
"""This module defines the types for the MCP protocol.
Check the latest schema at:
https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/schema/draft/schema.json
"""
# Re-export everything from _types for backward compatibility
from mcp_types._types import (
CLIENT_CAPABILITIES_META_KEY,
CLIENT_INFO_META_KEY,
DEFAULT_NEGOTIATED_VERSION,
LOG_LEVEL_META_KEY,
PROTOCOL_VERSION_META_KEY,
Annotations,
AudioContent,
BaseMetadata,
BlobResourceContents,
CacheableResult,
CallToolRequest,
CallToolRequestParams,
CallToolResult,
CancelledNotification,
CancelledNotificationParams,
CancelTaskRequest,
CancelTaskRequestParams,
CancelTaskResult,
ClientCapabilities,
ClientNotification,
ClientRequest,
ClientResult,
ClientTasksCapability,
ClientTasksRequestsCapability,
CompleteRequest,
CompleteRequestParams,
CompleteResult,
Completion,
CompletionArgument,
CompletionContext,
CompletionsCapability,
ContentBlock,
CreateMessageRequest,
CreateMessageRequestParams,
CreateMessageResult,
CreateMessageResultWithTools,
CreateTaskResult,
DiscoverRequest,
DiscoverResult,
ElicitationCapability,
ElicitationRequiredErrorData,
ElicitCompleteNotification,
ElicitCompleteNotificationParams,
ElicitRequest,
ElicitRequestedSchema,
ElicitRequestFormParams,
ElicitRequestParams,
ElicitRequestURLParams,
ElicitResult,
EmbeddedResource,
EmptyResult,
FormElicitationCapability,
GetPromptRequest,
GetPromptRequestParams,
GetPromptResult,
GetTaskPayloadRequest,
GetTaskPayloadRequestParams,
GetTaskPayloadResult,
GetTaskRequest,
GetTaskRequestParams,
GetTaskResult,
Icon,
IconTheme,
ImageContent,
Implementation,
IncludeContext,
InitializedNotification,
InitializeRequest,
InitializeRequestParams,
InitializeResult,
InputRequest,
InputRequests,
InputRequiredResult,
InputResponse,
InputResponseRequestParams,
InputResponses,
ListPromptsRequest,
ListPromptsResult,
ListResourcesRequest,
ListResourcesResult,
ListResourceTemplatesRequest,
ListResourceTemplatesResult,
ListRootsRequest,
ListRootsResult,
ListTasksRequest,
ListTasksResult,
ListToolsRequest,
ListToolsResult,
LoggingCapability,
LoggingLevel,
LoggingMessageNotification,
LoggingMessageNotificationParams,
MissingRequiredClientCapabilityErrorData,
ModelHint,
ModelPreferences,
Notification,
NotificationParams,
PaginatedRequest,
PaginatedRequestParams,
PaginatedResult,
PingRequest,
ProgressNotification,
ProgressNotificationParams,
ProgressToken,
Prompt,
PromptArgument,
PromptListChangedNotification,
PromptMessage,
PromptReference,
PromptsCapability,
ReadResourceRequest,
ReadResourceRequestParams,
ReadResourceResult,
RelatedTaskMetadata,
Request,
RequestParams,
RequestParamsMeta,
Resource,
ResourceContents,
ResourceLink,
ResourceListChangedNotification,
ResourcesCapability,
ResourceTemplate,
ResourceTemplateReference,
ResourceUpdatedNotification,
ResourceUpdatedNotificationParams,
Result,
ResultType,
Role,
Root,
RootsCapability,
RootsListChangedNotification,
SamplingCapability,
SamplingContent,
SamplingContextCapability,
SamplingMessage,
SamplingMessageContentBlock,
SamplingToolsCapability,
ServerCapabilities,
ServerNotification,
ServerRequest,
ServerResult,
ServerTasksCapability,
ServerTasksRequestsCapability,
SetLevelRequest,
SetLevelRequestParams,
StopReason,
SubscribeRequest,
SubscribeRequestParams,
SubscriptionFilter,
SubscriptionsAcknowledgedNotification,
SubscriptionsAcknowledgedNotificationParams,
SubscriptionsListenRequest,
SubscriptionsListenRequestParams,
Task,
TaskMetadata,
TasksCallCapability,
TasksCancelCapability,
TasksCreateElicitationCapability,
TasksCreateMessageCapability,
TasksElicitationCapability,
TasksListCapability,
TasksSamplingCapability,
TaskStatus,
TaskStatusNotification,
TaskStatusNotificationParams,
TasksToolsCapability,
TextContent,
TextResourceContents,
Tool,
ToolAnnotations,
ToolChoice,
ToolExecution,
ToolListChangedNotification,
ToolResultContent,
ToolsCapability,
ToolUseContent,
UnsubscribeRequest,
UnsubscribeRequestParams,
UnsupportedProtocolVersionErrorData,
UrlElicitationCapability,
client_notification_adapter,
client_request_adapter,
client_result_adapter,
server_notification_adapter,
server_request_adapter,
server_result_adapter,
)
# Re-export JSONRPC types
from mcp_types.jsonrpc import (
CONNECTION_CLOSED,
HEADER_MISMATCH,
INTERNAL_ERROR,
INVALID_PARAMS,
INVALID_REQUEST,
JSONRPC_VERSION,
METHOD_NOT_FOUND,
MISSING_REQUIRED_CLIENT_CAPABILITY,
PARSE_ERROR,
REQUEST_TIMEOUT,
UNSUPPORTED_PROTOCOL_VERSION,
URL_ELICITATION_REQUIRED,
ErrorData,
JSONRPCError,
JSONRPCMessage,
JSONRPCNotification,
JSONRPCRequest,
JSONRPCResponse,
RequestId,
jsonrpc_message_adapter,
)
from mcp_types.version import LATEST_PROTOCOL_VERSION
__all__ = [
# Protocol version constants
"LATEST_PROTOCOL_VERSION",
"DEFAULT_NEGOTIATED_VERSION",
# Reserved request _meta keys
"PROTOCOL_VERSION_META_KEY",
"CLIENT_INFO_META_KEY",
"CLIENT_CAPABILITIES_META_KEY",
"LOG_LEVEL_META_KEY",
# Type aliases and variables
"ContentBlock",
"ElicitRequestedSchema",
"ElicitRequestParams",
"IncludeContext",
"InputRequest",
"InputRequests",
"InputResponse",
"InputResponses",
"LoggingLevel",
"ProgressToken",
"ResultType",
"Role",
"SamplingContent",
"SamplingMessageContentBlock",
"StopReason",
"TaskStatus",
# Base classes
"BaseMetadata",
"Request",
"Notification",
"Result",
"RequestParams",
"RequestParamsMeta",
"InputResponseRequestParams",
"NotificationParams",
"PaginatedRequest",
"PaginatedRequestParams",
"PaginatedResult",
"CacheableResult",
"EmptyResult",
# Capabilities
"ClientCapabilities",
"ClientTasksCapability",
"ClientTasksRequestsCapability",
"CompletionsCapability",
"ElicitationCapability",
"FormElicitationCapability",
"LoggingCapability",
"PromptsCapability",
"ResourcesCapability",
"RootsCapability",
"SamplingCapability",
"SamplingContextCapability",
"SamplingToolsCapability",
"ServerCapabilities",
"ServerTasksCapability",
"ServerTasksRequestsCapability",
"TasksCallCapability",
"TasksCancelCapability",
"TasksCreateElicitationCapability",
"TasksCreateMessageCapability",
"TasksElicitationCapability",
"TasksListCapability",
"TasksSamplingCapability",
"TasksToolsCapability",
"ToolsCapability",
"UrlElicitationCapability",
# Content types
"Annotations",
"AudioContent",
"BlobResourceContents",
"EmbeddedResource",
"Icon",
"IconTheme",
"ImageContent",
"ResourceContents",
"ResourceLink",
"TextContent",
"TextResourceContents",
"ToolResultContent",
"ToolUseContent",
# Entity types
"Completion",
"CompletionArgument",
"CompletionContext",
"Implementation",
"ModelHint",
"ModelPreferences",
"Prompt",
"PromptArgument",
"PromptMessage",
"PromptReference",
"Resource",
"ResourceTemplate",
"ResourceTemplateReference",
"Root",
"SamplingMessage",
"SubscriptionFilter",
"Task",
"TaskMetadata",
"RelatedTaskMetadata",
"Tool",
"ToolAnnotations",
"ToolChoice",
"ToolExecution",
# Requests
"CallToolRequest",
"CallToolRequestParams",
"CompleteRequest",
"CompleteRequestParams",
"CancelTaskRequest",
"CancelTaskRequestParams",
"CreateMessageRequest",
"CreateMessageRequestParams",
"DiscoverRequest",
"ElicitRequest",
"ElicitRequestFormParams",
"ElicitRequestURLParams",
"GetPromptRequest",
"GetPromptRequestParams",
"GetTaskPayloadRequest",
"GetTaskPayloadRequestParams",
"GetTaskRequest",
"GetTaskRequestParams",
"InitializeRequest",
"InitializeRequestParams",
"ListPromptsRequest",
"ListResourcesRequest",
"ListResourceTemplatesRequest",
"ListRootsRequest",
"ListTasksRequest",
"ListToolsRequest",
"PingRequest",
"ReadResourceRequest",
"ReadResourceRequestParams",
"SetLevelRequest",
"SetLevelRequestParams",
"SubscribeRequest",
"SubscribeRequestParams",
"SubscriptionsListenRequest",
"SubscriptionsListenRequestParams",
"UnsubscribeRequest",
"UnsubscribeRequestParams",
# Results
"CallToolResult",
"CancelTaskResult",
"CompleteResult",
"CreateMessageResult",
"CreateMessageResultWithTools",
"CreateTaskResult",
"DiscoverResult",
"ElicitResult",
"ElicitationRequiredErrorData",
"GetPromptResult",
"GetTaskPayloadResult",
"GetTaskResult",
"InitializeResult",
"InputRequiredResult",
"ListPromptsResult",
"ListResourcesResult",
"ListResourceTemplatesResult",
"ListRootsResult",
"ListTasksResult",
"ListToolsResult",
"ReadResourceResult",
# Error data payloads
"MissingRequiredClientCapabilityErrorData",
"UnsupportedProtocolVersionErrorData",
# Notifications
"CancelledNotification",
"CancelledNotificationParams",
"ElicitCompleteNotification",
"ElicitCompleteNotificationParams",
"InitializedNotification",
"LoggingMessageNotification",
"LoggingMessageNotificationParams",
"ProgressNotification",
"ProgressNotificationParams",
"PromptListChangedNotification",
"ResourceListChangedNotification",
"ResourceUpdatedNotification",
"ResourceUpdatedNotificationParams",
"RootsListChangedNotification",
"SubscriptionsAcknowledgedNotification",
"SubscriptionsAcknowledgedNotificationParams",
"TaskStatusNotification",
"TaskStatusNotificationParams",
"ToolListChangedNotification",
# Union types for request/response routing
"ClientNotification",
"ClientRequest",
"ClientResult",
"ServerNotification",
"ServerRequest",
"ServerResult",
# Type adapters
"client_notification_adapter",
"client_request_adapter",
"client_result_adapter",
"server_notification_adapter",
"server_request_adapter",
"server_result_adapter",
# JSON-RPC types
"CONNECTION_CLOSED",
"HEADER_MISMATCH",
"INTERNAL_ERROR",
"INVALID_PARAMS",
"INVALID_REQUEST",
"JSONRPC_VERSION",
"METHOD_NOT_FOUND",
"MISSING_REQUIRED_CLIENT_CAPABILITY",
"PARSE_ERROR",
"REQUEST_TIMEOUT",
"UNSUPPORTED_PROTOCOL_VERSION",
"URL_ELICITATION_REQUIRED",
"ErrorData",
"JSONRPCError",
"JSONRPCMessage",
"JSONRPCNotification",
"JSONRPCRequest",
"JSONRPCResponse",
"RequestId",
"jsonrpc_message_adapter",
]

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,9 @@
"""Shared pydantic base for the generated `mcp_types.v*` wire-shape packages."""
from pydantic import BaseModel, ConfigDict
class WireModel(BaseModel):
"""Base for generated wire models: enables `populate_by_name`; subclasses set `extra` themselves."""
model_config = ConfigDict(populate_by_name=True)

View file

@ -0,0 +1,125 @@
"""This module follows the JSON-RPC 2.0 specification: https://www.jsonrpc.org/specification."""
from __future__ import annotations
from typing import Annotated, Any, Final, Literal
from pydantic import BaseModel, Field, TypeAdapter
RequestId = Annotated[int, Field(strict=True)] | str
"""The ID of a JSON-RPC request."""
JSONRPC_VERSION: Final[Literal["2.0"]] = "2.0"
"""The JSON-RPC version string carried by every MCP message envelope."""
class JSONRPCRequest(BaseModel):
"""A JSON-RPC request that expects a response."""
jsonrpc: Literal["2.0"]
id: RequestId
method: str
params: dict[str, Any] | None = None
class JSONRPCNotification(BaseModel):
"""A JSON-RPC notification which does not expect a response."""
jsonrpc: Literal["2.0"]
method: str
params: dict[str, Any] | None = None
class JSONRPCResponse(BaseModel):
"""A successful (non-error) response to a request.
Named `JSONRPCResultResponse` in the 2025-11-25+ schemas; the SDK keeps the original name.
"""
jsonrpc: Literal["2.0"]
id: RequestId
result: dict[str, Any]
# MCP error codes occupy the JSON-RPC server-error range -32000..-32099.
# Per the 2026-07-28 spec's allocation policy:
# -32000..-32019 implementation-defined
# -32020..-32099 reserved for spec-defined codes, allocated sequentially from -32020
# -32002, -32042 reserved-never-reused (retired by earlier protocol versions)
HEADER_MISMATCH = -32020
"""HTTP headers do not match the request body, or required headers are missing/malformed (protocol 2026-07-28)."""
MISSING_REQUIRED_CLIENT_CAPABILITY = -32021
"""The server requires a client capability the request did not declare (protocol 2026-07-28)."""
UNSUPPORTED_PROTOCOL_VERSION = -32022
"""The request's protocol version is not supported by the server (protocol 2026-07-28)."""
URL_ELICITATION_REQUIRED = -32042
"""A URL-mode elicitation is required before the request can be processed (protocol 2025-11-25 only)."""
# SDK error codes: SDK-internal allocations in the implementation-defined band
# -32000..-32019; not defined by the MCP schema.
CONNECTION_CLOSED = -32000
"""SDK-only: the connection closed before a response arrived; never emitted on the wire."""
REQUEST_TIMEOUT = -32001
"""SDK-only: a request timed out waiting for its response."""
# Standard JSON-RPC error codes
PARSE_ERROR = -32700
"""Standard JSON-RPC: invalid JSON was received."""
INVALID_REQUEST = -32600
"""Standard JSON-RPC: the message is not a valid request object."""
METHOD_NOT_FOUND = -32601
"""Standard JSON-RPC: the requested method does not exist or is not available."""
INVALID_PARAMS = -32602
"""Standard JSON-RPC: invalid method parameters."""
INTERNAL_ERROR = -32603
"""Standard JSON-RPC: an internal error occurred on the receiver.
The SDK uses the generic `ErrorData` envelope; the schema's per-code wrapper types are not constructed.
"""
class ErrorData(BaseModel):
"""Error information for JSON-RPC error responses."""
code: int
"""The error type that occurred."""
message: str
"""A short description of the error.
The message SHOULD be limited to a concise single sentence.
"""
data: Any = None
"""Additional information about the error.
The value of this member is defined by the sender (e.g. detailed error information, nested errors, etc.).
"""
class JSONRPCError(BaseModel):
"""A response to a request that indicates an error occurred."""
jsonrpc: Literal["2.0"]
id: RequestId | None
"""The id of the request this error responds to.
Required but nullable per JSON-RPC 2.0: `None` encodes `"id": null` (the id could not be determined).
"""
error: ErrorData
JSONRPCMessage = JSONRPCRequest | JSONRPCNotification | JSONRPCResponse | JSONRPCError
"""Any JSON-RPC envelope that can be decoded off the wire or encoded to be sent."""
jsonrpc_message_adapter: TypeAdapter[JSONRPCMessage] = TypeAdapter(JSONRPCMessage)

View file

@ -0,0 +1,708 @@
"""Per-version method maps and parse/serialize functions for MCP traffic.
This module is supported public API; the `mcp_types.v*` packages it draws on
are internal validators and not for direct import.
Surface maps key `(method, version)` to per-version wire types (key absence is
the version gate; shape validation is per schema era, i.e. 2025-11-25 for every
pre-2026 version and 2026-07-28 for 2026). Monolith maps key `method` to the
version-free `mcp_types` models user code receives."""
from __future__ import annotations
from collections.abc import Mapping
from functools import cache
from types import MappingProxyType, UnionType
from typing import Any, Final, TypeVar
from pydantic import BaseModel, TypeAdapter
import mcp_types as types
import mcp_types.v2025_11_25 as v2025
import mcp_types.v2026_07_28 as v2026
from mcp_types.version import KNOWN_PROTOCOL_VERSIONS
__all__ = [
"CLIENT_NOTIFICATIONS",
"CLIENT_REQUESTS",
"CLIENT_RESULTS",
"MONOLITH_NOTIFICATIONS",
"MONOLITH_REQUESTS",
"MONOLITH_RESULTS",
"SERVER_NOTIFICATIONS",
"SERVER_REQUESTS",
"SERVER_RESULTS",
"SPEC_CLIENT_METHODS",
"SPEC_CLIENT_NOTIFICATION_METHODS",
"parse_client_notification",
"parse_client_request",
"parse_client_result",
"parse_server_notification",
"parse_server_request",
"parse_server_result",
"serialize_server_result",
"validate_client_notification",
"validate_client_request",
"validate_client_result",
"validate_server_result",
]
# --- Surface maps: client-to-server ---
CLIENT_REQUESTS: Final[Mapping[tuple[str, str], type[BaseModel]]] = MappingProxyType(
{
# 2024-11-05
("completion/complete", "2024-11-05"): v2025.CompleteRequest,
("initialize", "2024-11-05"): v2025.InitializeRequest,
("logging/setLevel", "2024-11-05"): v2025.SetLevelRequest,
("ping", "2024-11-05"): v2025.PingRequest,
("prompts/get", "2024-11-05"): v2025.GetPromptRequest,
("prompts/list", "2024-11-05"): v2025.ListPromptsRequest,
("resources/list", "2024-11-05"): v2025.ListResourcesRequest,
("resources/read", "2024-11-05"): v2025.ReadResourceRequest,
("resources/subscribe", "2024-11-05"): v2025.SubscribeRequest,
("resources/templates/list", "2024-11-05"): v2025.ListResourceTemplatesRequest,
("resources/unsubscribe", "2024-11-05"): v2025.UnsubscribeRequest,
("tools/call", "2024-11-05"): v2025.CallToolRequest,
("tools/list", "2024-11-05"): v2025.ListToolsRequest,
# 2025-03-26
("completion/complete", "2025-03-26"): v2025.CompleteRequest,
("initialize", "2025-03-26"): v2025.InitializeRequest,
("logging/setLevel", "2025-03-26"): v2025.SetLevelRequest,
("ping", "2025-03-26"): v2025.PingRequest,
("prompts/get", "2025-03-26"): v2025.GetPromptRequest,
("prompts/list", "2025-03-26"): v2025.ListPromptsRequest,
("resources/list", "2025-03-26"): v2025.ListResourcesRequest,
("resources/read", "2025-03-26"): v2025.ReadResourceRequest,
("resources/subscribe", "2025-03-26"): v2025.SubscribeRequest,
("resources/templates/list", "2025-03-26"): v2025.ListResourceTemplatesRequest,
("resources/unsubscribe", "2025-03-26"): v2025.UnsubscribeRequest,
("tools/call", "2025-03-26"): v2025.CallToolRequest,
("tools/list", "2025-03-26"): v2025.ListToolsRequest,
# 2025-06-18
("completion/complete", "2025-06-18"): v2025.CompleteRequest,
("initialize", "2025-06-18"): v2025.InitializeRequest,
("logging/setLevel", "2025-06-18"): v2025.SetLevelRequest,
("ping", "2025-06-18"): v2025.PingRequest,
("prompts/get", "2025-06-18"): v2025.GetPromptRequest,
("prompts/list", "2025-06-18"): v2025.ListPromptsRequest,
("resources/list", "2025-06-18"): v2025.ListResourcesRequest,
("resources/read", "2025-06-18"): v2025.ReadResourceRequest,
("resources/subscribe", "2025-06-18"): v2025.SubscribeRequest,
("resources/templates/list", "2025-06-18"): v2025.ListResourceTemplatesRequest,
("resources/unsubscribe", "2025-06-18"): v2025.UnsubscribeRequest,
("tools/call", "2025-06-18"): v2025.CallToolRequest,
("tools/list", "2025-06-18"): v2025.ListToolsRequest,
# 2025-11-25 (tasks/* deliberately absent)
("completion/complete", "2025-11-25"): v2025.CompleteRequest,
("initialize", "2025-11-25"): v2025.InitializeRequest,
("logging/setLevel", "2025-11-25"): v2025.SetLevelRequest,
("ping", "2025-11-25"): v2025.PingRequest,
("prompts/get", "2025-11-25"): v2025.GetPromptRequest,
("prompts/list", "2025-11-25"): v2025.ListPromptsRequest,
("resources/list", "2025-11-25"): v2025.ListResourcesRequest,
("resources/read", "2025-11-25"): v2025.ReadResourceRequest,
("resources/subscribe", "2025-11-25"): v2025.SubscribeRequest,
("resources/templates/list", "2025-11-25"): v2025.ListResourceTemplatesRequest,
("resources/unsubscribe", "2025-11-25"): v2025.UnsubscribeRequest,
("tools/call", "2025-11-25"): v2025.CallToolRequest,
("tools/list", "2025-11-25"): v2025.ListToolsRequest,
# 2026-07-28 (lifecycle, logging, subscribe pair removed; discover/listen added)
("completion/complete", "2026-07-28"): v2026.CompleteRequest,
("prompts/get", "2026-07-28"): v2026.GetPromptRequest,
("prompts/list", "2026-07-28"): v2026.ListPromptsRequest,
("resources/list", "2026-07-28"): v2026.ListResourcesRequest,
("resources/read", "2026-07-28"): v2026.ReadResourceRequest,
("resources/templates/list", "2026-07-28"): v2026.ListResourceTemplatesRequest,
("server/discover", "2026-07-28"): v2026.DiscoverRequest,
("subscriptions/listen", "2026-07-28"): v2026.SubscriptionsListenRequest,
("tools/call", "2026-07-28"): v2026.CallToolRequest,
("tools/list", "2026-07-28"): v2026.ListToolsRequest,
}
)
CLIENT_NOTIFICATIONS: Final[Mapping[tuple[str, str], type[BaseModel]]] = MappingProxyType(
{
# 2024-11-05
("notifications/cancelled", "2024-11-05"): v2025.CancelledNotification,
("notifications/initialized", "2024-11-05"): v2025.InitializedNotification,
("notifications/progress", "2024-11-05"): v2025.ProgressNotification,
("notifications/roots/list_changed", "2024-11-05"): v2025.RootsListChangedNotification,
# 2025-03-26
("notifications/cancelled", "2025-03-26"): v2025.CancelledNotification,
("notifications/initialized", "2025-03-26"): v2025.InitializedNotification,
("notifications/progress", "2025-03-26"): v2025.ProgressNotification,
("notifications/roots/list_changed", "2025-03-26"): v2025.RootsListChangedNotification,
# 2025-06-18
("notifications/cancelled", "2025-06-18"): v2025.CancelledNotification,
("notifications/initialized", "2025-06-18"): v2025.InitializedNotification,
("notifications/progress", "2025-06-18"): v2025.ProgressNotification,
("notifications/roots/list_changed", "2025-06-18"): v2025.RootsListChangedNotification,
# 2025-11-25 (tasks/status deliberately absent)
("notifications/cancelled", "2025-11-25"): v2025.CancelledNotification,
("notifications/initialized", "2025-11-25"): v2025.InitializedNotification,
("notifications/progress", "2025-11-25"): v2025.ProgressNotification,
("notifications/roots/list_changed", "2025-11-25"): v2025.RootsListChangedNotification,
# 2026-07-28 (initialized, progress and roots/list_changed removed)
("notifications/cancelled", "2026-07-28"): v2026.CancelledNotification,
}
)
# --- Surface maps: server-to-client ---
SERVER_REQUESTS: Final[Mapping[tuple[str, str], type[BaseModel]]] = MappingProxyType(
{
# 2024-11-05
("ping", "2024-11-05"): v2025.PingRequest,
("roots/list", "2024-11-05"): v2025.ListRootsRequest,
("sampling/createMessage", "2024-11-05"): v2025.CreateMessageRequest,
# 2025-03-26
("ping", "2025-03-26"): v2025.PingRequest,
("roots/list", "2025-03-26"): v2025.ListRootsRequest,
("sampling/createMessage", "2025-03-26"): v2025.CreateMessageRequest,
# 2025-06-18 (adds elicitation/create)
("elicitation/create", "2025-06-18"): v2025.ElicitRequest,
("ping", "2025-06-18"): v2025.PingRequest,
("roots/list", "2025-06-18"): v2025.ListRootsRequest,
("sampling/createMessage", "2025-06-18"): v2025.CreateMessageRequest,
# 2025-11-25 (tasks/* deliberately absent)
("elicitation/create", "2025-11-25"): v2025.ElicitRequest,
("ping", "2025-11-25"): v2025.PingRequest,
("roots/list", "2025-11-25"): v2025.ListRootsRequest,
("sampling/createMessage", "2025-11-25"): v2025.CreateMessageRequest,
# 2026-07-28: none (schema defines no ServerRequest union)
}
)
SERVER_NOTIFICATIONS: Final[Mapping[tuple[str, str], type[BaseModel]]] = MappingProxyType(
{
# 2024-11-05
("notifications/cancelled", "2024-11-05"): v2025.CancelledNotification,
("notifications/message", "2024-11-05"): v2025.LoggingMessageNotification,
("notifications/progress", "2024-11-05"): v2025.ProgressNotification,
("notifications/prompts/list_changed", "2024-11-05"): v2025.PromptListChangedNotification,
("notifications/resources/list_changed", "2024-11-05"): v2025.ResourceListChangedNotification,
("notifications/resources/updated", "2024-11-05"): v2025.ResourceUpdatedNotification,
("notifications/tools/list_changed", "2024-11-05"): v2025.ToolListChangedNotification,
# 2025-03-26
("notifications/cancelled", "2025-03-26"): v2025.CancelledNotification,
("notifications/message", "2025-03-26"): v2025.LoggingMessageNotification,
("notifications/progress", "2025-03-26"): v2025.ProgressNotification,
("notifications/prompts/list_changed", "2025-03-26"): v2025.PromptListChangedNotification,
("notifications/resources/list_changed", "2025-03-26"): v2025.ResourceListChangedNotification,
("notifications/resources/updated", "2025-03-26"): v2025.ResourceUpdatedNotification,
("notifications/tools/list_changed", "2025-03-26"): v2025.ToolListChangedNotification,
# 2025-06-18
("notifications/cancelled", "2025-06-18"): v2025.CancelledNotification,
("notifications/message", "2025-06-18"): v2025.LoggingMessageNotification,
("notifications/progress", "2025-06-18"): v2025.ProgressNotification,
("notifications/prompts/list_changed", "2025-06-18"): v2025.PromptListChangedNotification,
("notifications/resources/list_changed", "2025-06-18"): v2025.ResourceListChangedNotification,
("notifications/resources/updated", "2025-06-18"): v2025.ResourceUpdatedNotification,
("notifications/tools/list_changed", "2025-06-18"): v2025.ToolListChangedNotification,
# 2025-11-25 (adds elicitation/complete; tasks/status deliberately absent)
("notifications/cancelled", "2025-11-25"): v2025.CancelledNotification,
("notifications/elicitation/complete", "2025-11-25"): v2025.ElicitationCompleteNotification,
("notifications/message", "2025-11-25"): v2025.LoggingMessageNotification,
("notifications/progress", "2025-11-25"): v2025.ProgressNotification,
("notifications/prompts/list_changed", "2025-11-25"): v2025.PromptListChangedNotification,
("notifications/resources/list_changed", "2025-11-25"): v2025.ResourceListChangedNotification,
("notifications/resources/updated", "2025-11-25"): v2025.ResourceUpdatedNotification,
("notifications/tools/list_changed", "2025-11-25"): v2025.ToolListChangedNotification,
# 2026-07-28 (adds subscriptions/acknowledged; elicitation/complete removed)
("notifications/cancelled", "2026-07-28"): v2026.CancelledNotification,
("notifications/message", "2026-07-28"): v2026.LoggingMessageNotification,
("notifications/progress", "2026-07-28"): v2026.ProgressNotification,
("notifications/prompts/list_changed", "2026-07-28"): v2026.PromptListChangedNotification,
("notifications/resources/list_changed", "2026-07-28"): v2026.ResourceListChangedNotification,
("notifications/resources/updated", "2026-07-28"): v2026.ResourceUpdatedNotification,
("notifications/subscriptions/acknowledged", "2026-07-28"): v2026.SubscriptionsAcknowledgedNotification,
("notifications/tools/list_changed", "2026-07-28"): v2026.ToolListChangedNotification,
}
)
# --- Surface maps: results ---
SERVER_RESULTS: Final[Mapping[tuple[str, str], type[BaseModel] | UnionType]] = MappingProxyType(
{
# 2024-11-05
("completion/complete", "2024-11-05"): v2025.CompleteResult,
("initialize", "2024-11-05"): v2025.InitializeResult,
("logging/setLevel", "2024-11-05"): v2025.EmptyResult,
("ping", "2024-11-05"): v2025.EmptyResult,
("prompts/get", "2024-11-05"): v2025.GetPromptResult,
("prompts/list", "2024-11-05"): v2025.ListPromptsResult,
("resources/list", "2024-11-05"): v2025.ListResourcesResult,
("resources/read", "2024-11-05"): v2025.ReadResourceResult,
("resources/subscribe", "2024-11-05"): v2025.EmptyResult,
("resources/templates/list", "2024-11-05"): v2025.ListResourceTemplatesResult,
("resources/unsubscribe", "2024-11-05"): v2025.EmptyResult,
("tools/call", "2024-11-05"): v2025.CallToolResult,
("tools/list", "2024-11-05"): v2025.ListToolsResult,
# 2025-03-26
("completion/complete", "2025-03-26"): v2025.CompleteResult,
("initialize", "2025-03-26"): v2025.InitializeResult,
("logging/setLevel", "2025-03-26"): v2025.EmptyResult,
("ping", "2025-03-26"): v2025.EmptyResult,
("prompts/get", "2025-03-26"): v2025.GetPromptResult,
("prompts/list", "2025-03-26"): v2025.ListPromptsResult,
("resources/list", "2025-03-26"): v2025.ListResourcesResult,
("resources/read", "2025-03-26"): v2025.ReadResourceResult,
("resources/subscribe", "2025-03-26"): v2025.EmptyResult,
("resources/templates/list", "2025-03-26"): v2025.ListResourceTemplatesResult,
("resources/unsubscribe", "2025-03-26"): v2025.EmptyResult,
("tools/call", "2025-03-26"): v2025.CallToolResult,
("tools/list", "2025-03-26"): v2025.ListToolsResult,
# 2025-06-18
("completion/complete", "2025-06-18"): v2025.CompleteResult,
("initialize", "2025-06-18"): v2025.InitializeResult,
("logging/setLevel", "2025-06-18"): v2025.EmptyResult,
("ping", "2025-06-18"): v2025.EmptyResult,
("prompts/get", "2025-06-18"): v2025.GetPromptResult,
("prompts/list", "2025-06-18"): v2025.ListPromptsResult,
("resources/list", "2025-06-18"): v2025.ListResourcesResult,
("resources/read", "2025-06-18"): v2025.ReadResourceResult,
("resources/subscribe", "2025-06-18"): v2025.EmptyResult,
("resources/templates/list", "2025-06-18"): v2025.ListResourceTemplatesResult,
("resources/unsubscribe", "2025-06-18"): v2025.EmptyResult,
("tools/call", "2025-06-18"): v2025.CallToolResult,
("tools/list", "2025-06-18"): v2025.ListToolsResult,
# 2025-11-25
("completion/complete", "2025-11-25"): v2025.CompleteResult,
("initialize", "2025-11-25"): v2025.InitializeResult,
("logging/setLevel", "2025-11-25"): v2025.EmptyResult,
("ping", "2025-11-25"): v2025.EmptyResult,
("prompts/get", "2025-11-25"): v2025.GetPromptResult,
("prompts/list", "2025-11-25"): v2025.ListPromptsResult,
("resources/list", "2025-11-25"): v2025.ListResourcesResult,
("resources/read", "2025-11-25"): v2025.ReadResourceResult,
("resources/subscribe", "2025-11-25"): v2025.EmptyResult,
("resources/templates/list", "2025-11-25"): v2025.ListResourceTemplatesResult,
("resources/unsubscribe", "2025-11-25"): v2025.EmptyResult,
("tools/call", "2025-11-25"): v2025.CallToolResult,
("tools/list", "2025-11-25"): v2025.ListToolsResult,
# 2026-07-28 (dual-result rows use the version's union aliases)
("completion/complete", "2026-07-28"): v2026.CompleteResult,
("prompts/get", "2026-07-28"): v2026.AnyGetPromptResult,
("prompts/list", "2026-07-28"): v2026.ListPromptsResult,
("resources/list", "2026-07-28"): v2026.ListResourcesResult,
("resources/read", "2026-07-28"): v2026.AnyReadResourceResult,
("resources/templates/list", "2026-07-28"): v2026.ListResourceTemplatesResult,
("server/discover", "2026-07-28"): v2026.DiscoverResult,
("subscriptions/listen", "2026-07-28"): v2026.EmptyResult,
("tools/call", "2026-07-28"): v2026.AnyCallToolResult,
("tools/list", "2026-07-28"): v2026.ListToolsResult,
}
)
"""Results servers send, keyed by the originating client request's (method, version)."""
CLIENT_RESULTS: Final[Mapping[tuple[str, str], type[BaseModel] | UnionType]] = MappingProxyType(
{
# 2024-11-05
("ping", "2024-11-05"): v2025.EmptyResult,
("roots/list", "2024-11-05"): v2025.ListRootsResult,
("sampling/createMessage", "2024-11-05"): v2025.CreateMessageResult,
# 2025-03-26
("ping", "2025-03-26"): v2025.EmptyResult,
("roots/list", "2025-03-26"): v2025.ListRootsResult,
("sampling/createMessage", "2025-03-26"): v2025.CreateMessageResult,
# 2025-06-18
("elicitation/create", "2025-06-18"): v2025.ElicitResult,
("ping", "2025-06-18"): v2025.EmptyResult,
("roots/list", "2025-06-18"): v2025.ListRootsResult,
("sampling/createMessage", "2025-06-18"): v2025.CreateMessageResult,
# 2025-11-25
("elicitation/create", "2025-11-25"): v2025.ElicitResult,
("ping", "2025-11-25"): v2025.EmptyResult,
("roots/list", "2025-11-25"): v2025.ListRootsResult,
("sampling/createMessage", "2025-11-25"): v2025.CreateMessageResult,
# 2026-07-28: none (no server-to-client requests at this version)
}
)
"""Results clients send, keyed by the originating server request's (method, version)."""
# --- Direction-specific method sets ---
SPEC_CLIENT_METHODS: Final[frozenset[str]] = frozenset(m for m, _ in CLIENT_REQUESTS)
"""Spec request methods a client may send (any version); the server-side spec-method discriminator."""
SPEC_CLIENT_NOTIFICATION_METHODS: Final[frozenset[str]] = frozenset(m for m, _ in CLIENT_NOTIFICATIONS)
"""Spec notification methods a client may send (any version); the server-side spec-method discriminator."""
# --- Monolith maps ---
MONOLITH_REQUESTS: Final[Mapping[str, type[types.Request[Any, Any]]]] = MappingProxyType(
{
"completion/complete": types.CompleteRequest,
"elicitation/create": types.ElicitRequest,
"initialize": types.InitializeRequest,
"logging/setLevel": types.SetLevelRequest,
"ping": types.PingRequest,
"prompts/get": types.GetPromptRequest,
"prompts/list": types.ListPromptsRequest,
"resources/list": types.ListResourcesRequest,
"resources/read": types.ReadResourceRequest,
"resources/subscribe": types.SubscribeRequest,
"resources/templates/list": types.ListResourceTemplatesRequest,
"resources/unsubscribe": types.UnsubscribeRequest,
"roots/list": types.ListRootsRequest,
"sampling/createMessage": types.CreateMessageRequest,
"server/discover": types.DiscoverRequest,
"subscriptions/listen": types.SubscriptionsListenRequest,
"tools/call": types.CallToolRequest,
"tools/list": types.ListToolsRequest,
}
)
"""Monolith request model per method, both directions."""
MONOLITH_NOTIFICATIONS: Final[Mapping[str, type[types.Notification[Any, Any]]]] = MappingProxyType(
{
"notifications/cancelled": types.CancelledNotification,
"notifications/elicitation/complete": types.ElicitCompleteNotification,
"notifications/initialized": types.InitializedNotification,
"notifications/message": types.LoggingMessageNotification,
"notifications/progress": types.ProgressNotification,
"notifications/prompts/list_changed": types.PromptListChangedNotification,
"notifications/resources/list_changed": types.ResourceListChangedNotification,
"notifications/resources/updated": types.ResourceUpdatedNotification,
"notifications/roots/list_changed": types.RootsListChangedNotification,
"notifications/subscriptions/acknowledged": types.SubscriptionsAcknowledgedNotification,
"notifications/tools/list_changed": types.ToolListChangedNotification,
}
)
"""Monolith notification model per method, both directions."""
MONOLITH_RESULTS: Final[Mapping[str, type[types.Result] | UnionType]] = MappingProxyType(
{
"completion/complete": types.CompleteResult,
"elicitation/create": types.ElicitResult,
"initialize": types.InitializeResult,
"logging/setLevel": types.EmptyResult,
"ping": types.EmptyResult,
"prompts/get": types.GetPromptResult | types.InputRequiredResult,
"prompts/list": types.ListPromptsResult,
"resources/list": types.ListResourcesResult,
"resources/read": types.ReadResourceResult | types.InputRequiredResult,
"resources/subscribe": types.EmptyResult,
"resources/templates/list": types.ListResourceTemplatesResult,
"resources/unsubscribe": types.EmptyResult,
"roots/list": types.ListRootsResult,
# Arm order load-bearing: a single-block body satisfies both arms and
# smart-union ties resolve leftmost. Pinned by tests/types/test_methods.py.
"sampling/createMessage": types.CreateMessageResult | types.CreateMessageResultWithTools,
"server/discover": types.DiscoverResult,
"subscriptions/listen": types.EmptyResult,
"tools/call": types.CallToolResult | types.InputRequiredResult,
"tools/list": types.ListToolsResult,
}
)
"""Monolith result model (or two-arm union) per request method."""
# --- Parse functions ---
# Envelope stubs merged into bodies for surface validation (surface classes are full frames).
_REQUEST_STUB: Final[Mapping[str, Any]] = MappingProxyType({"jsonrpc": "2.0", "id": 0})
_NOTIFICATION_STUB: Final[Mapping[str, Any]] = MappingProxyType({"jsonrpc": "2.0"})
def _check_known_version(version: str) -> None:
"""Raise ValueError for unknown `version` so a typo cannot silently gate every method."""
if version not in KNOWN_PROTOCOL_VERSIONS:
raise ValueError(f"version must be a known protocol version, got {version!r}")
def _body(method: str, params: Mapping[str, Any] | None) -> dict[str, Any]:
"""Build a JSON-RPC body, omitting `params` when None."""
body: dict[str, Any] = {"method": method}
if params is not None:
body["params"] = params
return body
@cache
def _adapter(target: type[BaseModel] | UnionType) -> TypeAdapter[Any]:
return TypeAdapter(target)
_MonolithT = TypeVar("_MonolithT")
def _monolith_row(monolith: Mapping[str, _MonolithT], method: str) -> _MonolithT:
"""Look up `method` in `monolith`, raising RuntimeError on miss.
Not KeyError: the surface row already matched, so a miss is inconsistent
extension maps and must not be caught by the session's `except KeyError` gate.
"""
try:
return monolith[method]
except KeyError:
raise RuntimeError(f"inconsistent extension maps: surface defines {method!r} but monolith does not") from None
def validate_client_request(
method: str,
version: str,
params: Mapping[str, Any] | None,
*,
surface: Mapping[tuple[str, str], type[BaseModel]] = CLIENT_REQUESTS,
) -> None:
"""Validate a client request against `surface` only.
Raises:
ValueError: `version` is not a known protocol version.
KeyError: `(method, version)` is not in `surface` (the version gate).
pydantic.ValidationError: body fails surface validation.
"""
_check_known_version(version)
surface[(method, version)].model_validate({**_REQUEST_STUB, **_body(method, params)}, by_name=False)
def parse_client_request(
method: str,
version: str,
params: Mapping[str, Any] | None,
*,
surface: Mapping[tuple[str, str], type[BaseModel]] = CLIENT_REQUESTS,
monolith: Mapping[str, type[types.Request[Any, Any]]] = MONOLITH_REQUESTS,
) -> types.Request[Any, Any]:
"""Validate a client request against `surface`, then parse and return its `monolith` model.
Args:
surface: `(method, version)` to wire-type map; the version-gate lookup
and (per-schema-era) shape check run against this. Pass an extended
map to admit custom methods.
monolith: `method` to version-free model map; the returned instance is
parsed from this row. Must cover every method `surface` admits.
Raises:
ValueError: `version` is not a known protocol version.
KeyError: `(method, version)` is not in `surface` (the version gate).
pydantic.ValidationError: body fails surface or monolith validation.
RuntimeError: surface matched but `method` has no monolith row.
"""
validate_client_request(method, version, params, surface=surface)
return _monolith_row(monolith, method).model_validate(_body(method, params), by_name=False)
def parse_server_request(
method: str,
version: str,
params: Mapping[str, Any] | None,
*,
surface: Mapping[tuple[str, str], type[BaseModel]] = SERVER_REQUESTS,
monolith: Mapping[str, type[types.Request[Any, Any]]] = MONOLITH_REQUESTS,
) -> types.Request[Any, Any]:
"""Validate a server request against `surface`, then parse and return its `monolith` model.
Args:
surface: `(method, version)` to wire-type map; the version-gate lookup
and (per-schema-era) shape check run against this. Pass an extended
map to admit custom methods.
monolith: `method` to version-free model map; the returned instance is
parsed from this row. Must cover every method `surface` admits.
Raises:
ValueError: `version` is not a known protocol version.
KeyError: `(method, version)` is not in `surface` (the version gate).
pydantic.ValidationError: body fails surface or monolith validation.
RuntimeError: surface matched but `method` has no monolith row.
"""
_check_known_version(version)
surface_type = surface[(method, version)]
surface_type.model_validate({**_REQUEST_STUB, **_body(method, params)}, by_name=False)
return _monolith_row(monolith, method).model_validate(_body(method, params), by_name=False)
def validate_client_notification(
method: str,
version: str,
params: Mapping[str, Any] | None,
*,
surface: Mapping[tuple[str, str], type[BaseModel]] = CLIENT_NOTIFICATIONS,
) -> None:
"""Validate a client notification against `surface` only.
Raises:
ValueError: `version` is not a known protocol version.
KeyError: `(method, version)` is not in `surface`.
pydantic.ValidationError: body fails surface validation.
"""
_check_known_version(version)
surface[(method, version)].model_validate({**_NOTIFICATION_STUB, **_body(method, params)}, by_name=False)
def parse_client_notification(
method: str,
version: str,
params: Mapping[str, Any] | None,
*,
surface: Mapping[tuple[str, str], type[BaseModel]] = CLIENT_NOTIFICATIONS,
monolith: Mapping[str, type[types.Notification[Any, Any]]] = MONOLITH_NOTIFICATIONS,
) -> types.Notification[Any, Any]:
"""Validate a client notification against `surface`, then parse and return its `monolith` model.
Args:
surface: `(method, version)` to wire-type map; the version-gate lookup
and (per-schema-era) shape check run against this. Pass an extended
map to admit custom methods.
monolith: `method` to version-free model map; the returned instance is
parsed from this row. Must cover every method `surface` admits.
Raises:
ValueError: `version` is not a known protocol version.
KeyError: `(method, version)` is not in `surface`.
pydantic.ValidationError: body fails surface or monolith validation.
RuntimeError: surface matched but `method` has no monolith row.
"""
validate_client_notification(method, version, params, surface=surface)
return _monolith_row(monolith, method).model_validate(_body(method, params), by_name=False)
def parse_server_notification(
method: str,
version: str,
params: Mapping[str, Any] | None,
*,
surface: Mapping[tuple[str, str], type[BaseModel]] = SERVER_NOTIFICATIONS,
monolith: Mapping[str, type[types.Notification[Any, Any]]] = MONOLITH_NOTIFICATIONS,
) -> types.Notification[Any, Any]:
"""Validate a server notification against `surface`, then parse and return its `monolith` model.
Args:
surface: `(method, version)` to wire-type map; the version-gate lookup
and (per-schema-era) shape check run against this. Pass an extended
map to admit custom methods.
monolith: `method` to version-free model map; the returned instance is
parsed from this row. Must cover every method `surface` admits.
Raises:
ValueError: `version` is not a known protocol version.
KeyError: `(method, version)` is not in `surface`.
pydantic.ValidationError: body fails surface or monolith validation.
RuntimeError: surface matched but `method` has no monolith row.
"""
_check_known_version(version)
surface_type = surface[(method, version)]
surface_type.model_validate({**_NOTIFICATION_STUB, **_body(method, params)}, by_name=False)
return _monolith_row(monolith, method).model_validate(_body(method, params), by_name=False)
def serialize_server_result(
method: str,
version: str,
data: Mapping[str, Any],
*,
surface: Mapping[tuple[str, str], type[BaseModel] | UnionType] = SERVER_RESULTS,
) -> dict[str, Any]:
"""Validate `data` against `surface` and return its surface-shaped dump.
The surface model carries `extra="ignore"`, so fields not in `version`'s
schema are dropped from the returned dict.
Raises:
ValueError: `version` is not a known protocol version.
KeyError: `(method, version)` is not in `surface`.
pydantic.ValidationError: result fails surface validation.
"""
_check_known_version(version)
adapter = _adapter(surface[(method, version)])
return adapter.dump_python(
adapter.validate_python(data, by_name=False), by_alias=True, mode="json", exclude_none=True
)
def validate_server_result(
method: str,
version: str,
data: Mapping[str, Any],
*,
surface: Mapping[tuple[str, str], type[BaseModel] | UnionType] = SERVER_RESULTS,
) -> None:
"""Validate a server result against `surface` only.
Raises:
ValueError: `version` is not a known protocol version.
KeyError: `(method, version)` is not in `surface`.
pydantic.ValidationError: result fails surface validation.
"""
serialize_server_result(method, version, data, surface=surface)
def parse_server_result(
method: str,
version: str,
data: Mapping[str, Any],
*,
surface: Mapping[tuple[str, str], type[BaseModel] | UnionType] = SERVER_RESULTS,
monolith: Mapping[str, type[types.Result] | UnionType] = MONOLITH_RESULTS,
) -> types.Result:
"""Validate a server result against `surface`, then parse and return its `monolith` model.
Args:
surface: `(method, version)` to wire-type map; the version-gate lookup
and (per-schema-era) shape check run against this. Pass an extended
map to admit custom methods.
monolith: `method` to version-free model map; the returned instance is
parsed from this row. Must cover every method `surface` admits.
Raises:
ValueError: `version` is not a known protocol version.
KeyError: `(method, version)` is not in `surface`.
pydantic.ValidationError: result fails surface or monolith validation.
RuntimeError: surface matched but `method` has no monolith row.
"""
validate_server_result(method, version, data, surface=surface)
result: types.Result = _adapter(_monolith_row(monolith, method)).validate_python(data, by_name=False)
return result
def validate_client_result(
method: str,
version: str,
data: Mapping[str, Any],
*,
surface: Mapping[tuple[str, str], type[BaseModel] | UnionType] = CLIENT_RESULTS,
) -> None:
"""Validate a client result against `surface` only.
Raises:
ValueError: `version` is not a known protocol version.
KeyError: `(method, version)` is not in `surface`.
pydantic.ValidationError: result fails surface validation.
"""
_check_known_version(version)
_adapter(surface[(method, version)]).validate_python(data, by_name=False)
def parse_client_result(
method: str,
version: str,
data: Mapping[str, Any],
*,
surface: Mapping[tuple[str, str], type[BaseModel] | UnionType] = CLIENT_RESULTS,
monolith: Mapping[str, type[types.Result] | UnionType] = MONOLITH_RESULTS,
) -> types.Result:
"""Validate a client result against `surface`, then parse and return its `monolith` model.
Args:
surface: `(method, version)` to wire-type map; the version-gate lookup
and (per-schema-era) shape check run against this. Pass an extended
map to admit custom methods.
monolith: `method` to version-free model map; the returned instance is
parsed from this row. Must cover every method `surface` admits.
Raises:
ValueError: `version` is not a known protocol version.
KeyError: `(method, version)` is not in `surface`.
pydantic.ValidationError: result fails surface or monolith validation.
RuntimeError: surface matched but `method` has no monolith row.
"""
validate_client_result(method, version, data, surface=surface)
result: types.Result = _adapter(_monolith_row(monolith, method)).validate_python(data, by_name=False)
return result

View file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,62 @@
"""Protocol-version registry and comparison helpers.
Date-string protocol revisions happen to sort lexicographically, but versions
are an enumerated set, not an ordered scalar: future identifiers are not
guaranteed to be date-shaped, and unrecognized peer strings must compare
conservatively instead of accidentally (e.g. "zzz" > "2025-11-25"). All
ordering questions go through KNOWN_PROTOCOL_VERSIONS.
"""
from typing import Final
KNOWN_PROTOCOL_VERSIONS: Final[tuple[str, ...]] = (
"2024-11-05",
"2025-03-26",
"2025-06-18",
"2025-11-25",
"2026-07-28",
)
"""Every released protocol revision, oldest to newest."""
HANDSHAKE_PROTOCOL_VERSIONS: Final[tuple[str, ...]] = (
"2024-11-05",
"2025-03-26",
"2025-06-18",
"2025-11-25",
)
"""Protocol revisions reachable via the initialize handshake."""
MODERN_PROTOCOL_VERSIONS: Final[tuple[str, ...]] = ("2026-07-28",)
"""Protocol revisions that use the stateless per-request envelope."""
SUPPORTED_PROTOCOL_VERSIONS: tuple[str, ...] = (*HANDSHAKE_PROTOCOL_VERSIONS, *MODERN_PROTOCOL_VERSIONS)
"""Deprecated: prefer HANDSHAKE_PROTOCOL_VERSIONS or MODERN_PROTOCOL_VERSIONS.
Kept as the union for v1.x compatibility.
"""
LATEST_PROTOCOL_VERSION: Final[str] = KNOWN_PROTOCOL_VERSIONS[-1]
"""Newest protocol revision this SDK speaks (any era)."""
LATEST_HANDSHAKE_VERSION: Final[str] = HANDSHAKE_PROTOCOL_VERSIONS[-1]
"""Newest revision reachable via the ``initialize`` handshake; the client's offer and server's counter-offer default."""
LATEST_MODERN_VERSION: Final[str] = MODERN_PROTOCOL_VERSIONS[-1]
"""Newest per-request-envelope revision; the ``server/discover`` probe default."""
OLDEST_SUPPORTED_VERSION: Final[str] = HANDSHAKE_PROTOCOL_VERSIONS[0]
"""Oldest revision this SDK still negotiates via the ``initialize`` handshake."""
def is_version_at_least(version: str, minimum: str) -> bool:
"""Return True if `version` is a known revision at least as new as `minimum`.
Unknown `version` strings return False (treat unrecognized peers
conservatively). `minimum` must be a member of KNOWN_PROTOCOL_VERSIONS;
passing anything else is programmer error and raises ValueError.
"""
if minimum not in KNOWN_PROTOCOL_VERSIONS:
raise ValueError(f"minimum must be a known protocol version, got {minimum!r}")
if version not in KNOWN_PROTOCOL_VERSIONS:
return False
return KNOWN_PROTOCOL_VERSIONS.index(version) >= KNOWN_PROTOCOL_VERSIONS.index(minimum)

View file

@ -0,0 +1,54 @@
[project]
name = "mcp-types"
dynamic = ["version"]
description = "Model Context Protocol wire types"
readme = "README.md"
requires-python = ">=3.10"
authors = [{ name = "Model Context Protocol a Series of LF Projects, LLC." }]
maintainers = [
{ name = "David Soria Parra", email = "davidsp@anthropic.com" },
{ name = "Marcelo Trylesinski", email = "marcelotryle@gmail.com" },
{ name = "Max Isbey", email = "maxisbey@anthropic.com" },
{ name = "Felix Weinberger", email = "fweinberger@anthropic.com" },
]
keywords = ["mcp", "llm", "automation"]
license = { text = "MIT" }
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
]
dependencies = [
"pydantic>=2.12.0",
"typing-extensions>=4.13.0",
]
[project.urls]
Homepage = "https://modelcontextprotocol.io"
Documentation = "https://py.sdk.modelcontextprotocol.io/v2/"
Repository = "https://github.com/modelcontextprotocol/python-sdk"
Issues = "https://github.com/modelcontextprotocol/python-sdk/issues"
[build-system]
requires = ["hatchling", "uv-dynamic-versioning"]
build-backend = "hatchling.build"
[tool.hatch.version]
source = "uv-dynamic-versioning"
[tool.uv-dynamic-versioning]
vcs = "git"
style = "pep440"
bump = true
[tool.hatch.build.targets.sdist.force-include]
"../../LICENSE" = "LICENSE"
[tool.hatch.build.targets.wheel]
packages = ["mcp_types"]