chrome-devtools-mcp 0.9.0 → 0.10.1

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 (66) hide show
  1. package/README.md +14 -9
  2. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Console.js +1 -8
  3. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/ParsedURL.js +10 -20
  4. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/SegmentedRange.js +1 -2
  5. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Settings.js +3 -0
  6. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/StringOutputStream.js +1 -4
  7. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/AidaClient.js +19 -0
  8. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/DispatchHttpRequestClient.js +54 -0
  9. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/GdpClient.js +6 -51
  10. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/InspectorFrontendHost.js +2 -2
  11. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/InspectorFrontendHostAPI.js +32 -29
  12. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/UserMetrics.js +14 -6
  13. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/host.js +2 -1
  14. package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/CDPConnection.js +17 -0
  15. package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/InspectorBackend.js +68 -188
  16. package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/protocol_client.js +2 -1
  17. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/AnimationModel.js +1 -2
  18. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSMatchedStyles.js +3 -3
  19. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSModel.js +1 -1
  20. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSProperty.js +3 -6
  21. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSPropertyParserMatchers.js +14 -10
  22. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSStyleDeclaration.js +4 -4
  23. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ChildTargetManager.js +5 -33
  24. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/Connections.js +9 -46
  25. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/DOMModel.js +1 -0
  26. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/DebuggerModel.js +1 -2
  27. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/EnhancedTracesParser.js +17 -3
  28. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/NetworkManager.js +59 -37
  29. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/NetworkRequest.js +5 -0
  30. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/RehydratingConnection.js +102 -4
  31. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/SourceMap.js +2 -3
  32. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/sdk-meta.js +8 -1
  33. package/build/node_modules/chrome-devtools-frontend/front_end/generated/InspectorBackendCommands.js +1 -39
  34. package/build/node_modules/chrome-devtools-frontend/front_end/generated/SupportedCSSProperties.js +58 -0
  35. package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.js +46 -45
  36. package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/performance/AIContext.js +10 -25
  37. package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/CompilerScriptMapping.js +1 -1
  38. package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/DebuggerWorkspaceBinding.js +1 -1
  39. package/build/node_modules/chrome-devtools-frontend/front_end/models/cpu_profile/ProfileTreeModel.js +6 -7
  40. package/build/node_modules/chrome-devtools-frontend/front_end/models/stack_trace/StackTraceModel.js +1 -1
  41. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/NetworkRequestsHandler.js +12 -3
  42. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/types/TraceEvents.js +3 -0
  43. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace_source_maps_resolver/SourceMapsResolver.js +1 -1
  44. package/build/node_modules/chrome-devtools-frontend/mcp/mcp.js +14 -0
  45. package/build/src/DevToolsConnectionAdapter.js +1 -0
  46. package/build/src/DevtoolsUtils.js +44 -0
  47. package/build/src/McpContext.js +133 -21
  48. package/build/src/McpResponse.js +33 -22
  49. package/build/src/PageCollector.js +21 -9
  50. package/build/src/browser.js +8 -8
  51. package/build/src/cli.js +8 -3
  52. package/build/src/formatters/networkFormatter.js +2 -2
  53. package/build/src/formatters/snapshotFormatter.js +18 -6
  54. package/build/src/main.js +7 -2
  55. package/build/src/third_party/THIRD_PARTY_NOTICES +72 -52
  56. package/build/src/third_party/index.js +12687 -6053
  57. package/build/src/tools/emulation.js +37 -44
  58. package/build/src/tools/input.js +36 -6
  59. package/build/src/tools/network.js +27 -5
  60. package/build/src/tools/pages.js +60 -34
  61. package/build/src/tools/performance.js +5 -2
  62. package/build/src/tools/screenshot.js +2 -1
  63. package/build/src/tools/snapshot.js +13 -4
  64. package/build/src/trace-processing/parse.js +6 -16
  65. package/build/src/utils/keyboard.js +291 -0
  66. package/package.json +7 -6
@@ -11,61 +11,54 @@ const throttlingOptions = [
11
11
  'Offline',
12
12
  ...Object.keys(PredefinedNetworkConditions),
13
13
  ];
14
- export const emulateNetwork = defineTool({
15
- name: 'emulate_network',
16
- description: `Emulates network conditions such as throttling or offline mode on the selected page.`,
14
+ export const emulate = defineTool({
15
+ name: 'emulate',
16
+ description: `Emulates various features on the selected page.`,
17
17
  annotations: {
18
18
  category: ToolCategory.EMULATION,
19
19
  readOnlyHint: false,
20
20
  },
21
21
  schema: {
22
- throttlingOption: zod
22
+ networkConditions: zod
23
23
  .enum(throttlingOptions)
24
- .describe(`The network throttling option to emulate. Available throttling options are: ${throttlingOptions.join(', ')}. Set to "No emulation" to disable. Set to "Offline" to simulate offline network conditions.`),
25
- },
26
- handler: async (request, _response, context) => {
27
- const page = context.getSelectedPage();
28
- const conditions = request.params.throttlingOption;
29
- if (conditions === 'No emulation') {
30
- await page.emulateNetworkConditions(null);
31
- context.setNetworkConditions(null);
32
- return;
33
- }
34
- if (conditions === 'Offline') {
35
- await page.emulateNetworkConditions({
36
- offline: true,
37
- download: 0,
38
- upload: 0,
39
- latency: 0,
40
- });
41
- context.setNetworkConditions('Offline');
42
- return;
43
- }
44
- if (conditions in PredefinedNetworkConditions) {
45
- const networkCondition = PredefinedNetworkConditions[conditions];
46
- await page.emulateNetworkConditions(networkCondition);
47
- context.setNetworkConditions(conditions);
48
- }
49
- },
50
- });
51
- export const emulateCpu = defineTool({
52
- name: 'emulate_cpu',
53
- description: `Emulates CPU throttling by slowing down the selected page's execution.`,
54
- annotations: {
55
- category: ToolCategory.EMULATION,
56
- readOnlyHint: false,
57
- },
58
- schema: {
59
- throttlingRate: zod
24
+ .optional()
25
+ .describe(`Throttle network. Set to "No emulation" to disable. If omitted, conditions remain unchanged.`),
26
+ cpuThrottlingRate: zod
60
27
  .number()
61
28
  .min(1)
62
29
  .max(20)
63
- .describe('The CPU throttling rate representing the slowdown factor 1-20x. Set the rate to 1 to disable throttling'),
30
+ .optional()
31
+ .describe('Represents the CPU slowdown factor. Set the rate to 1 to disable throttling. If omitted, throttling remains unchanged.'),
64
32
  },
65
33
  handler: async (request, _response, context) => {
66
34
  const page = context.getSelectedPage();
67
- const { throttlingRate } = request.params;
68
- await page.emulateCPUThrottling(throttlingRate);
69
- context.setCpuThrottlingRate(throttlingRate);
35
+ const networkConditions = request.params.networkConditions;
36
+ const cpuThrottlingRate = request.params.cpuThrottlingRate;
37
+ if (networkConditions) {
38
+ if (networkConditions === 'No emulation') {
39
+ await page.emulateNetworkConditions(null);
40
+ context.setNetworkConditions(null);
41
+ return;
42
+ }
43
+ if (networkConditions === 'Offline') {
44
+ await page.emulateNetworkConditions({
45
+ offline: true,
46
+ download: 0,
47
+ upload: 0,
48
+ latency: 0,
49
+ });
50
+ context.setNetworkConditions('Offline');
51
+ return;
52
+ }
53
+ if (networkConditions in PredefinedNetworkConditions) {
54
+ const networkCondition = PredefinedNetworkConditions[networkConditions];
55
+ await page.emulateNetworkConditions(networkCondition);
56
+ context.setNetworkConditions(networkConditions);
57
+ }
58
+ }
59
+ if (cpuThrottlingRate) {
60
+ await page.emulateCPUThrottling(cpuThrottlingRate);
61
+ context.setCpuThrottlingRate(cpuThrottlingRate);
62
+ }
70
63
  },
71
64
  });
@@ -4,6 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import { zod } from '../third_party/index.js';
7
+ import { parseKey } from '../utils/keyboard.js';
7
8
  import { ToolCategory } from './categories.js';
8
9
  import { defineTool } from './ToolDefinition.js';
9
10
  export const click = defineTool({
@@ -34,7 +35,7 @@ export const click = defineTool({
34
35
  response.appendResponseLine(request.params.dblClick
35
36
  ? `Successfully double clicked on the element`
36
37
  : `Successfully clicked on the element`);
37
- response.setIncludeSnapshot(true);
38
+ response.includeSnapshot();
38
39
  }
39
40
  finally {
40
41
  void handle.dispose();
@@ -61,7 +62,7 @@ export const hover = defineTool({
61
62
  await handle.asLocator().hover();
62
63
  });
63
64
  response.appendResponseLine(`Successfully hovered over the element`);
64
- response.setIncludeSnapshot(true);
65
+ response.includeSnapshot();
65
66
  }
66
67
  finally {
67
68
  void handle.dispose();
@@ -135,7 +136,7 @@ export const fill = defineTool({
135
136
  await fillFormElement(request.params.uid, request.params.value, context);
136
137
  });
137
138
  response.appendResponseLine(`Successfully filled out the element`);
138
- response.setIncludeSnapshot(true);
139
+ response.includeSnapshot();
139
140
  },
140
141
  });
141
142
  export const drag = defineTool({
@@ -159,7 +160,7 @@ export const drag = defineTool({
159
160
  await toHandle.drop(fromHandle);
160
161
  });
161
162
  response.appendResponseLine(`Successfully dragged an element`);
162
- response.setIncludeSnapshot(true);
163
+ response.includeSnapshot();
163
164
  }
164
165
  finally {
165
166
  void fromHandle.dispose();
@@ -189,7 +190,7 @@ export const fillForm = defineTool({
189
190
  });
190
191
  }
191
192
  response.appendResponseLine(`Successfully filled out the form`);
192
- response.setIncludeSnapshot(true);
193
+ response.includeSnapshot();
193
194
  },
194
195
  });
195
196
  export const uploadFile = defineTool({
@@ -228,7 +229,7 @@ export const uploadFile = defineTool({
228
229
  throw new Error(`Failed to upload file. The element could not accept the file directly, and clicking it did not trigger a file chooser.`);
229
230
  }
230
231
  }
231
- response.setIncludeSnapshot(true);
232
+ response.includeSnapshot();
232
233
  response.appendResponseLine(`File uploaded from ${filePath}.`);
233
234
  }
234
235
  finally {
@@ -236,3 +237,32 @@ export const uploadFile = defineTool({
236
237
  }
237
238
  },
238
239
  });
240
+ export const pressKey = defineTool({
241
+ name: 'press_key',
242
+ description: `Press a key or key combination. Use this when other input methods like fill() cannot be used (e.g., keyboard shortcuts, navigation keys, or special key combinations).`,
243
+ annotations: {
244
+ category: ToolCategory.INPUT,
245
+ readOnlyHint: false,
246
+ },
247
+ schema: {
248
+ key: zod
249
+ .string()
250
+ .describe('A key or a combination (e.g., "Enter", "Control+A", "Control++", "Control+Shift+R"). Modifiers: Control, Shift, Alt, Meta'),
251
+ },
252
+ handler: async (request, response, context) => {
253
+ const page = context.getSelectedPage();
254
+ const tokens = parseKey(request.params.key);
255
+ const [key, ...modifiers] = tokens;
256
+ await context.waitForEventsAfterAction(async () => {
257
+ for (const modifier of modifiers) {
258
+ await page.keyboard.down(modifier);
259
+ }
260
+ await page.keyboard.press(key);
261
+ for (const modifier of modifiers.toReversed()) {
262
+ await page.keyboard.up(modifier);
263
+ }
264
+ });
265
+ response.appendResponseLine(`Successfully pressed key: ${request.params.key}`);
266
+ response.includeSnapshot();
267
+ },
268
+ });
@@ -57,18 +57,24 @@ export const listNetworkRequests = defineTool({
57
57
  .optional()
58
58
  .describe('Set to true to return the preserved requests over the last 3 navigations.'),
59
59
  },
60
- handler: async (request, response) => {
60
+ handler: async (request, response, context) => {
61
+ const data = await context.getDevToolsData();
62
+ response.attachDevToolsData(data);
63
+ const reqid = data?.cdpRequestId
64
+ ? context.resolveCdpRequestId(data.cdpRequestId)
65
+ : undefined;
61
66
  response.setIncludeNetworkRequests(true, {
62
67
  pageSize: request.params.pageSize,
63
68
  pageIdx: request.params.pageIdx,
64
69
  resourceTypes: request.params.resourceTypes,
65
70
  includePreservedRequests: request.params.includePreservedRequests,
71
+ networkRequestIdInDevToolsUI: reqid,
66
72
  });
67
73
  },
68
74
  });
69
75
  export const getNetworkRequest = defineTool({
70
76
  name: 'get_network_request',
71
- description: `Gets a network request by URL. You can get all requests by calling ${listNetworkRequests.name}.`,
77
+ description: `Gets a network request by an optional reqid, if omitted returns the currently selected request in the DevTools Network panel.`,
72
78
  annotations: {
73
79
  category: ToolCategory.NETWORK,
74
80
  readOnlyHint: true,
@@ -76,9 +82,25 @@ export const getNetworkRequest = defineTool({
76
82
  schema: {
77
83
  reqid: zod
78
84
  .number()
79
- .describe('The reqid of a request on the page from the listed network requests'),
85
+ .optional()
86
+ .describe('The reqid of the network request. If omitted returns the currently selected request in the DevTools Network panel.'),
80
87
  },
81
- handler: async (request, response, _context) => {
82
- response.attachNetworkRequest(request.params.reqid);
88
+ handler: async (request, response, context) => {
89
+ if (request.params.reqid) {
90
+ response.attachNetworkRequest(request.params.reqid);
91
+ }
92
+ else {
93
+ const data = await context.getDevToolsData();
94
+ response.attachDevToolsData(data);
95
+ const reqid = data?.cdpRequestId
96
+ ? context.resolveCdpRequestId(data.cdpRequestId)
97
+ : undefined;
98
+ if (reqid) {
99
+ response.attachNetworkRequest(reqid);
100
+ }
101
+ else {
102
+ response.appendResponseLine(`Nothing is currently selected in the DevTools Network panel.`);
103
+ }
104
+ }
83
105
  },
84
106
  });
@@ -34,7 +34,7 @@ export const selectPage = defineTool({
34
34
  handler: async (request, response, context) => {
35
35
  const page = context.getPageByIdx(request.params.pageIdx);
36
36
  await page.bringToFront();
37
- context.setSelectedPageIdx(request.params.pageIdx);
37
+ context.selectPage(page);
38
38
  response.setIncludePages(true);
39
39
  },
40
40
  });
@@ -94,30 +94,15 @@ export const navigatePage = defineTool({
94
94
  readOnlyHint: false,
95
95
  },
96
96
  schema: {
97
- url: zod.string().describe('URL to navigate the page to'),
98
- ...timeoutSchema,
99
- },
100
- handler: async (request, response, context) => {
101
- const page = context.getSelectedPage();
102
- await context.waitForEventsAfterAction(async () => {
103
- await page.goto(request.params.url, {
104
- timeout: request.params.timeout,
105
- });
106
- });
107
- response.setIncludePages(true);
108
- },
109
- });
110
- export const navigatePageHistory = defineTool({
111
- name: 'navigate_page_history',
112
- description: `Navigates the currently selected page.`,
113
- annotations: {
114
- category: ToolCategory.NAVIGATION,
115
- readOnlyHint: false,
116
- },
117
- schema: {
118
- navigate: zod
119
- .enum(['back', 'forward'])
120
- .describe('Whether to navigate back or navigate forward in the selected pages history'),
97
+ type: zod
98
+ .enum(['url', 'back', 'forward', 'reload'])
99
+ .optional()
100
+ .describe('Navigate the page by URL, back or forward in history, or reload.'),
101
+ url: zod.string().optional().describe('Target URL (only type=url)'),
102
+ ignoreCache: zod
103
+ .boolean()
104
+ .optional()
105
+ .describe('Whether to ignore cache on reload.'),
121
106
  ...timeoutSchema,
122
107
  },
123
108
  handler: async (request, response, context) => {
@@ -125,17 +110,58 @@ export const navigatePageHistory = defineTool({
125
110
  const options = {
126
111
  timeout: request.params.timeout,
127
112
  };
128
- try {
129
- if (request.params.navigate === 'back') {
130
- await page.goBack(options);
131
- }
132
- else {
133
- await page.goForward(options);
134
- }
113
+ if (!request.params.type && !request.params.url) {
114
+ throw new Error('Either URL or a type is required.');
135
115
  }
136
- catch (error) {
137
- response.appendResponseLine(`Unable to navigate ${request.params.navigate} in currently selected page. ${error.message}`);
116
+ if (!request.params.type) {
117
+ request.params.type = 'url';
138
118
  }
119
+ await context.waitForEventsAfterAction(async () => {
120
+ switch (request.params.type) {
121
+ case 'url':
122
+ if (!request.params.url) {
123
+ throw new Error('A URL is required for navigation of type=url.');
124
+ }
125
+ try {
126
+ await page.goto(request.params.url, options);
127
+ response.appendResponseLine(`Successfully navigated to ${request.params.url}.`);
128
+ }
129
+ catch (error) {
130
+ response.appendResponseLine(`Unable to navigate in the selected page: ${error.message}.`);
131
+ }
132
+ break;
133
+ case 'back':
134
+ try {
135
+ await page.goBack(options);
136
+ response.appendResponseLine(`Successfully navigated back to ${page.url()}.`);
137
+ }
138
+ catch (error) {
139
+ response.appendResponseLine(`Unable to navigate back in the selected page: ${error.message}.`);
140
+ }
141
+ break;
142
+ case 'forward':
143
+ try {
144
+ await page.goForward(options);
145
+ response.appendResponseLine(`Successfully navigated forward to ${page.url()}.`);
146
+ }
147
+ catch (error) {
148
+ response.appendResponseLine(`Unable to navigate forward in the selected page: ${error.message}.`);
149
+ }
150
+ break;
151
+ case 'reload':
152
+ try {
153
+ await page.reload({
154
+ ...options,
155
+ ignoreCache: request.params.ignoreCache,
156
+ });
157
+ response.appendResponseLine(`Successfully reloaded the page.`);
158
+ }
159
+ catch (error) {
160
+ response.appendResponseLine(`Unable to reload the selected page: ${error.message}.`);
161
+ }
162
+ break;
163
+ }
164
+ });
139
165
  response.setIncludePages(true);
140
166
  },
141
167
  });
@@ -93,12 +93,15 @@ export const stopTrace = defineTool({
93
93
  });
94
94
  export const analyzeInsight = defineTool({
95
95
  name: 'performance_analyze_insight',
96
- description: 'Provides more detailed information on a specific Performance Insight that was highlighted in the results of a trace recording.',
96
+ description: 'Provides more detailed information on a specific Performance Insight of an insight set that was highlighted in the results of a trace recording.',
97
97
  annotations: {
98
98
  category: ToolCategory.PERFORMANCE,
99
99
  readOnlyHint: true,
100
100
  },
101
101
  schema: {
102
+ insightSetId: zod
103
+ .string()
104
+ .describe('The id for the specific insight set. Only use the ids given in the "Available insight sets" list.'),
102
105
  insightName: zod
103
106
  .string()
104
107
  .describe('The name of the Insight you want more information on. For example: "DocumentLatency" or "LCPBreakdown"'),
@@ -109,7 +112,7 @@ export const analyzeInsight = defineTool({
109
112
  response.appendResponseLine('No recorded traces found. Record a performance trace so you have Insights to analyze.');
110
113
  return;
111
114
  }
112
- const insightOutput = getInsightOutput(lastRecording, request.params.insightName);
115
+ const insightOutput = getInsightOutput(lastRecording, request.params.insightSetId, request.params.insightName);
113
116
  if ('error' in insightOutput) {
114
117
  response.appendResponseLine(insightOutput.error);
115
118
  return;
@@ -11,7 +11,8 @@ export const screenshot = defineTool({
11
11
  description: `Take a screenshot of the page or element.`,
12
12
  annotations: {
13
13
  category: ToolCategory.DEBUGGING,
14
- readOnlyHint: true,
14
+ // Not read-only due to filePath param.
15
+ readOnlyHint: false,
15
16
  },
16
17
  schema: {
17
18
  format: zod
@@ -9,19 +9,28 @@ import { defineTool, timeoutSchema } from './ToolDefinition.js';
9
9
  export const takeSnapshot = defineTool({
10
10
  name: 'take_snapshot',
11
11
  description: `Take a text snapshot of the currently selected page based on the a11y tree. The snapshot lists page elements along with a unique
12
- identifier (uid). Always use the latest snapshot. Prefer taking a snapshot over taking a screenshot.`,
12
+ identifier (uid). Always use the latest snapshot. Prefer taking a snapshot over taking a screenshot. The snapshot indicates the element selected
13
+ in the DevTools Elements panel (if any).`,
13
14
  annotations: {
14
15
  category: ToolCategory.DEBUGGING,
15
- readOnlyHint: true,
16
+ // Not read-only due to filePath param.
17
+ readOnlyHint: false,
16
18
  },
17
19
  schema: {
18
20
  verbose: zod
19
21
  .boolean()
20
22
  .optional()
21
23
  .describe('Whether to include all possible information available in the full a11y tree. Default is false.'),
24
+ filePath: zod
25
+ .string()
26
+ .optional()
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.'),
22
28
  },
23
29
  handler: async (request, response) => {
24
- response.setIncludeSnapshot(true, request.params.verbose ?? false);
30
+ response.includeSnapshot({
31
+ verbose: request.params.verbose ?? false,
32
+ filePath: request.params.filePath,
33
+ });
25
34
  },
26
35
  });
27
36
  export const waitFor = defineTool({
@@ -38,6 +47,6 @@ export const waitFor = defineTool({
38
47
  handler: async (request, response, context) => {
39
48
  await context.waitForTextOnPage(request.params);
40
49
  response.appendResponseLine(`Element with text "${request.params.text}" found.`);
41
- response.setIncludeSnapshot(true);
50
+ response.includeSnapshot();
42
51
  },
43
52
  });
@@ -3,10 +3,7 @@
3
3
  * Copyright 2025 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- import { PerformanceInsightFormatter } from '../../node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.js';
7
- import { PerformanceTraceFormatter } from '../../node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.js';
8
- import { AgentFocus } from '../../node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/performance/AIContext.js';
9
- import * as TraceEngine from '../../node_modules/chrome-devtools-frontend/front_end/models/trace/trace.js';
6
+ import { AgentFocus, TraceEngine, PerformanceTraceFormatter, PerformanceInsightFormatter, } from '../../node_modules/chrome-devtools-frontend/mcp/mcp.js';
10
7
  import { logger } from '../logger.js';
11
8
  const engine = TraceEngine.TraceModel.Model.createWithAllHandlers();
12
9
  export function traceResultIsSuccess(x) {
@@ -64,26 +61,19 @@ ${summaryText}
64
61
  ## Details on call tree & network request formats:
65
62
  ${extraFormatDescriptions}`;
66
63
  }
67
- export function getInsightOutput(result, insightName) {
64
+ export function getInsightOutput(result, insightSetId, insightName) {
68
65
  if (!result.insights) {
69
66
  return {
70
67
  error: 'No Performance insights are available for this trace.',
71
68
  };
72
69
  }
73
- // Currently, we do not support inspecting traces with multiple navigations. We either:
74
- // 1. Find Insights from the first navigation (common case: user records a trace with a page reload to test load performance)
75
- // 2. Fall back to finding Insights not associated with a navigation (common case: user tests an interaction without a page load).
76
- const mainNavigationId = result.parsedTrace.data.Meta.mainFrameNavigations.at(0)?.args.data
77
- ?.navigationId;
78
- const insightsForNav = result.insights.get(mainNavigationId ?? TraceEngine.Types.Events.NO_NAVIGATION);
79
- if (!insightsForNav) {
70
+ const insightSet = result.insights.get(insightSetId);
71
+ if (!insightSet) {
80
72
  return {
81
- error: 'No Performance Insights for this trace.',
73
+ error: 'No Performance Insights for the given insight set id. Only use ids given in the "Available insight sets" list.',
82
74
  };
83
75
  }
84
- const matchingInsight = insightName in insightsForNav.model
85
- ? insightsForNav.model[insightName]
86
- : null;
76
+ const matchingInsight = insightName in insightSet.model ? insightSet.model[insightName] : null;
87
77
  if (!matchingInsight) {
88
78
  return {
89
79
  error: `No Insight with the name ${insightName} found. Double check the name you provided is accurate and try again.`,