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.
Files changed (78) hide show
  1. package/README.md +4 -0
  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 +54 -126
  6. package/build/src/McpPage.js +204 -0
  7. package/build/src/McpResponse.js +44 -6
  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 +236 -0
  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 +206 -46
  15. package/build/src/bin/chrome-devtools-mcp-cli-options.js +13 -1
  16. package/build/src/bin/chrome-devtools-mcp-main.js +1 -0
  17. package/build/src/bin/chrome-devtools-mcp.js +1 -0
  18. package/build/src/bin/chrome-devtools.js +27 -27
  19. package/build/src/browser.js +1 -0
  20. package/build/src/daemon/client.js +14 -12
  21. package/build/src/daemon/daemon.js +7 -5
  22. package/build/src/daemon/types.js +1 -0
  23. package/build/src/daemon/utils.js +20 -14
  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 +32 -5
  43. package/build/src/third_party/bundled-packages.json +3 -2
  44. package/build/src/third_party/devtools-formatter-worker.js +2451 -2933
  45. package/build/src/third_party/devtools-heap-snapshot-worker.js +32 -26
  46. package/build/src/third_party/index.js +1942 -1536
  47. package/build/src/third_party/lighthouse-devtools-mcp-bundle.js +21717 -20261
  48. package/build/src/tools/ToolDefinition.js +1 -0
  49. package/build/src/tools/categories.js +6 -2
  50. package/build/src/tools/console.js +3 -0
  51. package/build/src/tools/emulation.js +2 -0
  52. package/build/src/tools/extensions.js +6 -0
  53. package/build/src/tools/inPage.js +5 -35
  54. package/build/src/tools/input.js +13 -2
  55. package/build/src/tools/lighthouse.js +17 -9
  56. package/build/src/tools/memory.js +34 -1
  57. package/build/src/tools/network.js +7 -2
  58. package/build/src/tools/pages.js +218 -146
  59. package/build/src/tools/performance.js +6 -0
  60. package/build/src/tools/screencast.js +25 -10
  61. package/build/src/tools/screenshot.js +3 -0
  62. package/build/src/tools/script.js +2 -0
  63. package/build/src/tools/slim/tools.js +4 -0
  64. package/build/src/tools/snapshot.js +5 -1
  65. package/build/src/tools/tools.js +1 -0
  66. package/build/src/tools/webmcp.js +3 -0
  67. package/build/src/trace-processing/parse.js +1 -0
  68. package/build/src/types.js +1 -0
  69. package/build/src/utils/check-for-updates.js +1 -0
  70. package/build/src/utils/files.js +5 -10
  71. package/build/src/utils/id.js +1 -0
  72. package/build/src/utils/keyboard.js +1 -0
  73. package/build/src/utils/pagination.js +1 -0
  74. package/build/src/utils/string.js +1 -0
  75. package/build/src/utils/types.js +1 -0
  76. package/build/src/version.js +2 -1
  77. package/package.json +10 -9
  78. package/build/src/bin/cliDefinitions.js +0 -621
@@ -12,11 +12,68 @@ import { Mutex } from './Mutex.js';
12
12
  import { SlimMcpResponse } from './SlimMcpResponse.js';
13
13
  import { ClearcutLogger } from './telemetry/ClearcutLogger.js';
14
14
  import { bucketizeLatency } from './telemetry/metricUtils.js';
15
- import { McpServer, SetLevelRequestSchema, } from './third_party/index.js';
16
- import { ToolCategory } from './tools/categories.js';
15
+ import { McpServer, SetLevelRequestSchema, ListRootsResultSchema, RootsListChangedNotificationSchema, } from './third_party/index.js';
16
+ import { labels, OFF_BY_DEFAULT_CATEGORIES } from './tools/categories.js';
17
17
  import { pageIdSchema } from './tools/ToolDefinition.js';
18
18
  import { createTools } from './tools/tools.js';
19
19
  import { VERSION } from './version.js';
20
+ export function buildFlag(category) {
21
+ return `category${category.charAt(0).toUpperCase() + category.slice(1)}`;
22
+ }
23
+ function buildDisabledMessage(toolName, flag, categoryLabel) {
24
+ const reason = categoryLabel
25
+ ? `is in category ${categoryLabel} which`
26
+ : `requires experimental feature ${flag} and`;
27
+ return `Tool ${toolName} ${reason} is currently disabled. Enable it by running chrome-devtools start ${flag}=true. For more information check the README.`;
28
+ }
29
+ function getCategoryStatus(category, serverArgs) {
30
+ const categoryFlag = buildFlag(category);
31
+ const flagValue = serverArgs[categoryFlag];
32
+ const isDisabled = OFF_BY_DEFAULT_CATEGORIES.includes(category)
33
+ ? !flagValue
34
+ : flagValue === false;
35
+ if (isDisabled) {
36
+ return {
37
+ categoryFlag,
38
+ disabled: true,
39
+ };
40
+ }
41
+ return {
42
+ disabled: false,
43
+ };
44
+ }
45
+ function getConditionStatus(condition, serverArgs) {
46
+ if (condition && !serverArgs[condition]) {
47
+ return { conditionFlag: condition, disabled: true };
48
+ }
49
+ return { disabled: false };
50
+ }
51
+ function getToolStatusInfo(tool, serverArgs) {
52
+ const category = tool.annotations.category;
53
+ const categoryCheck = getCategoryStatus(category, serverArgs);
54
+ if (category && categoryCheck.disabled) {
55
+ if (!categoryCheck.categoryFlag) {
56
+ throw new Error('when the category is disabled there should always be a flag set');
57
+ }
58
+ return {
59
+ disabled: true,
60
+ reason: buildDisabledMessage(tool.name, `--${categoryCheck.categoryFlag}`, labels[category]),
61
+ };
62
+ }
63
+ for (const condition of tool.annotations.conditions || []) {
64
+ const conditionCheck = getConditionStatus(condition, serverArgs);
65
+ if (conditionCheck.disabled) {
66
+ if (!conditionCheck.conditionFlag) {
67
+ throw new Error('when the condition is disabled there should always be a flag set');
68
+ }
69
+ return {
70
+ disabled: true,
71
+ reason: buildDisabledMessage(tool.name, `--${conditionCheck.conditionFlag}`),
72
+ };
73
+ }
74
+ }
75
+ return { disabled: false };
76
+ }
20
77
  export async function createMcpServer(serverArgs, options) {
21
78
  let clearcutLogger;
22
79
  if (serverArgs.usageStatistics) {
@@ -36,11 +93,29 @@ export async function createMcpServer(serverArgs, options) {
36
93
  server.server.setRequestHandler(SetLevelRequestSchema, () => {
37
94
  return {};
38
95
  });
96
+ const updateRoots = async () => {
97
+ if (!server.server.getClientCapabilities()?.roots) {
98
+ return;
99
+ }
100
+ try {
101
+ const roots = await server.server.request({ method: 'roots/list' }, ListRootsResultSchema);
102
+ context?.setRoots(roots.roots);
103
+ }
104
+ catch (e) {
105
+ logger('Failed to list roots', e);
106
+ }
107
+ };
39
108
  server.server.oninitialized = () => {
40
109
  const clientName = server.server.getClientVersion()?.name;
41
110
  if (clientName) {
42
111
  clearcutLogger?.setClientName(clientName);
43
112
  }
113
+ if (server.server.getClientCapabilities()?.roots) {
114
+ void updateRoots();
115
+ server.server.setNotificationHandler(RootsListChangedNotificationSchema, () => {
116
+ void updateRoots();
117
+ });
118
+ }
44
119
  };
45
120
  let context;
46
121
  async function getContext() {
@@ -83,49 +158,14 @@ export async function createMcpServer(serverArgs, options) {
83
158
  experimentalIncludeAllPages: serverArgs.experimentalIncludeAllPages,
84
159
  performanceCrux: serverArgs.performanceCrux,
85
160
  });
161
+ await updateRoots();
86
162
  }
87
163
  return context;
88
164
  }
89
165
  const toolMutex = new Mutex();
90
166
  function registerTool(tool) {
91
- if (tool.annotations.category === ToolCategory.EMULATION &&
92
- serverArgs.categoryEmulation === false) {
93
- return;
94
- }
95
- if (tool.annotations.category === ToolCategory.PERFORMANCE &&
96
- serverArgs.categoryPerformance === false) {
97
- return;
98
- }
99
- if (tool.annotations.category === ToolCategory.NETWORK &&
100
- serverArgs.categoryNetwork === false) {
101
- return;
102
- }
103
- if (tool.annotations.category === ToolCategory.EXTENSIONS &&
104
- serverArgs.categoryExtensions === false) {
105
- return;
106
- }
107
- if (tool.annotations.category === ToolCategory.IN_PAGE &&
108
- !serverArgs.categoryInPageTools) {
109
- return;
110
- }
111
- if (tool.annotations.conditions?.includes('computerVision') &&
112
- !serverArgs.experimentalVision) {
113
- return;
114
- }
115
- if (tool.annotations.conditions?.includes('experimentalMemory') &&
116
- !serverArgs.experimentalMemory) {
117
- return;
118
- }
119
- if (tool.annotations.conditions?.includes('experimentalInteropTools') &&
120
- !serverArgs.experimentalInteropTools) {
121
- return;
122
- }
123
- if (tool.annotations.conditions?.includes('screencast') &&
124
- !serverArgs.experimentalScreencast) {
125
- return;
126
- }
127
- if (tool.annotations.conditions?.includes('experimentalWebmcp') &&
128
- !serverArgs.experimentalWebmcp) {
167
+ const { disabled, reason: disabledReason } = getToolStatusInfo(tool, serverArgs);
168
+ if (disabled && !serverArgs.viaCli) {
129
169
  return;
130
170
  }
131
171
  const schema = 'pageScoped' in tool &&
@@ -139,6 +179,17 @@ export async function createMcpServer(serverArgs, options) {
139
179
  inputSchema: schema,
140
180
  annotations: tool.annotations,
141
181
  }, async (params) => {
182
+ if (disabledReason) {
183
+ return {
184
+ content: [
185
+ {
186
+ type: 'text',
187
+ text: disabledReason,
188
+ },
189
+ ],
190
+ isError: true,
191
+ };
192
+ }
142
193
  const guard = await toolMutex.acquire();
143
194
  const startTime = Date.now();
144
195
  let success = false;
@@ -151,29 +202,40 @@ export async function createMcpServer(serverArgs, options) {
151
202
  ? new SlimMcpResponse(serverArgs)
152
203
  : new McpResponse(serverArgs);
153
204
  response.setRedactNetworkHeaders(serverArgs.redactNetworkHeaders);
154
- if ('pageScoped' in tool && tool.pageScoped) {
205
+ try {
155
206
  const page = serverArgs.experimentalPageIdRouting &&
156
207
  params.pageId &&
157
208
  !serverArgs.slim
158
209
  ? context.getPageById(params.pageId)
159
210
  : context.getSelectedMcpPage();
160
211
  response.setPage(page);
161
- await tool.handler({
162
- params,
163
- page,
164
- }, response, context);
212
+ if (tool.blockedByDialog) {
213
+ page.throwIfDialogOpen();
214
+ }
215
+ if ('pageScoped' in tool && tool.pageScoped) {
216
+ await tool.handler({
217
+ params,
218
+ page,
219
+ }, response, context);
220
+ }
221
+ else {
222
+ await tool.handler(
223
+ // @ts-expect-error types do not match.
224
+ {
225
+ params,
226
+ }, response, context);
227
+ }
165
228
  }
166
- else {
167
- await tool.handler(
168
- // @ts-expect-error types do not match.
169
- {
170
- params,
171
- }, response, context);
229
+ catch (err) {
230
+ response.setError(err);
172
231
  }
173
232
  const { content, structuredContent } = await response.handle(tool.name, context);
174
233
  const result = {
175
234
  content,
176
235
  };
236
+ if (response.error) {
237
+ result.isError = true;
238
+ }
177
239
  success = true;
178
240
  if (serverArgs.experimentalStructuredContent) {
179
241
  result.structuredContent = structuredContent;
@@ -228,3 +290,4 @@ Google collects usage statistics to improve Chrome DevTools MCP. To opt-out, run
228
290
  For more details, visit: https://github.com/ChromeDevTools/chrome-devtools-mcp#usage-statistics`);
229
291
  }
230
292
  };
293
+ //# sourceMappingURL=index.js.map
@@ -37,3 +37,4 @@ export const ISSUE_UTILS = {
37
37
  loadIssueDescriptions,
38
38
  getIssueDescription,
39
39
  };
40
+ //# sourceMappingURL=issue-descriptions.js.map
@@ -34,3 +34,4 @@ export function flushLogs(logFile, timeoutMs = 2000) {
34
34
  });
35
35
  }
36
36
  export const logger = debug(mcpDebugNamespace);
37
+ //# sourceMappingURL=logger.js.map
@@ -5,3 +5,4 @@
5
5
  */
6
6
  // polyfills are now bundled with all other dependencies
7
7
  import './third_party/index.js';
8
+ //# sourceMappingURL=polyfill.js.map
@@ -64,9 +64,20 @@ export function transformArgType(zodType) {
64
64
  throw new Error(`Unsupported zod type for tool parameter: ${zodType}`);
65
65
  }
66
66
  }
67
+ const BUCKETS = [
68
+ 0, 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000,
69
+ ];
70
+ function bucketize(value) {
71
+ for (const bucket of BUCKETS) {
72
+ if (bucket >= value) {
73
+ return bucket;
74
+ }
75
+ }
76
+ return BUCKETS[BUCKETS.length - 1];
77
+ }
67
78
  function transformValue(zodType, value) {
68
79
  if (zodType === 'ZodString') {
69
- return value.length;
80
+ return bucketize(value.length);
70
81
  }
71
82
  else if (zodType === 'ZodArray') {
72
83
  return value.length;
@@ -239,3 +250,4 @@ export class ClearcutLogger {
239
250
  return !isSameDay;
240
251
  }
241
252
  }
253
+ //# sourceMappingURL=ClearcutLogger.js.map
@@ -58,3 +58,4 @@ export class WatchdogClient {
58
58
  }
59
59
  }
60
60
  }
61
+ //# sourceMappingURL=WatchdogClient.js.map
@@ -85,3 +85,4 @@ export function getPossibleFlagMetrics(options) {
85
85
  }
86
86
  return metrics;
87
87
  }
88
+ //# sourceMappingURL=flagUtils.js.map
@@ -12,3 +12,4 @@ export function bucketizeLatency(latencyMs) {
12
12
  }
13
13
  return LATENCY_BUCKETS[LATENCY_BUCKETS.length - 1];
14
14
  }
15
+ //# sourceMappingURL=metricUtils.js.map
@@ -51,3 +51,4 @@ export class FilePersistence {
51
51
  }
52
52
  }
53
53
  }
54
+ //# sourceMappingURL=persistence.js.map
@@ -32,7 +32,7 @@ export function applyToExistingMetrics(existing, update) {
32
32
  return tool;
33
33
  });
34
34
  }
35
- function applyToExisting(existing, update) {
35
+ export function applyToExisting(existing, update) {
36
36
  const existingNames = new Set(existing.map(item => item.name));
37
37
  const updatedNames = new Set(update.map(item => item.name));
38
38
  const result = [];
@@ -86,3 +86,4 @@ export function generateToolMetrics(tools) {
86
86
  };
87
87
  });
88
88
  }
89
+ //# sourceMappingURL=toolMetricsUtils.js.map
@@ -36,3 +36,4 @@ export var WatchdogMessageType;
36
36
  (function (WatchdogMessageType) {
37
37
  WatchdogMessageType["LOG_EVENT"] = "log-event";
38
38
  })(WatchdogMessageType || (WatchdogMessageType = {}));
39
+ //# sourceMappingURL=types.js.map
@@ -202,3 +202,4 @@ export class ClearcutSender {
202
202
  return this.#buffer.length;
203
203
  }
204
204
  }
205
+ //# sourceMappingURL=ClearcutSender.js.map
@@ -125,3 +125,4 @@ catch (err) {
125
125
  console.error('Watchdog fatal error:', err);
126
126
  process.exit(1);
127
127
  }
128
+ //# sourceMappingURL=main.js.map
@@ -1,3 +1,30 @@
1
+ Name: urlpattern-polyfill
2
+ URL: https://github.com/kenchris/urlpattern-polyfill
3
+ Version: 10.1.0
4
+ License: MIT
5
+
6
+ Copyright 2020 Intel Corporation
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ of this software and associated documentation files (the "Software"), to deal
10
+ in the Software without restriction, including without limitation the rights
11
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ copies of the Software, and to permit persons to whom the Software is
13
+ furnished to do so, subject to the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be included in
16
+ all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ THE SOFTWARE.
25
+
26
+ -------------------- DEPENDENCY DIVIDER --------------------
27
+
1
28
  Name: core-js
2
29
  URL: https://core-js.io
3
30
  Version: 3.49.0
@@ -2525,7 +2552,7 @@ SOFTWARE.
2525
2552
 
2526
2553
  Name: axe-core
2527
2554
  URL: https://www.deque.com/axe/
2528
- Version: 4.11.2
2555
+ Version: 4.11.4
2529
2556
  License: MPL-2.0
2530
2557
 
2531
2558
  Mozilla Public License, version 2.0
@@ -3961,7 +3988,7 @@ SOFTWARE.
3961
3988
 
3962
3989
  Name: puppeteer-core
3963
3990
  URL: https://github.com/puppeteer/puppeteer/tree/main/packages/puppeteer-core
3964
- Version: 24.40.0
3991
+ Version: 24.42.0
3965
3992
  License: Apache-2.0
3966
3993
 
3967
3994
  -------------------- DEPENDENCY DIVIDER --------------------
@@ -4027,7 +4054,7 @@ SOFTWARE.
4027
4054
 
4028
4055
  Name: tldts-core
4029
4056
  URL: https://github.com/remusao/tldts#readme
4030
- Version: 7.0.27
4057
+ Version: 7.0.29
4031
4058
  License: MIT
4032
4059
 
4033
4060
  Copyright (c) 2017 Thomas Parisot, 2018 Rémi Berson
@@ -4049,7 +4076,7 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTH
4049
4076
 
4050
4077
  Name: tldts-icann
4051
4078
  URL: https://github.com/remusao/tldts#readme
4052
- Version: 7.0.27
4079
+ Version: 7.0.29
4053
4080
  License: MIT
4054
4081
 
4055
4082
  Copyright (c) 2017 Thomas Parisot, 2018 Rémi Berson
@@ -4091,7 +4118,7 @@ PERFORMANCE OF THIS SOFTWARE.
4091
4118
 
4092
4119
  Name: web-features
4093
4120
  URL: git+https://github.com/web-platform-dx/web-features.git
4094
- Version: 3.21.0
4121
+ Version: 3.25.0
4095
4122
  License: Apache-2.0
4096
4123
 
4097
4124
  Apache License
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "@modelcontextprotocol/sdk": "1.29.0",
3
- "chrome-devtools-frontend": "1.0.1613625",
3
+ "chrome-devtools-frontend": "1.0.1618066",
4
4
  "core-js": "3.49.0",
5
5
  "debug": "4.4.3",
6
- "lighthouse": "13.1.0",
6
+ "lighthouse": "13.2.0",
7
7
  "semver": "^7.7.4",
8
+ "urlpattern-polyfill": "^10.1.0",
8
9
  "yargs": "18.0.0",
9
10
  "puppeteer-core": "24.42.0"
10
11
  }