What's going on?
Client is Claude Code, running the server over stdio as npx @playwright/mcp@latest --headless --browser chromium. chromium-1243, Node v22.22.3, Debian 13, 16 cores.
The server launches a browser on the first tool call and keeps it until the process exits. As far as I can tell there's no way to put a bound on that.
Usually that's fine. But if the last thing I did was navigate to a page with a running requestAnimationFrame loop, the browser just carries on rendering it. Headless chromium uses --use-angle=swiftshader-webgl, so a WebGL canvas gets rasterized on the CPU, and the gpu-process then sits at around 700% (13 raster threads) for as long as the server is up. I've had that go for 30 and for 90 minutes before I noticed, with load average up around 22 on a 16 core box.
I don't think it's a process leak. If I SIGTERM or SIGKILL the server the whole browser tree goes with it, both times I tried. The browser stays up because the server does, and a client will normally keep a stdio server running for the whole session.
The workaround is to call browser_close, but that leaves every client having to remember it every time, and closing at end of session is too late to help. --timeout-action, --timeout-navigation and --timeout-settle are all per operation, so none of them cover this.
Would you consider something like --timeout-idle <ms>, closing the browser after that long with no tool call and relaunching on the next one? The lazy launch already exists for the first call.
To reproduce:
- Start
npx @playwright/mcp@latest --headless --browser chromium.
browser_navigate to any page with a continuous WebGL rAF loop.
- Stop issuing tool calls, leave the server up.
ps -eo pid,pcpu,args --sort=-pcpu | grep '[m]s-playwright'
Happy to put together a PR if you'd take one, but I'd rather hear first whether you want this at all and how you'd want it defaulted.
Version
@playwright/mcp 0.0.80
What's going on?
Client is Claude Code, running the server over stdio as
npx @playwright/mcp@latest --headless --browser chromium. chromium-1243, Node v22.22.3, Debian 13, 16 cores.The server launches a browser on the first tool call and keeps it until the process exits. As far as I can tell there's no way to put a bound on that.
Usually that's fine. But if the last thing I did was navigate to a page with a running requestAnimationFrame loop, the browser just carries on rendering it. Headless chromium uses
--use-angle=swiftshader-webgl, so a WebGL canvas gets rasterized on the CPU, and the gpu-process then sits at around 700% (13 raster threads) for as long as the server is up. I've had that go for 30 and for 90 minutes before I noticed, with load average up around 22 on a 16 core box.I don't think it's a process leak. If I SIGTERM or SIGKILL the server the whole browser tree goes with it, both times I tried. The browser stays up because the server does, and a client will normally keep a stdio server running for the whole session.
The workaround is to call
browser_close, but that leaves every client having to remember it every time, and closing at end of session is too late to help.--timeout-action,--timeout-navigationand--timeout-settleare all per operation, so none of them cover this.Would you consider something like
--timeout-idle <ms>, closing the browser after that long with no tool call and relaunching on the next one? The lazy launch already exists for the first call.To reproduce:
npx @playwright/mcp@latest --headless --browser chromium.browser_navigateto any page with a continuous WebGL rAF loop.ps -eo pid,pcpu,args --sort=-pcpu | grep '[m]s-playwright'Happy to put together a PR if you'd take one, but I'd rather hear first whether you want this at all and how you'd want it defaulted.
Version
@playwright/mcp 0.0.80