Fix TypeScript Compilation OOM (JavaScript heap out of memory) When Using @modelcontextprotocol/sdk in CI/CD, Turborepo, and Containerized Builds
The @modelcontextprotocol/sdk package causes severe TypeScript compilation memory consumption (4GB+ for a 32-file project vs. expected ~170MB), leading to 'JavaScript heap out of memory' / 'Ineffective mark-compacts near heap limit' OOM errors. Root cause: the SDK's Zod-derived type definitions create deeply nested recursive type structures that cause TypeScript to process 430+ files instead of the expected 32. MCP SDK maintainer felixweinberger acknowledged and bumped to P0 after Microsoft Playwright core maintainer reported being blocked from upgrading. The fix (removing Zod pass-through types) is planned for SDK v2 — not yet released on npm as of June 2026 (latest: v1.29.0). Multiple workarounds exist: tsc --noCheck, any-casting tool callbacks, pinning Zod versions, or downgrading to v1.22.0.
Symptoms
- TypeScript compilation consumes 4GB+ memory for projects importing @modelcontextprotocol/sdk
- FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
- FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
- Stack trace shows 200+ repeated InterpreterEntryTrampoline frames
- tsc processes 430+ files instead of 32 when SDK is imported
- CI/CD pipelines fail with 100% OOM rate on standard runners
Error signatures
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
Builtins_InterpreterEntryTrampoline [node] (repeated 200+ times)
Mark-Compact (reduce) 1020.8 (1047.8) -> 1020.0 (1043.8) MB
Possible causes
- MCP SDK's Zod-derived type definitions (ToolCallback<Args>, server.tool) create deeply nested recursive type structures that cause exponential memory growth during TypeScript type resolution
- The SDK's internal type definitions pull in 104 .d.ts files (9.1MB) with complex conditional/generic types that TypeScript must fully resolve even for simple imports
- Conflicting Zod versions in the dependency tree (e.g., one package pulls Zod v4 while MCP SDK uses Zod v3) cause TypeScript to process both type graphs simultaneously, doubling memory pressure
- Package manager hoisting (npm/yarn/pnpm) can silently resolve different Zod major versions at runtime, triggering the OOM even when 'npm list zod' shows only one version
Solutions
Downgrade @modelcontextprotocol/sdk to v1.22.0
Version 1.22.0 is the last known version where TypeScript compilation memory is manageable. Versions >=1.23.0 introduced Zod v4 dual-support types that increased type complexity, with users reporting memory regression persisting through 1.25.1+. Downgrading to 1.22.0 avoids the newer type definitions while keeping type checking functional.
- Step 1: Install SDK v1.22.0: `npm install @modelcontextprotocol/sdk@1.22.0`
- Step 2: Verify zod dependency is ^3.23.8 (Zod v3 only): `npm view @modelcontextprotocol/sdk@1.22.0 dependencies.zod`
- Step 3: Rebuild and verify memory usage
Commands
npm install @modelcontextprotocol/sdk@1.22.0
npm view @modelcontextprotocol/sdk@1.22.0 dependencies.zod
NODE_OPTIONS="--max-old-space-size=1536" tsc -p tsconfig.build.json
Config examples
// Verified: v1.22.0 has zod ^3.23.8 (v3 only, no v4 dual-support) // Verified: v1.25.1+ has zod ^3.25 || ^4.0 (triggers OOM for some users) // Latest v1.x as of June 2026: v1.29.0
Risks
- Loses features and bug fixes from v1.23.0+ (including Zod v4 MCP server compatibility)
- May have unpatched vulnerabilities in older version
- Not a permanent fix — SDK v2 (unreleased) is the planned permanent fix
Verification
- Step 1: Run `npm view @modelcontextprotocol/sdk@1.22.0 dependencies.zod` → expect: '^3.23.8'
- Step 2: Run `NODE_OPTIONS="--max-old-space-size=1536" tsc -p tsconfig.build.json` → expect: build completes without OOM, exit code 0
- Step 3: Run `tsc --listFiles | wc -l` → expect: significantly fewer files than 430+
Pin to a single Zod version across the entire dependency tree
Ensure only ONE major version of Zod exists in your dependency tree. The OOM is exacerbated when TypeScript must resolve types from both Zod v3 and Zod v4 simultaneously. Use pnpm overrides, npm overrides, or yarn resolutions to force a single Zod version.
- Step 1: Run `npm why zod` (or `pnpm why zod`) to detect duplicate Zod versions
- Step 2: Add package.json overrides to pin all Zod dependencies to a single version
- Step 3: Clear node_modules and lockfile, reinstall, rebuild
Commands
npm why zod
rm -rf node_modules package-lock.json && npm install
npm run build
Config examples
// package.json — npm overrides (npm 8.3+):
{
"overrides": {
"zod": "3.25.76"
}
}
// package.json — pnpm:
{
"pnpm": {
"overrides": {
"zod": "3.25.76"
}
}
}
// package.json — yarn:
{
"resolutions": {
"zod": "3.25.76"
}
}Risks
- May break packages that genuinely require Zod v4 features
- Requires testing all transitive dependencies for Zod v4 compatibility
Verification
- Step 1: Run `npm why zod` → expect: single version of zod listed (e.g., 'zod@3.25.76')
- Step 2: Run `npm run build` → expect: build completes without OOM in < 2 minutes
Use any casting for MCP tool definitions (avoids triggering complex type resolution)
Cast MCP tool callback parameters to `any` instead of using the SDK's generic types. This prevents TypeScript from resolving the deeply nested Zod-derived types entirely, avoiding the memory explosion while keeping type checking enabled for the rest of your project.
- Step 1: Identify all server.tool() and server.registerTool() calls in your MCP server
- Step 2: Replace the typed callback signature with `any` cast
- Step 3: Verify build completes without OOM
Commands
npm run build
Config examples
// Before (triggers OOM):
server.registerTool('search', {
title: 'Search Articles',
description: 'Search the knowledge base',
inputSchema: SearchParamsSchema,
}, async (params: z.infer<typeof SearchParamsSchema>) => {
// implementation
});
// After (avoids OOM):
server.registerTool('search', {
title: 'Search Articles',
description: 'Search the knowledge base',
inputSchema: SearchParamsSchema as any,
}, async (params: any) => {
// implementation — lose param type safety but keep rest of project typed
});Risks
- Loses parameter type safety for MCP tool callbacks
- Individual tool handlers must manually validate/assert types
Verification
- Step 1: Apply `any` cast to all MCP tool callbacks → expect: tsc compilation succeeds without OOM
- Step 2: Verify remaining project type checking still works: run `tsc --noEmit` → expect: only intentional `any` warnings, no new type errors
Build with tsc --noCheck (fastest fix — skips type checking during build)
Add --noCheck flag to TypeScript compilation to bypass type checking entirely during the build step, reducing memory from 4GB+ to ~512MB. Move type checking to a separate lint step that doesn't block builds.
- Step 1: Modify your build script in package.json to add --noCheck
- Step 2: Move type checking to a separate script (e.g., 'typecheck')
- Step 3: Run only the build step in CI; run typecheck as a non-blocking parallel job
Commands
NODE_OPTIONS="--max-old-space-size=1536" tsc -p tsconfig.build.json --noCheck
npm pkg set scripts.typecheck="tsc --noEmit"
Config examples
{
"scripts": {
"build": "NODE_OPTIONS=\"--max-old-space-size=1536\" tsc -p tsconfig.build.json --noCheck",
"typecheck": "tsc --noEmit"
}
}Risks
- No type checking during build — type errors only caught in separate typecheck step
- Does not fix the underlying SDK type definition issue — only bypasses it
Verification
- Step 1: Run `npm run build` with --noCheck → expect: build completes in < 30 seconds with < 1GB memory
- Step 2: Run `npm run typecheck` separately → expect: type errors (if any) reported without OOM crash
Agent JSON
Canonical machine-readable representation of this issue:
{
"issue_id": "3daf6ad4-6760-4b48-9e46-bff577df4ce4",
"slug": "fix-typescript-compilation-oom-javascript-heap-out-of-memory-when-using-modelcontextprotocol-sdk-in-ci-cd-turborepo-and--p0s25g",
"verification_status": "unverified",
"canonical_json": "https://codekb.dev/v1/issues/fix-typescript-compilation-oom-javascript-heap-out-of-memory-when-using-modelcontextprotocol-sdk-in-ci-cd-turborepo-and--p0s25g"
}