Accept boolean sub-schemas in 2025-11-25 tool schema properties (#3354)

This commit is contained in:
Peter Alexander 2026-08-24 15:41:59 +01:00 • committed by GitHub
commit f1c40b062f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 30 additions and 2 deletions

View file

@ -55,6 +55,18 @@ SCHEMA_PATCHES: dict[str, list[tuple[str, Any, Any]]] = {
{"$ref": "#/$defs/PrimitiveSchemaDefinition"},
{},
),
# JSON Schema 2020-12 allows a boolean wherever a sub-schema is expected, and
# 2026-07-28 already leaves these free-form; accept `true`/`false` property schemas.
(
"$defs/Tool/properties/inputSchema/properties/properties/additionalProperties",
{"additionalProperties": True, "properties": {}, "type": "object"},
{"anyOf": [{"additionalProperties": True, "properties": {}, "type": "object"}, {"type": "boolean"}]},
),
(
"$defs/Tool/properties/outputSchema/properties/properties/additionalProperties",
{"additionalProperties": True, "properties": {}, "type": "object"},
{"anyOf": [{"additionalProperties": True, "properties": {}, "type": "object"}, {"type": "boolean"}]},
),
],
"2026-07-28": [
("$defs/NumberSchema/properties/default/type", "number", ["integer", "number"]),

View file

@ -1358,7 +1358,7 @@ class InputSchema(WireModel):
extra="allow",
)
schema_: Annotated[str | None, Field(alias="$schema")] = None
properties: dict[str, dict[str, Any]] | None = None
properties: dict[str, dict[str, Any] | bool] | None = None
required: list[str] | None = None
type: Literal["object"]
@ -1376,7 +1376,7 @@ class OutputSchema(WireModel):
extra="allow",
)
schema_: Annotated[str | None, Field(alias="$schema")] = None
properties: dict[str, dict[str, Any]] | None = None
properties: dict[str, dict[str, Any] | bool] | None = None
required: list[str] | None = None
type: Literal["object"]

View file

@ -474,6 +474,22 @@ def test_elicit_request_surface_accepts_loose_property_schemas():
assert isinstance(parsed, types.ElicitRequest)
def test_2025_11_25_tool_schema_surfaces_accept_boolean_sub_schemas():
"""JSON Schema 2020-12 allows `true`/`false` wherever a sub-schema is expected; real servers emit them."""
tool = {
"name": "echo",
"inputSchema": {"type": "object", "properties": {"arg": True}},
"outputSchema": {
"type": "object",
"properties": {"result": True, "hidden": False, "rows": {"type": "array", "items": True}},
"required": ["result"],
},
}
sieved = methods.serialize_server_result("tools/list", "2025-11-25", {"tools": [tool]})
assert sieved["tools"][0]["inputSchema"] == tool["inputSchema"]
assert sieved["tools"][0]["outputSchema"] == tool["outputSchema"]
def test_response_map_keys_mirror_the_request_map_keys():
assert set(methods.SERVER_RESULTS) == set(methods.CLIENT_REQUESTS)
assert set(methods.CLIENT_RESULTS) == set(methods.SERVER_REQUESTS)