Summary
On a long-lived self-hosted chrome-devtools-mcp 1.7.0 deployment, a page left open after an agent finishes can continue consuming substantial CPU indefinitely even though there are no MCP tool calls in flight.
This appears distinct from the 1.6.0 memory/source-map issues in #2431 / #2456, which are marked fixed in 1.7.0. The problem here is lifecycle: an active page remains live forever unless the client explicitly navigates it away/closes it or the server/browser process is recycled.
Environment
chrome-devtools-mcp 1.7.0
- Linux x86_64
- Headless Chrome launched by the MCP server
- Persistent, long-lived MCP gateway/server
- Docker container with a 2 GiB memory limit
- Real-world, script-heavy SPA as the target
Observed behaviour
A stale page left by a completed investigation held roughly 28–30% CPU continuously for hours on a 4-core host.
Without restarting the container or MCP gateway, simply closing/navigating the stale page away and leaving only about:blank dropped container CPU to roughly 0.03%, then effectively 0%.
The relevant Chrome launch configuration disables background throttling for debugging accuracy, so a page that remains open can legitimately keep timers/rendering/network activity alive in the background. That behaviour is useful while an investigation is active, but there is currently no lifecycle boundary once the client disappears or stops making calls.
Why this is operationally awkward
For a persistent remote MCP service, persistence currently means browser/page state can survive indefinitely. If a client vanishes without cleanup, the server has no way to distinguish "active investigation" from "abandoned live page".
This is particularly noticeable on dynamic SPAs where background timers, polling, rendering or other work continue after the agent is gone.
Production workaround tested successfully
I added an external gateway lifecycle around the upstream 1.7.0 server with two idle stages:
-
Park after a shorter idle period
- retain one page
- close other stale pages
- select the retained page
- navigate it to
about:blank
-
Recycle after a longer idle period
- stop and recreate only the internal
chrome-devtools-mcp child
- keep the public gateway/container alive
- release retained V8/performance/browser state
The production thresholds I tested were:
- park: 20 minutes idle
- recycle: 60 minutes idle
- lifecycle check: 10 seconds
Long-running manual operations such as a performance trace or screencast hold an activity lease so lifecycle maintenance does not interrupt legitimate work.
Acceptance evidence from the lifecycle implementation
In isolated testing:
- a live test page was automatically parked to
about:blank
- post-park CPU fell to about 0.13%
- a manual performance-trace lease prevented both park and recycle while the trace was active
- after the trace stopped, one park and one internal recycle occurred
- child PID changed while the Docker container remained running
- working set fell from roughly 327 MiB to 139 MiB
- CPU fell to about 0.02%
- Docker restart count remained zero
- the MCP tool surface still worked after recycle
In production, the same approach removed a stale-page case that had been burning roughly 28–30% CPU for hours.
Suggested upstream direction
Would you be open to an upstream idle lifecycle for persistent server usage, for example:
- track external MCP tool activity
- park stale pages after configurable idle time
- optionally recycle/recreate internal browser/server state after a longer idle period
- protect manual traces/screencasts or other long-running operations with an explicit activity lease
I have a tested implementation in a persistent gateway wrapper and can adapt the concept into an upstream PR if this is a direction the project would accept.
I am deliberately filing this separately from the previous memory issues because 1.7.0 fixed those specific regressions, while this stale-page CPU/lifecycle behaviour is still reproducible on 1.7.0.
Summary
On a long-lived self-hosted
chrome-devtools-mcp1.7.0 deployment, a page left open after an agent finishes can continue consuming substantial CPU indefinitely even though there are no MCP tool calls in flight.This appears distinct from the 1.6.0 memory/source-map issues in #2431 / #2456, which are marked fixed in 1.7.0. The problem here is lifecycle: an active page remains live forever unless the client explicitly navigates it away/closes it or the server/browser process is recycled.
Environment
chrome-devtools-mcp1.7.0Observed behaviour
A stale page left by a completed investigation held roughly 28–30% CPU continuously for hours on a 4-core host.
Without restarting the container or MCP gateway, simply closing/navigating the stale page away and leaving only
about:blankdropped container CPU to roughly 0.03%, then effectively 0%.The relevant Chrome launch configuration disables background throttling for debugging accuracy, so a page that remains open can legitimately keep timers/rendering/network activity alive in the background. That behaviour is useful while an investigation is active, but there is currently no lifecycle boundary once the client disappears or stops making calls.
Why this is operationally awkward
For a persistent remote MCP service, persistence currently means browser/page state can survive indefinitely. If a client vanishes without cleanup, the server has no way to distinguish "active investigation" from "abandoned live page".
This is particularly noticeable on dynamic SPAs where background timers, polling, rendering or other work continue after the agent is gone.
Production workaround tested successfully
I added an external gateway lifecycle around the upstream 1.7.0 server with two idle stages:
Park after a shorter idle period
about:blankRecycle after a longer idle period
chrome-devtools-mcpchildThe production thresholds I tested were:
Long-running manual operations such as a performance trace or screencast hold an activity lease so lifecycle maintenance does not interrupt legitimate work.
Acceptance evidence from the lifecycle implementation
In isolated testing:
about:blankIn production, the same approach removed a stale-page case that had been burning roughly 28–30% CPU for hours.
Suggested upstream direction
Would you be open to an upstream idle lifecycle for persistent server usage, for example:
I have a tested implementation in a persistent gateway wrapper and can adapt the concept into an upstream PR if this is a direction the project would accept.
I am deliberately filing this separately from the previous memory issues because 1.7.0 fixed those specific regressions, while this stale-page CPU/lifecycle behaviour is still reproducible on 1.7.0.