Repository navigation
Description
Package: @modelcontextprotocol/sdk 1.30.0
Affects: any server built with McpServer that declares an outputSchema (e.g. @modelcontextprotocol/server-filesystem 2026.7.10), consumed by a client with a strict output-schema validator.
Bug
In src/server/zod-json-schema-compat.ts (compiled to dist/{cjs,esm}/server/zod-json-schema-compat.js), mapMiniTarget() falls back to 'draft-7' whenever no explicit target is passed:
function mapMiniTarget(t) {
if (!t) return 'draft-7'; // <-- always hit in practice
...
}McpServer's tool-listing handler (src/server/mcp.ts) never passes a target when calling toJsonSchemaCompat() for either inputSchema or outputSchema:
toolDefinition.outputSchema = toJsonSchemaCompat(obj, {
strictUnions: true,
pipeStrategy: 'output'
});So every registered tool's outputSchema (Zod v4 branch, via zod/v4-mini's toJSONSchema) is emitted with "$schema": "http://json-schema.org/draft-07/schema#", with no way for the server author to opt into 2020-12.
Impact
A client that validates outputSchema strictly against JSON Schema 2020-12 rejects every tool from every SDK-based server that declares an outputSchema, e.g. (observed in Claude Desktop 1.37937.1):
Tool 'list_directory' 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.
This breaks @modelcontextprotocol/server-filesystem entirely — every tool call fails client-side before even reaching the server.
Suggested fix
Default mapMiniTarget's fallback to 'draft-2020-12' instead of 'draft-7' (2020-12 is a superset-compatible, more current dialect and z4mini.toJSONSchema already supports it via the existing branch), or have McpServer pass target: 'draft-2020-12' explicitly.
Confirmed locally that swapping the fallback produces "$schema": "https://json-schema.org/draft/2020-12/schema" and resolves the client-side rejection with no other code changes needed.
Repro
- Any MCP server built with
McpServer+outputSchema(e.g.[email protected]). - A client validating
outputSchemastrictly against 2020-12 (e.g. Claude Desktop 1.37937.1+). - Every tool call fails with the "unsupported dialect" error above.
Activity
dhk commentedon Aug 26, 2026
Confirming this against a second server, in case a non-first-party data point is useful.
Affected: @perplexity-ai/[email protected] (Perplexity's official MCP server), which pins @modelcontextprotocol/sdk: ^1.29.0 — resolving to 1.30.0, the version in this report. All four of its tools declare an outputSchema.
Client: Claude Code. Same rejection text as the Claude Desktop case above:
Every tool on the server is rejected identically (perplexity_search, perplexity_ask, perplexity_research, perplexity_reason).
Two details that might help anyone triaging this:
tools/list succeeds — the rejection is downstream of it. The handshake completes and all four tools are listed with correct names and descriptions. The failure only appears at tools/call, client-side, before any request reaches the server. From the server's logs the session looks entirely healthy, which makes this awkward to diagnose from the server side.
The server itself is fine. Calling the same server over HTTP directly, bypassing the client's validator, works normally:
So this isn't a server bug and isn't fixable by the server author while mapMiniTarget() has no way to opt into 2020-12. It also can't currently be fixed by bumping the SDK: 1.30.0 is the latest published release, so every SDK-based server declaring an outputSchema is affected today with no version to upgrade to.
Worth noting the inputSchema half of this was reported in #745 and closed; outputSchema appears to have been missed by that fix, which matches the behaviour here — schemas list fine, calls fail.
Ben-Home commentedon Aug 27, 2026
GXsolutions28 commentedon Sep 7, 2026
Confirming this against
server-filesystem, and adding one thing that isn't inthe thread yet: downgrading the server is not a workaround. No published
version of
@modelcontextprotocol/server-filesystemescapes draft-07 — theolder releases just move it to a field that fails earlier.
I launched each version over stdio (
initializeat protocol2025-06-18→notifications/initialized→tools/list) and inspected the emitted schemas:inputSchemaonread_fileoutputSchema0.5.1…2025.8.21{"$schema": "http://json-schema.org/draft-07/schema#"}and nothing elsetools/listrejected — no tools at all2025.11.25…2026.8.31$schema, type, properties, required)On
0.6.2that first cell is the entire schema — notype, noproperties:{ "$schema": "http://json-schema.org/draft-07/schema#" }so the client rejects the listing outright:
while
2026.8.31lists its 14 tools fine and fails at call time, as described inthis issue:
Measured on 16 of the 19 published versions;
0.2.0,0.3.0and0.5.0did notcomplete an
initializehandshake at this protocol version.Two things follow. The draft-07 dialect is constant across the package's entire
published history — only the field carrying it moves — so
@-pinning is a deadend for anyone who lands here looking for one, and the SDK fix in #2084 is the
only route for this server. And the failure is quiet in an unhelpful way: the
desktop chat client works fine,
mcp-server-brainos.logshowsServer started and connected successfullywith a cleantools/list, andnothing anywhere mentions
draft-07. The rejection happens in the callingclient, so grepping logs finds nothing and one tool call finds it immediately —
worth knowing for anyone triaging a report of "the server connects but the tools
don't work".
@modelcontextprotocol/[email protected],[email protected].iaraslanov86-droid commentedon Sep 12, 2026
Another confirmation, plus one data point I don't see in the thread yet: draft-07 on
inputSchemaalone does not trip the validator — onlyoutputSchemadoes.Two stdio servers on the same machine, same client (Claude Code in the Claude desktop app 1.52386.3, macOS arm64, Node 25.9.0), probed over raw stdio (
initialize@2025-06-18→notifications/initialized→tools/list):inputSchemadraft-07outputSchemadraft-07@modelcontextprotocol/[email protected](sdk 1.30.0)@sinco-lab/mcp-youtube-transcriptThe filesystem server fails exactly as reported:
The transcript server advertises well-formed
inputSchemas ($schema+type+properties) tagged draft-07 on all 5 tools, declares nooutputSchema, and its tools call successfully in the same session. So the blast radius is narrower than "every SDK server": servers that register tools without anoutputSchemaare unaffected in practice, even though their advertised dialect is equally non-conformant with SEP-1613. That may matter for triage/severity — and it means theoutputSchemacall site inmcp.tsis the one that actually breaks users today.This is a client-side asymmetry, not an SDK one, so it doesn't change the fix in #2653 — worth recording so people don't chase schema errors on servers that are in fact fine.
Also checked, in case it saves someone a step:
$schemaappears only at the top level ofinputSchema/outputSchema, never nested inside$defs/properties(recursive walk over all 14 tools, 0 nested occurrences).resources/listandprompts/listreturn-32601on this server, sotools/listis the only affected response.Workaround until #2653 lands — a ~40-line stdio proxy that strips
$schemafrom tool schemas intools/listand passes everything else through untouched:Over raw stdio, 14/14 tools go from draft-07 to clean, all 14 remain listed, and
tools/callround-trips (list_allowed_directories,list_directory) pass through unchanged. Stripping and replacing withhttps://json-schema.org/draft/2020-12/schemaboth work; these schemas use no dialect-sensitive keywords.mildlydiverting commentedon Sep 13, 2026
Another confirmation, for what it's worth: hit this on whitney-mcp-ts, an MCP server over the Whitney Museum's public API — 10 of 11 tools had outputSchema (built from a Zod v3 shape), all emitting $schema: draft-07, all rejected by a 2020-12-only client. SDK 1.30.0.
Worked around it by dropping outputSchema from the affected tools rather than patching the schema on the wire — structuredContent is unaffected, just no longer pre-advertised. Details in the v0.1.1 release notes / README if useful as another real-world case.
oliverames commentedon Sep 22, 2026
One more data point from the Claude desktop app side (macOS, Claude 2.2553.13, checked 2026-09-22).
Anthropic's packaged Filesystem extension (
ant.dir.ant.anthropic.filesystem2026.7.10, SDK 1.29.0) emits"$schema": "http://json-schema.org/draft-07/schema#"on everyinputSchemaandoutputSchemaintools/list. In a Cowork session, every tool (list_directory,list_allowed_directories, and so on) then fails with:The validator bundled in the app still accepts only the two 2020-12 meta-schema URIs, so it predates #2534 (merged 2026-07-27, closed #2532). That means the SDK v1 emission fix here (#2084 / #2085) is the only fix that reaches users today. The client-side fix has not shipped in this app build.
Zaky63 commentedon Oct 1, 2026
Still reproducible on SDK 1.31.0 (resolved by
@modelcontextprotocol/[email protected]with[email protected]), so 1.30.1 and 1.31.0 didn't change this.Minimal check against the installed package:
Impact on Claude Desktop (Windows, MSIX build): every
server-filesystemtool is listed, but every call fails withinvalid outputSchema: JSON Schema declares an unsupported dialect. Pinning an older server doesn't help:2025.8.21has nooutputSchema, but with Zod v4 resolved today itsinputSchemaloses"type": "object"and is rejected attools/list.For anyone blocked until #2085 / #2653 land: a client-side stdio proxy that strips
$schemaandoutputSchemafrom thetools/listresult works. Details and code in modelcontextprotocol/servers#4841.+1 for getting #2085 (covers both the Zod v3 and v4 paths) into a 1.x release.
clash-90 commentedon Oct 8, 2026
Another confirmation, plus two data points I don't think are in the thread yet: a newer SDK version, and a commercial third-party server.
Still reproducible on SDK 1.32.1 (current latest; newest report here is 1.31.0). Checked against the installed package with zod 4.4.3:
So 1.30.1, 1.31.0 and now 1.32.1 are all unchanged.
Affected server: Lightdash (self-hosted 2.427.4, SDK 1.30.0) — a commercial BI platform. Every case in the thread so far is a small or first-party server, so the blast radius on a larger tool surface may be a useful data point: 14 of its 32 exposed tools declare an outputSchema, and all 14 are unusable in a 2020-12-only client. That includes every query-execution tool
(run_metric_query, run_sql, get_query_result) and every schema-discovery tool (grep_fields, get_metadata, get_context), i.e.
the entire documented query workflow. The 18 tools without an outputSchema (list_projects, list_explores, get_lightdash_version, …) work normally, which makes the product look partially broken rather than misconfigured.
The outputSchema-presence split predicted pass/fail for all 8 tools tested, with no exceptions.
Client: the Claude desktop app 2.26454.2 (macOS, local agent mode). Error text matches the report verbatim:
Tool 'get_context' 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
Two things that might help triage:
The schema bodies are already 2020-12-valid — only the declaration is wrong. I scanned all of Lightdash's emitted schemas for draft-07-only constructs (definitions, tuple-form items, additionalItems, dependencies, $ref into #/definitions, boolean exclusiveMinimum): zero hits. They use only anyOf, const, enum, pattern, propertyNames, additionalProperties, required. Compiling the real schemas under Ajv 2020-12 fails as-is and succeeds for every one of them with $schema either deleted or rewritten — and a conformant run_metric_query payload still validates against the rewritten schema, so correcting the dialect doesn't weaken the contract. That supports fix: default Zod v4 JSON Schema target to draft-2020-12 #2653 / [v1.x] fix(server): emit JSON Schema 2020-12 in tools/list (SEP-1613) #2085 being safe for existing servers, not just correct.
Same server, same bytes, different outcome across two clients. Claude Code accepts these schemas and works normally against the same endpoint; only the desktop app rejects them. Reduced to the two validator classes:
const schema = { "$schema": "http://json-schema.org/draft-07/schema#",
type: "object", properties: { a: { type: "string" } } };
new Ajv({ strict: false }).compile(schema); // draft-07 class: OK
new Ajv2020({ strict: false }).compile(schema); // 2020-12 class:
// Error: no schema with key or ref "http://json-schema.org/draft-07/schema#"
xka0085-byte commentedon Oct 11, 2026
Same class of issue, observed from the client side: we run a read-only scanner (MCP
initialize+tools/listonly) over the ~10k endpoints registered in the official MCP Registry, and draft-07-onlyoutputSchemais a recurring shape in the wild. It usually passes unnoticed because most clients tolerate draft-07 in practice — until one validates strictly, at which point it again looks like the client's bug.For anyone debugging this on the server side: the published
$schema(or its absence) is mechanically detectable before deploy, the same way missingrequiredfields are. We gate that in CI with a read-only check (MIT: https://github.com/xka0085-byte/mcp-doctor). If it helps the maintainers weigh #2677 vs this one: both stem from the sametoJsonSchemaCompattarget default, so a single fix path likely covers both.docs: reconcile ledgers with the v2.19.0 merge
docs: reconcile ledgers with the v2.19.0 merge