文件历史

提交图

44 次代码提交

作者 SHA1 备注 提交日期
Alex Rudenko 58ba174273 refactor: move remaining McpContext getters (#2342)
Moves various getters to McpPage.
2026-07-10 12:46:01 +00:00
Alex Rudenko 8a4ddb3256 refactor: remove isolated context getter (#2336) 2026-07-09 15:13:33 +00:00
Nikolay Vitkov 64005f924f refactor: use helper for Dialog handle (#2334)
Re-use the logic in the wait for helper to expose per dialog type
handling.
2026-07-09 15:12:48 +00:00
Alex Rudenko 9cd734b0a3 refactor: clean up more of the context interface (#2335)
- removed redundant page getters
2026-07-09 13:50:48 +00:00
Alex Rudenko 16db01f79c refactor: clean up page management (#2333)
- remove `#pages` and Puppeteer page getters
- rename methods for clarity
2026-07-09 11:42:11 +00:00
Piotr Paulski a38ef5e7ea test: fix flaky dialog tests by awaiting evaluate promises (#2284)
Fixes flakiness in pages.test.ts where unawaited page.evaluate()
promises triggering dialogs would resolve after the test ended, causing
TargetCloseError when the next test closed the pages.

TAG=agy
CONV=dc6c530f-5d71-4a91-9440-6a7006d168e6

Co-authored-by: Piotr Paulski <piotrpaulski@chromium.org>
2026-07-02 15:44:18 +00:00
Nikolay Vitkov fecef2698d test: reduce type casting in tests (#2251) 2026-06-24 09:45:16 +00:00
Alex Rudenko f8fb2a9236 test: drop node20 code in tests (#2146) 2026-05-27 11:12:22 +00:00
Samiya Caur 64a02d8c8e test: fix flaky navigate_page with open dialog test (#2020)
Attempt to fix flakiness reported in #2019
2026-05-08 11:20:49 +00:00
Samiya Caur f1afe842ae test: add tests for checking behavior when dialog is open (#1977)
This is the first part of adding tests for checking tool behavior when a
dialog is already open (related to #1069)

In future CL, I will be focusing on tools which currently get blocked
due to open dialogs. As part of those CLs, proactive rejection of tool
execution will be implemented.
2026-04-29 10:38:27 +00:00
Alex Rudenko d50255778a feat: support experimental allowlist for navigate tool calls (#1935)
This PR adds an experimental allowlist for the page navigate tool call
(requires `--experimentalNavigationAllowlist`, off by default). The
feature uses a list of URLPatterns to decline navigations that land on
disallowed URLs. If that happens, the client can update the allowlist
and re-try. The purpose of the this feature is to offer additional
guardrails on top of the MCP server. It does not restrict subresources
or JS/iframe navigations in any way. The performance impact is minimized
by turning off interception as soon as the navigation request is done.
2026-04-22 12:16:10 +00:00
Nicholas Roscino ec895f195a refactor: use puppeteer Extension API (#1911)
This PR refactor the extension usages using the new Puppeteer API.

Requires puppeteer release before merging
2026-04-20 14:38:48 +00:00
atian8179 2664455302 fix: list_pages should work after selected page is closed (#1145)
## Problem

After closing the currently selected page, calling `list_pages` throws
an error:
```
The selected page has been closed. Call list_pages to see open pages.
```

This creates a deadlock: the error message tells users to call
`list_pages`, but `list_pages` itself throws the same error.

## Root Cause

`list_pages` is defined with `definePageTool`, which marks it as
`pageScoped: true`. The handler dispatch in `index.ts` (line ~186) calls
`context.getSelectedMcpPage()` for all page-scoped tools **before**
invoking the handler. When the selected page is closed,
`getSelectedPptrPage()` throws.

However, `list_pages` doesn't actually use the `page` parameter — its
handler only calls `response.setIncludePages(true)`.

## Fix

Change `list_pages` from `definePageTool` to `defineTool`. This bypasses
the page-scoped check while preserving all existing behavior since the
handler never used the page reference.

## Testing

Reproduced the issue following the steps in #1138:
1. Call `list_pages` → returns page list 
2. Close the selected page
3. Call `list_pages` → now returns updated page list instead of throwing


Fixes #1138

---------

Co-authored-by: Piotr Paulski <piotrpaulski@chromium.org>
2026-03-30 08:42:39 +00:00
Alex Rudenko 0c0a538921 test: fix flaky test (#1132) 2026-03-06 10:01:36 +00:00
Alex Rudenko c2d8009ff7 refactor: move main files (#1120)
- `chrome-devtools-mcp.js` is the `npx chrome-devtools-mcp`
- `chrome-devtools.js` is the new CLI
- `-cli-options.js` is the corresponding options
- all these files are in the bin folder to indicate they are executable
2026-03-05 21:51:37 +00:00
Nicholas Roscino 2a6ac709ea chore: extension pages list (#1065)
This PR introduces extension pages in the listPages tool under the flag
--category-extension.
2026-03-05 20:57:07 +00:00
Alex Rudenko f763da24a1 fix: simplify focus state management (#1063)
Simplify focus management by emulating focused state for all pages. This
is especially useful in the new multi agent use case.
2026-02-27 14:10:00 +01:00
Alex Rudenko 9628dabcb4 refactor: clean up more of the context getters (#1062)
- moves more code to the McpPage
- deleted Context specific tests
2026-02-27 12:53:20 +00:00
Alex Rudenko 40c241bbfc refactor: move dialog handling to McpPage (#1059)
- renamed getSelectedPage to getSelectedPptrPage
- removes getSelectedPptrPage from tool interfaces
- moves dialog handling to McpPage
- makes responses to be optionally McpPage-scoped
2026-02-27 11:49:43 +01:00
Alex Rudenko 302e5a0419 refactor: consistently use McpPage in tools (#1057)
Follow-up to
https://github.com/ChromeDevTools/chrome-devtools-mcp/commit/caf601a32832bb87cfac801a6bbeacb87508412f

The work is not complete and as a follow-up I will handle other Context
methods and moved whatever is relevant to the McpPage. Also, duplicate
getters would go away.
2026-02-27 09:41:08 +00:00
Alex Rudenko 5f694c60ff refactor: improve type safety for page scoped tools (#1051)
I think we should create proper classes for tool definitions soon.

Follow-up for
https://github.com/ChromeDevTools/chrome-devtools-mcp/pull/1022
2026-02-26 14:33:57 +00:00
Stanislav Publika caf601a328 feat: add pageId routing for parallel multi-agent workflows (#1022)
## Summary

Adds optional `pageId` routing to page-scoped tools, gated behind
`--experimental-page-id-routing`. When enabled, multi-agent callers can
target a specific page without relying on global selection state. Fully
backward-compatible: without the flag, behavior is unchanged.

### Key changes

- **`pageScoped` annotation**: tools declare `pageScoped: true`; the
server merges `pageId` into their schema at registration time (when the
flag is on)
- **`McpPage` wrapper**: consolidates per-page state (numeric id,
isolated context name, focus tracking) into a single class
- **Request-scoped page routing**: `resolvePageById()` resolves the
target page, `setRequestPage()` threads it through the handler so tools
like `getSelectedPage()` see the right page
- **`assertPageIsFocused`**: keyboard/input tools validate that the
target page holds browser focus, returning an actionable error ("call
select_page first") instead of silently dispatching to the wrong page
- **`--experimental-page-id-routing` CLI flag** (hidden): gates schema
injection and request-scoped routing so the feature can be tested before
graduating
- **Eval scenarios**: `page_id_routing_test` and
`page_focus_keyboard_test` with `serverArgs` support in the eval harness

Addresses #1019
2026-02-26 11:39:38 +00:00
Nicholas Roscino 1a4eaba95b chore: list service workers (#1035)
This PR adds the extension service workers to the output of listPages.
This is available only behind "--category-extensions" flag
2026-02-25 13:49:37 +00:00
RobertWsp 59f6477a70 feat: add storage-isolated browser contexts (#991)
## Summary

Adds storage-isolated browser contexts via an optional `isolatedContext`
parameter on the `new_page` tool, following the simplified design
proposed by @OrKoN in #926.

Pages created with the same `isolatedContext` name share cookies,
localStorage, and storage. Pages in different isolated contexts (or the
default context) are fully isolated — ideal for testing multi-user
real-time features like chat, notifications, or collaborative editing.

## Changes

### `new_page` tool
- New optional `isolatedContext: string` parameter
- If specified, creates/reuses a named `BrowserContext` and opens a page
in it
- If omitted, uses the default browser context (existing behavior
unchanged)

### `McpContext`
- `#isolatedContexts` Map: LLM-provided names → Puppeteer
`BrowserContext` instances
- `#pageToIsolatedContextName` WeakMap: GC-safe page → context name
reverse lookup
- Auto-discovery: externally created browser contexts get
`isolated-context-1`, `isolated-context-2`, etc.
- `getIsolatedContextName(page)`: returns the isolated context name for
a page (used by response formatting)
- `page.browserContext()` used for context membership detection (no
custom target event forwarding needed)
- No context cleanup in `dispose()` or `closePage()` — either the entire
browser is closed or we disconnect without destroying state

### `McpResponse`
- Page list includes `isolatedContext=${name}` labels (both text and
structured JSON output)

### `ToolDefinition`
- `Context` interface extended with `getIsolatedContextName(page)`
method

## What's NOT included (by design)
- **No `TargetEventEmitter`**: Puppeteer forwards target events from
`BrowserContext` → `Browser` internally
- **No context cleanup**: Browser contexts are not closed on `dispose()`
or page close, per maintainer guidance
- **No `about:blank` cleanup**: Default context and isolated contexts
coexist side-by-side

## Example

```
> new_page url="https://app.example.com/chat" isolatedContext="userA"
> new_page url="https://app.example.com/chat" isolatedContext="userB"
> list_pages

Page 1: [app.example.com/chat] isolatedContext=userA
Page 2: [app.example.com/chat] isolatedContext=userB [selected]
```

Pages in different isolated contexts have fully independent cookies,
localStorage, IndexedDB, and WebSocket connections.

## Tests

- 6 new tests covering `isolatedContext` feature in
`tests/tools/pages.test.ts`
- All existing tests pass (333+)
- Zero type errors, lint clean

Closes #926

---------

Co-authored-by: Alex Rudenko <alexrudenko@chromium.org>
2026-02-23 11:36:16 +00:00
Alex Rudenko c9691c6250 test: fix missing sinon.restore (#989) 2026-02-18 15:39:30 +00:00
Alex Rudenko a0aeb97693 fix: respect custom timeouts in navigate tools (#865)
Closes https://github.com/ChromeDevTools/chrome-devtools-mcp/issues/863
2026-01-30 09:40:48 +00:00
Gustav Ernberg von Heijne d845ad4858 feat: Add ability to inject script to run on page load (#568)
Adds a parameter "initScript" to be used to inject a script into the
page load before other scripts execute.

[Page.evaluateOnNewDocument](https://pptr.dev/api/puppeteer.page.evaluateonnewdocument)

See #567

---------

Co-authored-by: Alex Rudenko <alexrudenko@chromium.org>
2026-01-28 12:29:33 +00:00
adam jones d7568881ba feat: add background parameter to new_page tool (#837)
## Summary

- Add `background` boolean parameter to the `new_page` tool
- When set to `true`, the new page opens in the background without
bringing it to the front
- Uses Puppeteer's existing `background` option for `browser.newPage()`

Fixes #826

---------

Co-authored-by: Alex Rudenko <OrKoN@users.noreply.github.com>
Co-authored-by: Alex Rudenko <alexrudenko@chromium.org>
2026-01-26 16:06:59 +00:00
Alex Rudenko 9b21f8b2e9 fix: handle beforeunload dialogs in navigations (#788)
Closes https://github.com/ChromeDevTools/chrome-devtools-mcp/issues/713
2026-01-19 10:04:45 +00:00
Lakshan Perera 4d9ac227dd fix: support resize_page when browser window is maximized/fullscreenwindow state (#748)
Related Issue -
[465](https://github.com/ChromeDevTools/chrome-devtools-mcp/issues/465)

### Description

This change make sure that the browser window is restored to a `normal`
state before resizing the page. When the window is in `fullscreen` mode
we have to set the state twice to match how Chrome CDP behaves.

Tests cover window resizing for every available window states `type
WindowState = 'normal' | 'minimized' | 'maximized' | 'fullscreen';`

---------

Co-authored-by: Alex Rudenko <OrKoN@users.noreply.github.com>
2026-01-13 16:25:22 +00:00
Alex Rudenko 8f3fcf6582 chore: get tab ID tool (#756)
An experimental tools to allow interop with other CDP tooling.
2026-01-12 16:26:03 +00:00
Alex Rudenko a23c6ba8c9 refactor: change pageIdx to page ids (#741)
This allows for order-independent page IDs that are still easy to
consume by LLMs (incremental integers).
2026-01-08 15:59:30 +01:00
Alex Rudenko ceae17be26 fix: make bringToFront optional in select_page (#668)
bringToFront() not only brings the tab to front in the browser but also
the browser window itself. This PR fixes the issue by making the call to
bringToFront() optional allowing agents to bring a tab to the user's
attention if needed but not always. To mitigate the risk of selected
page that is in the background being throttled, this PR implements
emulation of the focused page to make background tabs run as usual.
2025-12-12 11:04:04 +00:00
Simon Zünd 8e90a92780 chore: split withBrowser into withBrowser and withMcpContext (#620)
I split this PR off from my "create one DevTools universe per page" PR
in preparation. This allows tests to re-use browser instances without
creating an `McpContext`.

Drive-by: Move mocked browser/page into utils.ts.
2025-11-28 07:52:52 +01:00
zyzyzyryxy 94752ffade fix: prevent dropping license notices on some files when publishing (#604)
This PR prevents license notices being dropped when creating package for
publication.

This can happen when first import in the file is type-only import that
gets removed during build. When there is no empty line between the
license block comment and such import, the comment is treated as related
to the import and gets removed alongside it.
Adding an empty line between copyright notice and the import fixes the
issue.

Co-authored-by: Piotr Paulski <piotrpaulski@chromium.org>
2025-11-24 12:38:30 +00:00
Alex Rudenko 4724bbba93 fix: avoid no page selected errors (#537)
Uses object identity to track the selected page. This helps to be in
sync with the browser state better.

Closes https://github.com/ChromeDevTools/chrome-devtools-mcp/issues/492

---------

Co-authored-by: Nikolay Vitkov <34244704+Lightning00Blade@users.noreply.github.com>
2025-11-07 12:55:01 +01:00
Alex Rudenko d177087981 feat: support page reload (#462)
- merges navigation tools into a single tool.
- adds reload functionality.
- in a follow-up we will add options to reload.
2025-10-24 09:00:04 +00:00
Mithun Gowda B 0624029e0f fix: improve navigate_page_history error messages (#321) 2025-10-13 09:46:09 +02:00
Nikolay Vitkov 2714158eb3 docs: fix typos (#260)
This also implements the suggestion from
https://github.com/ChromeDevTools/chrome-devtools-mcp/pull/244
but that includes other parts that I am not sure we would want for now.
2025-10-02 16:59:09 +02:00
Alex Rudenko d9f77f8509 fix: do not error if the dialog was already handled (#208)
users report that the MCP client gets stuck if the dialog was closed
manually as the MCP state never updates.
2025-09-29 13:53:25 +00:00
Nikolay Vitkov 15277541d8 chore: add additional EsLint rule (#147) 2025-09-25 17:20:01 +02:00
Alex Rudenko 44cfc8f945 fix: avoid reporting page close errors as errors (#127)
Closes https://github.com/ChromeDevTools/chrome-devtools-mcp/issues/125
2025-09-25 10:40:51 +00:00
Alex Rudenko 0ca2434a29 fix: forbid closing the last page (#90)
McpContext currently assumes that there is a page. Eventually we might
support closing the browser by closing the last page but right now we do
not really have responses that indicate that the browser was closed. So
this PR helps the LLM understand that it is okay to keep the last page
running (and there are platform-specific differences as to what happens
if the last page is closed).

Ref https://github.com/ChromeDevTools/chrome-devtools-mcp/issues/87
2025-09-24 07:23:53 +00:00
Alex Rudenko 31a0bdce26 feat: initial version 2025-09-11 12:46:05 +02:00