3131# gets its typed `$ref` stripped by `make_server_info_opaque` below.
3232SERVER_INFO_META_PROPERTY = "io.modelcontextprotocol/serverInfo"
3333
34+ LEGACY_EXTENSIONS_FIELD = {
35+ "additionalProperties" : {"additionalProperties" : True , "properties" : {}, "type" : "object" },
36+ "description" : "Optional MCP extensions that the peer supports, keyed by extension identifier." ,
37+ "type" : "object" ,
38+ }
39+
3440# schema.ts -> schema.json renders TypeScript `number` as JSON Schema
3541# `integer` at these sites; patch the JSON before codegen so floats validate.
3642# Patched to `["integer", "number"]` (not bare `"number"`) so codegen emits
6874 {"additionalProperties" : True , "properties" : {}, "type" : "object" },
6975 {"anyOf" : [{"additionalProperties" : True , "properties" : {}, "type" : "object" }, {"type" : "boolean" }]},
7076 ),
77+ # Extensions are negotiated through `initialize` before 2026-07-28 too (e.g. MCP Apps);
78+ # carry the 2026-07-28 field so the result sieve doesn't drop a server's acceptance.
79+ ("$defs/ClientCapabilities/properties/extensions" , None , LEGACY_EXTENSIONS_FIELD ),
80+ ("$defs/ServerCapabilities/properties/extensions" , None , LEGACY_EXTENSIONS_FIELD ),
7181 ],
7282 "2026-07-28" : [
7383 ("$defs/NumberSchema/properties/default/type" , "number" , ["integer" , "number" ]),
@@ -149,6 +159,8 @@ def load_pinned() -> list[dict[str, str]]:
149159def patch_schema (schema : dict [str , Any ], patches : list [tuple [str , Any , Any ]]) -> None :
150160 """Apply `(path, old, new)` JSON-pointer-ish patches in place, asserting the old value.
151161
162+ An `old` of `None` asserts the key is absent, so a patch can add a property.
163+
152164 Path segments use JSON-pointer escaping (`~1` for `/`, `~0` for `~`) so keys
153165 that themselves contain a slash (the reserved `io.modelcontextprotocol/*`
154166 `_meta` keys) are addressable.
@@ -158,8 +170,8 @@ def patch_schema(schema: dict[str, Any], patches: list[tuple[str, Any, Any]]) ->
158170 node : Any = schema
159171 for part in parts :
160172 node = node [int (part ) if part .isdigit () else part ]
161- if node [ leaf ] != old :
162- raise SystemExit (f"schema patch { path } : expected { old !r} , found { node [ leaf ] !r} " )
173+ if node . get ( leaf ) != old :
174+ raise SystemExit (f"schema patch { path } : expected { old !r} , found { node . get ( leaf ) !r} " )
163175 node [leaf ] = new
164176
165177
0 commit comments