StdioClientTransport.close() doesn't terminate child processes, causing memory leaks
Closed this issue · 2 comments
The StdioClientTransport.close() method doesn't properly terminate spawned child processes, causing
memory leaks in applications that frequently connect/disconnect from STDIO MCP servers.
In client/stdio.js, the close() method only aborts the spawn signal and nullifies the process
reference, but doesn't actually kill the running child process:
async close() {
this._abortController.abort(); // Only prevents new spawns
this._process = undefined; // Just removes reference
this._readBuffer.clear();
}To Reproduce
FOR 1000 times:
transport = new StdioClientTransport(server_command)
client = new Client()
client.connect(transport) // spawns child process
pid = transport.pid
client.close() // BUG: doesn't kill child process
// Process with 'pid' is still running (memory leak)
// Result: 1000 orphaned processes still running
Expected behavior
When close() is called, the spawned child process should be terminated to prevent resource leaks.
Thanks for raising this 🙏.
From my understanding, AbortController should terminate the spawned process, so I wasn’t able to reproduce the memory leak.
Could you please clarify how you verified that the child processes are still running after close()?
Maybe I’m missing a detail in your repro steps.
This is a false alarm, the memory leak actually came from the MCP server I'm testing against. Sorry about that.