Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

dclark27
Copy link

@dclark27 dclark27 commented Aug 12, 2025

Upgrade to Zod v4 for compatibility with v3 and v4.

  • Replaces zod-to-json-schema with a temporary utility inside of mcp.ts until zod-to-json-schema supports v4.
  • Runs https://github.com/nicoespeon/zod-v3-to-v4 and then manual changes after the fact to clean up any remaining issues.
  • Includes a small zod-to-json schema patch since that does not support zod 4 yet, should be replaced once released
  • Small tweak to jest.config to get things running again

Note, it wasn't clear which formatter to use so some commas changed and some lines I did not intend to.

Motivation and Context

This has been a blocking issue for my team and many others. When versions mismatch across dependencies with older Zod versions, memory leaks become present and can slow or stall development.

This also will help unblock downstream dependencies, such as with vercel's AI SDK and mcp-tools.

#494
vercel/ai#7160
vercel/mcp-handler#93

How Has This Been Tested?

  • Ran the full test suite locally:
    • 34 test suites, 669 tests, all passing (no linter errors introduced)
  • Validated scenarios:
    • Tools with input schema: names and types appear as expected
    • Tools with output schema: JSON schema produced and used for server-side validation
    • Optional fields correctly omitted from required, enums produce { type: "string", enum: [...] }
  • Install to my Next.js app that spins up a remote MCP with tools and was able to successfully call them
  • Nested objects supported recursively
  • Platform: macOS, Node >= 18

Breaking Changes

Users will need to use Zod 3.25.76+ or Zod 4 and import from either /v3 or /v4.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • 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
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

@dclark27 dclark27 requested review from a team as code owners August 12, 2025 17:43
@dclark27 dclark27 requested review from ochafik and domdomegg August 12, 2025 17:43
@dclark27 dclark27 changed the title Zod v4 feat: zod v4 Aug 12, 2025
enum?: string[];
};

function zodToJsonSchema(schema: ZodObject<ZodRawShape>): JsonSchema {
Copy link
Member

Choose a reason for hiding this comment

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

Still need to think about this PR more broadly, e.g. what the impacts of this potentially breaking change will be.

But I think for this we could use https://zod.dev/json-schema instead?

Copy link
Author

Choose a reason for hiding this comment

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

Happy to give it a shot today!

Copy link
Author

@dclark27 dclark27 Aug 13, 2025

Choose a reason for hiding this comment

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

@domdomegg
So I definitely just had a misunderstanding of how the new toJSONSchema method from Zod 4 worked -- just updated and stripped out the custom code in favor of that. Tests passed without issue. Check it out!

@ihrpr
Copy link
Contributor

ihrpr commented Aug 13, 2025

Thanks for working on this. We are preparing for Typescript V2, this potentially can be included there

@ihrpr ihrpr added this to the v2 milestone Aug 13, 2025
@dclark27
Copy link
Author

Thanks for working on this. We are preparing for Typescript V2, this potentially can be included there

Let me know if I can help! @ihrpr

@@ -25,8 +25,8 @@ const getServer = () => {
'start-notification-stream',
'Starts sending periodic notifications',
{
interval: z.number().describe('Interval in milliseconds between notifications').default(1000),
count: z.number().describe('Number of notifications to send').default(10),
interval: z.number().describe('Interval in milliseconds between notifications').prefault(1000),

Choose a reason for hiding this comment

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

why is prefault preferred in this case?
as far as I understand from https://zod.dev/v4/changelog#default-updates it's about expected input type (in their example it's a string) and output type (in their example the string goes through transform to output a number)

looks like here default will work as well since input type is same as output type - number

Copy link
Author

Choose a reason for hiding this comment

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

yeah we can use default! let me get it updated. the util I used defaults to prefault to preserve default functionality so I left it as is.

@dclark27
Copy link
Author

dclark27 commented Aug 19, 2025

@avivnakar / all

Updated with main, resolved conflicts, reverted to use default over prefault. I've been running since this PR went live by publishing behind our org and it's been lovely!

Comment on lines 2 to 4
// Lightweight replacement for zod-to-json-schema tailored for this SDK's needs.
// Produces a minimal JSON Schema subset: { type: "object", properties, required? }
// Supports primitives, enums, and nested objects. Sufficient for our tool list output tests.
Copy link

Choose a reason for hiding this comment

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

obsolete comment

@ochafik
Copy link
Contributor

ochafik commented Sep 8, 2025

Hi @dclark27, thanks for your work on this!

I wonder if the v3 & v4 compatibility can be tested (and maybe documented)? Maybe adding v3 as a dev dependency and have some tests explicitly importing the /v3 paths?

Copy link
Contributor

@ochafik ochafik 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, with some reservations:

  • Can we provide some testing of backwards compatibility (client / server code w/ v3)
  • Wonder how this will interplay w/ #792 (what is the v4 equiv. of strip? ideally we'll want to merge the two PRs to see how they mesh)

@JosephAnson
Copy link

Just thought I'd let you know after reading the guide here (https://zod.dev/library-authors?id=how-to-support-zod-4) for library authors, you shouldn't be importing from zod/v4 for library usage, it should be zod/v4/core. There is also recommendations for having it work simultaneously with v3 and v4 of zod: https://zod.dev/library-authors?id=how-to-support-zod-and-zod-mini-simultaneously.

@dclark27
Copy link
Author

dclark27 commented Sep 9, 2025

@ochafik

Two ways forward here, I can adjust this PR to include backward compatibility with v3 and go adjust his PR after it merges, or I can merge his branch into mine and tackle holistically once theirs is merged.

We can use strictObject and looseObject for interplay it looks like. https://zod.dev/v4/changelog?id=deprecates-strict-and-passthrough

For now I will start with backward compatibility in this branch and see what progress is made with #792 unless you have a strong preference.

@dclark27
Copy link
Author

dclark27 commented Sep 9, 2025

cc: @ochafik @domdomegg

I have updated this branch with main and resolved conflicts. There is a blocking issue though preventing us from supporting Zod v3 and v4, which is that zod-to-json-schema does not allow 3.25 as a peer dependency.

  • Zod 3.23
    • Fine for zod-to-json-schema library and we could use to fallback schema generation, however it is not cross compatible with zod v4
  • Zod 3.35
    • Cross compatible with zod 4 but cannot use zod-to-json-schema for fallback schema generation due to peer dependency issue
  • Zod 4
    • Implements z.toJsonSchema and the dependency is not required.

Check out my changes here with backwards compatibility changes and extra regression tests for v3 and v4: socotra@c1e5d38

We might be blocked until StefanTerdell/zod-to-json-schema#180 is merged. Others have published around them but I'd rather find another option.

@KKonstantinov
Copy link
Contributor

Could the migration to zod v4 replace the usage of Ajv since Zod v4 supports json schema conversion natively?

@punkpeye
Copy link

Have you by any chance published this branch on npm?

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