Repository navigation
Description
Describe the bug
On @modelcontextprotocol/server-filesystem versions up to and including 2025.8.21, a fresh install resolves zod v4, and the server then advertises every tool with an empty inputSchema — just {"$schema": "http://json-schema.org/draft-07/schema#"}, with no type, no properties, and no required.
Schema conversion appears to fail silently rather than throwing. The server logs Server started and connected successfully and returns a well-formed tools/list response, so nothing looks wrong from the outside — but every tool definition in it is unusable. Strict MCP clients reject the server outright at tools/list.
Forcing zod back to 3.25.76 fixes it completely. Same server version, same Node, same config — the zod version is the only variable.
To Reproduce
Steps to reproduce the behavior:
Install the server on its own:
mkdir /tmp/fsrepro && cd /tmp/fsrepro
npm init -y
npm install @modelcontextprotocol/[email protected]
Confirm zod resolved to v4:
node -e "console.log(require('./node_modules/zod/package.json').version)"
Launch the server over stdio:
node node_modules/@modelcontextprotocol/server-filesystem/dist/index.js /tmp
Send initialize, then notifications/initialized, then tools/list.
Inspect any tool's inputSchema in the response.
To confirm the cause, add an overrides block forcing zod to 3.25.76, reinstall, and repeat steps 3–5. The schemas come back correct.
Expected behavior
tools/list should return complete input schemas, as it does when zod v3 is installed:
{
"name": "write_file",
"inputSchema": {
"type": "object",
"properties": {
"path": { "type": "string" },
"content": { "type": "string" }
},
"required": ["path", "content"],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
}
}
Failing that, the schema conversion should throw rather than silently returning an empty object, so the incompatibility surfaces immediately instead of appearing as a client-side problem.
Logs
With zod v4 resolved, all 14 tools come back like this:
{
"name": "write_file",
"inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#" }
}
The client rejects the server:
Invalid result for tools/list: [ {
"code": "invalid_value",
"values": ["object"],
"path": ["tools", 0, "inputSchema", "type"],
"message": "Invalid input: expected "object""
}, ... ]
With zod pinned to 3.25.76, probing the same build: 14 tools, all with inputSchema.type == "object", full properties and required. Server loads and every tool works.
Additional context
Verified workaround — npm overrides forcing zod to v3:
{
"dependencies": { "@modelcontextprotocol/server-filesystem": "2025.8.21" },
"overrides": { "zod": "3.25.76" }
}
Likely cause — flagging this as a hypothesis, since I haven't read the conversion code: these releases look like they call a zod v3 API surface while the dependency range permits v4 to resolve, and the mismatch makes conversion return an empty object instead of raising. What I verified directly is only the input/output relationship: zod v4 → empty schemas, zod v3.25.76 → correct schemas, everything else held constant.
Suggested fix — constrain the zod dependency to the major version the code targets, or make schema conversion throw on failure. Either would turn this into an immediate, obvious error.
Why it's worth fixing rather than leaving to version pinning: the failure is silent and misattributed. The resulting client-side error reads like a filesystem permissions or sandbox problem, so users go looking at their own folder configuration. I spent several weeks there before finding this.
Environment
@modelcontextprotocol/server-filesystem 2025.8.21; also reproduced on 2025.7.29 and 2025.8.18
macOS, Darwin 25.6.0
Reproduced both via npx -y and via local npm install
Related, but not this repo's bug: versions from 2025.11.25 onward emit correct input schemas, but declare outputSchema in JSON Schema draft-07, which some clients reject as an unsupported dialect. That's a client-side strictness question and I've reported it to that vendor separately. Worth mentioning only because the combination means there's currently no release of this package that works with such a client — newer releases fail on outputSchema, older ones fail on the empty inputSchema described above.
Activity
ramiiZPD commentedon Aug 21, 2026
Thanks for the detailed writeup, the repro steps made this easy to check. I pulled current
main(599dafc1), installedsrc/filesystemfresh with no overrides, and it resolved the same zod major you flagged ([email protected]alongside@modelcontextprotocol/[email protected]). Built it, ran it over stdio, and walked throughinitialize→notifications/initialized→tools/listby hand.Couldn't reproduce it, though. All 14 tools came back with full schemas.
write_filelooked like this:{ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "path": { "type": "string" }, "content": { "type": "string" } }, "required": ["path", "content"] }Dug a bit further to see why, since your hypothesis about the conversion made sense to me. Turns out
@modelcontextprotocol/[email protected]already has a fix for this:server/zod-json-schema-compat.jschecks for zod v4 (schema._zod) and hands those schemas tozod/v4-mini's owntoJSONSchema()instead of the oldzod-to-json-schemapackage, which really is still v3-only under the hood. That compat file evidently didn't exist yet in the SDK version bundled with theserver-filesystemrelease you tested (2025.7.29 through 2025.8.21), so this was a real bug, it's just been fixed one layer up since then.Since
serversitself never does the schema conversion (it just hands.shapetoregisterTool), there's nothing to patch here. It's inherited automatically once the SDK dependency is current. Probably safe to close, unless there's a still-publishedserver-filesystembuild out there pinned to an older SDK that would still hit this.pauxier-coder commentedon Aug 21, 2026
Thanks for running it. That's more than I expected.
I think we tested two different things. You built main. My report is about the published tarballs on npm, which is what npx -y @modelcontextprotocol/[email protected] actually runs, and that's different code.
I re-ran it today against the published 2025.8.21. Fresh install, no overrides:
@modelcontextprotocol/[email protected]
+-- @modelcontextprotocol/[email protected]
| +-- [email protected] deduped
|
-- [email protected]-- [email protected]Same SDK 1.30.0 and the same zod 4.4.3 you had. Still broken. Walking initialize → notifications/initialized → tools/list gives 14 tools, and 13 of them come back as just this:
{ "$schema": "http://json-schema.org/draft-07/schema#" }
The one that survives is list_allowed_directories, and only because its schema is written out as a literal object in the source instead of being converted.
Here's why the SDK compat file doesn't help. Published 2025.8.21 never calls registerTool. It registers a raw handler and builds every schema itself:
dist/index.js:9 import { zodToJsonSchema } from "zod-to-json-schema";
dist/index.js:134 server.setRequestHandler(ListToolsRequestSchema, async () => {
dist/index.js:173 inputSchema: zodToJsonSchema(WriteFileArgsSchema),
zod-to-json-schema is a direct dependency of the package at that version. The conversion happens before the SDK sees anything, so server/zod-json-schema-compat.js never runs. And the package declares @modelcontextprotocol/sdk: ^1.17.0, so a fresh install already pulls 1.30.0. A current SDK doesn't rescue it.
What did fix it is the move to registerTool. Published 2025.11.25 and 2026.7.10 both use it, and neither imports zod-to-json-schema at all, which matches those versions emitting correct input schemas in my original table. main picks up the SDK fix for the same reason.
So I'm fine with closing this. The bug is real but bounded: published versions ≤2025.8.21 only, no SDK upgrade clears it, and from a user's side the only fixes are moving to 2025.11.25 or later, or pinning zod to 3.25.76.
banks0frome commentedon Aug 27, 2026
I built and independently verified a bounded proof for this issue.
The independently accepted artifact contains this standalone checker for maintainer review:
This inline artifact is the product test; it is not evidence of maintainer adoption.
If this is useful, I’ll wait for maintainer direction on this issue before opening a PR.
olaservo commentedon Aug 27, 2026
Confirmed, and fixed from
2025.11.25onward.Reproduced your report exactly against the published tarball. A fresh
npm install @modelcontextprotocol/[email protected]resolves zod 4.4.3 and SDK 1.30.0, andtools/listreturns 13 of 14 tools as bare{"$schema": "http://json-schema.org/draft-07/schema#"}.list_allowed_directoriessurvives because its schema is a literal object in the source rather than a converted one. The control on2026.7.10, same zod 4.4.3, returns full schemas for all 14.zodToJsonSchemacall siteszod-to-json-schemadep^3.23.5direct@pauxier-coder is right that a current SDK does not rescue
2025.8.21. That version callszodToJsonSchemaitself atdist/index.js:173and declareszod-to-json-schemaas its own direct dependency, so the conversion completes before the SDK sees the schema andserver/zod-json-schema-compat.jsnever runs. @ramiiZPD's run was againstmain, which usesregisterTooland was never affected.Nothing left to patch:
mainhas nozod-to-json-schemausage insrc, and none of the currently published TypeScript servers declare it. Fixes are to move to2025.11.25or later, or pin zod to3.25.76if you must stay on the older release.Agreed the silent failure was the worst part of this. Thanks for the repro steps!
dodogeny commentedon Sep 1, 2026
This is a brutal one to debug — “surfaces client-side as what looks like a permissions or sandbox problem” is exactly why it took someone weeks to trace back to the server. Nothing about the symptom points at the real cause.
We build Apitella, which diffs a server’s tools/resources/prompts across releases — this is close to the canonical case for it: 13 of 14 schemas silently collapsing to {} would show up as a breaking-change alert the moment that release went out, not weeks later downstream. Mentioning it mainly because the mechanism here is such a clean illustration, not trying to sell you on anything — you clearly know this problem better than most.