[BUG] MCP Tools with draft-07 are rejected

Status Open
Reported on v2.1.240
Maintainer reply None cached
Activity 7 comments · opened Aug 22, 2026

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 and
outputSchema 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)

  1. The SDK should not emit $schema at 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.

  1. registerTool should expose target, since its absence is what makes this

unfixable downstream.

Environment

  • @anthropic-ai/claude-code 2.1.240 (darwin arm64)
  • @modelcontextprotocol/sdk 1.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

  1. 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"]
}
}
}

  1. Start a session. The server connects and all 14 of its tools register

successfully — no error at this stage.

  1. Call any one of its tools, e.g. list_allowed_directories (it takes no

arguments), or read_text_file.

  1. 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 an
outputSchema 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_

View original on GitHub ↗

3 Comments

NormSimpliGRC · 1 month ago

Confirming this on Claude Code (not Desktop), and adding what I think is the missing
piece in the reports so far: an exact client version boundary from a bisect over local
session transcripts.

Version boundary

Counted mcp__filesystem__* tool calls against occurrences of unsupported dialect
across 45 local session transcripts, grouped by the version field recorded in each
transcript:

| Date | Claude Code | filesystem calls | dialect errors |
|------------|-------------|------------------|----------------|
| 2026-07-26 | 2.1.219 | 91 | 0 |
| 2026-08-01 | 2.1.219 | 157 | 0 |
| 2026-08-02 | 2.1.219 | 297 | 0 |
| 2026-08-08 | 2.1.219 | 180 | 0 |
| 2026-08-10 | 2.1.219 | 23 | 0 |
| 2026-08-14 | 2.1.229 | 9 | 2 ← first |
| 2026-08-22 | 2.1.237 | 6 | 3 |
| 2026-08-25 | 2.1.237 | 12 | 10 |

748 successful calls on 2.1.219 with zero errors. Failures begin at 2.1.229 and never stop.
So the regression landed somewhere in 2.1.220 … 2.1.229.

The server did not change

Same @modelcontextprotocol/server-filesystem@2026.1.14 throughout, installed
2026-04-12 and untouched since — its install timestamp straddles both the working and
the broken period. Same package, same outputSchema, same draft-07 stamp. The only
variable that moved is the client version.

Upgrading the server does not help

Worth flagging for anyone arriving here looking for a workaround: the newest published
server-filesystem (2026.7.10) is affected too — see the report earlier in #86142 of
Anthropic's own bundled filesystem extension at v2026.7.10 failing identically. There is
no version of this server that passes, because the schema shape is the same across all
of them.

Root cause chain (client-side, reproducible)

  1. server-filesystem declares outputSchema on its tools — 14 occurrences in

dist/index.js (e.g. lines 158, 175, 185, 235, 264, 288), all the shape
outputSchema: { content: z.string() }.

  1. Those are converted with zod-to-json-schema, which unconditionally sets

combined.$schema = "http://json-schema.org/draft-07/schema#" at
dist/cjs/zodToJsonSchema.js:76.

  1. The client compiles each outputSchema with an Ajv instance restricted to

JSON Schema 2020-12. Ajv throws at validator-construction time on an unknown dialect.

  1. Construction happens at registration/invocation, before dispatch — so the server

process is never contacted and retrying cannot help.

Useful negative control

A co-installed SQL Server MCP on the same machine also emits
"$schema": "http://json-schema.org/draft-07/schema#" — but only in its inputSchema,
and it declares no outputSchema. It works perfectly, in the same sessions, at the same
client versions where every filesystem tool fails.

That isolates the trigger precisely: it is outputSchema validation, not draft-07
in general. Input schemas in draft-07 are accepted without complaint.

Scope

Every tool on the server, including zero-argument ones — list_allowed_directories
(no parameters at all) fails identically to read_text_file. There is no usable subset,
so no partial workaround.

Environment

  • Claude Code 2.1.237 (broken), 2.1.219 (last known good)
  • Windows 11 Pro 10.0.26200
  • @modelcontextprotocol/server-filesystem@2026.1.14
  • deps: @modelcontextprotocol/sdk@^1.25.2, zod-to-json-schema@^3.23.5
  • Node v22.23.1

Expected

Either configure Ajv to accept draft-07 for outputSchema, or degrade gracefully — log a
warning and skip output validation rather than hard-failing the tool before dispatch.
Hard-failing turns a validation nicety into total loss of the server.

avigilante · 1 month ago

Confirming issue on Claude Cowork.
Confirming it started between 2026-08-12 and 2026-08-14.

KALeiter · 1 month ago

Can confirm — hitting the exact same error, reproduced with 7 independently configured
instances of @modelcontextprotocol/server-filesystem (each pointing at a different
allowed directory, via npx -y @modelcontextprotocol/server-filesystem <dir> in
claude_desktop_config.json). All 7 fail identically on every tool invocation
(read_file, write_file, edit_file, list_directory, search_files,
list_allowed_directories, etc.), not just list_allowed_directories.

Also observed through the Claude Desktop app's conversational interface (not just a
CLI session), so this affects that code path too.

Environment: macOS, Claude Desktop app.

Showing cached comments. Read the full discussion on GitHub ↗