-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Description
Summary
The @modelcontextprotocol/sdk
package causes severe memory consumption during TypeScript compilation, leading to out-of-memory (OOM) errors in CI/CD environments and even locally with constrained memory. This issue affects projects that import the SDK, particularly in containerized build environments.
Environment Details
Package Version
@modelcontextprotocol/sdk
:^1.18.2
- TypeScript:
5.7.2
- Node.js:
22.17.1
- pnpm:
9.0.0
Project Context
- Project Type: TypeScript monorepo with Turborepo
- Architecture: Node.js backend (Fastify) with shared types package
- Build Tool: TypeScript compiler (
tsc
) - CI Environment: GitLab CI with Kubernetes runners
- Local Environment: macOS with 16GB RAM
Affected Imports
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
Problem Description
Memory Consumption Analysis
- Expected: ~170MB for a 32-file TypeScript project (1,800 lines total)
- Actual: 4GB+ memory usage leading to heap exhaustion
- Root Cause: TypeScript compiler processes 430+ files instead of expected 32 files
- Files breakdown:
- Project source files: 32
- MCP SDK type definitions: 104
.d.ts
files - Total package size: 9.1MB
- Additional transitive dependencies pulled in during type resolution
Error Symptoms
Local Development (512MB heap limit)
<--- Last few GCs --->
[88854:0x130008000] 15675 ms: Mark-Compact (reduce) 1020.8 (1047.8) -> 1020.0 (1043.8) MB
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
CI Environment (4GB heap limit)
<--- Last few GCs --->
[109:0xe7de000] 333165 ms: Mark-Compact 4037.9 (4128.7) -> 4022.3 (4128.9) MB
[109:0xe7de000] 336634 ms: Mark-Compact 4038.1 (4128.9) -> 4022.6 (4129.2) MB
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
Stack Trace Analysis
The crash shows repeated InterpreterEntryTrampoline
calls, indicating potential infinite recursion or circular dependency resolution during TypeScript compilation:
171: 0x101990ef0 Builtins_InterpreterEntryTrampoline [node]
172: 0x101990ef0 Builtins_InterpreterEntryTrampoline [node]
[... repeated 200+ times ...]
Attempted Solutions
1. Memory Limit Increases (❌ Failed)
- Increased Node.js heap from 4GB to 5GB
- Used Kubernetes high-memory runners (8GB+)
- Result: Still hit OOM, just took longer
2. TypeScript Configuration Optimizations (❌ Insufficient)
{
"compilerOptions": {
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"incremental": false,
"declaration": false,
"isolatedModules": true,
"strict": false
}
}
- Result: Reduced memory slightly but still exceeded 4GB
3. Node.js Runtime Optimizations (❌ Insufficient)
NODE_OPTIONS="--max-old-space-size=4096 --gc-interval=50 --max-semi-space-size=64"
- Result: Failed due to invalid flags, and valid flags didn't solve the core issue
Working Solution
TypeScript Compilation with --noCheck
Flag
The only effective solution was to bypass type checking during the build process:
{
"scripts": {
"build": "NODE_OPTIONS=\"--max-old-space-size=1536\" tsc -p tsconfig.build.json --noCheck"
}
}
Results:
- ✅ Memory usage: 512MB (down from 4GB+)
- ✅ Build time: ~18 seconds (acceptable)
- ✅ Output: Proper JavaScript transpilation
⚠️ Trade-off: No type checking during build (moved to separate lint step)
Impact Assessment
CI/CD Pipeline Impact
- Build failures: 100% failure rate on standard and high-memory runners
- Resource waste: Requiring oversized CI runners for simple TypeScript projects
- Development velocity: Blocked deployments and feature development
Developer Experience Impact
- Local development: Forced to use
--noCheck
workaround - Type safety: Had to separate type checking from build process
- Debugging: Difficult to identify if issues are project-specific or package-related
Technical Analysis
File Resolution Explosion
Normal TypeScript compilation for our project:
# Expected files
find src -name "*.ts" | wc -l
# Output: 32
# Actual files processed by TypeScript with MCP SDK
tsc --listFiles | wc -l
# Output: 430+
Package Dependency Analysis
# MCP SDK type definitions
find node_modules/@modelcontextprotocol -name "*.d.ts" | wc -l
# Output: 104
# Package size
du -sh node_modules/.pnpm/@modelcontextprotocol+sdk@1.18.2
# Output: 9.1M
Reproduction Steps
- Create a TypeScript project with the MCP SDK dependency
- Import any module from
@modelcontextprotocol/sdk
- Run TypeScript compilation with memory monitoring:
NODE_OPTIONS="--max-old-space-size=1024" npx tsc --build
- Observe memory growth to 1GB+ for even minimal projects
Expected Behavior
TypeScript compilation should:
- Process only necessary files for the specific imports used
- Consume reasonable memory proportional to project size
- Complete successfully on standard CI runners (2-4GB memory)
- Not require
--noCheck
workarounds for basic functionality
Suggested Investigation Areas
- Type Definition Complexity: Review if type definitions can be simplified or split
- Circular Dependencies: Check for circular references in type definitions
- Import Strategy: Consider if barrel exports or deep imports cause different behavior
- TypeScript Compatibility: Test with different TypeScript versions for regressions
- Bundle Analysis: Analyze what specific files cause the memory explosion
Additional Context
This issue appears to be related to similar TypeScript memory problems reported in the ecosystem:
- Complex type definitions causing exponential memory growth
- Type resolution loops in certain package configurations
- Known issues with TypeScript 5.x memory management in specific scenarios
The fact that --noCheck
completely resolves the issue suggests the problem is specifically in the type checking/resolution phase rather than the transpilation phase.
Workaround Impact
While our workaround is functional, it has implications:
- Reduced type safety: Build process no longer catches type errors
- Increased complexity: Separate type checking step required
- CI configuration: Special handling needed for affected packages
- Developer confusion: Non-obvious solution to a common import
We would greatly appreciate investigation into this issue to restore normal TypeScript compilation capabilities for projects using the MCP SDK.