Skip to content

Commit da96a6f

Browse files
Merge branch 'modelcontextprotocol:main' into issue-3683-file-system-support
2 parents 9c75fd6 + 77001c9 commit da96a6f

10 files changed

Lines changed: 367 additions & 912 deletions

File tree

‎docs/client/index.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ Everything else on this page is identical across all four. Headers, subprocesses
4242
Four read-only properties, populated the moment you enter the block:
4343

4444
* `client.server_info`: the server's identity, or `None` for a 2026-era server that does not report one (python-sdk servers do by default). `server_info.name` here is `"Bookshop"`, `server_info.version` is whatever the server reports.
45-
* `client.server_capabilities`: what the server can do (`tools`, `resources`, `prompts`, `completions`, ...). A capability the server doesn't have is `None`.
45+
* `client.server_capabilities`: what the server can do (`tools`, `resources`, `prompts`, `completions`, ...). A capability the server doesn't have is `None`. Capabilities the SDK doesn't model, such as MCP Events' `events`, are in `client.server_capabilities.model_extra`.
4646
* `client.protocol_version`: the protocol version the two sides agreed on. Here it is `"2026-07-28"`.
4747
* `client.instructions`: the server's `instructions=` string, or `None` if it didn't set one.
4848

‎docs/migration.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,8 @@ params = CallToolRequestParams(
365365

366366
If you relied on extra fields round-tripping through MCP types, move that data into `_meta`.
367367

368+
`ClientCapabilities` and `ServerCapabilities` are exceptions: the spec defines them as an open set, so unknown top-level keys are kept in `model_extra` and sent on the wire.
369+
368370
### Resource URI type changed from `AnyUrl` to `str`
369371

370372
The `uri` field on resource-related types now uses `str` instead of Pydantic's `AnyUrl`. This aligns with the [MCP specification schema](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/schema/2025-11-25/schema.ts) which defines URIs as plain strings (`uri: string`) without strict URL validation. This change allows relative paths like `users/me` that were previously rejected.
@@ -2653,7 +2655,7 @@ Validation runs when the result is serialized onto the wire, not when the model
26532655

26542656
### Client validates inbound traffic against the protocol schema
26552657

2656-
`ClientSession` now validates server requests, notifications, and results against the negotiated protocol version's schema before parsing them into `mcp.types` models. Spec-invalid server output that the previous monolith parse tolerated may now raise `pydantic.ValidationError` from `list_tools()`, `call_tool()`, and similar calls. `_meta` remains the sanctioned place for result extras (and `experimental` for capability extras).
2658+
`ClientSession` now validates server requests, notifications, and results against the negotiated protocol version's schema before parsing them into `mcp.types` models. Spec-invalid server output that the previous monolith parse tolerated may now raise `pydantic.ValidationError` from `list_tools()`, `call_tool()`, and similar calls. `_meta` remains the sanctioned place for result extras. Capabilities are an open set, so unknown capability keys are kept.
26572659

26582660
### Unknown request methods now return `-32601` (Method not found)
26592661

‎scripts/gen_surface_types.py‎

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,24 @@
106106
}
107107

108108
# Classes the spec defines as open key-value bags: `_meta` content, the
109-
# JSON-Schema-document fields on `Tool`, and the schemas with explicit
110-
# `additionalProperties: {}`. These keep `extra="allow"` so the sieve preserves
111-
# arbitrary keys; every other class ignores extras. Per-version because codegen
112-
# reuses class names across versions for unrelated schemas (e.g. `Data`).
109+
# JSON-Schema-document fields on `Tool`, the capability objects (documented as
110+
# "not a closed set"), and the schemas with explicit `additionalProperties: {}`.
111+
# These keep `extra="allow"` so the sieve preserves arbitrary keys; every other
112+
# class ignores extras. Per-version because codegen reuses class names across
113+
# versions for unrelated schemas (e.g. `Data`).
113114
OPEN_CLASSES: dict[str, frozenset[str]] = {
114-
"2025-11-25": frozenset({"Meta", "InputSchema", "OutputSchema", "Result", "GetTaskPayloadResult", "Data"}),
115+
"2025-11-25": frozenset(
116+
{
117+
"Meta",
118+
"InputSchema",
119+
"OutputSchema",
120+
"Result",
121+
"GetTaskPayloadResult",
122+
"Data",
123+
"ClientCapabilities",
124+
"ServerCapabilities",
125+
}
126+
),
115127
"2026-07-28": frozenset(
116128
{
117129
"MetaObject",
@@ -122,6 +134,8 @@
122134
"InputSchema",
123135
"OutputSchema",
124136
"Result",
137+
"ClientCapabilities",
138+
"ServerCapabilities",
125139
}
126140
),
127141
}
@@ -236,7 +250,7 @@ def patch(match: re.Match[str]) -> str:
236250
return match.group(0).replace('extra="ignore"', 'extra="allow"')
237251

238252
source = re.sub(
239-
r'^class (\w+)\(WireModel\):\n(?: {4}.*\n|\n)*? {4}model_config = ConfigDict\(\n {8}extra="ignore",\n {4}\)\n',
253+
r'^class (\w+)\(WireModel\):\n(?: {4}.*\n|\n)*? {4}model_config = ConfigDict\(extra="ignore"\)\n',
240254
patch,
241255
source,
242256
flags=re.MULTILINE,
@@ -296,6 +310,9 @@ def build(entry: dict[str, str]) -> str:
296310
# them to full URLs so they resolve from the rendered API docs and pass the
297311
# strict mkdocs link validation.
298312
source = source.replace("](/", "](https://modelcontextprotocol.io/")
313+
source = re.sub(
314+
r'model_config = ConfigDict\(\n\s+(extra="ignore"),\n\s+\)', r"model_config = ConfigDict(\1)", source
315+
)
299316
source = allow_open_class_extras(source, OPEN_CLASSES[version])
300317
if epilogue := EPILOGUES.get(version, ""):
301318
# Resolve aliases before rebuilding models with forward references.

‎src/mcp-types/mcp_types/_types.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,8 @@ class ClientCapabilities(MCPModel):
393393
`initialize` through 2025-11-25; per-request in `_meta` on 2026-07-28.
394394
"""
395395

396+
model_config = ConfigDict(extra="allow")
397+
396398
experimental: dict[str, dict[str, Any]] | None = None
397399
"""Experimental, non-standard capabilities that the client supports."""
398400
sampling: SamplingCapability | None = None
@@ -485,6 +487,8 @@ class ServerTasksCapability(MCPModel):
485487
class ServerCapabilities(MCPModel):
486488
"""Capabilities that a server may support. Not a closed set."""
487489

490+
model_config = ConfigDict(extra="allow")
491+
488492
experimental: dict[str, dict[str, Any]] | None = None
489493
"""Experimental, non-standard capabilities that the server supports."""
490494

0 commit comments

Comments
 (0)