modelcontextprotocol / modelcontextprotocol/typescript-sdk
Bulk tool registration causes EventEmitter memory leak warnings
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 13.4k
- Forks
- 2.2k
- Avg merge
- 3d 15h
- Merged PRs (30d)
- 4
Description
Problem Description
When registering many tools dynamically (80+ tools), the MCP SDK triggers EventEmitter memory leak warnings due to individual sendToolListChanged() calls per tool registration.
Root Cause
- Each
server.tool()call automatically triggerssendToolListChanged() - Rapid notifications overwhelm stdout buffer in
StdioServerTransport - Multiple
'drain'listeners accumulate temporarily, exceeding Node.js default limit (10)
Stack Trace
MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 drain listeners added to [Socket]. MaxListeners is 10.
at genericNodeError (node:internal/errors:983:15)
at wrappedFn (node:internal/errors:537:14)
at _addListener (node:events:581:17)
at Socket.addListener (node:events:599:10)
at Readable.on (node:internal/streams/readable:1131:35)
at Socket.once (node:events:643:8)
at StdioServerTransport.send (/@modelcontextprotocol/sdk/dist/esm/server/stdio.js:73:30)
at Promise.resolve.then.then._a (/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js:151:83)
Reproduction Steps
- Create an MCP server with dynamic tool registration
- Register 80+ tools rapidly in a loop:
for (const tool of manyTools) { server.tool(tool.name, tool.description, tool.schema, tool.handler); } - Observe EventEmitter memory leak warnings in stderr
Expected Behavior
- Bulk tool registration should not trigger memory leak warnings
- Efficient batch operations without notification spam
Current Workaround
// Increase maxListeners before bulk registration
process.stdout.setMaxListeners(100);
Proposed Solutions
- Batch Notification API: Add optional
deferparameter totool()method - Bulk Registration: Add
registerTools(tools[])method with single notification - Increase Default MaxListeners: Set higher default for stdio transport
- Documentation: Document bulk registration patterns and best practices
Use Case
Servers like XcodeBuildMCP that load 80+ tools dynamically based on user context need efficient bulk registration without warning spam. Dynamic tool loading is becoming common for context-aware MCP servers.
Environment
- MCP SDK Version: 1.17.1
- Node.js Version: 18+
- Transport: StdioServerTransport
- Platform: macOS/Linux
Impact
- False positive memory leak warnings confuse developers
- Performance degradation from stdout buffer backpressure
- Client receives excessive individual
ToolListChangedNotificationmessages
The core issue is that the MCP SDK wasn't designed for bulk tool registration scenarios common in dynamic, context-aware servers.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the server.tool() registration flow and StdioServerTransport.send, using the provided 80+ tool reproduction to observe drain listeners and notifications. Compare the proposed batching or deferred-notification approaches, then verify that bulk registration avoids warning spam while preserving the expected tool-list update behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, typescript
- Domain
- backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100