fix(client): validate JSON-null structuredContent against outputSchema - #3346
Conversation
SEP-2106 allows structuredContent to be JSON null. The client presence check used `is None`, which also matches an omitted field, so a tool that advertised a null-capable outputSchema and returned null was rejected as missing structured content. Use model_fields_set so omitted still fails closed, explicit null is schema-validated, and falsy JSON values (0, false, "") stay checked. Fixes modelcontextprotocol#3345
|
This PR has been closed automatically. It's still a draft, but we close those early so you don't put in more time only to have it closed the moment you mark it ready. This repo only keeps pull requests open when they come from a maintainer, or from a contributor a maintainer has assigned to the linked issue, and you aren't currently assigned to #3345. If a maintainer assigns you to #3345, this PR reopens on its own and there's nothing more you need to do here. Assignment is a maintainer call based on capacity; comments that only ask to be assigned don't factor in. What does help is engaging on the issue itself by confirming the repro, explaining why it matters for your use case, or describing the approach you'd take. You're welcome to keep pushing commits here (just avoid force-pushing, since GitHub can't reopen a rewritten branch), but that on its own won't get the PR reviewed or the issue assigned, and realistically most auto-closed PRs stay closed. There's no need to open a new PR either way. CONTRIBUTING.md has the full reasoning, but in short:
Maintainers: reopen, remove |
Fixes #3345
SEP-2106 allows
structuredContentto be JSON null.validate_tool_resulttreatedstructured_content is Noneas a missing field, so a tool that advertised a null-capableoutputSchemaand returned"structuredContent": nullnever reached jsonschema validation.Pydantic stores both omitted and explicit JSON null as
None. This usesmodel_fields_setas the presence check, matching the TypeScript SDK's=== undefined(not null / not falsy) check.Motivation and Context
Declared
outputSchemawas not validated against a legal JSON-nullstructuredContentvalue. Clients rejected a conforming result as missing instead of schema-checking it. OmittedstructuredContentstill fails closed.How Has This Been Tested?
uv run --frozen pytest tests/client/test_session_promotions.py tests/interaction/lowlevel/test_tools.py::test_declared_output_schema_with_no_structured_content_is_rejected_by_the_client tests/interaction/lowlevel/test_tools.py::test_call_tool_structured_content_violating_output_schema_is_rejected_by_the_client -q24 passed, including new cases for:
{"type": "null"}(accept)0/falseBreaking Changes
None. Omitted
structuredContentstill raises the same RuntimeError. Only an explicit JSON null is now schema-validated.Types of changes
Checklist
help wanted, or I'm a maintainer)Additional context
Not assigned on #3345. Opening as a draft per the small-fix-with-tests shape; CONTRIBUTING may auto-close until a maintainer assigns the issue. Reporter of #3345.
AI assistance: researched and implemented with Grok 4.6; I reviewed the spec text, the TypeScript v2 presence check, Pydantic
model_fields_seton parsedCallToolResult, and the new tests.No protocol change. No new schema surface. Does not duplicate the existing jsonschema check; it only stops the presence check from swallowing JSON null before that check runs.