Skip to content

fix(core): accept MCP tools whose output schema is not a root object - #58224

Merged
rekram1-node merged 1 commit into
devfrom
mcp-output-schema
Oct 22, 2026
Merged

rekram1-node merged 1 commit into
devfrom
mcp-output-schema

Conversation

@rekram1-node

@rekram1-node rekram1-node commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #57643

Problem

If one tool in an MCP server's tools/list has an outputSchema with a top-level anyOf/oneOf and no "type": "object", the whole server fails to connect and none of its tools load:

MCP server failed: <server_name>
Invalid result for tools/list:
  path: ["tools", 3, "outputSchema", "type"]
  message: "Invalid input: expected \"object\""

The MCP client SDK validates legacy (pre-2026-07-28) tools/list results with a tool schema whose outputSchema must be type: "object". 2025-06-18 and 2025-11-25 did declare that restriction, but 2026-07-28 allows any JSON Schema 2020-12 here, and real servers (cqs, 10 of 31 tools) already use it. The SDK rejects the whole list over one tool's metadata, and SDK 2.3.1 behaves the same, so upgrading would not fix this.

Change

Our @modelcontextprotocol/client@2.0.0 patch now gives the legacy tool schema the same outputSchema shape as the SDK's own 2026-07-28 schema in the same file:

 const ToolSchema$1 = z.object({
   ...
   inputSchema: z.object({ type: z.literal("object"), ... }).catchall(z.unknown()),
-  outputSchema: z.object({
-    type: z.literal("object"),
-    properties: z.record(z.string(), JSONValueSchema$1).optional(),
-    required: z.array(z.string()).optional()
-  }).catchall(z.unknown()).optional(),
+  outputSchema: z.looseObject({ $schema: z.string().optional() }).optional(),

inputSchema keeps its type: "object" requirement. listTools() still caches the schemas, so callTool still validates structuredContent against them. Only the root-shape restriction on outputSchema is gone.

Out of scope

Verification

  • New test accepts legacy MCP tools whose output schema is not a root object, using a raw JSON-RPC stdio fixture. The server SDK can't be used here, because it rewrites non-object output schemas for legacy clients. With the patch, the tool lists with its anyOf schema intact and the call returns its structured result. Without it, the test fails with the error from the issue.
  • Against a minimal raw stdio server with one type: "object" tool and one $defs + anyOf tool: unpatched 2.0.0 and 2.3.1 both fail with Invalid result for tools/list; patched 2.0.0 lists both tools and calls the anyOf one successfully.
  • bun test test/mcp.test.ts test/mcp-oauth.test.ts test/mcp-instructions.test.ts test/mcp-import-boundary.test.ts in packages/core: 97 pass, 0 fail.
  • bun run check from the repo root: 34/34 tasks pass.

The MCP client SDK validates legacy tools/list results with an
outputSchema that must be `type: "object"`. One tool with a top-level
anyOf/oneOf schema makes the whole result invalid, so the server fails
and none of its tools load. 2026-07-28 allows any JSON Schema here, and
the SDK's own 2026-07-28 schema already accepts any object. Use that
same shape for legacy connections in our SDK patch.

Fixes #57643

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good. I reproduced #57643 from source on the base (Invalid result for tools/list … expected "object", server fails). With this change the same server connects. The new test fails on the base and passes here, and packages/core type-checks cleanly. The one failing test in mcp.test.ts (descendant termination) fails the same way on the base.

The patch only loosens the legacy outputSchema shape to match the SDK's own 2026-07-28 schema. inputSchema still requires type: "object", and the SDK's legacy wrapping happens only on the server side, so client-side structuredContent handling isn't affected.

Public API: unchanged.

@rekram1-node
rekram1-node merged commit c41c3a0 into dev Oct 22, 2026
21 of 22 checks passed
@rekram1-node
rekram1-node deleted the mcp-output-schema branch October 22, 2026 20:19
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.

MCP: outputSchema anyOf/oneOf rejected — valid JSON Schema combinators cause entire server to fail

1 participant