Skip to content

Conversation

@jpmcb
Copy link
Contributor

@jpmcb jpmcb commented Jun 30, 2025

Motivation and Context

TLDR:

  • Loosens inputSchema to be an object with type: object and any additional property to support JSON schema Draft 2020-12 and more powerful validation compositions (like anyOf, oneOf, etc.)
  • Loosens outputSchema to fully support JSON Schema 2020-12 since MCP servers may return any valid JSON.
    • Loosens structuredContent to support any JSON validated by outputSchema's JSON Schema.

Fixes: #834

Related to and upstream fix for:


This RFC loosens the restrictions on tool inputSchema and outputSchema in order to better fully support JSON Schema.

The specification currently states:

outputSchema: Optional JSON Schema defining expected output structure
inputSchema: JSON Schema defining expected parameters

which is not entierly true:

inputSchema

inputSchema is currently expected to be JSON Schema of type: object. This mostly makes sense since tool calls are expected to be well defined object key / values. This has been more accurately defined in the specification. Any additional property is now also acceptable to allow for much more powerful JSON Schema compositions (like with anyOf, oneOf, etc.)

outputSchema & structuredContent

outputSchema is also currently expected to be JSON schema of type: object which can cause some headaches for MCP servers that return other forms of JSON like arrays of objects:

[
  { "id": "abc123", "property": "hello" },
  { "id": "xyz987", "property": "world" }
]

In order to accommodate results that may be structured as an array (or really anything that can be validated by JSON Schema), outputSchema now is defined simply as an object.

This impacts structuredContent which was previously restricted to be an object: but, if outputSchema can validate any JSON, then structuredContent must be able to also be any valid JSON. Thus, it has been loosened to unknown.

How Has This Been Tested?

Tested in a weather application I'm building that returns a sorted array of weather hourly objects (see comment: #834 (comment))

Breaking Changes

No updates required. All existing type: object based schemas still work with JSON Schema. Not sure if this belongs in draft or would be better suited for 2025-06-18: I leave that to the maintainers.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Copy link
Member

@sambhav sambhav left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Mihailoff
Copy link

Mihailoff commented Jul 9, 2025

+1

FastMCP just works, with MCP SDK I had a number of issues with schemas because of the confusing (input/output)Schema signature.

server.addTool({
  name: "add",
  description: "Add two numbers",
  parameters: z.object({
    a: z.number(),
    b: z.number(),
  }),
  execute: async (args) => {
    return String(args.a + args.b);
  },
})

Also, https://modelcontextprotocol.io/docs/concepts/tools provide this example:

// Define available tools
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [{
      name: "calculate_sum",
      description: "Add two numbers together",
      inputSchema: {
        type: "object",
        properties: {
          a: { type: "number" },
          b: { type: "number" }
        },
        required: ["a", "b"]
      }
    }]
  };
});

And then after reading spec you do the same and ... it doesn't work. Very confusing.

@olaservo
Copy link
Member

Hi @jpmcb, it looks like there is some overlap with my older PR here which addresses being more explicit about the JSON Schema dialect: #655

If we're replacing that PR with a new SEP based on this PR, should we also add explicit dialect support by using the $schema field?

@jpmcb
Copy link
Contributor Author

jpmcb commented Jul 17, 2025

Thanks for the reference @olaservo - yes, the overlap makes a ton of sense. I can create a new one that is based on the new SEP and I can include your changes and add you as a co-author on the commit?

@jpmcb jpmcb force-pushed the output-schema-fix branch from 6164798 to ea05ada Compare July 21, 2025 21:19
@jpmcb jpmcb requested a review from a team July 21, 2025 21:19
@jpmcb
Copy link
Contributor Author

jpmcb commented Jul 21, 2025

cc @olaservo - I brought in 29b8528 from your PR and updated #834 to reflect a SEP. I'll get this ironed out and ready for review / sponsorship.

@xlogix
Copy link

xlogix commented Sep 8, 2025

Hi folks, any chance that this can be merged?

@dsp-ant dsp-ant changed the title RFC: Tools inputSchema & outputSchema conform to JSON Schema 2020-12 SEP-834: Tools inputSchema & outputSchema conform to JSON Schema 2020-12 Sep 12, 2025
@jpmcb jpmcb force-pushed the output-schema-fix branch 3 times, most recently from 27b2414 to d9cdb6a Compare September 16, 2025 21:06
@jpmcb
Copy link
Contributor Author

jpmcb commented Sep 16, 2025

  • Squashed to 1 commit with Co-authored-by @olaservo
  • Resolved merge conflict
  • Addressed and applied feedback from @dsp-ant and @jonathanhefner
  • Added another example to the valid permissible JSON Schemas under ### Schema Validation

Not certain why the broken link checker in schema.mdx is failing: I re-generated the schema via npm run generate:schema but still get this broken link:

error Syntax error - Unable to parse specification/draft/schema.mdx - 264:270-264:271: Unexpected closing slash `/` in tag,
     expected an open tag first

which seems to be caused by a </section> that wasn't opened on line 264

jonathanhefner added a commit to jonathanhefner/modelcontextprotocol that referenced this pull request Sep 16, 2025
Mintlify's Markdown parser treats dollar signs as special characters in
some cases.  The exact cause is not clear, but it might be related to
MDX's [LaTeX support](https://mdxjs.com/guides/math/).

An example of this behavior can be seen in the build failure for
[modelcontextprotocol#881][], in which `npm run check:docs:links` failed to parse
`schema.mdx` due to newly introduced `$schema` properties.

This commit modifies the `schema.mdx` generator to HTML encode dollar
signs, thus preventing such parse errors.

[modelcontextprotocol#881]: modelcontextprotocol#881
@jonathanhefner
Copy link
Member

Not certain why the broken link checker in schema.mdx is failing: I re-generated the schema via npm run generate:schema but still get this broken link:

error Syntax error - Unable to parse specification/draft/schema.mdx - 264:270-264:271: Unexpected closing slash `/` in tag,
     expected an open tag first

which seems to be caused by a </section> that wasn't opened on line 264

I believe that is due to the new $schema properties, though I'm 100% sure of the root cause. I've submitted #1485 which works around the issue.

@findleyr
Copy link
Contributor

+1 this LGTM, and I think the clarity it adds will help mitigate confusion and inconsistency across SDKs. Thanks!

Do we expect this will land for the October spec?

dsp-ant pushed a commit that referenced this pull request Sep 19, 2025
Mintlify's Markdown parser treats dollar signs as special characters in
some cases.  The exact cause is not clear, but it might be related to
MDX's [LaTeX support](https://mdxjs.com/guides/math/).

An example of this behavior can be seen in the build failure for
[#881][], in which `npm run check:docs:links` failed to parse
`schema.mdx` due to newly introduced `$schema` properties.

This commit modifies the `schema.mdx` generator to HTML encode dollar
signs, thus preventing such parse errors.

[#881]: #881
@jpmcb
Copy link
Contributor Author

jpmcb commented Sep 25, 2025

Thanks for the feedback @findleyr - current plan is to solicite more feedback from client and SDK implementers since a few of the core maintainers had concerns about the backwards compatibility of loosening the schema object requirement.

#834 (comment)

But, I 100% agree: to not adopt this would continue to cause confusion across clients, SDKs, and serves leading to drifts in how different implementers work.

* General guidance on using JSON Schema 2020-12
* Tools `inputSchema` conforms to JSON Schema 2020-12 as "type: object"
* Tools `outputSchema` conforms to JSON Schema 2020-12
* Tools `structuredContent` can be any valid JSON (as it coforms to
  potentially provided `outputSchema`)
* Elicitation `requestedSchema` aligns with JSON Schema 2020-12

Co-authored-by: olaservo <[email protected]>
Signed-off-by: John McBride <[email protected]>
@logseq-cldwalker
Copy link

Adding another vote for conforming to json schema and allowing for a fix for modelcontextprotocol/typescript-sdk#685 . I just had to work the inputSchema limitation of not being able to pass an array of objects. Hopefully this PR gets reviewed soon as it would enable a number of workflows

@errodrigues
Copy link

I 2nd that

@findleyr
Copy link
Contributor

findleyr commented Sep 25, 2025

@logseq-cldwalker are you saying you want to be able to accept array values as tool arguments? This proposal doesn't change inputSchema to be anything other than an "object", and I agree that doing so would probably cause issues for SDKs.

Frankly, I don't necessarily see the need to relax the requirement that outputSchema is an "object". If that is a point of concern from maintainers, perhaps we could move it to a separate proposal. Formalizing on 2020-12 is (in my opinion) the most important aspect of this SEP.

@jpmcb
Copy link
Contributor Author

jpmcb commented Sep 30, 2025

are you saying you want to be able to accept array values as tool arguments?

Yes.

This proposes conforming to JSON Schema 2020-12 which also, by proxy, requires us to loosen the inputSchema and outputSchema fields to be valid JSON schema 2020-12.

In my eyes, you cannot have one without the other.

The new spec would be:

inputSchema: {
  $schema?: string;
  [key: string]: any;
};

which conforms to JSON schema 2020-12 and allows for inputs like arrays of objects (a very common use case):

{
  "$schema": "http://json-schema.org/2020-12/schema#",
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "id": {
        "type": "number"
      }
    },
    "required": ["id"]
  }
}

Forcing type: object severely limits the capabilities of enabling calling tools with more complex arguments.

@jpmcb
Copy link
Contributor Author

jpmcb commented Oct 29, 2025

MCP seems to be repeating history with what OpenAPI did: for years, they also only supported a subset of JSON schema, much to the frustration of the community. They even faced similar pain where they couldn't support arrays of objects:

Eventually, with OpenAPI 3.1 in 2021, they transitioned to fully supporting JSON schema:

The mismatch between OpenAPI JSON Schema-like structures and JSON Schema itself has long been a problem for users and implementers. Full alignment of OpenAPI 3.1.0 with JSON Schema draft 2020-12 will not only save users much pain, but also ushers in a new standardised approach to schema extensions

https://www.openapis.org/blog/2021/02/18/openapi-specification-3-1-released

I would strongly encourage the maintainers to act quickly and fully adopt JSON schema 2020-12 before adoption and misalignment becomes a bigger problem.

@errodrigues
Copy link

I 100% second that suggestion!

@olaservo
Copy link
Member

Quick update: I wanted to help move this forward this round, but since this requires breaking modifications we wanted to ensure that we have a way to tag in enough client representation as part of the discussion. Despite adding more folks to the Client Implementers group and tagging people in Discord, we still hadn't seen enough engagement there to help validate breaking changes on the timeline needed for spec release.

Given this constraint, I've asked the maintainer group to help establish a better engagement model so we can actually have those conversations based on client maintainer feedback instead of general wariness of breaking changes. I think we can give this proposal a much fairer chance in the next round if we can create a better forum for that over the next couple months.

@mikekistler
Copy link
Contributor

@olaservo How is this different from SEP-1613?

And I don't see SEP-834 in the list of accepted SEPs for the 2025-11-25 spec version, so is this something we (SDK maintainers) need to think about right now?

@olaservo
Copy link
Member

@mikekistler SEP-1613 is making the target default JSON schema dialect explicit, and SEP-834 extends that to remove the limitations on schemas which only support a subset of JSON Schema. SEP-834 isn't currently planned for the next spec release.

@domdomegg domdomegg requested a review from a team as a code owner November 25, 2025 19:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SEP-834 Support full JSON Schema 2020-12