chrome-devtools-mcp 0.6.0 → 0.7.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 (63) hide show
  1. package/README.md +13 -6
  2. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Color.js +13 -9
  3. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/ColorConverter.js +9 -7
  4. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Gzip.js +1 -1
  5. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/MapWithDefault.js +5 -3
  6. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/ResourceType.js +0 -11
  7. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/ReturnToPanel.js +6 -4
  8. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/AidaClient.js +1 -1
  9. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/GdpClient.js +116 -59
  10. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/Platform.js +5 -3
  11. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/UserMetrics.js +6 -4
  12. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/ArrayUtilities.js +1 -1
  13. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/StringUtilities.js +33 -31
  14. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSMetadata.js +4 -2
  15. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSPropertyParser.js +11 -9
  16. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSPropertyParserMatchers.js +19 -13
  17. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ChildTargetManager.js +30 -0
  18. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/DOMModel.js +1 -1
  19. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/EventBreakpointsModel.js +4 -2
  20. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/HttpReasonPhraseStrings.js +4 -2
  21. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/NetworkManager.js +9 -41
  22. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/NetworkRequest.js +0 -14
  23. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/PageResourceLoader.js +1 -1
  24. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/PreloadingModel.js +7 -5
  25. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/RehydratingConnection.js +1 -1
  26. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/RemoteObject.js +1 -1
  27. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ResourceTreeModel.js +1 -0
  28. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ScreenCaptureModel.js +20 -18
  29. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/Target.js +7 -1
  30. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/TraceObject.js +2 -2
  31. package/build/node_modules/chrome-devtools-frontend/front_end/generated/Deprecation.js +4 -4
  32. package/build/node_modules/chrome-devtools-frontend/front_end/generated/InspectorBackendCommands.js +2 -2
  33. package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.js +30 -3
  34. package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/performance/AIContext.js +18 -4
  35. package/build/node_modules/chrome-devtools-frontend/front_end/models/crux-manager/CrUXManager.js +1 -1
  36. package/build/node_modules/chrome-devtools-frontend/front_end/models/network_time_calculator/RequestTimeRanges.js +6 -4
  37. package/build/node_modules/chrome-devtools-frontend/front_end/models/source_map_scopes/NamesResolver.js +7 -5
  38. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/LanternComputationData.js +1 -0
  39. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/extras/TraceTree.js +1 -1
  40. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/FramesHandler.js +7 -5
  41. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/LayoutShiftsHandler.js +8 -4
  42. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/NetworkRequestsHandler.js +17 -0
  43. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/helpers.js +1 -1
  44. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/helpers/Timing.js +4 -2
  45. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/helpers/Trace.js +8 -4
  46. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/DocumentLatency.js +10 -10
  47. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/INPBreakdown.js +12 -1
  48. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/LCPBreakdown.js +11 -1
  49. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/NetworkDependencyTree.js +2 -2
  50. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/types/TraceEvents.js +5 -3
  51. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace_source_maps_resolver/SourceMapsResolver.js +1 -1
  52. package/build/src/McpContext.js +24 -7
  53. package/build/src/McpResponse.js +49 -20
  54. package/build/src/Mutex.js +3 -6
  55. package/build/src/browser.js +6 -5
  56. package/build/src/cli.js +10 -2
  57. package/build/src/formatters/consoleFormatter.js +1 -1
  58. package/build/src/formatters/networkFormatter.js +44 -0
  59. package/build/src/tools/emulation.js +13 -2
  60. package/build/src/tools/performance.js +3 -4
  61. package/build/src/tools/screenshot.js +2 -3
  62. package/build/src/trace-processing/parse.js +7 -6
  63. package/package.json +7 -6
@@ -27,8 +27,6 @@ function targetFilter(target) {
27
27
  }
28
28
  const connectOptions = {
29
29
  targetFilter,
30
- // We do not expect any single CDP command to take more than 10sec.
31
- protocolTimeout: 10_000,
32
30
  };
33
31
  export async function ensureBrowserConnected(browserURL) {
34
32
  if (browser?.connected) {
@@ -60,9 +58,12 @@ export async function launch(options) {
60
58
  if (customDevTools) {
61
59
  args.push(`--custom-devtools-frontend=file://${customDevTools}`);
62
60
  }
63
- let puppeterChannel;
61
+ if (headless) {
62
+ args.push('--screen-info={3840x2160}');
63
+ }
64
+ let puppeteerChannel;
64
65
  if (!executablePath) {
65
- puppeterChannel =
66
+ puppeteerChannel =
66
67
  channel && channel !== 'stable'
67
68
  ? `chrome-${channel}`
68
69
  : 'chrome';
@@ -70,7 +71,7 @@ export async function launch(options) {
70
71
  try {
71
72
  const browser = await puppeteer.launch({
72
73
  ...connectOptions,
73
- channel: puppeterChannel,
74
+ channel: puppeteerChannel,
74
75
  executablePath,
75
76
  defaultViewport: null,
76
77
  userDataDir,
package/build/src/cli.js CHANGED
@@ -11,7 +11,15 @@ export const cliOptions = {
11
11
  description: 'Connect to a running Chrome instance using port forwarding. For more details see: https://developer.chrome.com/docs/devtools/remote-debugging/local-server.',
12
12
  alias: 'u',
13
13
  coerce: (url) => {
14
- new URL(url);
14
+ if (!url) {
15
+ return;
16
+ }
17
+ try {
18
+ new URL(url);
19
+ }
20
+ catch {
21
+ throw new Error(`Provided browserUrl ${url} is not valid URL.`);
22
+ }
15
23
  return url;
16
24
  },
17
25
  },
@@ -50,7 +58,7 @@ export const cliOptions = {
50
58
  },
51
59
  viewport: {
52
60
  type: 'string',
53
- describe: 'Initial viewport size for the Chromee instances started by the server. For example, `1280x720`',
61
+ describe: 'Initial viewport size for the Chrome instances started by the server. For example, `1280x720`. In headless mode, max size is 3840x2160px.',
54
62
  coerce: (arg) => {
55
63
  if (arg === undefined) {
56
64
  return;
@@ -30,7 +30,7 @@ async function formatConsoleMessage(msg) {
30
30
  return error.toString();
31
31
  })
32
32
  .catch(() => {
33
- return 'Error occured';
33
+ return 'Error occurred';
34
34
  });
35
35
  void errorHandle.dispose().catch();
36
36
  const formattedArgs = await formatArgs(args.slice(1));
@@ -3,6 +3,8 @@
3
3
  * Copyright 2025 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
+ import { isUtf8 } from 'node:buffer';
7
+ const BODY_CONTEXT_SIZE_LIMIT = 10000;
6
8
  export function getShortDescriptionForRequest(request) {
7
9
  return `${request.url()} ${request.method()} ${getStatusFromRequest(request)}`;
8
10
  }
@@ -32,3 +34,45 @@ export function getFormattedHeaderValue(headers) {
32
34
  }
33
35
  return response;
34
36
  }
37
+ export async function getFormattedResponseBody(httpResponse, sizeLimit = BODY_CONTEXT_SIZE_LIMIT) {
38
+ try {
39
+ const responseBuffer = await httpResponse.buffer();
40
+ if (isUtf8(responseBuffer)) {
41
+ const responseAsTest = responseBuffer.toString('utf-8');
42
+ if (responseAsTest.length === 0) {
43
+ return `<empty response>`;
44
+ }
45
+ return `${getSizeLimitedString(responseAsTest, sizeLimit)}`;
46
+ }
47
+ return `<binary data>`;
48
+ }
49
+ catch {
50
+ // buffer() call might fail with CDP exception, in this case we don't print anything in the context
51
+ return;
52
+ }
53
+ }
54
+ export async function getFormattedRequestBody(httpRequest, sizeLimit = BODY_CONTEXT_SIZE_LIMIT) {
55
+ if (httpRequest.hasPostData()) {
56
+ const data = httpRequest.postData();
57
+ if (data) {
58
+ return `${getSizeLimitedString(data, sizeLimit)}`;
59
+ }
60
+ try {
61
+ const fetchData = await httpRequest.fetchPostData();
62
+ if (fetchData) {
63
+ return `${getSizeLimitedString(fetchData, sizeLimit)}`;
64
+ }
65
+ }
66
+ catch {
67
+ // fetchPostData() call might fail with CDP exception, in this case we don't print anything in the context
68
+ return;
69
+ }
70
+ }
71
+ return;
72
+ }
73
+ function getSizeLimitedString(text, sizeLimit) {
74
+ if (text.length > sizeLimit) {
75
+ return `${text.substring(0, sizeLimit) + '... <truncated>'}`;
76
+ }
77
+ return `${text}`;
78
+ }
@@ -9,11 +9,12 @@ import { ToolCategories } from './categories.js';
9
9
  import { defineTool } from './ToolDefinition.js';
10
10
  const throttlingOptions = [
11
11
  'No emulation',
12
+ 'Offline',
12
13
  ...Object.keys(PredefinedNetworkConditions),
13
14
  ];
14
15
  export const emulateNetwork = defineTool({
15
16
  name: 'emulate_network',
16
- description: `Emulates network conditions such as throttling on the selected page.`,
17
+ description: `Emulates network conditions such as throttling or offline mode on the selected page.`,
17
18
  annotations: {
18
19
  category: ToolCategories.EMULATION,
19
20
  readOnlyHint: false,
@@ -21,7 +22,7 @@ export const emulateNetwork = defineTool({
21
22
  schema: {
22
23
  throttlingOption: z
23
24
  .enum(throttlingOptions)
24
- .describe(`The network throttling option to emulate. Available throttling options are: ${throttlingOptions.join(', ')}. Set to "No emulation" to disable.`),
25
+ .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
  },
26
27
  handler: async (request, _response, context) => {
27
28
  const page = context.getSelectedPage();
@@ -31,6 +32,16 @@ export const emulateNetwork = defineTool({
31
32
  context.setNetworkConditions(null);
32
33
  return;
33
34
  }
35
+ if (conditions === 'Offline') {
36
+ await page.emulateNetworkConditions({
37
+ offline: true,
38
+ download: 0,
39
+ upload: 0,
40
+ latency: 0,
41
+ });
42
+ context.setNetworkConditions('Offline');
43
+ return;
44
+ }
34
45
  if (conditions in PredefinedNetworkConditions) {
35
46
  const networkCondition = PredefinedNetworkConditions[conditions];
36
47
  await page.emulateNetworkConditions(networkCondition);
@@ -84,7 +84,7 @@ export const stopTrace = defineTool({
84
84
  },
85
85
  schema: {},
86
86
  handler: async (_request, response, context) => {
87
- if (!context.isRunningPerformanceTrace) {
87
+ if (!context.isRunningPerformanceTrace()) {
88
88
  return;
89
89
  }
90
90
  const page = context.getSelectedPage();
@@ -93,7 +93,7 @@ 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 highlighed in the results of a trace recording.',
96
+ description: 'Provides more detailed information on a specific Performance Insight that was highlighted in the results of a trace recording.',
97
97
  annotations: {
98
98
  category: ToolCategories.PERFORMANCE,
99
99
  readOnlyHint: true,
@@ -124,7 +124,6 @@ async function stopTracingAndAppendOutput(page, response, context) {
124
124
  response.appendResponseLine('The performance trace has been stopped.');
125
125
  if (traceResultIsSuccess(result)) {
126
126
  context.storeTraceRecording(result);
127
- response.appendResponseLine('Here is a high level summary of the trace and the Insights that were found:');
128
127
  const traceSummaryText = getTraceSummary(result);
129
128
  response.appendResponseLine(traceSummaryText);
130
129
  }
@@ -136,7 +135,7 @@ async function stopTracingAndAppendOutput(page, response, context) {
136
135
  catch (e) {
137
136
  const errorText = e instanceof Error ? e.message : JSON.stringify(e);
138
137
  logger(`Error stopping performance trace: ${errorText}`);
139
- response.appendResponseLine('An error occured generating the response for this trace:');
138
+ response.appendResponseLine('An error occurred generating the response for this trace:');
140
139
  response.appendResponseLine(errorText);
141
140
  }
142
141
  finally {
@@ -3,7 +3,6 @@
3
3
  * Copyright 2025 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- import { writeFile } from 'node:fs/promises';
7
6
  import z from 'zod';
8
7
  import { ToolCategories } from './categories.js';
9
8
  import { defineTool } from './ToolDefinition.js';
@@ -65,8 +64,8 @@ export const screenshot = defineTool({
65
64
  response.appendResponseLine("Took a screenshot of the current page's viewport.");
66
65
  }
67
66
  if (request.params.filePath) {
68
- await writeFile(request.params.filePath, screenshot);
69
- response.appendResponseLine(`Saved screenshot to ${request.params.filePath}.`);
67
+ const file = await context.saveFile(screenshot, request.params.filePath);
68
+ response.appendResponseLine(`Saved screenshot to ${file.filename}.`);
70
69
  }
71
70
  else if (screenshot.length >= 2_000_000) {
72
71
  const { filename } = await context.saveTemporaryFile(screenshot, `image/${request.params.format}`);
@@ -43,7 +43,7 @@ export async function parseRawTraceBuffer(buffer) {
43
43
  }
44
44
  catch (e) {
45
45
  const errorText = e instanceof Error ? e.message : JSON.stringify(e);
46
- logger(`Unexpeced error parsing trace: ${errorText}`);
46
+ logger(`Unexpected error parsing trace: ${errorText}`);
47
47
  return {
48
48
  error: errorText,
49
49
  };
@@ -53,15 +53,16 @@ const extraFormatDescriptions = `Information on performance traces may contain m
53
53
 
54
54
  ${PerformanceTraceFormatter.callFrameDataFormatDescription}
55
55
 
56
- ${PerformanceTraceFormatter.networkDataFormatDescription}
57
- `;
56
+ ${PerformanceTraceFormatter.networkDataFormatDescription}`;
58
57
  export function getTraceSummary(result) {
59
58
  const focus = AgentFocus.fromParsedTrace(result.parsedTrace);
60
59
  const formatter = new PerformanceTraceFormatter(focus);
61
- const output = formatter.formatTraceSummary();
62
- return `${extraFormatDescriptions}
60
+ const summaryText = formatter.formatTraceSummary();
61
+ return `## Summary of Performance trace findings:
62
+ ${summaryText}
63
63
 
64
- ${output}`;
64
+ ## Details on call tree & network request formats:
65
+ ${extraFormatDescriptions}`;
65
66
  }
66
67
  export function getInsightOutput(result, insightName) {
67
68
  if (!result.insights) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chrome-devtools-mcp",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "MCP server for Chrome DevTools",
5
5
  "type": "module",
6
6
  "bin": "./build/src/index.js",
@@ -37,11 +37,12 @@
37
37
  "homepage": "https://github.com/ChromeDevTools/chrome-devtools-mcp#readme",
38
38
  "mcpName": "io.github.ChromeDevTools/chrome-devtools-mcp",
39
39
  "dependencies": {
40
- "@modelcontextprotocol/sdk": "1.18.2",
40
+ "@modelcontextprotocol/sdk": "1.19.1",
41
41
  "core-js": "3.45.1",
42
42
  "debug": "4.4.3",
43
- "puppeteer-core": "24.22.3",
44
- "yargs": "18.0.0"
43
+ "puppeteer-core": "^24.23.1",
44
+ "yargs": "18.0.0",
45
+ "zod": "^3.25.76"
45
46
  },
46
47
  "devDependencies": {
47
48
  "@eslint/js": "^9.35.0",
@@ -53,13 +54,13 @@
53
54
  "@types/yargs": "^17.0.33",
54
55
  "@typescript-eslint/eslint-plugin": "^8.43.0",
55
56
  "@typescript-eslint/parser": "^8.43.0",
56
- "chrome-devtools-frontend": "1.0.1521880",
57
+ "chrome-devtools-frontend": "1.0.1524741",
57
58
  "eslint": "^9.35.0",
58
59
  "eslint-import-resolver-typescript": "^4.4.4",
59
60
  "eslint-plugin-import": "^2.32.0",
60
61
  "globals": "^16.4.0",
61
62
  "prettier": "^3.6.2",
62
- "puppeteer": "24.22.3",
63
+ "puppeteer": "24.23.1",
63
64
  "sinon": "^21.0.0",
64
65
  "typescript": "^5.9.2",
65
66
  "typescript-eslint": "^8.43.0"