[BUG] JSON schema is invalid. It must match JSON Schema draft 2020-12
Environment
- Platform (select one):
- [x] Anthropic API
- [ ] AWS Bedrock
- [ ] Google Vertex AI
- [ ] Other: <!-- specify -->
- Claude CLI version: 0.2.52
- Operating System: NixOS 25.05.20250201.3a22805 (Warbler)
- Terminal: ZSH
Bug Description
Claude Code chokes on a simple MCP server with tuples (also happens with some other Zod syntaxes).
Steps to Reproduce
- Have this tool in your MCP server:
server.tool(
"someTool",
"some description",
{
document: z
.object({
section: z.string(),
}) ,
},
async () => {
return {
content: [{ type: "text", text: "response" }],
}
}
);
- Give any prompt to Claude, it works 🎉
- Replace the MCP server tool with (the only difference is that
z.string()becomesz.tuple([z.string(), z.string()])):
server.tool(
"someTool",
"some description",
{
document: z
.object({
section: z.tuple([z.string(), z.string()]),
}) ,
},
async () => {
return {
content: [{ type: "text", text: "response" }],
}
}
);
- Give any prompt to Claude, it breaks with
API Error: 400 {"type":"error","error":{"type":"invalid_request_error","message":"tools.12.custom.input_schema: JSON schema is invalid. It must match JSON Schema draft 2020-12 (https://json-schema.org/draft/2020-12). Learn more about tool use at https://docs.anthropic.com/en/docs/tool-use."}}
Note: run claude and type the prompt inside. If you run claude test then it will succeed, I assume because the MCP server is not started yet?
Expected Behavior
I have given a Zod schema, not a JSON schema, so it should work.
OR, I would be happy to pass a JSON schema directly instead of a Zod schema (we originally have a JSON schema and convert it to Zod using https://www.npmjs.com/package/json-schema-to-zod, so if then Claude Code converts this Zod schema back to JSON Schema, I would love todirectly pass a JSON schema instead...).
Actual Behavior
It breaks on any prompt, even "test".
Additional Context
Using Zod tuples is not the only Zod syntax that breaks, but it's one of the simplest examples I have pinpointed.
This issue has 14 comments on GitHub. Read the full discussion on GitHub ↗