diff --git a/README.md b/README.md
index b17b72451..73da3190b 100644
--- a/README.md
+++ b/README.md
@@ -596,9 +596,10 @@ The Chrome DevTools MCP server supports the following configuration option:
If enabled, ignores errors relative to self-signed and expired certificates. Use with caution.
- **Type:** boolean
-- **`--experimentalPageIdRouting`/ `--experimental-page-id-routing`**
- Whether to expose pageId on page-scoped tools and route requests by page ID (useful for concurrent agent sessions).
+- **`--pageIdRouting`/ `--page-id-routing`**
+ Expose pageId on page-scoped tools and route requests by page ID (useful for concurrent agent sessions). Use --no-page-id-routing to disable.
- **Type:** boolean
+ - **Default:** `true`
- **`--experimentalDevtools`/ `--experimental-devtools`**
Whether to enable automation over DevTools targets
diff --git a/docs/tool-reference.md b/docs/tool-reference.md
index 747193452..fb6feeaa6 100644
--- a/docs/tool-reference.md
+++ b/docs/tool-reference.md
@@ -66,6 +66,7 @@
**Parameters:**
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **uid** (string) **(required)**: The uid of an element on the page from the page content snapshot
- **dblClick** (boolean) _(optional)_: Set to true for double clicks. Default is false.
- **includeSnapshot** (boolean) _(optional)_: Whether to include a snapshot in the response. Default is false.
@@ -79,6 +80,7 @@
**Parameters:**
- **from_uid** (string) **(required)**: The uid of the element to [`drag`](#drag)
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **to_uid** (string) **(required)**: The uid of the element to drop into
- **includeSnapshot** (boolean) _(optional)_: Whether to include a snapshot in the response. Default is false.
@@ -90,6 +92,7 @@
**Parameters:**
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **uid** (string) **(required)**: The uid of an element on the page from the page content snapshot
- **value** (string) **(required)**: The value to [`fill`](#fill) in. "true" or "false" for checkboxes and toggles, "true" for radio buttons.
- **includeSnapshot** (boolean) _(optional)_: Whether to include a snapshot in the response. Default is false.
@@ -103,6 +106,7 @@
**Parameters:**
- **elements** (array) **(required)**: Elements from snapshot to [`fill`](#fill) out.
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **includeSnapshot** (boolean) _(optional)_: Whether to include a snapshot in the response. Default is false.
---
@@ -114,6 +118,7 @@
**Parameters:**
- **action** (enum: "accept", "dismiss") **(required)**: Whether to dismiss or accept the dialog
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **promptText** (string) _(optional)_: Optional prompt text to enter into the dialog.
---
@@ -124,6 +129,7 @@
**Parameters:**
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **uid** (string) **(required)**: The uid of an element on the page from the page content snapshot
- **includeSnapshot** (boolean) _(optional)_: Whether to include a snapshot in the response. Default is false.
@@ -136,6 +142,7 @@
**Parameters:**
- **key** (string) **(required)**: A key or a combination (e.g., "Enter", "Control+A", "Control++", "Control+Shift+R"). Modifiers: Control, Shift, Alt, Meta
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **includeSnapshot** (boolean) _(optional)_: Whether to include a snapshot in the response. Default is false.
---
@@ -146,6 +153,7 @@
**Parameters:**
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **text** (string) **(required)**: The text to type
- **submitKey** (string) _(optional)_: Optional key to press after typing. E.g., "Enter", "Tab", "Escape"
@@ -158,6 +166,7 @@
**Parameters:**
- **filePath** (string) **(required)**: The local path of the file to upload
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **uid** (string) **(required)**: The uid of the file input element or an element that will open file chooser on the page from the page content snapshot
- **includeSnapshot** (boolean) _(optional)_: Whether to include a snapshot in the response. Default is false.
@@ -169,6 +178,7 @@
**Parameters:**
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **x** (number) **(required)**: The x coordinate
- **y** (number) **(required)**: The y coordinate
- **dblClick** (boolean) _(optional)_: Set to true for double clicks. Default is false.
@@ -202,6 +212,7 @@
**Parameters:**
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **handleBeforeUnload** (enum: "accept", "decline") _(optional)_: Whether to auto accept or beforeunload dialogs triggered by this navigation. Default is accept.
- **ignoreCache** (boolean) _(optional)_: Whether to ignore cache on reload.
- **initScript** (string) _(optional)_: A JavaScript script to be executed on each new document before any other scripts for the next navigation.
@@ -241,6 +252,7 @@
**Parameters:**
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **text** (array) **(required)**: Non-empty list of texts. Resolves when any value appears on the page.
- **timeout** (integer) _(optional)_: Maximum wait time in milliseconds. If set to 0, the default timeout will be used.
@@ -254,6 +266,7 @@
**Parameters:**
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **colorScheme** (enum: "dark", "light", "auto") _(optional)_: [`Emulate`](#emulate) the dark or the light mode. Set to "auto" to reset to the default.
- **cpuThrottlingRate** (number) _(optional)_: Represents the CPU slowdown factor. Omit or set the rate to 1 to disable throttling
- **extraHttpHeaders** (string) _(optional)_: Extra HTTP headers as a JSON string object, e.g. {"X-Custom": "value", "Authorization": "Bearer token"}. Headers are included into every HTTP request originating from the page and persist across navigations until cleared. Pass an empty string to clear all extra headers.
@@ -271,6 +284,7 @@
**Parameters:**
- **height** (number) **(required)**: Page height
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **width** (number) **(required)**: Page width
---
@@ -285,6 +299,7 @@
- **insightName** (string) **(required)**: The name of the Insight you want more information on. For example: "DocumentLatency" or "LCPBreakdown"
- **insightSetId** (string) **(required)**: The id for the specific insight set. Only use the ids given in the "Available insight sets" list.
+- **pageId** (number) **(required)**: Targets a specific page by ID.
---
@@ -294,6 +309,7 @@
**Parameters:**
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **autoStop** (boolean) _(optional)_: Determines if the trace recording should be automatically stopped.
- **filePath** (string) _(optional)_: The absolute file path, or a file path relative to the current working directory, to save the raw trace data. For example, trace.json.gz (compressed) or trace.json (uncompressed).
- **reload** (boolean) _(optional)_: Determines if, once tracing has started, the current selected page should be automatically reloaded. Navigate the page to the right URL using the [`navigate_page`](#navigate_page) tool BEFORE starting the trace if reload or autoStop is set to true.
@@ -306,6 +322,7 @@
**Parameters:**
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **filePath** (string) _(optional)_: The absolute file path, or a file path relative to the current working directory, to save the raw trace data. For example, trace.json.gz (compressed) or trace.json (uncompressed).
---
@@ -318,6 +335,7 @@
**Parameters:**
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **reqid** (number) _(optional)_: The reqid of the network request. If omitted returns the currently selected request in the DevTools Network panel.
- **requestFilePath** (string) _(optional)_: The absolute or relative path to a .network-request file to save the request body to. If omitted, the body is returned inline.
- **responseFilePath** (string) _(optional)_: The absolute or relative path to a .network-response file to save the response body to. If omitted, the body is returned inline.
@@ -330,6 +348,7 @@
**Parameters:**
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **includePreservedRequests** (boolean) _(optional)_: Set to true to return the preserved requests over the last 3 navigations.
- **pageIdx** (integer) _(optional)_: Page number to return (0-based). When omitted, returns the first page.
- **pageSize** (integer) _(optional)_: Maximum number of requests to return. When omitted, returns all requests.
@@ -369,6 +388,7 @@ so returned values have to be JSON-serializable.
**Parameters:**
- **msgid** (number) **(required)**: The msgid of a console message on the page from the listed console messages
+- **pageId** (number) **(required)**: Targets a specific page by ID.
---
@@ -378,6 +398,7 @@ so returned values have to be JSON-serializable.
**Parameters:**
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **device** (enum: "desktop", "mobile") _(optional)_: Device to [`emulate`](#emulate).
- **mode** (enum: "navigation", "snapshot") _(optional)_: "navigation" reloads & audits. "snapshot" analyzes current state.
- **outputDirPath** (string) _(optional)_: Directory for reports. If omitted, uses temporary files.
@@ -390,6 +411,7 @@ so returned values have to be JSON-serializable.
**Parameters:**
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **includePreservedMessages** (boolean) _(optional)_: Set to true to return the preserved messages over the last 3 navigations.
- **pageIdx** (integer) _(optional)_: Page number to return (0-based). When omitted, returns the first page.
- **pageSize** (integer) _(optional)_: Maximum number of messages to return. When omitted, returns all messages.
@@ -403,6 +425,7 @@ so returned values have to be JSON-serializable.
**Parameters:**
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **filePath** (string) _(optional)_: The absolute path, or a path relative to the current working directory, to save the screenshot to instead of attaching it to the response.
- **format** (enum: "png", "jpeg", "webp") _(optional)_: Type of format to save the screenshot as. Default is "png"
- **fullPage** (boolean) _(optional)_: If set to true takes a screenshot of the full page instead of the currently visible viewport. Incompatible with uid.
@@ -419,6 +442,7 @@ in the DevTools Elements panel (if any).
**Parameters:**
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **filePath** (string) _(optional)_: The absolute path, or a path relative to the current working directory, to save the snapshot to instead of attaching it to the response.
- **verbose** (boolean) _(optional)_: Whether to include all possible information available in the full a11y tree. Default is false.
@@ -430,6 +454,7 @@ in the DevTools Elements panel (if any).
**Parameters:**
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **filePath** (string) _(optional)_: Output file path (.webm,.mp4 are supported). Uses mkdtemp to generate a unique path if not provided.
---
@@ -438,7 +463,9 @@ in the DevTools Elements panel (if any).
**Description:** Stops the active screencast recording on the selected page. (requires flag: --experimentalScreencast=true)
-**Parameters:** None
+**Parameters:**
+
+- **pageId** (number) **(required)**: Targets a specific page by ID.
---
@@ -451,6 +478,7 @@ in the DevTools Elements panel (if any).
**Parameters:**
- **filePath** (string) **(required)**: A path to a .heapsnapshot file to save the heapsnapshot to.
+- **pageId** (number) **(required)**: Targets a specific page by ID.
---
@@ -564,6 +592,7 @@ in the DevTools Elements panel (if any).
**Parameters:**
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **toolName** (string) **(required)**: The name of the tool to execute
- **params** (string) _(optional)_: The JSON-stringified parameters to pass to the tool
@@ -579,7 +608,9 @@ following command to the script:
This might be helpful when the third-party developer tools return non-serializable values or when composing
third-party developer tools with additional functionality. (requires flag: --categoryExperimentalThirdParty=true)
-**Parameters:** None
+**Parameters:**
+
+- **pageId** (number) **(required)**: Targets a specific page by ID.
---
@@ -593,6 +624,7 @@ third-party developer tools with additional functionality. (requires flag: --cat
**Parameters:**
+- **pageId** (number) **(required)**: Targets a specific page by ID.
- **toolName** (string) **(required)**: The name of the WebMCP tool to execute
- **input** (string) _(optional)_: The JSON-stringified parameters to pass to the WebMCP tool
@@ -602,6 +634,8 @@ third-party developer tools with additional functionality. (requires flag: --cat
**Description:** Lists all WebMCP tools the page exposes. (requires flag: --categoryExperimentalWebmcp=true)
-**Parameters:** None
+**Parameters:**
+
+- **pageId** (number) **(required)**: Targets a specific page by ID.
---
diff --git a/scripts/eval_scenarios/page_focus_keyboard_test.ts b/scripts/eval_scenarios/page_focus_keyboard_test.ts
index f56c7c629..9812b8686 100644
--- a/scripts/eval_scenarios/page_focus_keyboard_test.ts
+++ b/scripts/eval_scenarios/page_focus_keyboard_test.ts
@@ -9,7 +9,6 @@ import assert from 'node:assert';
import type {TestScenario} from '../eval_gemini.ts';
export const scenario: TestScenario = {
- serverArgs: ['--experimental-page-id-routing'],
prompt: `Open two pages in the same isolated context "session":
- Page 1 at data:text/html,
- Page 2 at data:text/html,
Other
diff --git a/scripts/eval_scenarios/page_id_routing_test.ts b/scripts/eval_scenarios/page_id_routing_test.ts
index a65c9e839..864c6bf63 100644
--- a/scripts/eval_scenarios/page_id_routing_test.ts
+++ b/scripts/eval_scenarios/page_id_routing_test.ts
@@ -9,7 +9,6 @@ import assert from 'node:assert';
import type {TestScenario} from '../eval_gemini.ts';
export const scenario: TestScenario = {
- serverArgs: ['--experimental-page-id-routing'],
prompt: `Open two new pages in isolated contexts:
- Page A (isolatedContext "contextA") at data:text/html,
- Page B (isolatedContext "contextB") at data:text/html,
diff --git a/scripts/generate-docs.ts b/scripts/generate-docs.ts
index 77dc37b8c..36b64cdc3 100644
--- a/scripts/generate-docs.ts
+++ b/scripts/generate-docs.ts
@@ -16,6 +16,7 @@ import {
OFF_BY_DEFAULT_CATEGORIES,
labels,
} from '../build/src/tools/categories.js';
+import {pageIdSchema} from '../build/src/tools/ToolDefinition.js';
import {createTools} from '../build/src/tools/tools.js';
const OUTPUT_PATH = './docs/tool-reference.md';
@@ -434,7 +435,7 @@ async function generateReference(
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
-function getToolsAndCategories(tools: any) {
+function getToolsAndCategories(tools: any, slim = false) {
// Convert ToolDefinitions to ToolWithAnnotations
const toolsWithAnnotations: ToolWithAnnotations[] = tools
.filter(tool => {
@@ -455,8 +456,12 @@ function getToolsAndCategories(tools: any) {
const properties: Record = {};
const required: string[] = [];
+ const toolSchema = {
+ ...tool.schema,
+ ...(tool.pageScoped && !slim ? pageIdSchema : {}),
+ };
for (const [key, schema] of Object.entries(
- tool.schema as unknown as Record,
+ toolSchema as unknown as Record,
)) {
const info = getZodTypeInfo(schema);
properties[key] = info;
@@ -536,7 +541,10 @@ async function generateToolDocumentation(): Promise {
{
const {toolsWithAnnotations, categories, sortedCategories} =
- getToolsAndCategories(createTools({slim: true} as ParsedArguments));
+ getToolsAndCategories(
+ createTools({slim: true} as ParsedArguments),
+ true,
+ );
await generateReference(
'Chrome DevTools MCP Slim Tool Reference',
SLIM_OUTPUT_PATH,
diff --git a/src/ToolHandler.ts b/src/ToolHandler.ts
index c9bf56d9f..b177e6af3 100644
--- a/src/ToolHandler.ts
+++ b/src/ToolHandler.ts
@@ -161,7 +161,7 @@ export class ToolHandler {
this.inputSchema =
'pageScoped' in tool &&
tool.pageScoped &&
- serverArgs.experimentalPageIdRouting &&
+ serverArgs.pageIdRouting &&
!serverArgs.slim
? {...tool.schema, ...pageIdSchema}
: tool.schema;
@@ -224,7 +224,7 @@ export class ToolHandler {
const pageId =
typeof params.pageId === 'number' ? params.pageId : undefined;
const page =
- this.serverArgs.experimentalPageIdRouting &&
+ this.serverArgs.pageIdRouting &&
pageId !== undefined &&
!this.serverArgs.slim
? context.getPageById(pageId)
diff --git a/src/bin/chrome-devtools-cli-options.ts b/src/bin/chrome-devtools-cli-options.ts
index af92dccd5..86bfbcf0d 100644
--- a/src/bin/chrome-devtools-cli-options.ts
+++ b/src/bin/chrome-devtools-cli-options.ts
@@ -47,6 +47,12 @@ export const commands: Commands = {
'Whether to include a snapshot in the response. Default is false.',
required: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
click_at: {
@@ -79,6 +85,12 @@ export const commands: Commands = {
'Whether to include a snapshot in the response. Default is false.',
required: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
close_page: {
@@ -118,6 +130,12 @@ export const commands: Commands = {
'Whether to include a snapshot in the response. Default is false.',
required: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
emulate: {
@@ -174,6 +192,12 @@ export const commands: Commands = {
'Extra HTTP headers as a JSON string object, e.g. {"X-Custom": "value", "Authorization": "Bearer token"}. Headers are included into every HTTP request originating from the page and persist across navigations until cleared. Pass an empty string to clear all extra headers.',
required: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
evaluate_script: {
@@ -208,6 +232,12 @@ export const commands: Commands = {
'Handle dialogs while execution. "accept", "dismiss", or string for response of window.prompt. Defaults to accept.',
required: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
execute_3p_developer_tool: {
@@ -227,6 +257,12 @@ export const commands: Commands = {
description: 'The JSON-stringified parameters to pass to the tool',
required: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
execute_webmcp_tool: {
@@ -247,6 +283,12 @@ export const commands: Commands = {
'The JSON-stringified parameters to pass to the WebMCP tool',
required: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
fill: {
@@ -275,6 +317,12 @@ export const commands: Commands = {
'Whether to include a snapshot in the response. Default is false.',
required: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
get_console_message: {
@@ -289,6 +337,12 @@ export const commands: Commands = {
'The msgid of a console message on the page from the listed console messages',
required: true,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
get_heapsnapshot_class_nodes: {
@@ -417,6 +471,12 @@ export const commands: Commands = {
'The absolute or relative path to a .network-response file to save the response body to. If omitted, the body is returned inline.',
required: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
handle_dialog: {
@@ -437,6 +497,12 @@ export const commands: Commands = {
description: 'Optional prompt text to enter into the dialog.',
required: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
hover: {
@@ -457,6 +523,12 @@ export const commands: Commands = {
'Whether to include a snapshot in the response. Default is false.',
required: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
install_extension: {
@@ -500,13 +572,26 @@ export const commands: Commands = {
description: 'Directory for reports. If omitted, uses temporary files.',
required: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
list_3p_developer_tools: {
description:
"Lists all third-party developer tools the page exposes for providing runtime information.\n Third-party developer tools can be called via the 'execute_3p_developer_tool()' MCP tool.\n Alternatively, third-party developer tools can be executed by calling 'evaluate_script' and adding the\n following command to the script:\n 'window.__dtmcp.executeTool(toolName, params)'\n This might be helpful when the third-party developer tools return non-serializable values or when composing\n third-party developer tools with additional functionality. (requires flag: --categoryExperimentalThirdParty=true)",
category: 'Third-party',
- args: {},
+ args: {
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
+ },
},
list_console_messages: {
description:
@@ -542,6 +627,12 @@ export const commands: Commands = {
required: false,
default: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
list_extensions: {
@@ -584,6 +675,12 @@ export const commands: Commands = {
required: false,
default: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
list_pages: {
@@ -595,7 +692,14 @@ export const commands: Commands = {
description:
'Lists all WebMCP tools the page exposes. (requires flag: --categoryExperimentalWebmcp=true)',
category: 'WebMCP',
- args: {},
+ args: {
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
+ },
},
navigate_page: {
description:
@@ -644,6 +748,12 @@ export const commands: Commands = {
'Maximum wait time in milliseconds. If set to 0, the default timeout will be used.',
required: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
new_page: {
@@ -699,6 +809,12 @@ export const commands: Commands = {
'The name of the Insight you want more information on. For example: "DocumentLatency" or "LCPBreakdown"',
required: true,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
performance_start_trace: {
@@ -729,6 +845,12 @@ export const commands: Commands = {
'The absolute file path, or a file path relative to the current working directory, to save the raw trace data. For example, trace.json.gz (compressed) or trace.json (uncompressed).',
required: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
performance_stop_trace: {
@@ -743,6 +865,12 @@ export const commands: Commands = {
'The absolute file path, or a file path relative to the current working directory, to save the raw trace data. For example, trace.json.gz (compressed) or trace.json (uncompressed).',
required: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
press_key: {
@@ -764,6 +892,12 @@ export const commands: Commands = {
'Whether to include a snapshot in the response. Default is false.',
required: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
reload_extension: {
@@ -796,6 +930,12 @@ export const commands: Commands = {
description: 'Page height',
required: true,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
screencast_start: {
@@ -810,13 +950,26 @@ export const commands: Commands = {
'Output file path (.webm,.mp4 are supported). Uses mkdtemp to generate a unique path if not provided.',
required: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
screencast_stop: {
description:
'Stops the active screencast recording on the selected page. (requires flag: --experimentalScreencast=true)',
category: 'Debugging',
- args: {},
+ args: {
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
+ },
},
select_page: {
description: 'Select a page as a context for future tool calls.',
@@ -849,6 +1002,12 @@ export const commands: Commands = {
'A path to a .heapsnapshot file to save the heapsnapshot to.',
required: true,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
take_screenshot: {
@@ -892,6 +1051,12 @@ export const commands: Commands = {
'The absolute path, or a path relative to the current working directory, to save the screenshot to instead of attaching it to the response.',
required: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
take_snapshot: {
@@ -913,6 +1078,12 @@ export const commands: Commands = {
'The absolute path, or a path relative to the current working directory, to save the snapshot to instead of attaching it to the response.',
required: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
trigger_extension_action: {
@@ -945,6 +1116,12 @@ export const commands: Commands = {
'Optional key to press after typing. E.g., "Enter", "Tab", "Escape"',
required: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
uninstall_extension: {
@@ -984,6 +1161,12 @@ export const commands: Commands = {
'Whether to include a snapshot in the response. Default is false.',
required: false,
},
+ pageId: {
+ name: 'pageId',
+ type: 'number',
+ description: 'Targets a specific page by ID.',
+ required: true,
+ },
},
},
} as const;
diff --git a/src/bin/chrome-devtools-mcp-cli-options.ts b/src/bin/chrome-devtools-mcp-cli-options.ts
index f510744d3..f10b5edf3 100644
--- a/src/bin/chrome-devtools-mcp-cli-options.ts
+++ b/src/bin/chrome-devtools-mcp-cli-options.ts
@@ -147,10 +147,11 @@ export const cliOptions = {
type: 'boolean',
description: `If enabled, ignores errors relative to self-signed and expired certificates. Use with caution.`,
},
- experimentalPageIdRouting: {
+ pageIdRouting: {
type: 'boolean',
describe:
- 'Whether to expose pageId on page-scoped tools and route requests by page ID (useful for concurrent agent sessions).',
+ 'Expose pageId on page-scoped tools and route requests by page ID (useful for concurrent agent sessions). Use --no-page-id-routing to disable.',
+ default: true,
},
experimentalDevtools: {
type: 'boolean',
diff --git a/src/bin/chrome-devtools.ts b/src/bin/chrome-devtools.ts
index cab71cb3a..64166c890 100644
--- a/src/bin/chrome-devtools.ts
+++ b/src/bin/chrome-devtools.ts
@@ -49,7 +49,6 @@ delete startCliOptions.viewport;
// Change the defaults for the CLI.
delete startCliOptions.experimentalStructuredContent;
delete startCliOptions.experimentalInteropTools;
-delete startCliOptions.experimentalPageIdRouting;
if (!('default' in cliOptions.headless)) {
throw new Error('headless cli option unexpectedly does not have a default');
}
diff --git a/src/telemetry/flag_usage_metrics.json b/src/telemetry/flag_usage_metrics.json
index 9982b1838..33091b138 100644
--- a/src/telemetry/flag_usage_metrics.json
+++ b/src/telemetry/flag_usage_metrics.json
@@ -238,11 +238,13 @@
},
{
"name": "experimental_page_id_routing",
- "flagType": "boolean"
+ "flagType": "boolean",
+ "isDeprecated": true
},
{
"name": "experimental_page_id_routing_present",
- "flagType": "boolean"
+ "flagType": "boolean",
+ "isDeprecated": true
},
{
"name": "experimental_webmcp",
@@ -295,5 +297,13 @@
{
"name": "category_experimental_third_party",
"flagType": "boolean"
+ },
+ {
+ "name": "page_id_routing_present",
+ "flagType": "boolean"
+ },
+ {
+ "name": "page_id_routing",
+ "flagType": "boolean"
}
]
diff --git a/src/telemetry/tool_call_metrics.json b/src/telemetry/tool_call_metrics.json
index 597bfa7a3..201867d3d 100644
--- a/src/telemetry/tool_call_metrics.json
+++ b/src/telemetry/tool_call_metrics.json
@@ -119,6 +119,10 @@
{
"name": "file_path_length",
"argType": "number"
+ },
+ {
+ "name": "page_id",
+ "argType": "number"
}
]
},
diff --git a/src/tools/script.ts b/src/tools/script.ts
index 0d5bb9ec8..6b060583f 100644
--- a/src/tools/script.ts
+++ b/src/tools/script.ts
@@ -58,7 +58,7 @@ Example with arguments: \`(el) => {
.describe(
'Handle dialogs while execution. "accept", "dismiss", or string for response of window.prompt. Defaults to accept.',
),
- ...(cliArgs?.experimentalPageIdRouting ? pageIdSchema : {}),
+ ...(cliArgs?.pageIdRouting ? pageIdSchema : {}),
...(cliArgs?.categoryExtensions
? {
serviceWorkerId: zod
@@ -109,9 +109,10 @@ Example with arguments: \`(el) => {
return;
}
- const mcpPage = cliArgs?.experimentalPageIdRouting
- ? context.getPageById(request.params.pageId)
- : context.getSelectedMcpPage();
+ const mcpPage =
+ cliArgs?.pageIdRouting && request.params.pageId
+ ? context.getPageById(request.params.pageId)
+ : context.getSelectedMcpPage();
const page: Page = mcpPage.pptrPage;
const args: Array> = [];
diff --git a/tests/cli.test.ts b/tests/cli.test.ts
index 05f2d3b06..3ca595277 100644
--- a/tests/cli.test.ts
+++ b/tests/cli.test.ts
@@ -29,6 +29,8 @@ describe('cli args parsing', () => {
usageStatistics: true,
'redact-network-headers': false,
redactNetworkHeaders: false,
+ 'page-id-routing': true,
+ pageIdRouting: true,
};
it('parses with default args', async () => {
diff --git a/tests/tools/script.test.ts b/tests/tools/script.test.ts
index 2718deb21..7b1657ae4 100644
--- a/tests/tools/script.test.ts
+++ b/tests/tools/script.test.ts
@@ -370,7 +370,7 @@ describe('script', () => {
params: {
function: String(() => 'test'),
serviceWorkerId: 'example_service_worker',
- pageId: '1',
+ pageId: 1,
},
},
response,