Repository navigation
fix(server): validate non-object outputSchema roots instead of crashing #3161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Devt7
wants to merge
1
commit into
modelcontextprotocol:v1.x
Choose a base branch
from
Devt7:fix/output-schema-union-roots
base: v1.x
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| --- | ||
| '@modelcontextprotocol/sdk': patch | ||
| --- | ||
|
|
||
| Fix the `tools/call` crash for non-object `outputSchema` roots (`.optional()`, `.nullable()`, `.nullish()`, `z.union(...)`): output validation now parses the schema directly when it cannot be normalized to an object, mirroring the input-validation path. `tools/list` still cannot | ||
| advertise such schemas (the wire schema requires `type: "object"` at the root, per the MCP specification), but registration now warns about the omission instead of dropping it silently. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| /** | ||
| * Registration-time warning for non-object output schemas. | ||
| * | ||
| * The MCP specification requires `Tool.outputSchema` to be an object schema | ||
| * (type: "object" at its root), so a non-object root (union, optional, …) cannot be | ||
| * serialized into `tools/list` — clients would never see it and would not validate | ||
| * the tool's output. `tools/call` still validates against the schema itself. This | ||
| * warning makes the listing omission visible instead of silent (#1308). | ||
| */ | ||
|
|
||
| export function issueNonObjectOutputSchemaWarning(name: string): void { | ||
| console.warn(`Tool outputSchema warning for "${name}":`); | ||
| console.warn( | ||
| ' - The outputSchema is not an object schema, so tools/list cannot advertise it (the MCP specification requires type "object" at the root).' | ||
| ); | ||
| console.warn(" - tools/call still validates results against it, but clients will not validate this tool's output."); | ||
| console.warn('Consider wrapping the schema in z.object(...) — e.g. merging an error envelope in as an optional `error` property.'); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the
!result.structuredContentcheck above also take this fallback into account? With an.optional()or.nullish()root, a tool that returns onlycontentstill getshas an output schema but no structured content was providedbefore this parse runs (I tried a quick local test at this commit with both roots), so the optional part of the schema never applies. If that's intended, since the spec expects structured content whenever an output schema is set, it might be worth a sentence in the changeset so people don't expect.optional()to makestructuredContentoptional. Otherwise a case where the handler omitsstructuredContentcould go into the new test.