Skip to content

feat(cli): shut idle headless sessions down after an hour - #42676

Merged
Yury Semikhatsky (yury-s) merged 4 commits into
microsoft:mainfrom
yury-s:fix-cli-460
Sep 11, 2026
Merged

Yury Semikhatsky (yury-s) merged 4 commits into
microsoft:mainfrom
yury-s:fix-cli-460

Conversation

@yury-s

@yury-s Yury Semikhatsky (yury-s) commented Sep 11, 2026

Copy link
Copy Markdown
Member

Summary

  • A CLI session whose browser is headless and launched by Playwright now shuts itself down after an hour without commands, the same way close does, so a session an agent never closed stops holding a browser. Headed and attached browsers are left alone.
  • The MCP server applies the same default, closing the browser and launching a new one on the next tool call.
  • --idle-timeout <ms> on open, attach and the MCP server overrides the default in any mode, 0 disables it. Also settable as timeouts.idle in the config file or PLAYWRIGHT_MCP_IDLE_TIMEOUT. The MCP option was named --timeout-idle in 1.64.0-next and is renamed here before it ships.
  • IdleTimer gains poke(), called when a tool call starts and once when a CLI session is ready, which covers a session that never receives a command.

Fixes microsoft/playwright-cli#460

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should bubble up from the tools/backend/Context. It should self-destruct upon inactivity, which will be destroying backend server.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

Copy link
Copy Markdown
Contributor

🟢 CI is clear — the one failure is a pre-existing Firefox flake

Hi, I'm the Playwright bot and I took a first look at the failing check.

The latest merge report (run 34641795387) has a single failure, [firefox] › mcp/cli-core.spec.ts:123 › select, and it's a known Firefox-only flake — not something this PR caused. This PR only wires up idle-session shutdown (idleTimer.ts, cli-daemon/*, mcp/program.ts, mcp/config.ts); the failing test just performs a CLI select and never touches idle timeouts.

Details

Pre-existing flake / infra

  • [firefox] › mcp/cli-core.spec.ts:123 › select — rare Firefox-only flake. Across the test-results DB it fails only on firefox (2 of 716 runs; 0 failures on chromium/chrome/msedge/webkit over 700+ runs each) and both failures are on SHAs this PR can't be responsible for: a push on main (sha a5e5632, run 33913247836, 2026-09-04) and PR feat(ui-mode): update individual snapshots #42421 (sha f4dc9b9, run 32992366860, 2026-08-26) — both before this branch. This PR's diff is scoped to the idle-timeout shutdown path, which the CLI select flow doesn't exercise, and a Firefox-only failure in code the PR didn't change for that engine reinforces the flake read. Note the earlier runs on this same PR failed different tests (mcp/cli-core.spec.ts:262, mcp/annotate.spec.ts, mcp/cli-devtools.spec.ts:173) that then passed — churn across reruns is itself a flake tell.

Triaged by the Playwright bot - agent run

The daemon now honors timeouts.idle and defaults it to one hour for
headless browsers it launched, exiting the same way `close` does. Headed
and attached browsers keep running unless a timeout is set explicitly.
`open --idle-timeout=<ms>` overrides the default and 0 disables it.

The MCP server gets the same default, and its option is renamed to
--idle-timeout to match.

Fixes microsoft/playwright-cli#460
Drops the running-call bookkeeping: a tool call is expected to be short
relative to the timeout, so restarting the countdown when the call starts
is enough and removes the callTool wrapper.
@github-actions

This comment has been minimized.

Also drops unref(): both the MCP server and the CLI daemon exit through
process.exit(), so the timer never decides whether the process lives.
@yury-s
Yury Semikhatsky (yury-s) merged commit 3b346c8 into microsoft:main Sep 11, 2026
17 checks passed
@yury-s
Yury Semikhatsky (yury-s) deleted the fix-cli-460 branch September 11, 2026 22:51
@github-actions

Copy link
Copy Markdown
Contributor

Test results for "MCP"

8509 passed, 1436 skipped


Merge workflow run.

Yury Semikhatsky (yury-s) added a commit to microsoft/playwright-mcp that referenced this pull request Sep 14, 2026
## What's New

### 🎉 New Tools

- **`browser_webmcp_list` / `browser_webmcp_call`** — List and call the
tools a page registers through the
[WebMCP](https://webmachinelearning.github.io/webmcp/) API, letting the
page do the work instead of driving its UI. When a page has WebMCP
tools, the page status reports how many are available
([#42613](microsoft/playwright#42613)). WebMCP
is experimental, see [WebMCP in
Chrome](https://developer.chrome.com/docs/ai/webmcp) for how to enable
it.

### Other Changes

- New `--profile-dir-name <name>` option (env
`PLAYWRIGHT_MCP_PROFILE_DIR_NAME`) selects the Chrome profile to connect
to in extension mode when the extension is installed in several
profiles, for example `"Profile 1"`
([#42527](microsoft/playwright#42527))
- Headless browsers launched by the server are now closed after one hour
without tool calls; the next tool call launches a new one. Use
`--idle-timeout <ms>` (config `timeouts.idle`, env
`PLAYWRIGHT_MCP_IDLE_TIMEOUT`) to change the timeout, `0` disables it.
Headed and attached browsers are not closed unless a timeout is set
explicitly
([#42663](microsoft/playwright#42663),
[#42676](microsoft/playwright#42676))
- `--image-responses` accepts `only`: a response that carries an image
consists of the image parts alone, without the text part
([#42672](microsoft/playwright#42672))

## Bug Fixes

- `browser_close` returns an error when the browser context is shared
(`--shared-browser-context`) instead of breaking the calling client's
session. This supersedes the v0.0.80 change that dropped the backend
after `browser_close`
([#42495](microsoft/playwright#42495))
- With `--shared-browser-context`, `browser_start_recording` /
`browser_stop_recording` (opt-in via `--caps=devtools`) keep each
client's recording separate instead of delivering one client's recorded
actions to another
([#42622](microsoft/playwright#42622),
[#42627](microsoft/playwright#42627))
- The file access check follows symlinks, so a symlink inside the
workspace can no longer be used to read or write files outside the
allowed roots
([#42628](microsoft/playwright#42628))
- Explicitly named output files in a nested directory (e.g.
`sub/shot.png`) no longer fail with `ENOENT`; `browser_file_upload` and
`browser_drop` resolve relative paths against the workspace root
([#42540](microsoft/playwright#42540))
- In extension mode with `PLAYWRIGHT_MCP_EXTENSION_TOKEN` set, a
connection that never completes (e.g. the token belongs to another
Chrome profile) now fails after 30 seconds with a hint instead of
hanging the tool call forever
([#42525](microsoft/playwright#42525))
- Disable the Chromium sandbox by default on Linux for the bundled
Chromium build, which lacks the setuid sandbox helper
([#42490](microsoft/playwright#42490))
Yury Semikhatsky (yury-s) added a commit to microsoft/playwright-cli that referenced this pull request Sep 14, 2026
## What's New

### 🎉 New Commands

- **`webmcp-list` / `webmcp-call`** — List and call the tools a page
registers through the
[WebMCP](https://webmachinelearning.github.io/webmcp/) API, letting the
page do the work instead of driving its UI. When a page has WebMCP
tools, the page status reports how many are available
([#42613](microsoft/playwright#42613)). WebMCP
is experimental, see [WebMCP in
Chrome](https://developer.chrome.com/docs/ai/webmcp) for how to enable
it.

### Other Changes

- Headless sessions now shut down after one hour without commands, so a
session an agent never closed no longer holds a browser; run `open`
again to start a new one. Use `open --idle-timeout <ms>` (config
`timeouts.idle`, env `PLAYWRIGHT_MCP_IDLE_TIMEOUT`) to change the
timeout, `0` disables it. Headed browsers stay open, and attached
browsers are only detached when `attach --idle-timeout <ms>` is set
([#42676](microsoft/playwright#42676))
- The skill includes a guide for attaching screenshots and videos to
pull requests with `gh --attach`
([#42645](microsoft/playwright#42645))

## Bug Fixes

- Session daemons exit when their control socket is deleted or replaced,
instead of staying alive with the browser
([#42454](microsoft/playwright#42454))
- Explicitly named output files in a nested directory (e.g. `screenshot
--filename=sub/shot.png`) no longer fail with `ENOENT`
([#42540](microsoft/playwright#42540))
- Video chapters and screencast overlays are no longer hidden behind
open dialogs and popovers
([#42642](microsoft/playwright#42642))
- `npx playwright test --debug=cli` works for tests that create more
than one browser context and for every test in a worker, not just the
first ([#42503](microsoft/playwright#42503))
- With `PLAYWRIGHT_MCP_EXTENSION_TOKEN` set, `attach --extension` fails
after 30 seconds with a hint when the extension never connects (e.g. the
token belongs to another Chrome profile) instead of hanging forever
([#42525](microsoft/playwright#42525))
- Disable the Chromium sandbox by default on Linux for the bundled
Chromium build, which lacks the setuid sandbox helper
([#42490](microsoft/playwright#42490))

## Upgrading

```bash
npm install -g @playwright/cli@0.1.20
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Daemon has no lifetime bound: sessions opened by agents each leak a headless Chrome

2 participants