TS2589: Type instantiation is excessively deep and possibly infinite after upgrading the SDK?This TypeScript error can appear when upgrading to newer SDK versions that support Zod v4 (for example, from older @modelcontextprotocol/sdk releases to newer @modelcontextprotocol/client / @modelcontextprotocol/server releases) and your project ends up with multiple
zod versions in the dependency tree.
When there are multiple copies or versions of zod, TypeScript may try to instantiate very complex, cross-version types and hit its recursion limits, resulting in TS2589. This scenario is discussed in GitHub issue
#1180.
To diagnose and fix this:
zod versions:
npm ls zod or npm explain zod, pnpm list zod or pnpm why zod, or yarn why zod and check whether more than one version is installed.zod version:
zod use a compatible version range so that your package manager can hoist a single copy.zod at the workspace root and using compatible ranges in individual packages.overrides / resolutions to force a single zod version if some transitive dependencies pull in a different one.Once your project is using a single, compatible zod version, the TS2589 error should no longer occur.
globalThis.crypto) for client authentication in older Node.js versions?The SDK’s OAuth client authentication helpers (for example, those in packages/client/src/client/auth-extensions.ts that use jose) rely on the Web Crypto API exposed as globalThis.crypto. This is especially important for client credentials and JWT-based
authentication flows used by MCP clients.
globalThis.crypto is available by default.globalThis.crypto may not be defined by default. In this repository we polyfill it for tests (see packages/client/vitest.setup.js), and you should do the same in your app if it is missing – or alternatively, run Node with --experimental-global-webcrypto
as per your Node version documentation. (See https://nodejs.org/dist/latest-v18.x/docs/api/globals.html#crypto )If you run clients on Node.js versions where globalThis.crypto is missing, you can polyfill it using the built-in node:crypto module, similar to the SDK's own vitest.setup.ts:
import { webcrypto } from 'node:crypto';
if (typeof globalThis.crypto === 'undefined') {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(globalThis as any).crypto = webcrypto as unknown as Crypto;
}
For production use, you can either:
globalThis.crypto is available by default (recommended), orThe SDK ships several runnable server examples under examples/server/src. Start from the server examples index in examples/server/README.md and the entry-point quick start in the root README.md.
server auth exports?Server authentication & authorization is outside of the scope of the SDK, and the recommendation is to use packages that focus on this area specifically (or a full-fledged Authorization Server for those who use such). Example packages provide an example with better-auth.
server SSE transport?The SSE transport has been deprecated for a long time, and v2 will not support it on the server side any more. Client side will keep supporting it in order to be able to connect to legacy SSE servers via the v2 SDK, but serving SSE from v2 will not be possible. Servers
wanting to switch to v2 and using SSE should migrate to Streamable HTTP.
The v1 API documentation is available at https://ts.sdk.modelcontextprotocol.io/. The v1 source code and any v1-specific fixes live on the long-lived v1.x branch. V2 API docs are at /v2/.