chrome-devtools-mcp 0.23.0 → 0.25.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.
Files changed (83) hide show
  1. package/README.md +22 -5
  2. package/build/src/DevToolsConnectionAdapter.js +1 -0
  3. package/build/src/DevtoolsUtils.js +1 -0
  4. package/build/src/HeapSnapshotManager.js +16 -0
  5. package/build/src/McpContext.js +57 -4
  6. package/build/src/McpPage.js +10 -4
  7. package/build/src/McpResponse.js +55 -19
  8. package/build/src/Mutex.js +1 -0
  9. package/build/src/PageCollector.js +1 -0
  10. package/build/src/SlimMcpResponse.js +1 -0
  11. package/build/src/TextSnapshot.js +13 -7
  12. package/build/src/WaitForHelper.js +6 -0
  13. package/build/src/bin/check-latest-version.js +1 -0
  14. package/build/src/bin/chrome-devtools-cli-options.js +229 -46
  15. package/build/src/bin/chrome-devtools-mcp-cli-options.js +10 -5
  16. package/build/src/bin/chrome-devtools-mcp-main.js +1 -5
  17. package/build/src/bin/chrome-devtools-mcp.js +1 -0
  18. package/build/src/bin/chrome-devtools.js +5 -13
  19. package/build/src/browser.js +1 -0
  20. package/build/src/daemon/client.js +4 -2
  21. package/build/src/daemon/daemon.js +1 -0
  22. package/build/src/daemon/types.js +1 -0
  23. package/build/src/daemon/utils.js +1 -0
  24. package/build/src/formatters/ConsoleFormatter.js +48 -1
  25. package/build/src/formatters/HeapSnapshotFormatter.js +18 -2
  26. package/build/src/formatters/IssueFormatter.js +1 -0
  27. package/build/src/formatters/NetworkFormatter.js +1 -0
  28. package/build/src/formatters/SnapshotFormatter.js +2 -1
  29. package/build/src/index.js +114 -51
  30. package/build/src/issue-descriptions.js +1 -0
  31. package/build/src/logger.js +1 -0
  32. package/build/src/polyfill.js +1 -0
  33. package/build/src/telemetry/ClearcutLogger.js +13 -1
  34. package/build/src/telemetry/WatchdogClient.js +1 -0
  35. package/build/src/telemetry/flagUtils.js +1 -0
  36. package/build/src/telemetry/metricUtils.js +1 -0
  37. package/build/src/telemetry/persistence.js +1 -0
  38. package/build/src/telemetry/toolMetricsUtils.js +2 -1
  39. package/build/src/telemetry/types.js +1 -0
  40. package/build/src/telemetry/watchdog/ClearcutSender.js +1 -0
  41. package/build/src/telemetry/watchdog/main.js +1 -0
  42. package/build/src/third_party/THIRD_PARTY_NOTICES +8 -8
  43. package/build/src/third_party/bundled-packages.json +3 -3
  44. package/build/src/third_party/devtools-formatter-worker.js +2469 -2933
  45. package/build/src/third_party/devtools-heap-snapshot-worker.js +50 -26
  46. package/build/src/third_party/index.js +1107 -407
  47. package/build/src/third_party/issue-descriptions/genericFormModelContextMissingToolDescription.md +5 -0
  48. package/build/src/third_party/issue-descriptions/genericFormModelContextMissingToolName.md +5 -0
  49. package/build/src/third_party/issue-descriptions/genericFormModelContextParameterMissingName.md +5 -0
  50. package/build/src/third_party/issue-descriptions/genericFormModelContextParameterMissingTitleAndDescription.md +5 -0
  51. package/build/src/third_party/issue-descriptions/genericFormModelContextRequiredParameterMissingName.md +5 -0
  52. package/build/src/third_party/lighthouse-devtools-mcp-bundle.js +21717 -20261
  53. package/build/src/tools/ToolDefinition.js +1 -0
  54. package/build/src/tools/categories.js +10 -3
  55. package/build/src/tools/console.js +3 -0
  56. package/build/src/tools/emulation.js +2 -0
  57. package/build/src/tools/extensions.js +6 -0
  58. package/build/src/tools/input.js +57 -2
  59. package/build/src/tools/lighthouse.js +17 -9
  60. package/build/src/tools/memory.js +34 -1
  61. package/build/src/tools/network.js +5 -0
  62. package/build/src/tools/pages.js +14 -5
  63. package/build/src/tools/performance.js +6 -0
  64. package/build/src/tools/screencast.js +6 -2
  65. package/build/src/tools/screenshot.js +3 -0
  66. package/build/src/tools/script.js +2 -0
  67. package/build/src/tools/slim/tools.js +4 -0
  68. package/build/src/tools/snapshot.js +5 -1
  69. package/build/src/tools/{inPage.js → thirdPartyDeveloper.js} +17 -16
  70. package/build/src/tools/tools.js +3 -2
  71. package/build/src/tools/webmcp.js +5 -4
  72. package/build/src/trace-processing/parse.js +1 -0
  73. package/build/src/types.js +1 -0
  74. package/build/src/utils/check-for-updates.js +1 -0
  75. package/build/src/utils/files.js +5 -10
  76. package/build/src/utils/id.js +1 -0
  77. package/build/src/utils/keyboard.js +1 -0
  78. package/build/src/utils/pagination.js +1 -0
  79. package/build/src/utils/string.js +1 -0
  80. package/build/src/utils/types.js +1 -0
  81. package/build/src/version.js +2 -1
  82. package/package.json +10 -11
  83. package/build/src/bin/cliDefinitions.js +0 -621
@@ -70,3 +70,4 @@ export function geolocationTransform(arg) {
70
70
  longitude,
71
71
  };
72
72
  }
73
+ //# sourceMappingURL=ToolDefinition.js.map
@@ -12,8 +12,9 @@ export var ToolCategory;
12
12
  ToolCategory["NETWORK"] = "network";
13
13
  ToolCategory["DEBUGGING"] = "debugging";
14
14
  ToolCategory["EXTENSIONS"] = "extensions";
15
- ToolCategory["IN_PAGE"] = "in-page";
15
+ ToolCategory["THIRD_PARTY"] = "experimentalThirdParty";
16
16
  ToolCategory["MEMORY"] = "memory";
17
+ ToolCategory["WEBMCP"] = "experimentalWebmcp";
17
18
  })(ToolCategory || (ToolCategory = {}));
18
19
  export const labels = {
19
20
  [ToolCategory.INPUT]: 'Input automation',
@@ -23,7 +24,13 @@ export const labels = {
23
24
  [ToolCategory.NETWORK]: 'Network',
24
25
  [ToolCategory.DEBUGGING]: 'Debugging',
25
26
  [ToolCategory.EXTENSIONS]: 'Extensions',
26
- [ToolCategory.IN_PAGE]: 'In-page tools',
27
+ [ToolCategory.THIRD_PARTY]: 'Third-party',
27
28
  [ToolCategory.MEMORY]: 'Memory',
29
+ [ToolCategory.WEBMCP]: 'WebMCP',
28
30
  };
29
- export const OFF_BY_DEFAULT_CATEGORIES = [ToolCategory.EXTENSIONS];
31
+ export const OFF_BY_DEFAULT_CATEGORIES = [
32
+ ToolCategory.EXTENSIONS,
33
+ ToolCategory.THIRD_PARTY,
34
+ ToolCategory.WEBMCP,
35
+ ];
36
+ //# sourceMappingURL=categories.js.map
@@ -60,6 +60,7 @@ export const listConsoleMessages = definePageTool(cliArgs => {
60
60
  .optional()
61
61
  .describe('Set to true to return the preserved messages over the last 3 navigations.'),
62
62
  },
63
+ blockedByDialog: false,
63
64
  handler: async (request, response) => {
64
65
  response.setIncludeConsoleData(true, {
65
66
  pageSize: request.params.pageSize,
@@ -82,7 +83,9 @@ export const getConsoleMessage = definePageTool({
82
83
  .number()
83
84
  .describe('The msgid of a console message on the page from the listed console messages'),
84
85
  },
86
+ blockedByDialog: false,
85
87
  handler: async (request, response) => {
86
88
  response.attachConsoleMessage(request.params.msgid);
87
89
  },
88
90
  });
91
+ //# sourceMappingURL=console.js.map
@@ -48,8 +48,10 @@ export const emulate = definePageTool({
48
48
  .transform(viewportTransform)
49
49
  .describe(`Emulate device viewports '<width>x<height>x<devicePixelRatio>[,mobile][,touch][,landscape]'. 'touch' and 'mobile' to emulate mobile devices. 'landscape' to emulate landscape mode.`),
50
50
  },
51
+ blockedByDialog: true,
51
52
  handler: async (request, _response, context) => {
52
53
  const page = request.page;
53
54
  await context.emulate(request.params, page.pptrPage);
54
55
  },
55
56
  });
57
+ //# sourceMappingURL=emulation.js.map
@@ -18,6 +18,7 @@ export const installExtension = defineTool({
18
18
  .string()
19
19
  .describe('Absolute path to the unpacked extension folder.'),
20
20
  },
21
+ blockedByDialog: false,
21
22
  handler: async (request, response, context) => {
22
23
  const { path } = request.params;
23
24
  const id = await context.installExtension(path);
@@ -34,6 +35,7 @@ export const uninstallExtension = defineTool({
34
35
  schema: {
35
36
  id: zod.string().describe('ID of the extension to uninstall.'),
36
37
  },
38
+ blockedByDialog: false,
37
39
  handler: async (request, response, context) => {
38
40
  const { id } = request.params;
39
41
  await context.uninstallExtension(id);
@@ -48,6 +50,7 @@ export const listExtensions = defineTool({
48
50
  readOnlyHint: true,
49
51
  },
50
52
  schema: {},
53
+ blockedByDialog: false,
51
54
  handler: async (_request, response, _context) => {
52
55
  response.setListExtensions();
53
56
  },
@@ -62,6 +65,7 @@ export const reloadExtension = defineTool({
62
65
  schema: {
63
66
  id: zod.string().describe('ID of the extension to reload.'),
64
67
  },
68
+ blockedByDialog: false,
65
69
  handler: async (request, response, context) => {
66
70
  const { id } = request.params;
67
71
  const extension = await context.getExtension(id);
@@ -82,9 +86,11 @@ export const triggerExtensionAction = defineTool({
82
86
  schema: {
83
87
  id: zod.string().describe('ID of the extension to trigger the action for.'),
84
88
  },
89
+ blockedByDialog: false,
85
90
  handler: async (request, response, context) => {
86
91
  const { id } = request.params;
87
92
  await context.triggerExtensionAction(id);
88
93
  response.appendResponseLine(`Extension action triggered for ID ${id}`);
89
94
  },
90
95
  });
96
+ //# sourceMappingURL=extensions.js.map
@@ -26,6 +26,44 @@ function handleActionError(error, uid) {
26
26
  cause: error,
27
27
  });
28
28
  }
29
+ async function selectNativeSelectOption(handle) {
30
+ const selectHandle = await handle.evaluateHandle(node => {
31
+ if (!(node instanceof HTMLOptionElement)) {
32
+ return null;
33
+ }
34
+ const select = node.closest('select');
35
+ if (!select || select.multiple || select.disabled || node.disabled) {
36
+ return null;
37
+ }
38
+ const parentElement = node.parentElement;
39
+ if (parentElement instanceof HTMLOptGroupElement &&
40
+ parentElement.disabled) {
41
+ return null;
42
+ }
43
+ return select;
44
+ });
45
+ try {
46
+ const select = selectHandle.asElement();
47
+ if (!select) {
48
+ return false;
49
+ }
50
+ const valueHandle = await handle.getProperty('value');
51
+ try {
52
+ const value = await valueHandle.jsonValue();
53
+ if (typeof value !== 'string') {
54
+ return false;
55
+ }
56
+ await select.asLocator().fill(value);
57
+ }
58
+ finally {
59
+ void valueHandle.dispose();
60
+ }
61
+ return true;
62
+ }
63
+ finally {
64
+ void selectHandle.dispose();
65
+ }
66
+ }
29
67
  export const click = definePageTool({
30
68
  name: 'click',
31
69
  description: `Clicks on the provided element`,
@@ -40,11 +78,18 @@ export const click = definePageTool({
40
78
  dblClick: dblClickSchema,
41
79
  includeSnapshot: includeSnapshotSchema,
42
80
  },
81
+ blockedByDialog: true,
43
82
  handler: async (request, response) => {
44
83
  const uid = request.params.uid;
45
84
  const handle = await request.page.getElementByUid(uid);
85
+ const aXNode = request.page.getAXNodeByUid(uid);
86
+ const shouldSelectNativeOption = !request.params.dblClick && aXNode?.role === 'option';
46
87
  try {
47
88
  await request.page.waitForEventsAfterAction(async () => {
89
+ if (shouldSelectNativeOption &&
90
+ (await selectNativeSelectOption(handle))) {
91
+ return;
92
+ }
48
93
  await handle.asLocator().click({
49
94
  count: request.params.dblClick ? 2 : 1,
50
95
  });
@@ -70,7 +115,7 @@ export const clickAt = definePageTool({
70
115
  annotations: {
71
116
  category: ToolCategory.INPUT,
72
117
  readOnlyHint: false,
73
- conditions: ['computerVision'],
118
+ conditions: ['experimentalVision'],
74
119
  },
75
120
  schema: {
76
121
  x: zod.number().describe('The x coordinate'),
@@ -78,6 +123,7 @@ export const clickAt = definePageTool({
78
123
  dblClick: dblClickSchema,
79
124
  includeSnapshot: includeSnapshotSchema,
80
125
  },
126
+ blockedByDialog: true,
81
127
  handler: async (request, response) => {
82
128
  const page = request.page;
83
129
  await page.waitForEventsAfterAction(async () => {
@@ -106,6 +152,7 @@ export const hover = definePageTool({
106
152
  .describe('The uid of an element on the page from the page content snapshot'),
107
153
  includeSnapshot: includeSnapshotSchema,
108
154
  },
155
+ blockedByDialog: true,
109
156
  handler: async (request, response) => {
110
157
  const uid = request.params.uid;
111
158
  const handle = await request.page.getElementByUid(uid);
@@ -200,6 +247,7 @@ export const fill = definePageTool({
200
247
  value: zod.string().describe('The value to fill in'),
201
248
  includeSnapshot: includeSnapshotSchema,
202
249
  },
250
+ blockedByDialog: true,
203
251
  handler: async (request, response, context) => {
204
252
  const page = request.page;
205
253
  await page.waitForEventsAfterAction(async () => {
@@ -222,6 +270,7 @@ export const typeText = definePageTool({
222
270
  text: zod.string().describe('The text to type'),
223
271
  submitKey: submitKeySchema,
224
272
  },
273
+ blockedByDialog: true,
225
274
  handler: async (request, response) => {
226
275
  const page = request.page;
227
276
  await page.waitForEventsAfterAction(async () => {
@@ -245,6 +294,7 @@ export const drag = definePageTool({
245
294
  to_uid: zod.string().describe('The uid of the element to drop into'),
246
295
  includeSnapshot: includeSnapshotSchema,
247
296
  },
297
+ blockedByDialog: true,
248
298
  handler: async (request, response) => {
249
299
  const fromHandle = await request.page.getElementByUid(request.params.from_uid);
250
300
  const toHandle = await request.page.getElementByUid(request.params.to_uid);
@@ -283,6 +333,7 @@ export const fillForm = definePageTool({
283
333
  .describe('Elements from snapshot to fill out.'),
284
334
  includeSnapshot: includeSnapshotSchema,
285
335
  },
336
+ blockedByDialog: true,
286
337
  handler: async (request, response, context) => {
287
338
  const page = request.page;
288
339
  for (const element of request.params.elements) {
@@ -310,8 +361,10 @@ export const uploadFile = definePageTool({
310
361
  filePath: zod.string().describe('The local path of the file to upload'),
311
362
  includeSnapshot: includeSnapshotSchema,
312
363
  },
313
- handler: async (request, response) => {
364
+ blockedByDialog: true,
365
+ handler: async (request, response, context) => {
314
366
  const { uid, filePath } = request.params;
367
+ context.validatePath(filePath);
315
368
  const handle = (await request.page.getElementByUid(uid));
316
369
  try {
317
370
  try {
@@ -355,6 +408,7 @@ export const pressKey = definePageTool({
355
408
  .describe('A key or a combination (e.g., "Enter", "Control+A", "Control++", "Control+Shift+R"). Modifiers: Control, Shift, Alt, Meta'),
356
409
  includeSnapshot: includeSnapshotSchema,
357
410
  },
411
+ blockedByDialog: true,
358
412
  handler: async (request, response) => {
359
413
  const page = request.page;
360
414
  const tokens = parseKey(request.params.key);
@@ -374,3 +428,4 @@ export const pressKey = definePageTool({
374
428
  }
375
429
  },
376
430
  });
431
+ //# sourceMappingURL=input.js.map
@@ -4,13 +4,13 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import path from 'node:path';
7
- import { snapshot, navigation, generateReport, zod, } from '../third_party/index.js';
7
+ import { snapshot, navigation, generateReport, zod, agenticBrowsingConfig, } from '../third_party/index.js';
8
8
  import { ToolCategory } from './categories.js';
9
9
  import { startTrace } from './performance.js';
10
10
  import { definePageTool } from './ToolDefinition.js';
11
11
  export const lighthouseAudit = definePageTool({
12
12
  name: 'lighthouse_audit',
13
- description: `Get Lighthouse score and reports for accessibility, SEO and best practices. This excludes performance. For performance audits, run ${startTrace.name}`,
13
+ description: `Get Lighthouse score and reports for accessibility, SEO, best practices, and agentic browsing. This excludes performance. For performance audits, run ${startTrace.name}`,
14
14
  annotations: {
15
15
  category: ToolCategory.DEBUGGING,
16
16
  readOnlyHint: false,
@@ -29,11 +29,18 @@ export const lighthouseAudit = definePageTool({
29
29
  .optional()
30
30
  .describe('Directory for reports. If omitted, uses temporary files.'),
31
31
  },
32
+ blockedByDialog: true,
32
33
  handler: async (request, response, context) => {
33
34
  const page = request.page;
34
- const categories = ['accessibility', 'seo', 'best-practices'];
35
+ const categories = [
36
+ 'accessibility',
37
+ 'seo',
38
+ 'best-practices',
39
+ 'agentic-browsing',
40
+ ];
35
41
  const formats = ['json', 'html'];
36
42
  const { mode = 'navigation', device = 'desktop', outputDirPath, } = request.params;
43
+ context.validatePath(outputDirPath);
37
44
  const flags = {
38
45
  onlyCategories: categories,
39
46
  output: formats,
@@ -60,17 +67,17 @@ export const lighthouseAudit = definePageTool({
60
67
  disabled: false,
61
68
  };
62
69
  }
70
+ const options = {
71
+ flags,
72
+ config: agenticBrowsingConfig,
73
+ };
63
74
  let result;
64
75
  try {
65
76
  if (mode === 'navigation') {
66
- result = await navigation(page.pptrPage, page.pptrPage.url(), {
67
- flags,
68
- });
77
+ result = await navigation(page.pptrPage, page.pptrPage.url(), options);
69
78
  }
70
79
  else {
71
- result = await snapshot(page.pptrPage, {
72
- flags,
73
- });
80
+ result = await snapshot(page.pptrPage, options);
74
81
  }
75
82
  if (!result) {
76
83
  throw new Error('Lighthouse audit failed.');
@@ -121,3 +128,4 @@ export const lighthouseAudit = definePageTool({
121
128
  response.attachLighthouseResult(output);
122
129
  },
123
130
  });
131
+ //# sourceMappingURL=lighthouse.js.map
@@ -19,8 +19,10 @@ export const takeMemorySnapshot = definePageTool({
19
19
  .string()
20
20
  .describe('A path to a .heapsnapshot file to save the heapsnapshot to.'),
21
21
  },
22
- handler: async (request, response, _context) => {
22
+ blockedByDialog: true,
23
+ handler: async (request, response, context) => {
23
24
  const page = request.page;
25
+ context.validatePath(request.params.filePath);
24
26
  await page.pptrPage.captureHeapSnapshot({
25
27
  path: ensureExtension(request.params.filePath, '.heapsnapshot'),
26
28
  });
@@ -38,7 +40,9 @@ export const exploreMemorySnapshot = defineTool({
38
40
  schema: {
39
41
  filePath: zod.string().describe('A path to a .heapsnapshot file to read.'),
40
42
  },
43
+ blockedByDialog: false,
41
44
  handler: async (request, response, context) => {
45
+ context.validatePath(request.params.filePath);
42
46
  const stats = await context.getHeapSnapshotStats(request.params.filePath);
43
47
  const staticData = await context.getHeapSnapshotStaticData(request.params.filePath);
44
48
  response.setHeapSnapshotStats(stats, staticData);
@@ -63,7 +67,9 @@ export const getMemorySnapshotDetails = defineTool({
63
67
  .optional()
64
68
  .describe('The page size for pagination of aggregates.'),
65
69
  },
70
+ blockedByDialog: false,
66
71
  handler: async (request, response, context) => {
72
+ context.validatePath(request.params.filePath);
67
73
  const aggregates = await context.getHeapSnapshotAggregates(request.params.filePath);
68
74
  response.setHeapSnapshotAggregates(aggregates, {
69
75
  pageIdx: request.params.pageIdx,
@@ -71,3 +77,30 @@ export const getMemorySnapshotDetails = defineTool({
71
77
  });
72
78
  },
73
79
  });
80
+ export const getNodesByClass = defineTool({
81
+ name: 'get_nodes_by_class',
82
+ description: 'Loads a memory heapsnapshot and returns instances of a specific class with their stable IDs.',
83
+ annotations: {
84
+ category: ToolCategory.MEMORY,
85
+ readOnlyHint: true,
86
+ conditions: ['experimentalMemory'],
87
+ },
88
+ schema: {
89
+ filePath: zod.string().describe('A path to a .heapsnapshot file to read.'),
90
+ uid: zod
91
+ .number()
92
+ .describe('The unique UID for the class, obtained from aggregates listing.'),
93
+ pageIdx: zod.number().optional().describe('The page index for pagination.'),
94
+ pageSize: zod.number().optional().describe('The page size for pagination.'),
95
+ },
96
+ blockedByDialog: false,
97
+ handler: async (request, response, context) => {
98
+ context.validatePath(request.params.filePath);
99
+ const nodes = await context.getHeapSnapshotNodesByUid(request.params.filePath, request.params.uid);
100
+ response.setHeapSnapshotNodes(nodes, {
101
+ pageIdx: request.params.pageIdx,
102
+ pageSize: request.params.pageSize,
103
+ });
104
+ },
105
+ });
106
+ //# sourceMappingURL=memory.js.map
@@ -57,6 +57,7 @@ export const listNetworkRequests = definePageTool({
57
57
  .optional()
58
58
  .describe('Set to true to return the preserved requests over the last 3 navigations.'),
59
59
  },
60
+ blockedByDialog: false,
60
61
  handler: async (request, response, context) => {
61
62
  const data = await request.page.getDevToolsData();
62
63
  response.attachDevToolsData(data);
@@ -93,7 +94,10 @@ export const getNetworkRequest = definePageTool({
93
94
  .optional()
94
95
  .describe('The absolute or relative path to a .network-response file to save the response body to. If omitted, the body is returned inline.'),
95
96
  },
97
+ blockedByDialog: true,
96
98
  handler: async (request, response, context) => {
99
+ context.validatePath(request.params.requestFilePath);
100
+ context.validatePath(request.params.responseFilePath);
97
101
  if (request.params.reqid) {
98
102
  response.attachNetworkRequest(request.params.reqid, {
99
103
  requestFilePath: request.params.requestFilePath,
@@ -118,3 +122,4 @@ export const getNetworkRequest = definePageTool({
118
122
  }
119
123
  },
120
124
  });
125
+ //# sourceMappingURL=network.js.map
@@ -61,9 +61,10 @@ export const listPages = defineTool(args => {
61
61
  readOnlyHint: true,
62
62
  },
63
63
  schema: {},
64
+ blockedByDialog: false,
64
65
  handler: async (_request, response) => {
65
66
  response.setIncludePages(true);
66
- response.setListInPageTools();
67
+ response.setListThirdPartyDeveloperTools();
67
68
  response.setListWebMcpTools();
68
69
  },
69
70
  };
@@ -84,11 +85,12 @@ export const selectPage = defineTool({
84
85
  .optional()
85
86
  .describe('Whether to focus the page and bring it to the top.'),
86
87
  },
88
+ blockedByDialog: false,
87
89
  handler: async (request, response, context) => {
88
90
  const page = context.getPageById(request.params.pageId);
89
91
  context.selectPage(page);
90
92
  response.setIncludePages(true);
91
- response.setListInPageTools();
93
+ response.setListThirdPartyDeveloperTools();
92
94
  response.setListWebMcpTools();
93
95
  if (request.params.bringToFront) {
94
96
  await page.pptrPage.bringToFront();
@@ -107,6 +109,7 @@ export const closePage = defineTool({
107
109
  .number()
108
110
  .describe('The ID of the page to close. Call list_pages to list pages.'),
109
111
  },
112
+ blockedByDialog: false,
110
113
  handler: async (request, response, context) => {
111
114
  try {
112
115
  await context.closePage(request.params.pageId);
@@ -120,7 +123,7 @@ export const closePage = defineTool({
120
123
  }
121
124
  }
122
125
  response.setIncludePages(true);
123
- response.setListInPageTools();
126
+ response.setListThirdPartyDeveloperTools();
124
127
  },
125
128
  });
126
129
  export const newPage = defineTool(args => {
@@ -153,13 +156,14 @@ export const newPage = defineTool(args => {
153
156
  : {}),
154
157
  ...timeoutSchema,
155
158
  },
159
+ blockedByDialog: false,
156
160
  handler: async (request, response, context) => {
157
161
  const page = await context.newPage(request.params.background, request.params.isolatedContext);
158
162
  await navigateWithInterception(page, () => page.pptrPage.goto(request.params.url, {
159
163
  timeout: request.params.timeout,
160
164
  }), request.params.allowList, request.params.timeout);
161
165
  response.setIncludePages(true);
162
- response.setListInPageTools();
166
+ response.setListThirdPartyDeveloperTools();
163
167
  },
164
168
  };
165
169
  });
@@ -199,6 +203,7 @@ export const navigatePage = definePageTool(args => {
199
203
  : {}),
200
204
  ...timeoutSchema,
201
205
  },
206
+ blockedByDialog: false,
202
207
  handler: async (request, response) => {
203
208
  const page = request.page;
204
209
  const options = {
@@ -290,7 +295,7 @@ export const navigatePage = definePageTool(args => {
290
295
  }
291
296
  }
292
297
  response.setIncludePages(true);
293
- response.setListInPageTools();
298
+ response.setListThirdPartyDeveloperTools();
294
299
  response.setListWebMcpTools();
295
300
  },
296
301
  };
@@ -306,6 +311,7 @@ export const resizePage = definePageTool({
306
311
  width: zod.number().describe('Page width'),
307
312
  height: zod.number().describe('Page height'),
308
313
  },
314
+ blockedByDialog: false,
309
315
  handler: async (request, response, _context) => {
310
316
  const page = request.page;
311
317
  try {
@@ -347,6 +353,7 @@ export const handleDialog = definePageTool({
347
353
  .optional()
348
354
  .describe('Optional prompt text to enter into the dialog.'),
349
355
  },
356
+ blockedByDialog: false,
350
357
  handler: async (request, response, _context) => {
351
358
  const page = request.page;
352
359
  const dialog = page.getDialog();
@@ -394,9 +401,11 @@ export const getTabId = definePageTool({
394
401
  .number()
395
402
  .describe(`The ID of the page to get the tab ID for. Call ${listPages().name} to get available pages.`),
396
403
  },
404
+ blockedByDialog: false,
397
405
  handler: async (request, response, context) => {
398
406
  const page = context.getPageById(request.params.pageId);
399
407
  const tabId = page.pptrPage._tabId;
400
408
  response.setTabId(tabId);
401
409
  },
402
410
  });
411
+ //# sourceMappingURL=pages.js.map
@@ -31,7 +31,9 @@ export const startTrace = definePageTool({
31
31
  .describe('Determines if the trace recording should be automatically stopped.'),
32
32
  filePath: filePathSchema,
33
33
  },
34
+ blockedByDialog: true,
34
35
  handler: async (request, response, context) => {
36
+ context.validatePath(request.params.filePath);
35
37
  if (context.isRunningPerformanceTrace()) {
36
38
  response.appendResponseLine('Error: a performance trace is already running. Use performance_stop_trace to stop it. Only one trace can be running at any given time.');
37
39
  return;
@@ -93,7 +95,9 @@ export const stopTrace = definePageTool({
93
95
  schema: {
94
96
  filePath: filePathSchema,
95
97
  },
98
+ blockedByDialog: true,
96
99
  handler: async (request, response, context) => {
100
+ context.validatePath(request.params.filePath);
97
101
  if (!context.isRunningPerformanceTrace()) {
98
102
  return;
99
103
  }
@@ -116,6 +120,7 @@ export const analyzeInsight = definePageTool({
116
120
  .string()
117
121
  .describe('The name of the Insight you want more information on. For example: "DocumentLatency" or "LCPBreakdown"'),
118
122
  },
123
+ blockedByDialog: false,
119
124
  handler: async (request, response, context) => {
120
125
  const lastRecording = context.recordedTraces().at(-1);
121
126
  if (!lastRecording) {
@@ -188,3 +193,4 @@ async function populateCruxData(result) {
188
193
  }));
189
194
  result.parsedTrace.metadata.cruxFieldData = cruxData;
190
195
  }
196
+ //# sourceMappingURL=performance.js.map
@@ -21,7 +21,7 @@ export const startScreencast = definePageTool(args => ({
21
21
  annotations: {
22
22
  category: ToolCategory.DEBUGGING,
23
23
  readOnlyHint: false,
24
- conditions: ['screencast'],
24
+ conditions: ['experimentalScreencast'],
25
25
  },
26
26
  schema: {
27
27
  filePath: zod
@@ -29,7 +29,9 @@ export const startScreencast = definePageTool(args => ({
29
29
  .optional()
30
30
  .describe(`Output file path (${supportedExtensions.join(',')} are supported). Uses mkdtemp to generate a unique path if not provided.`),
31
31
  },
32
+ blockedByDialog: false,
32
33
  handler: async (request, response, context) => {
34
+ context.validatePath(request.params.filePath);
33
35
  if (context.getScreenRecorder() !== null) {
34
36
  response.appendResponseLine('Error: a screencast recording is already in progress. Use screencast_stop to stop it before starting a new one.');
35
37
  return;
@@ -72,9 +74,10 @@ export const stopScreencast = definePageTool({
72
74
  annotations: {
73
75
  category: ToolCategory.DEBUGGING,
74
76
  readOnlyHint: false,
75
- conditions: ['screencast'],
77
+ conditions: ['experimentalScreencast'],
76
78
  },
77
79
  schema: {},
80
+ blockedByDialog: false,
78
81
  handler: async (_request, response, context) => {
79
82
  const data = context.getScreenRecorder();
80
83
  if (!data) {
@@ -89,3 +92,4 @@ export const stopScreencast = definePageTool({
89
92
  }
90
93
  },
91
94
  });
95
+ //# sourceMappingURL=screencast.js.map
@@ -38,7 +38,9 @@ export const screenshot = definePageTool({
38
38
  .optional()
39
39
  .describe('The absolute path, or a path relative to the current working directory, to save the screenshot to instead of attaching it to the response.'),
40
40
  },
41
+ blockedByDialog: true,
41
42
  handler: async (request, response, context) => {
43
+ context.validatePath(request.params.filePath);
42
44
  if (request.params.uid && request.params.fullPage) {
43
45
  throw new Error('Providing both "uid" and "fullPage" is not allowed.');
44
46
  }
@@ -82,3 +84,4 @@ export const screenshot = definePageTool({
82
84
  }
83
85
  },
84
86
  });
87
+ //# sourceMappingURL=screenshot.js.map
@@ -46,6 +46,7 @@ Example with arguments: \`(el) => {
46
46
  }
47
47
  : {}),
48
48
  },
49
+ blockedByDialog: true,
49
50
  handler: async (request, response, context) => {
50
51
  const { serviceWorkerId, args: uidArgs, function: fnString, pageId, dialogAction, } = request.params;
51
52
  if (cliArgs?.categoryExtensions && serviceWorkerId) {
@@ -125,3 +126,4 @@ const getWebWorker = async (context, serviceWorkerId) => {
125
126
  throw new Error('Service worker not found.');
126
127
  }
127
128
  };
129
+ //# sourceMappingURL=script.js.map
@@ -15,6 +15,7 @@ export const screenshot = definePageTool({
15
15
  readOnlyHint: false,
16
16
  },
17
17
  schema: {},
18
+ blockedByDialog: true,
18
19
  handler: async (request, response, context) => {
19
20
  const page = request.page;
20
21
  const screenshot = await page.pptrPage.screenshot({
@@ -35,6 +36,7 @@ export const navigate = definePageTool({
35
36
  schema: {
36
37
  url: zod.string().describe('URL to navigate to'),
37
38
  },
39
+ blockedByDialog: false,
38
40
  handler: async (request, response) => {
39
41
  const page = request.page;
40
42
  const options = {
@@ -68,6 +70,7 @@ export const evaluate = definePageTool({
68
70
  schema: {
69
71
  script: zod.string().describe(`JS script to run on the page`),
70
72
  },
73
+ blockedByDialog: true,
71
74
  handler: async (request, response) => {
72
75
  const page = request.page;
73
76
  try {
@@ -79,3 +82,4 @@ export const evaluate = definePageTool({
79
82
  }
80
83
  },
81
84
  });
85
+ //# sourceMappingURL=tools.js.map
@@ -26,7 +26,9 @@ in the DevTools Elements panel (if any).`,
26
26
  .optional()
27
27
  .describe('The absolute path, or a path relative to the current working directory, to save the snapshot to instead of attaching it to the response.'),
28
28
  },
29
- handler: async (request, response) => {
29
+ blockedByDialog: true,
30
+ handler: async (request, response, context) => {
31
+ context.validatePath(request.params.filePath);
30
32
  response.includeSnapshot({
31
33
  verbose: request.params.verbose ?? false,
32
34
  filePath: request.params.filePath,
@@ -47,6 +49,7 @@ export const waitFor = definePageTool({
47
49
  .describe('Non-empty list of texts. Resolves when any value appears on the page.'),
48
50
  ...timeoutSchema,
49
51
  },
52
+ blockedByDialog: true,
50
53
  handler: async (request, response, context) => {
51
54
  const page = request.page;
52
55
  await context.waitForTextOnPage(request.params.text, request.params.timeout, page.pptrPage);
@@ -54,3 +57,4 @@ export const waitFor = definePageTool({
54
57
  response.includeSnapshot();
55
58
  },
56
59
  });
60
+ //# sourceMappingURL=snapshot.js.map