[BUG] MCP Tools with draft-07 are rejected
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
MCP tools with a draft-07 outputSchema are rejected; current server-filesystem is unusable
Summary
Claude Code validates MCP tool outputSchema with an Ajv instance that supports
JSON Schema 2020-12 only. The MCP TypeScript SDK emits draft-07 by default, so any
server declaring an outputSchema fails at tool-call time:
Error: Tool 'list_allowed_directories' has an invalid outputSchema:
JSON Schema declares an unsupported dialect ("$schema": "http://json-schema.org/draft-07/schema#").
The default validator supports JSON Schema 2020-12 only; pass a pre-configured Ajv instance to AjvJs…
Note the failure mode: tools/list succeeds and the tools appear registered. The error
only surfaces when a tool is actually invoked.
Impact
This is not specific to one server. @modelcontextprotocol/sdk defaults its conversion
target to draft-7, so a large share of MCP servers in the wild emit draft-07 schemas.
Any of them that declare an outputSchema is unusable in Claude Code.
Concretely, every release of @modelcontextprotocol/server-filesystem since
2025.11.25 is broken with Claude Code, including the current 2026.7.10.
Reproduction
npx -y @modelcontextprotocol/server-filesystem@2026.7.10 /tmp
Register it as an MCP server, then call any of its tools (e.g. list_allowed_directories).
All 14 tools carry a draft-07 outputSchema.
Probe across versions (14 tools each):
| version | bad inputSchema | tools w/ outputSchema | draft-07 output |
|------------|-------------------|--------------------------|-----------------|
| 2025.7.29 | 13 | 0 | 0 |
| 2025.8.21 | 13 | 0 | 0 |
| 2025.11.25 | 0 | 14 | 14 |
| 2026.1.14 | 0 | 14 | 14 |
| 2026.7.10 | 0 | 14 | 14 |
(The inputSchema breakage in older versions is a separate upstream issue — those
releases convert via zod-to-json-schema@3, which yields empty schemas under zod 4.
The net effect is that no version of this server works with Claude Code out of the box.)
Root cause
@modelcontextprotocol/sdk@1.30.0, dist/esm/server/zod-json-schema-compat.js:
function mapMiniTarget(t) {
if (!t) return 'draft-7'; // <-- default
...
return 'draft-7'; // <-- fallback
}
dist/esm/server/mcp.js calls toJsonSchemaCompat for both inputSchema andoutputSchema and never passes target, so every schema is draft-07. There is no
public API on registerTool to override the dialect, so server authors cannot fix this
downstream.
Suggested fix (client)
Accept draft-07 rather than 2020-12 only — e.g. select the validator based on the
declared $schema, or register the draft-07 meta-schema on the Ajv instance. The error
text implies the code path already supports an injected pre-configured Ajv.
This is the highest-leverage fix: it repairs every affected server at once, including
unmaintained ones, with no ecosystem coordination.
Related SDK issues (filed separately)
- The SDK should not emit
$schemaat all. Note that switching the target to
draft-2020-12 is insufficient — the zod v3 branch uses zod-to-json-schema@3,
which supports only jsonSchema7 and jsonSchema2019-09 and has no 2020-12 target.
Omitting $schema is the only fix that works across both the zod v3 and v4 branches.
Verified the emitted bodies are byte-identical apart from that key for typical
object-of-scalars tool schemas.
registerToolshould exposetarget, since its absence is what makes this
unfixable downstream.
Environment
@anthropic-ai/claude-code2.1.240 (darwin arm64)@modelcontextprotocol/sdk1.30.0- macOS 26.5.2, node v25.9.0
What Should Happen?
Calling an MCP tool whose outputSchema declares JSON Schema draft-07 should
succeed. Claude Code should validate against the dialect the schema declares —
selecting the validator from $schema, or registering the draft-07 meta-schema
on the Ajv instance — rather than assuming 2020-12.
Concretely: npx -y @modelcontextprotocol/server-filesystem@2026.7.10 /tmp
should work out of the box. Today all 14 of its tools register successfully and
then fail on invocation.
Secondarily, an unsupported dialect should degrade gracefully rather than hard-fail
the call. tools/list already succeeded and the tools appear registered, so the
current behavior surfaces as a broken tool at call time with no indication the
cause is schema validation. Skipping output validation with a warning would be
strictly better than making the tool unusable.
Error Messages/Logs
Steps to Reproduce
- Register the current filesystem server as an MCP server. Either run:
claude mcp add repro -- npx -y @modelcontextprotocol/server-filesystem@2026.7.10 /tmp
...or add this to the MCP config and restart the client:
{
"mcpServers": {
"repro": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem@2026.7.10", "/tmp"]
}
}
}
- Start a session. The server connects and all 14 of its tools register
successfully — no error at this stage.
- Call any one of its tools, e.g.
list_allowed_directories(it takes no
arguments), or read_text_file.
- Observe the call fail:
Error: Tool 'list_allowed_directories' has an invalid outputSchema:
JSON Schema declares an unsupported dialect
("$schema": "http://json-schema.org/draft-07/schema#").
The default validator supports JSON Schema 2020-12 only;
pass a pre-configured Ajv instance to AjvJs…
Every tool on the server fails the same way, so the server is entirely unusable.
---
Confirming the server side independently (no Claude Code involved)
This speaks MCP over stdio directly and prints the declared dialect:
cd /tmp && printf '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"p","version":"1"}}}\n{"jsonrpc":"2.0","method":"notifications/initialized"}\n{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}\n' | npx -y @modelcontextprotocol/server-filesystem@2026.7.10 /tmp 2>/dev/null | grep '"id":2' | python3 -c 'import sys,json; t=json.load(sys.stdin)["result"]["tools"]; print(len(t),"tools;",sum(1 for x in t if x.get("outputSchema")),"with outputSchema"); print("dialect:",t[0]["outputSchema"]["$schema"])'
Output:
14 tools; 14 with outputSchema
dialect: http://json-schema.org/draft-07/schema#
This confirms the server emits valid MCP — the schemas are simply draft-07, which
the SDK produces by default. Swapping in any other server that declares anoutputSchema reproduces the same client-side failure.
Claude Model
None
Is this a regression?
Yes, this worked in a previous version
Last Working Version
_No response_
Claude Code Version
2.1.240 (Claude Code)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
_No response_
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗