-
Notifications
You must be signed in to change notification settings - Fork 1.4k
feat: zod v4 with backwards compatibility for v3.25+ #1040
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: zod v4 with backwards compatibility for v3.25+ #1040
Conversation
|
Update: Merge conflicts resolved. 1.20.2-next.0 published under Update 10/31: Updated to 1.21.0 and released under @socotra/modelcontextprotocol-sdk |
|
any info when we should expect this PR to merge? 🤔 |
|
This PR cannot land soon enough. |
|
publishing a 3.25.x for |
package.json
Outdated
| "raw-body": "^3.0.0", | ||
| "zod": "^3.23.8", | ||
| "zod-to-json-schema": "^3.24.1" | ||
| "zod": "^3.25 || ^4.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the Anthropic team: Zod 3.25 was a minor release with no breaking changes from Zod 3.24. It did however introduce a pre-release version of Zod 4 at the "zod/v4" subpath. It also added a re-export of Zod 3 from "zod/v3".
The idea is that these subpaths are "permalinks" to these associated versions that can be referenced by any library with a peer dependency on zod@>3.25.0 (including 4.x, and additional future majors beyond).
That's why this PR is using this pattern. The usage of Zod in this PR is idiomatic and consistent with the best practices described in my Library Authors writeup, which are already in use in the AI SDK, React Hook Form, and several others in the wild.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for taking time to review!
| "peerDependencies": { | ||
| "@cfworker/json-schema": "^4.1.1" | ||
| "@cfworker/json-schema": "^4.1.1", | ||
| "zod": "^3.25 || ^4.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR does bump the minimum version to 3.25.0, so any users fro Zod 3.23.x or 3.24.x would need to bump their version.
You could categorize this as a breaking change, but I personally think bumping a peer dep to a new minor version does not constitute a breaking change on your part. There were no breaking changes between Zod 3.23 -> 3.25 so it's a one-line npm command for users to upgrade.
There are also far more Zod 3.25 & Zod 4 users (52m/wk downlods) than Zod 3.24 users (6m/wk) or Zod 3.23 users (5m/wk). The upside of merging this is far greater than the downside to users who are pinned on older versions. Feel free to tag me if you receive any pushback on this and I'll explain why the bump was necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the additional explanation here - very helpful context to have these numbers.
I believe npm install would warn folks if they have an outdated peer dependency pinned, so it would at least not be a silent failure, so that's an additional mitigating factor. I'll also call this out in the release notes for this one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't these files actually be put into a subfolder, so that the full path would be src/vendor/zod-to-json-schema/? It would be problematic if we add another vendored library in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
|
Please tag me when ready for the merge conflicts to be resolved. The new work in #816 and #1086 makes resolving quite complex with the existing changes in here and I'd like to batch the fixes when you guys are ready to merge. @KKonstantinov @pcarleton Please review as soon as possible. We have a very large backlog of folks waiting for this PR and we have the author of Zod providing feedback for us. |
|
Hey @dclark27. Thanks so much for your contribution and all this work. I want to get this merged and support this change. Could you help me understand the vendoring then I'd love if you could rebase and we can get this going. Why are you vendoring the zod-to-json-schema lib? This sdk was using this lib directly before no? I'm guessing this would remove a whole class of bugs if so. I have tested this in some of my own projects and it seems to work well :) |
|
Hi @mattzcarey ! The vendor idea comes from openai's openai-node package. They have the same bottleneck as us which is that zod-to-json-schema's maintainers have disappeared and we are all stuck without a good option to get onto zod 3.25+. I will get this PR cleaned up today, bother the zod-to-json-schema folks one more time, and ping you when it's ready to be merged. Thanks! |
733dce2 to
2fce53c
Compare
2fce53c to
df56e35
Compare
commit: |
commit: |
|
@mattzcarey good to review again Give it a rip |
|
@mattzcarey StefanTerdell/zod-to-json-schema#180 has been merged and the |
|
A new version of |
Yep! I removed it ~an hour after the PR landed. |
|
Reviewing this today. Thanks for all your work :) |
mattzcarey
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me. Waiting other maintainers to have a look.
|
Hey @dclark27 could you give maintainers permissions to fix the rebase or would you be happy to do it :) |
|
@mattzcarey |
|
Ahh dont worry about it @dclark27 it might be github freaking out but i see this.
|
|
@mattzcarey working on it now! edit: good to go |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huge thanks @dclark27 @colinhacks @trojanowski @mattzcarey for your patience and tenacity in making this backwards compatible and unblocking a merge! Really appreciate how much effort has gone into this.
Couple of things we want to follow-up on, but not blocking this PR. We'll take on these follow-ups on within the team before the release so we can avoid a back-and-forth.
- README updates to call out dual support + make clear that it's a peerDependency and users should / can "bring their own"
- Remove the
pnpm-lock.yamlfile as we're standardizing onnpmatm - @KKonstantinov proposed adding a "stress test" for a large/complex schema to ensure it remains compatible.
- There's probably ways to dedupe the tests so we don't have
v3separately.
| "peerDependencies": { | ||
| "@cfworker/json-schema": "^4.1.1" | ||
| "@cfworker/json-schema": "^4.1.1", | ||
| "zod": "^3.25 || ^4.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the additional explanation here - very helpful context to have these numbers.
I believe npm install would warn folks if they have an outdated peer dependency pinned, so it would at least not be a silent failure, so that's an additional mitigating factor. I'll also call this out in the release notes for this one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we want to officially support pnpm as we're standardizing on npm atm, but can be removed in a follow-up before we release.
| import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'; | ||
| import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; | ||
| import express from 'express'; | ||
| import { z } from 'zod'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should call out the peerDependency status on the README somewhere and that v3 and v4 are both supported. We can do that in a follow-up though.
|
Thank you so much!! |

Add transparent Zod v3/v4 compatibility to the MCP TypeScript SDK, allowing users to install and use either version without any code changes or configuration. This addresses the need for the SDK to support multiple major versions of Zod in user applications.
The SDK exports v4 schemas by default, but the compatibility layer detects the Zod version at runtime and routes all schema operations (parsing, JSON Schema conversion, schema construction) to the appropriate implementation.
How Has This Been Tested?
Install the published version and test in your own app:
npm i @modelcontextprotocol/sdk # or pnpm i @modelcontextprotocol/sdkComprehensive Test Coverage
49 Test Suites | 1045 Tests (all passing)
User-facing APIs tested with both v3 and v4:
Internal utilities tested with v4 only:
Test Files Created
.v3.test.tsfiles demonstrating real Zod v3 usage patternstypes.jsBreaking Changes
None. This is purely additive:
Types of changes
Checklist
Migration Path
Users can migrate from v3 to v4 at their own pace:
zod@3- everything works as beforezod@4orzod/v4imports - get smaller bundle size and better performance