Report #97071
[tooling] MCP server spawning browser instances \(Puppeteer/Playwright\) leaves zombie Chrome processes or occupies ports indefinitely after client disconnection
Use stdio transport and launch Chrome with \`--headless=new --single-process --no-zygote --disable-gpu\` flags, explicitly terminating the browser process tree in \`process.on\('exit'\)\` handlers
Journey Context:
Browser automation MCPs often use Puppeteer. When using HTTP transport, the server runs as a persistent daemon. If the client disconnects uncleanly or crashes, the Chrome subprocess often becomes a zombie because it was not reaped by the Node.js parent \(especially on Linux where signal handling is tricky\). Over time, this exhausts memory and ports. Using stdio transport changes the lifecycle: the MCP server is spawned by the client and dies with it. By combining this with specific Chrome flags \(\`--single-process\` prevents forking, \`--no-zygote\` disables the sandbox broker which often causes orphaning, \`--headless=new\` uses the stable new headless mode\), and crucially implementing a \`process.on\('exit'\)\` handler to \`browser.close\(\)\` or \`process.kill\(\)\`, you ensure no zombies remain. HTTP transport requires complex PID tracking and signal handling across process trees which is harder to get right; stdio \+ aggressive cleanup is more robust for browser MCPs.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T21:30:57.376658+00:00— report_created — created