Skip to content

Conversation

@dclark27
Copy link
Contributor

@dclark27 dclark27 commented Oct 23, 2025

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/sdk

Comprehensive Test Coverage

  • 49 Test Suites | 1045 Tests (all passing)

  • User-facing APIs tested with both v3 and v4:

    • Client core functionality (v3 + v4)
    • Server core functionality (v3 + v4)
    • MCP protocol handling (v3 + v4)
    • All major transports: SSE, HTTP, stdio (v3 + v4)
    • Completable schemas (v3 + v4)
    • Client authentication (v3 + v4)
    • Integration tests: task resumability, state management (v3 + v4)
  • Internal utilities tested with v4 only:

    • OAuth schemas and utilities (internal SDK infrastructure)
    • Shared protocol utilities

Test Files Created

  • 9 .v3.test.ts files demonstrating real Zod v3 usage patterns
  • Tests import SDK schemas directly from types.js
  • Tests define custom schemas using their Zod version
  • Identical test logic between v3 and v4 versions

Breaking Changes

None. This is purely additive:

  • All v4 (default) behavior unchanged
  • No API modifications
  • No configuration required

Types of changes

  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally (1045/1045 passing)
  • I have added appropriate error handling (compat layer includes runtime guards)
  • I have added or updated documentation as needed (updated README.md)

Migration Path

Users can migrate from v3 to v4 at their own pace:

  • v3 users: Continue using zod@3 - everything works as before
  • v4 users: Use zod@4 or zod/v4 imports - get smaller bundle size and better performance
  • Mixed environments: Each schema shape must use a single version (enforced at runtime)

@dclark27
Copy link
Contributor Author

dclark27 commented Oct 30, 2025

Update:

Merge conflicts resolved. 1.20.2-next.0 published under @socotra/modelcontextprotocol-sdk@next

Update 10/31:

Updated to 1.21.0 and released under @socotra/modelcontextprotocol-sdk

@wladyslawczyzewski
Copy link

any info when we should expect this PR to merge? 🤔

@punkpeye
Copy link

punkpeye commented Nov 2, 2025

This PR cannot land soon enough.

@colinhacks
Copy link

cc @StefanTerdell

publishing a 3.25.x for zod-to-json-schema would go a long way here.

package.json Outdated
"raw-body": "^3.0.0",
"zod": "^3.23.8",
"zod-to-json-schema": "^3.24.1"
"zod": "^3.25 || ^4.0"

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.

Copy link
Contributor Author

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"

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.

Copy link
Contributor

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.

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.

Copy link
Contributor Author

@dclark27 dclark27 Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

@dclark27
Copy link
Contributor Author

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.

@mattzcarey
Copy link
Contributor

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 :)

@dclark27
Copy link
Contributor Author

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!

@dclark27 dclark27 force-pushed the feature/zod-v3-compat branch 2 times, most recently from 733dce2 to 2fce53c Compare November 17, 2025 21:54
@dclark27 dclark27 closed this Nov 17, 2025
@dclark27 dclark27 force-pushed the feature/zod-v3-compat branch from 2fce53c to df56e35 Compare November 17, 2025 23:09
@dclark27 dclark27 reopened this Nov 17, 2025
@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 17, 2025

Open in StackBlitz

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/sdk@1040

commit: 86b51fd

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 17, 2025

Open in StackBlitz

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/sdk@1040

commit: 205d379

@dclark27
Copy link
Contributor Author

dclark27 commented Nov 17, 2025

@mattzcarey good to review again

Give it a rip npm install @socotra/modelcontextprotocol-sdk@next

@dclark27
Copy link
Contributor Author

dclark27 commented Nov 18, 2025

@mattzcarey StefanTerdell/zod-to-json-schema#180 has been merged and the _vendor folder has been removed. New changes have been brought in and merge conflicts resolved. cc @colinhacks

@colinhacks
Copy link

A new version of zod-to-json-schema that supports Zod 3.25+ has been released. Theoretically you could now avoid vendoring that package (but it would still require bumping the min Zod version to 3.25): https://github.com/StefanTerdell/zod-to-json-schema

@dclark27
Copy link
Contributor Author

A new version of zod-to-json-schema that supports Zod 3.25+ has been released. Theoretically you could now avoid vendoring that package (but it would still require bumping the min Zod version to 3.25): https://github.com/StefanTerdell/zod-to-json-schema

Yep! I removed it ~an hour after the PR landed.

@mattzcarey
Copy link
Contributor

Reviewing this today. Thanks for all your work :)

Copy link
Contributor

@mattzcarey mattzcarey left a 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.

@mattzcarey
Copy link
Contributor

Hey @dclark27 could you give maintainers permissions to fix the rebase or would you be happy to do it :)

@dclark27
Copy link
Contributor Author

dclark27 commented Nov 19, 2025

@mattzcarey
Looks like my org restricts that option, can you let me know what you'd like for the rebase and I'd be happy to do it! Otherwise I can recreate this changeset under my personal github account, not ideal for PR history though

@mattzcarey
Copy link
Contributor

Ahh dont worry about it @dclark27 it might be github freaking out but i see this.

Screenshot 2025-11-19 at 17 00 00

@dclark27
Copy link
Contributor Author

dclark27 commented Nov 19, 2025

@mattzcarey working on it now!

edit: good to go

Copy link
Contributor

@felixweinberger felixweinberger left a 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.yaml file as we're standardizing on npm atm
  • @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 v3 separately.

"peerDependencies": {
"@cfworker/json-schema": "^4.1.1"
"@cfworker/json-schema": "^4.1.1",
"zod": "^3.25 || ^4.0"
Copy link
Contributor

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.

Copy link
Contributor

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';
Copy link
Contributor

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.

@felixweinberger felixweinberger merged commit 418b7f9 into modelcontextprotocol:main Nov 19, 2025
6 checks passed
@ryoppippi
Copy link

Thank you so much!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants