-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Open
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
defer
parameter 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
ToolListChangedNotification
messages
The core issue is that the MCP SDK wasn't designed for bulk tool registration scenarios common in dynamic, context-aware servers.
Metadata
Metadata
Assignees
Labels
No labels