chrome-devtools-mcp 0.22.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/build/src/DevToolsConnectionAdapter.js +1 -0
- package/build/src/DevtoolsUtils.js +1 -0
- package/build/src/HeapSnapshotManager.js +16 -0
- package/build/src/McpContext.js +54 -126
- package/build/src/McpPage.js +204 -0
- package/build/src/McpResponse.js +44 -6
- package/build/src/Mutex.js +1 -0
- package/build/src/PageCollector.js +1 -0
- package/build/src/SlimMcpResponse.js +1 -0
- package/build/src/TextSnapshot.js +236 -0
- package/build/src/WaitForHelper.js +6 -0
- package/build/src/bin/check-latest-version.js +1 -0
- package/build/src/bin/chrome-devtools-cli-options.js +206 -46
- package/build/src/bin/chrome-devtools-mcp-cli-options.js +13 -1
- package/build/src/bin/chrome-devtools-mcp-main.js +1 -0
- package/build/src/bin/chrome-devtools-mcp.js +1 -0
- package/build/src/bin/chrome-devtools.js +27 -27
- package/build/src/browser.js +1 -0
- package/build/src/daemon/client.js +14 -12
- package/build/src/daemon/daemon.js +7 -5
- package/build/src/daemon/types.js +1 -0
- package/build/src/daemon/utils.js +20 -14
- package/build/src/formatters/ConsoleFormatter.js +48 -1
- package/build/src/formatters/HeapSnapshotFormatter.js +18 -2
- package/build/src/formatters/IssueFormatter.js +1 -0
- package/build/src/formatters/NetworkFormatter.js +1 -0
- package/build/src/formatters/SnapshotFormatter.js +2 -1
- package/build/src/index.js +114 -51
- package/build/src/issue-descriptions.js +1 -0
- package/build/src/logger.js +1 -0
- package/build/src/polyfill.js +1 -0
- package/build/src/telemetry/ClearcutLogger.js +13 -1
- package/build/src/telemetry/WatchdogClient.js +1 -0
- package/build/src/telemetry/flagUtils.js +1 -0
- package/build/src/telemetry/metricUtils.js +1 -0
- package/build/src/telemetry/persistence.js +1 -0
- package/build/src/telemetry/toolMetricsUtils.js +2 -1
- package/build/src/telemetry/types.js +1 -0
- package/build/src/telemetry/watchdog/ClearcutSender.js +1 -0
- package/build/src/telemetry/watchdog/main.js +1 -0
- package/build/src/third_party/THIRD_PARTY_NOTICES +32 -5
- package/build/src/third_party/bundled-packages.json +3 -2
- package/build/src/third_party/devtools-formatter-worker.js +2451 -2933
- package/build/src/third_party/devtools-heap-snapshot-worker.js +32 -26
- package/build/src/third_party/index.js +1942 -1536
- package/build/src/third_party/lighthouse-devtools-mcp-bundle.js +21717 -20261
- package/build/src/tools/ToolDefinition.js +1 -0
- package/build/src/tools/categories.js +6 -2
- package/build/src/tools/console.js +3 -0
- package/build/src/tools/emulation.js +2 -0
- package/build/src/tools/extensions.js +6 -0
- package/build/src/tools/inPage.js +5 -35
- package/build/src/tools/input.js +13 -2
- package/build/src/tools/lighthouse.js +17 -9
- package/build/src/tools/memory.js +34 -1
- package/build/src/tools/network.js +7 -2
- package/build/src/tools/pages.js +218 -146
- package/build/src/tools/performance.js +6 -0
- package/build/src/tools/screencast.js +25 -10
- package/build/src/tools/screenshot.js +3 -0
- package/build/src/tools/script.js +2 -0
- package/build/src/tools/slim/tools.js +4 -0
- package/build/src/tools/snapshot.js +5 -1
- package/build/src/tools/tools.js +1 -0
- package/build/src/tools/webmcp.js +3 -0
- package/build/src/trace-processing/parse.js +1 -0
- package/build/src/types.js +1 -0
- package/build/src/utils/check-for-updates.js +1 -0
- package/build/src/utils/files.js +5 -10
- package/build/src/utils/id.js +1 -0
- package/build/src/utils/keyboard.js +1 -0
- package/build/src/utils/pagination.js +1 -0
- package/build/src/utils/string.js +1 -0
- package/build/src/utils/types.js +1 -0
- package/build/src/version.js +2 -1
- package/package.json +10 -9
- package/build/src/bin/cliDefinitions.js +0 -621
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { logger } from './logger.js';
|
|
7
|
+
export class TextSnapshot {
|
|
8
|
+
static nextSnapshotId = 1;
|
|
9
|
+
static resetCounter() {
|
|
10
|
+
TextSnapshot.nextSnapshotId = 1;
|
|
11
|
+
}
|
|
12
|
+
root;
|
|
13
|
+
idToNode;
|
|
14
|
+
snapshotId;
|
|
15
|
+
selectedElementUid;
|
|
16
|
+
hasSelectedElement;
|
|
17
|
+
verbose;
|
|
18
|
+
constructor(data) {
|
|
19
|
+
this.root = data.root;
|
|
20
|
+
this.idToNode = data.idToNode;
|
|
21
|
+
this.snapshotId = data.snapshotId;
|
|
22
|
+
this.selectedElementUid = data.selectedElementUid;
|
|
23
|
+
this.hasSelectedElement = data.hasSelectedElement;
|
|
24
|
+
this.verbose = data.verbose;
|
|
25
|
+
}
|
|
26
|
+
static async create(page, options = {}) {
|
|
27
|
+
const verbose = options.verbose ?? false;
|
|
28
|
+
const rootNode = await page.pptrPage.accessibility.snapshot({
|
|
29
|
+
includeIframes: true,
|
|
30
|
+
interestingOnly: !verbose,
|
|
31
|
+
});
|
|
32
|
+
if (!rootNode) {
|
|
33
|
+
throw new Error('Failed to create accessibility snapshot');
|
|
34
|
+
}
|
|
35
|
+
const { uniqueBackendNodeIdToMcpId } = page;
|
|
36
|
+
const snapshotId = TextSnapshot.nextSnapshotId++;
|
|
37
|
+
// Iterate through the whole accessibility node tree and assign node ids that
|
|
38
|
+
// will be used for the tree serialization and mapping ids back to nodes.
|
|
39
|
+
let idCounter = 0;
|
|
40
|
+
const idToNode = new Map();
|
|
41
|
+
const seenUniqueIds = new Set();
|
|
42
|
+
const seenBackendNodeIds = new Set();
|
|
43
|
+
const assignIds = (node) => {
|
|
44
|
+
let id = '';
|
|
45
|
+
// @ts-expect-error untyped backendNodeId.
|
|
46
|
+
const backendNodeId = node.backendNodeId;
|
|
47
|
+
// @ts-expect-error untyped loaderId.
|
|
48
|
+
const uniqueBackendId = `${node.loaderId}_${backendNodeId}`;
|
|
49
|
+
const existingMcpId = uniqueBackendNodeIdToMcpId.get(uniqueBackendId);
|
|
50
|
+
if (existingMcpId !== undefined) {
|
|
51
|
+
// Re-use MCP exposed ID if the uniqueId is the same.
|
|
52
|
+
id = existingMcpId;
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
// Only generate a new ID if we have not seen the node before.
|
|
56
|
+
id = `${snapshotId}_${idCounter++}`;
|
|
57
|
+
uniqueBackendNodeIdToMcpId.set(uniqueBackendId, id);
|
|
58
|
+
}
|
|
59
|
+
seenUniqueIds.add(uniqueBackendId);
|
|
60
|
+
seenBackendNodeIds.add(backendNodeId);
|
|
61
|
+
const nodeWithId = {
|
|
62
|
+
...node,
|
|
63
|
+
id,
|
|
64
|
+
children: node.children
|
|
65
|
+
? node.children.map(child => assignIds(child))
|
|
66
|
+
: [],
|
|
67
|
+
};
|
|
68
|
+
// The AXNode for an option doesn't contain its `value`.
|
|
69
|
+
// Therefore, set text content of the option as value.
|
|
70
|
+
if (node.role === 'option') {
|
|
71
|
+
const optionText = node.name;
|
|
72
|
+
if (optionText) {
|
|
73
|
+
nodeWithId.value = optionText.toString();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
idToNode.set(nodeWithId.id, nodeWithId);
|
|
77
|
+
return nodeWithId;
|
|
78
|
+
};
|
|
79
|
+
const rootNodeWithId = assignIds(rootNode);
|
|
80
|
+
await TextSnapshot.insertExtraNodes(page, idToNode, seenUniqueIds, snapshotId, idCounter, rootNodeWithId, seenBackendNodeIds, options.extraHandles ?? []);
|
|
81
|
+
const snapshot = new TextSnapshot({
|
|
82
|
+
root: rootNodeWithId,
|
|
83
|
+
snapshotId: String(snapshotId),
|
|
84
|
+
idToNode,
|
|
85
|
+
hasSelectedElement: false,
|
|
86
|
+
verbose,
|
|
87
|
+
});
|
|
88
|
+
const data = options.devtoolsData ?? (await page.getDevToolsData());
|
|
89
|
+
if (data?.cdpBackendNodeId) {
|
|
90
|
+
snapshot.hasSelectedElement = true;
|
|
91
|
+
snapshot.selectedElementUid = page.resolveCdpElementId(data.cdpBackendNodeId);
|
|
92
|
+
}
|
|
93
|
+
// Clean up unique IDs that we did not see anymore.
|
|
94
|
+
for (const key of uniqueBackendNodeIdToMcpId.keys()) {
|
|
95
|
+
if (!seenUniqueIds.has(key)) {
|
|
96
|
+
uniqueBackendNodeIdToMcpId.delete(key);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return snapshot;
|
|
100
|
+
}
|
|
101
|
+
// ExtraHandles represent DOM nodes which might not be part of the accessibility tree, e.g. DOM nodes
|
|
102
|
+
// returned by in-page tools. We insert them into the tree by finding the closest ancestor in the
|
|
103
|
+
// tree and inserting the node as a child. The ancestor's child nodes are re-parented if necessary.
|
|
104
|
+
static async insertExtraNodes(page, idToNode, seenUniqueIds, snapshotId, idCounter, rootNodeWithId, seenBackendNodeIds, extraHandles) {
|
|
105
|
+
const { uniqueBackendNodeIdToMcpId } = page;
|
|
106
|
+
const createExtraNode = async (handle) => {
|
|
107
|
+
const backendNodeId = await handle.backendNodeId();
|
|
108
|
+
if (!backendNodeId || seenBackendNodeIds.has(backendNodeId)) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
const uniqueBackendId = `custom_${backendNodeId}`;
|
|
112
|
+
if (seenUniqueIds.has(uniqueBackendId)) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
seenBackendNodeIds.add(backendNodeId);
|
|
116
|
+
let id = '';
|
|
117
|
+
const mcpId = uniqueBackendNodeIdToMcpId.get(uniqueBackendId);
|
|
118
|
+
if (mcpId !== undefined) {
|
|
119
|
+
id = mcpId;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
id = `${snapshotId}_${idCounter++}`;
|
|
123
|
+
uniqueBackendNodeIdToMcpId.set(uniqueBackendId, id);
|
|
124
|
+
}
|
|
125
|
+
seenUniqueIds.add(uniqueBackendId);
|
|
126
|
+
const tagHandle = await handle.getProperty('localName');
|
|
127
|
+
const tagValue = await tagHandle.jsonValue();
|
|
128
|
+
const extraNode = {
|
|
129
|
+
role: tagValue,
|
|
130
|
+
id,
|
|
131
|
+
backendNodeId,
|
|
132
|
+
children: [],
|
|
133
|
+
elementHandle: async () => handle,
|
|
134
|
+
};
|
|
135
|
+
return extraNode;
|
|
136
|
+
};
|
|
137
|
+
const findAncestorNode = async (handle) => {
|
|
138
|
+
let ancestorHandle = await handle.evaluateHandle(el => el.parentElement);
|
|
139
|
+
while (ancestorHandle) {
|
|
140
|
+
const ancestorElement = ancestorHandle.asElement();
|
|
141
|
+
if (!ancestorElement) {
|
|
142
|
+
await ancestorHandle.dispose();
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
const ancestorBackendId = await ancestorElement.backendNodeId();
|
|
146
|
+
if (ancestorBackendId) {
|
|
147
|
+
const ancestorNode = idToNode
|
|
148
|
+
.values()
|
|
149
|
+
.find(node => node.backendNodeId === ancestorBackendId);
|
|
150
|
+
if (ancestorNode) {
|
|
151
|
+
await ancestorHandle.dispose();
|
|
152
|
+
return ancestorNode;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const nextHandle = await ancestorElement.evaluateHandle(el => el.parentElement);
|
|
156
|
+
await ancestorHandle.dispose();
|
|
157
|
+
ancestorHandle = nextHandle;
|
|
158
|
+
}
|
|
159
|
+
return null;
|
|
160
|
+
};
|
|
161
|
+
const findDescendantNodes = async (backendNodeId) => {
|
|
162
|
+
const descendantIds = new Set();
|
|
163
|
+
if (!backendNodeId) {
|
|
164
|
+
return descendantIds;
|
|
165
|
+
}
|
|
166
|
+
try {
|
|
167
|
+
// @ts-expect-error internal API
|
|
168
|
+
const client = page.pptrPage._client();
|
|
169
|
+
if (client) {
|
|
170
|
+
const { node } = await client.send('DOM.describeNode', {
|
|
171
|
+
backendNodeId,
|
|
172
|
+
depth: -1,
|
|
173
|
+
pierce: true,
|
|
174
|
+
});
|
|
175
|
+
const collect = (node) => {
|
|
176
|
+
if (node.backendNodeId && node.backendNodeId !== backendNodeId) {
|
|
177
|
+
descendantIds.add(node.backendNodeId);
|
|
178
|
+
}
|
|
179
|
+
if (node.children) {
|
|
180
|
+
for (const child of node.children) {
|
|
181
|
+
collect(child);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
collect(node);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
catch (e) {
|
|
189
|
+
logger(`Failed to collect descendants for backend node ${backendNodeId}`, e);
|
|
190
|
+
}
|
|
191
|
+
return descendantIds;
|
|
192
|
+
};
|
|
193
|
+
const moveChildNodes = (attachTarget, extraNode, descendantIds) => {
|
|
194
|
+
let firstMovedIndex = -1;
|
|
195
|
+
if (descendantIds.size > 0 && attachTarget.children) {
|
|
196
|
+
const remainingChildren = [];
|
|
197
|
+
for (const child of attachTarget.children) {
|
|
198
|
+
if (child.backendNodeId && descendantIds.has(child.backendNodeId)) {
|
|
199
|
+
if (firstMovedIndex === -1) {
|
|
200
|
+
firstMovedIndex = remainingChildren.length;
|
|
201
|
+
}
|
|
202
|
+
extraNode.children.push(child);
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
remainingChildren.push(child);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
attachTarget.children = remainingChildren;
|
|
209
|
+
}
|
|
210
|
+
return firstMovedIndex !== -1
|
|
211
|
+
? firstMovedIndex
|
|
212
|
+
: attachTarget.children
|
|
213
|
+
? attachTarget.children.length
|
|
214
|
+
: 0;
|
|
215
|
+
};
|
|
216
|
+
if (extraHandles.length) {
|
|
217
|
+
page.extraHandles = extraHandles;
|
|
218
|
+
}
|
|
219
|
+
const reorgInfo = [];
|
|
220
|
+
for (const handle of page.extraHandles) {
|
|
221
|
+
const extraNode = await createExtraNode(handle);
|
|
222
|
+
if (!extraNode) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
idToNode.set(extraNode.id, extraNode);
|
|
226
|
+
const attachTarget = (await findAncestorNode(handle)) || rootNodeWithId;
|
|
227
|
+
const descendantIds = await findDescendantNodes(extraNode.backendNodeId);
|
|
228
|
+
reorgInfo.push({ extraNode, attachTarget, descendantIds });
|
|
229
|
+
}
|
|
230
|
+
for (const { extraNode, attachTarget, descendantIds } of reorgInfo) {
|
|
231
|
+
const index = moveChildNodes(attachTarget, extraNode, descendantIds);
|
|
232
|
+
attachTarget.children.splice(index, 0, extraNode);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=TextSnapshot.js.map
|
|
@@ -104,8 +104,10 @@ export class WaitForHelper {
|
|
|
104
104
|
});
|
|
105
105
|
}
|
|
106
106
|
async waitForEventsAfterAction(action, options) {
|
|
107
|
+
let dialogOpened = false;
|
|
107
108
|
if (options?.handleDialog) {
|
|
108
109
|
const dialogHandler = (dialog) => {
|
|
110
|
+
dialogOpened = true;
|
|
109
111
|
if (options.handleDialog === 'dismiss') {
|
|
110
112
|
void dialog.dismiss();
|
|
111
113
|
}
|
|
@@ -142,6 +144,9 @@ export class WaitForHelper {
|
|
|
142
144
|
}
|
|
143
145
|
try {
|
|
144
146
|
await navigationFinished;
|
|
147
|
+
if (dialogOpened) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
145
150
|
// Wait for stable dom after navigation so we execute in
|
|
146
151
|
// the correct context
|
|
147
152
|
await this.waitForStableDom();
|
|
@@ -168,3 +173,4 @@ export function getNetworkMultiplierFromString(condition) {
|
|
|
168
173
|
}
|
|
169
174
|
return 1;
|
|
170
175
|
}
|
|
176
|
+
//# sourceMappingURL=WaitForHelper.js.map
|
|
@@ -28,6 +28,36 @@ export const commands = {
|
|
|
28
28
|
},
|
|
29
29
|
},
|
|
30
30
|
},
|
|
31
|
+
click_at: {
|
|
32
|
+
description: 'Clicks at the provided coordinates (requires flag: --experimentalVision=true)',
|
|
33
|
+
category: 'Input automation',
|
|
34
|
+
args: {
|
|
35
|
+
x: {
|
|
36
|
+
name: 'x',
|
|
37
|
+
type: 'number',
|
|
38
|
+
description: 'The x coordinate',
|
|
39
|
+
required: true,
|
|
40
|
+
},
|
|
41
|
+
y: {
|
|
42
|
+
name: 'y',
|
|
43
|
+
type: 'number',
|
|
44
|
+
description: 'The y coordinate',
|
|
45
|
+
required: true,
|
|
46
|
+
},
|
|
47
|
+
dblClick: {
|
|
48
|
+
name: 'dblClick',
|
|
49
|
+
type: 'boolean',
|
|
50
|
+
description: 'Set to true for double clicks. Default is false.',
|
|
51
|
+
required: false,
|
|
52
|
+
},
|
|
53
|
+
includeSnapshot: {
|
|
54
|
+
name: 'includeSnapshot',
|
|
55
|
+
type: 'boolean',
|
|
56
|
+
description: 'Whether to include a snapshot in the response. Default is false.',
|
|
57
|
+
required: false,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
},
|
|
31
61
|
close_page: {
|
|
32
62
|
description: 'Closes the page by its index. The last open page cannot be closed.',
|
|
33
63
|
category: 'Navigation automation',
|
|
@@ -84,7 +114,7 @@ export const commands = {
|
|
|
84
114
|
geolocation: {
|
|
85
115
|
name: 'geolocation',
|
|
86
116
|
type: 'string',
|
|
87
|
-
description: 'Geolocation (`<latitude>x<longitude>`) to emulate. Latitude between -90 and 90. Longitude between -180 and 180. Omit clear the geolocation override.',
|
|
117
|
+
description: 'Geolocation (`<latitude>x<longitude>`) to emulate. Latitude between -90 and 90. Longitude between -180 and 180. Omit to clear the geolocation override.',
|
|
88
118
|
required: false,
|
|
89
119
|
},
|
|
90
120
|
userAgent: {
|
|
@@ -124,10 +154,34 @@ export const commands = {
|
|
|
124
154
|
description: 'An optional list of arguments to pass to the function.',
|
|
125
155
|
required: false,
|
|
126
156
|
},
|
|
157
|
+
dialogAction: {
|
|
158
|
+
name: 'dialogAction',
|
|
159
|
+
type: 'string',
|
|
160
|
+
description: 'Handle dialogs while execution. "accept", "dismiss", or string for response of window.prompt. Defaults to accept.',
|
|
161
|
+
required: false,
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
execute_webmcp_tool: {
|
|
166
|
+
description: 'Executes a WebMCP tool exposed by the page. (requires flag: --experimentalWebmcp=true)',
|
|
167
|
+
category: 'Debugging',
|
|
168
|
+
args: {
|
|
169
|
+
toolName: {
|
|
170
|
+
name: 'toolName',
|
|
171
|
+
type: 'string',
|
|
172
|
+
description: 'The name of the WebMCP tool to execute',
|
|
173
|
+
required: true,
|
|
174
|
+
},
|
|
175
|
+
input: {
|
|
176
|
+
name: 'input',
|
|
177
|
+
type: 'string',
|
|
178
|
+
description: 'The JSON-stringified parameters to pass to the WebMCP tool',
|
|
179
|
+
required: false,
|
|
180
|
+
},
|
|
127
181
|
},
|
|
128
182
|
},
|
|
129
183
|
fill: {
|
|
130
|
-
description: 'Type text into
|
|
184
|
+
description: 'Type text into an input, text area or select an option from a <select> element.',
|
|
131
185
|
category: 'Input automation',
|
|
132
186
|
args: {
|
|
133
187
|
uid: {
|
|
@@ -150,24 +204,6 @@ export const commands = {
|
|
|
150
204
|
},
|
|
151
205
|
},
|
|
152
206
|
},
|
|
153
|
-
fill_form: {
|
|
154
|
-
description: 'Fill out multiple form elements at once',
|
|
155
|
-
category: 'Input automation',
|
|
156
|
-
args: {
|
|
157
|
-
elements: {
|
|
158
|
-
name: 'elements',
|
|
159
|
-
type: 'array',
|
|
160
|
-
description: 'Elements from snapshot to fill out.',
|
|
161
|
-
required: true,
|
|
162
|
-
},
|
|
163
|
-
includeSnapshot: {
|
|
164
|
-
name: 'includeSnapshot',
|
|
165
|
-
type: 'boolean',
|
|
166
|
-
description: 'Whether to include a snapshot in the response. Default is false.',
|
|
167
|
-
required: false,
|
|
168
|
-
},
|
|
169
|
-
},
|
|
170
|
-
},
|
|
171
207
|
get_console_message: {
|
|
172
208
|
description: 'Gets a console message by its ID. You can get all messages by calling list_console_messages.',
|
|
173
209
|
category: 'Debugging',
|
|
@@ -180,6 +216,30 @@ export const commands = {
|
|
|
180
216
|
},
|
|
181
217
|
},
|
|
182
218
|
},
|
|
219
|
+
get_memory_snapshot_details: {
|
|
220
|
+
description: 'Loads a memory heapsnapshot and returns all available information including statistics, static data, and aggregated node information. Supports pagination for aggregates. (requires flag: --experimentalMemory=true)',
|
|
221
|
+
category: 'Memory',
|
|
222
|
+
args: {
|
|
223
|
+
filePath: {
|
|
224
|
+
name: 'filePath',
|
|
225
|
+
type: 'string',
|
|
226
|
+
description: 'A path to a .heapsnapshot file to read.',
|
|
227
|
+
required: true,
|
|
228
|
+
},
|
|
229
|
+
pageIdx: {
|
|
230
|
+
name: 'pageIdx',
|
|
231
|
+
type: 'number',
|
|
232
|
+
description: 'The page index for pagination of aggregates.',
|
|
233
|
+
required: false,
|
|
234
|
+
},
|
|
235
|
+
pageSize: {
|
|
236
|
+
name: 'pageSize',
|
|
237
|
+
type: 'number',
|
|
238
|
+
description: 'The page size for pagination of aggregates.',
|
|
239
|
+
required: false,
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
},
|
|
183
243
|
get_network_request: {
|
|
184
244
|
description: 'Gets a network request by an optional reqid, if omitted returns the currently selected request in the DevTools Network panel.',
|
|
185
245
|
category: 'Network',
|
|
@@ -193,13 +253,43 @@ export const commands = {
|
|
|
193
253
|
requestFilePath: {
|
|
194
254
|
name: 'requestFilePath',
|
|
195
255
|
type: 'string',
|
|
196
|
-
description: 'The absolute or relative path to save the request body to. If omitted, the body is returned inline.',
|
|
256
|
+
description: 'The absolute or relative path to a .network-request file to save the request body to. If omitted, the body is returned inline.',
|
|
197
257
|
required: false,
|
|
198
258
|
},
|
|
199
259
|
responseFilePath: {
|
|
200
260
|
name: 'responseFilePath',
|
|
201
261
|
type: 'string',
|
|
202
|
-
description: 'The absolute or relative path to save the response body to. If omitted, the body is returned inline.',
|
|
262
|
+
description: 'The absolute or relative path to a .network-response file to save the response body to. If omitted, the body is returned inline.',
|
|
263
|
+
required: false,
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
get_nodes_by_class: {
|
|
268
|
+
description: 'Loads a memory heapsnapshot and returns instances of a specific class with their stable IDs. (requires flag: --experimentalMemory=true)',
|
|
269
|
+
category: 'Memory',
|
|
270
|
+
args: {
|
|
271
|
+
filePath: {
|
|
272
|
+
name: 'filePath',
|
|
273
|
+
type: 'string',
|
|
274
|
+
description: 'A path to a .heapsnapshot file to read.',
|
|
275
|
+
required: true,
|
|
276
|
+
},
|
|
277
|
+
uid: {
|
|
278
|
+
name: 'uid',
|
|
279
|
+
type: 'number',
|
|
280
|
+
description: 'The unique UID for the class, obtained from aggregates listing.',
|
|
281
|
+
required: true,
|
|
282
|
+
},
|
|
283
|
+
pageIdx: {
|
|
284
|
+
name: 'pageIdx',
|
|
285
|
+
type: 'number',
|
|
286
|
+
description: 'The page index for pagination.',
|
|
287
|
+
required: false,
|
|
288
|
+
},
|
|
289
|
+
pageSize: {
|
|
290
|
+
name: 'pageSize',
|
|
291
|
+
type: 'number',
|
|
292
|
+
description: 'The page size for pagination.',
|
|
203
293
|
required: false,
|
|
204
294
|
},
|
|
205
295
|
},
|
|
@@ -241,8 +331,20 @@ export const commands = {
|
|
|
241
331
|
},
|
|
242
332
|
},
|
|
243
333
|
},
|
|
334
|
+
install_extension: {
|
|
335
|
+
description: 'Installs a Chrome extension from the given path. (requires flag: --categoryExtensions=true)',
|
|
336
|
+
category: 'Extensions',
|
|
337
|
+
args: {
|
|
338
|
+
path: {
|
|
339
|
+
name: 'path',
|
|
340
|
+
type: 'string',
|
|
341
|
+
description: 'Absolute path to the unpacked extension folder.',
|
|
342
|
+
required: true,
|
|
343
|
+
},
|
|
344
|
+
},
|
|
345
|
+
},
|
|
244
346
|
lighthouse_audit: {
|
|
245
|
-
description: 'Get Lighthouse score and reports for accessibility, SEO and
|
|
347
|
+
description: 'Get Lighthouse score and reports for accessibility, SEO, best practices, and agentic browsing. This excludes performance. For performance audits, run performance_start_trace',
|
|
246
348
|
category: 'Debugging',
|
|
247
349
|
args: {
|
|
248
350
|
mode: {
|
|
@@ -276,7 +378,7 @@ export const commands = {
|
|
|
276
378
|
pageSize: {
|
|
277
379
|
name: 'pageSize',
|
|
278
380
|
type: 'integer',
|
|
279
|
-
description: 'Maximum number of messages to return. When omitted, returns all
|
|
381
|
+
description: 'Maximum number of messages to return. When omitted, returns all messages.',
|
|
280
382
|
required: false,
|
|
281
383
|
},
|
|
282
384
|
pageIdx: {
|
|
@@ -300,6 +402,11 @@ export const commands = {
|
|
|
300
402
|
},
|
|
301
403
|
},
|
|
302
404
|
},
|
|
405
|
+
list_extensions: {
|
|
406
|
+
description: 'Lists all the Chrome extensions installed in the browser. This includes their name, ID, version, and enabled status. (requires flag: --categoryExtensions=true)',
|
|
407
|
+
category: 'Extensions',
|
|
408
|
+
args: {},
|
|
409
|
+
},
|
|
303
410
|
list_network_requests: {
|
|
304
411
|
description: 'List all requests for the currently selected page since the last navigation.',
|
|
305
412
|
category: 'Network',
|
|
@@ -332,10 +439,27 @@ export const commands = {
|
|
|
332
439
|
},
|
|
333
440
|
},
|
|
334
441
|
list_pages: {
|
|
335
|
-
description: 'Get a list of pages
|
|
442
|
+
description: 'Get a list of pages open in the browser.',
|
|
336
443
|
category: 'Navigation automation',
|
|
337
444
|
args: {},
|
|
338
445
|
},
|
|
446
|
+
list_webmcp_tools: {
|
|
447
|
+
description: 'Lists all WebMCP tools the page exposes. (requires flag: --experimentalWebmcp=true)',
|
|
448
|
+
category: 'Debugging',
|
|
449
|
+
args: {},
|
|
450
|
+
},
|
|
451
|
+
load_memory_snapshot: {
|
|
452
|
+
description: 'Loads a memory heapsnapshot and returns snapshot summary stats. (requires flag: --experimentalMemory=true)',
|
|
453
|
+
category: 'Memory',
|
|
454
|
+
args: {
|
|
455
|
+
filePath: {
|
|
456
|
+
name: 'filePath',
|
|
457
|
+
type: 'string',
|
|
458
|
+
description: 'A path to a .heapsnapshot file to read.',
|
|
459
|
+
required: true,
|
|
460
|
+
},
|
|
461
|
+
},
|
|
462
|
+
},
|
|
339
463
|
navigate_page: {
|
|
340
464
|
description: 'Go to a URL, or back, forward, or reload. Use project URL if not specified otherwise.',
|
|
341
465
|
category: 'Navigation automation',
|
|
@@ -484,6 +608,18 @@ export const commands = {
|
|
|
484
608
|
},
|
|
485
609
|
},
|
|
486
610
|
},
|
|
611
|
+
reload_extension: {
|
|
612
|
+
description: 'Reloads an unpacked Chrome extension by its ID. (requires flag: --categoryExtensions=true)',
|
|
613
|
+
category: 'Extensions',
|
|
614
|
+
args: {
|
|
615
|
+
id: {
|
|
616
|
+
name: 'id',
|
|
617
|
+
type: 'string',
|
|
618
|
+
description: 'ID of the extension to reload.',
|
|
619
|
+
required: true,
|
|
620
|
+
},
|
|
621
|
+
},
|
|
622
|
+
},
|
|
487
623
|
resize_page: {
|
|
488
624
|
description: "Resizes the selected page's window so that the page has specified dimension",
|
|
489
625
|
category: 'Emulation',
|
|
@@ -502,6 +638,23 @@ export const commands = {
|
|
|
502
638
|
},
|
|
503
639
|
},
|
|
504
640
|
},
|
|
641
|
+
screencast_start: {
|
|
642
|
+
description: 'Starts recording a screencast (video) of the selected page in specified format. (requires flag: --experimentalScreencast=true)',
|
|
643
|
+
category: 'Debugging',
|
|
644
|
+
args: {
|
|
645
|
+
filePath: {
|
|
646
|
+
name: 'filePath',
|
|
647
|
+
type: 'string',
|
|
648
|
+
description: 'Output file path (.webm,.mp4 are supported). Uses mkdtemp to generate a unique path if not provided.',
|
|
649
|
+
required: false,
|
|
650
|
+
},
|
|
651
|
+
},
|
|
652
|
+
},
|
|
653
|
+
screencast_stop: {
|
|
654
|
+
description: 'Stops the active screencast recording on the selected page. (requires flag: --experimentalScreencast=true)',
|
|
655
|
+
category: 'Debugging',
|
|
656
|
+
args: {},
|
|
657
|
+
},
|
|
505
658
|
select_page: {
|
|
506
659
|
description: 'Select a page as a context for future tool calls.',
|
|
507
660
|
category: 'Navigation automation',
|
|
@@ -521,8 +674,8 @@ export const commands = {
|
|
|
521
674
|
},
|
|
522
675
|
},
|
|
523
676
|
take_memory_snapshot: {
|
|
524
|
-
description: 'Capture a
|
|
525
|
-
category: '
|
|
677
|
+
description: 'Capture a heap snapshot of the currently selected page. Use to analyze the memory distribution of JavaScript objects and debug memory leaks.',
|
|
678
|
+
category: 'Memory',
|
|
526
679
|
args: {
|
|
527
680
|
filePath: {
|
|
528
681
|
name: 'filePath',
|
|
@@ -553,7 +706,7 @@ export const commands = {
|
|
|
553
706
|
uid: {
|
|
554
707
|
name: 'uid',
|
|
555
708
|
type: 'string',
|
|
556
|
-
description: 'The uid of an element on the page from the page content snapshot. If omitted takes a
|
|
709
|
+
description: 'The uid of an element on the page from the page content snapshot. If omitted, takes a page screenshot.',
|
|
557
710
|
required: false,
|
|
558
711
|
},
|
|
559
712
|
fullPage: {
|
|
@@ -588,6 +741,18 @@ export const commands = {
|
|
|
588
741
|
},
|
|
589
742
|
},
|
|
590
743
|
},
|
|
744
|
+
trigger_extension_action: {
|
|
745
|
+
description: 'Triggers the default action of an extension by its ID. (requires flag: --categoryExtensions=true)',
|
|
746
|
+
category: 'Extensions',
|
|
747
|
+
args: {
|
|
748
|
+
id: {
|
|
749
|
+
name: 'id',
|
|
750
|
+
type: 'string',
|
|
751
|
+
description: 'ID of the extension to trigger the action for.',
|
|
752
|
+
required: true,
|
|
753
|
+
},
|
|
754
|
+
},
|
|
755
|
+
},
|
|
591
756
|
type_text: {
|
|
592
757
|
description: 'Type text using keyboard into a previously focused input',
|
|
593
758
|
category: 'Input automation',
|
|
@@ -606,6 +771,18 @@ export const commands = {
|
|
|
606
771
|
},
|
|
607
772
|
},
|
|
608
773
|
},
|
|
774
|
+
uninstall_extension: {
|
|
775
|
+
description: 'Uninstalls a Chrome extension by its ID. (requires flag: --categoryExtensions=true)',
|
|
776
|
+
category: 'Extensions',
|
|
777
|
+
args: {
|
|
778
|
+
id: {
|
|
779
|
+
name: 'id',
|
|
780
|
+
type: 'string',
|
|
781
|
+
description: 'ID of the extension to uninstall.',
|
|
782
|
+
required: true,
|
|
783
|
+
},
|
|
784
|
+
},
|
|
785
|
+
},
|
|
609
786
|
upload_file: {
|
|
610
787
|
description: 'Upload a file through a provided element.',
|
|
611
788
|
category: 'Input automation',
|
|
@@ -630,22 +807,5 @@ export const commands = {
|
|
|
630
807
|
},
|
|
631
808
|
},
|
|
632
809
|
},
|
|
633
|
-
wait_for: {
|
|
634
|
-
description: 'Wait for the specified text to appear on the selected page.',
|
|
635
|
-
category: 'Navigation automation',
|
|
636
|
-
args: {
|
|
637
|
-
text: {
|
|
638
|
-
name: 'text',
|
|
639
|
-
type: 'array',
|
|
640
|
-
description: 'Non-empty list of texts. Resolves when any value appears on the page.',
|
|
641
|
-
required: true,
|
|
642
|
-
},
|
|
643
|
-
timeout: {
|
|
644
|
-
name: 'timeout',
|
|
645
|
-
type: 'integer',
|
|
646
|
-
description: 'Maximum wait time in milliseconds. If set to 0, the default timeout will be used.',
|
|
647
|
-
required: false,
|
|
648
|
-
},
|
|
649
|
-
},
|
|
650
|
-
},
|
|
651
810
|
};
|
|
811
|
+
//# sourceMappingURL=chrome-devtools-cli-options.js.map
|