Repository navigation
Description
Preamble
Title: Support full JSON Schema 2020-12
Co-author: John McBride - @jpmcb
Co-author: Ola Hungerford - @olaservo (adopted from #655 per #881 (comment))
Status: proposal
PR: #881
Abstract
There's a major discrepancy with how 2025-06-18 handles structuredContent in relation to outputSchema being defined as JSON Schema.
Because structuredContent must be an object, the types that can be returned by servers and validated by clients (like type: array which is fully supported by JSON Schema but throws errors in Inspector, the Typescript-SDK, etc) is dramatically narrow.
Further, which draft of JSON Schema clients and servers use is not well defined leading to general drift among client, SDK, and server implementations. For example, JSON Schema specs in one client that uses JSON Schema draft-07 will be very different from another that uses 2020-12.
Related:
outputSchemadoes not fully support JSON Schema inspector#552- Tool
inputSchemaandoutputSchemado not support JSON Schema typescript-sdk#685 - Support JSON Schema
allOf,oneOf, etc. inspector#496
This SEP loosens JSON schema usage across clients and servers as well as defines using JSON Schema 2020-12
Motivation
In 5.1 Data Types: Tool, the spec states:
outputSchema: Optional JSON Schema defining expected output structure
JSON Schema may be of type object, array, string, null, etc. etc. If it's valid JSON, then JSON Schema can validate it.
But the spec then goes on, in 5.2.6 Structured Content, to state:
Structured content is returned as a JSON object in the
structuredContentfield of a result.
This represents a dramatic discrepency and severly limits what type of content can be returned by a server and validated in the structured content.
Consider the following valid JSON Schema:
{
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "A unique UUID"
}
},
"required": ["id"],
"additionalProperties": false
}
}which defines an array of objects where the objects must have an id property. This is pretty typical, especially in "list" type of operations.
Now, suppose a server responds with the following JSON as structured content:
[
{ "id": "abc123" },
{ "id": "xyz987" }
]The spec would consider this structured content invalid and non-verifiable by the output schema.
Originally, the MCP specification didn't explicitly state which JSON Schema version to use for tool inputSchema/outputSchema and elicitation requestedSchema, causing compatibility issues between implementations. Different clients and servers assume different versions, leading to validation failures and runtime errors. See: https://github.com/orgs/modelcontextprotocol/discussions/366 (discussion includes links to related issues)
(original context before merged with this SEP: #655)
Specification
- Clarifies JSON Schema dialect usage for embedded schemas within MCP messages by establishing
2020-12as the default dialect and allowing explicit dialect declaration via the$schemafield. - Loosens
inputSchemato be an object withtype: objectand any additional property to support JSON schema Draft2020-12and more powerful validation compositions (likeanyOf,oneOf, etc.) - Loosens
outputSchemato fully support JSON Schema2020-12since MCP servers may return any valid JSON.- Loosens
structuredContentto support any JSON validated byoutputSchema's JSON Schema.
- Loosens
PR: #881
Backward Compatibility
No breaking changes.
Existing schemas without $schema will default to 2020-12. Servers can optionally add $schema to use other dialects.
Object schemas will continue to work as expected while the loosened specification can accept other valid JSON schema (like arrays of objects, etc.)
Rationale
The expectation is that any 2020-12 JSON Schema should be valid for fields that expect JSON schema. This includes outputSchema and structuredContent to be authentically validated by outputSchema, not just expected to always be an object: this is far too strict and narrows how tools can respond in ways that backends may not conform to. Further, 2020-12 has been widely adopted by the industry as the current standard but servers can define the schema they expect via the $schema metadata field.
Reference Implementation
TODO
Security Implications
There are no security implications.
Activity
jpmcb commentedon Jun 24, 2025
Related discussion in the original RFC I'd like to surface: #371 (comment)
In my opinion, keeping an
objecttop level primitive opinion in the specification makes for a really challenging end-developer experience and will narrow the capabilities of downstream clients: are we to expect that clients can't use generic JSON Schema libraries and, instead, have to stick with a custom solution that expectsobjectsthroughout?bhosmer-ant commentedon Jun 27, 2025
@jpmcb Hi John - not sure what you mean by "can't use generic JSON Schema libraries", the usual ones should work fine, this just constrains what gets fed through them. The motivation for the object restriction was to observe what seems to be a convention on the part of many libraries and frameworks in this space (that transferred data will always be objects). The extra burden - tools wanting to return non-object data need to wrap it in an object - seems pretty minor compared to being in a position where an intake pipeline would need to be customized to accept non-object data.
That said, if you're thinking of concrete examples where this will cause real pain of a kind we hadn't anticipated, can you elaborate?
jpmcb commentedon Jun 29, 2025
Arrays of objects are probably the most likely use case.
Let's take some weather data I've been working with that gets returned by an API in a MCP server as an example. The idea is that this is the aggregate over a number of hours of weather forecasts.
Say I want to feed back this array of data to an MCP client as a structured array of objects:
This is clean, easy to understand, and conforms to the API usage that the MCP server has.
I can't do that out of the box if it's forced to be an object.
Wrapping it in an object seems like an unnecessary conformity with 1 key in the object:
resultsis basically meaningless since it could just as easily be destructured to a single array of objects. Good API design would dictate that we remove `results and not have an unnecessary top level object.You can find this all over the place:
Why the restriction? It seems like an unnecessary piece of abstraction when JSON schema already supports valid JSON. My point being,
outputSchemacannot really be "JSON schema" if it doesn't even support arrays.This overall leads to poor server developer experience because I can't take advantage of the full breadth and depth of
outputSchemabeing JSON schema becausestructuredContentis restricted to an object.bhosmer-ant commentedon Jul 3, 2025
@jpmcb fair point about API endpoints that return lists being easy to find. Since the main motivation for the restriction was reducing client burden, I think it's worth taking the temperature of client implementors w.r.t. how well-grounded this consideration is (started a thread about this on Discord). And yeah, definitely worth considering relaxing the restriction if it turns out not to be useful from their POV.
dsp-ant commentedon Jul 15, 2025
Thanks for bringing this up. I think it's a reasonable request and @bhosmer-ant appraoch to asking client implementors seems worth it. @jpmcb would you be up to creating a SEP (you can just change this issue with the more formal template).
jpmcb commentedon Jul 15, 2025
@dsp-ant - I've already cut an RFC here: #881 before the SEP process was in place.
I can go back and transform it into a SEP if you'd like but this RFC is ready to go in.
[-]`2025-06-18` Discrepancy: `structuredContent` does not support full `outputSchema` JSON Schema[/-][+]Support full JSON Schema `2020-12`[/+]fix: calculator example/test return type
fix: calculator example/test return type
JMLX42 commentedon Aug 25, 2025
Implementor here. I'm the developer of rmcp-openapi, which uses the
rmcpRust crate (the official Rust MCP SDK) to create an MCP <=> OpenAPI bridge.To workaround the discrepancies with what the MCP schema expects, I had to implement the following quirks:
To make things simpler for implementors, IMHO the best solution is to use what OpenAPI does to leverage the existing ecosystem. Which is
2020-12based on the OpenAPI specification:jpmcb commentedon Sep 9, 2025
Good feedback @JMLX42 - I agree, aligning to
2020-12is critical for clarity on both the server and client side.cc @dsp-ant @cliffhall - what's holding this up? This SEP has yet to be assigned a sponsor and has been waiting for nearly 3 months (this even pre-dates the SEP process!)
He-Pin commentedon Sep 9, 2025
I think the old one is better.
Then the input schema should be any JSON type too, I think an object is better for future extension, you can't add a field to a boolean type.
cliffhall commentedon Sep 9, 2025
Hi @jpmcb I think this message reveals the way forward. We need some feedback from client developers about this. I suggest starting a discussion thread about it in the client-implementors channel in the MCP Contributors Discord.
41 remaining items
handrews commentedon Mar 6, 2026
@JMLX42 yes you'd think that, but someone probably needs to connect the dots for them. We at the OpenAPI Foundation have been struggling to get VSCode to update for years, and when I was involved with the JSON Schema Org, we had been struggling to get them to do anything to update past draft-07 as well.
Having someone who carries weight in the MCP world get in touch with them might finally get them moving. We (OpenAPI) are also hoping that the positive press on how much the OpenAPI Specification 3.2 (which depends on 2020-12) helps LLM use cases, including MCP servers, will motivate them, but we don't have as much buzz as MCP (to put it mildly).
localden commentedon Mar 11, 2026
@handrews @JMLX42 we have a pretty good relationship with the Microsoft folks working on VS Code, so we'll work with them and other clients help update things.
@olaservo - do you happen to have the new SEP PR we can take a peek at? Assuming it's #2106?
royalpinto333 commentedon Mar 22, 2026
+1 for this. We have a tool that returns two different response shapes depending on the mode,
which requires
anyOfto express accurately in the output schema. Without it we're forced toeither skip the output schema entirely or merge both shapes into one bloated nullable schema,
which is misleading for the LLM. Would love to see
anyOf/oneOfsupport inMcpSchema.JsonSchema.sep-automation-bot commentedon Mar 30, 2026
Maintainer Activity Check
Hi @olaservo!
You're assigned to this SEP but there hasn't been any activity from you in 18 days.
Please provide an update on:
If you're no longer able to sponsor this SEP, please let us know so we can find another maintainer.
This is an automated message from the SEP lifecycle bot.
sep-automation-bot commentedon Apr 13, 2026
Maintainer Activity Check
Hi @olaservo!
You're assigned to this SEP but there hasn't been any activity from you in 14 days.
Please provide an update on:
If you're no longer able to sponsor this SEP, please let us know so we can find another maintainer.
This is an automated message from the SEP lifecycle bot.
sep-automation-bot commentedon Apr 27, 2026
Maintainer Activity Check
Hi @olaservo!
You're assigned to this SEP but there hasn't been any activity from you in 14 days.
Please provide an update on:
If you're no longer able to sponsor this SEP, please let us know so we can find another maintainer.
This is an automated message from the SEP lifecycle bot.
sep-automation-bot commentedon May 11, 2026
Maintainer Activity Check
Hi @olaservo!
You're assigned to this SEP but there hasn't been any activity from you in 14 days.
Please provide an update on:
If you're no longer able to sponsor this SEP, please let us know so we can find another maintainer.
This is an automated message from the SEP lifecycle bot.
SEP-2106: Tools `inputSchema` & `outputSchema` Conform to JSON Schema…
sep-automation-bot commentedon May 25, 2026
Maintainer Activity Check
Hi @olaservo!
You're assigned to this SEP but there hasn't been any activity from you in 14 days.
Please provide an update on:
If you're no longer able to sponsor this SEP, please let us know so we can find another maintainer.
This is an automated message from the SEP lifecycle bot.
sep-automation-bot commentedon Jun 8, 2026
Maintainer Activity Check
Hi @olaservo!
You're assigned to this SEP but there hasn't been any activity from you in 14 days.
Please provide an update on:
If you're no longer able to sponsor this SEP, please let us know so we can find another maintainer.
This is an automated message from the SEP lifecycle bot.
sep-automation-bot commentedon Jun 22, 2026
Maintainer Activity Check
Hi @olaservo!
You're assigned to this SEP but there hasn't been any activity from you in 14 days.
Please provide an update on:
If you're no longer able to sponsor this SEP, please let us know so we can find another maintainer.
This is an automated message from the SEP lifecycle bot.
link #115926 Upgrade MCP SDK fork to upstream v0.18.2 for streamable …
localden commentedon Jun 26, 2026
#1613 and #2106 should now cover this. Thank you again for the contribution, @jpmcb!