chrome-devtools-mcp 0.24.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 (25) hide show
  1. package/README.md +22 -5
  2. package/build/src/McpPage.js +4 -4
  3. package/build/src/McpResponse.js +18 -16
  4. package/build/src/TextSnapshot.js +2 -2
  5. package/build/src/bin/chrome-devtools-cli-options.js +27 -4
  6. package/build/src/bin/chrome-devtools-mcp-cli-options.js +8 -5
  7. package/build/src/bin/chrome-devtools-mcp-main.js +0 -5
  8. package/build/src/third_party/THIRD_PARTY_NOTICES +3 -3
  9. package/build/src/third_party/bundled-packages.json +2 -2
  10. package/build/src/third_party/devtools-formatter-worker.js +18 -0
  11. package/build/src/third_party/devtools-heap-snapshot-worker.js +18 -0
  12. package/build/src/third_party/index.js +578 -278
  13. package/build/src/third_party/issue-descriptions/genericFormModelContextMissingToolDescription.md +5 -0
  14. package/build/src/third_party/issue-descriptions/genericFormModelContextMissingToolName.md +5 -0
  15. package/build/src/third_party/issue-descriptions/genericFormModelContextParameterMissingName.md +5 -0
  16. package/build/src/third_party/issue-descriptions/genericFormModelContextParameterMissingTitleAndDescription.md +5 -0
  17. package/build/src/third_party/issue-descriptions/genericFormModelContextRequiredParameterMissingName.md +5 -0
  18. package/build/src/tools/categories.js +6 -3
  19. package/build/src/tools/input.js +44 -0
  20. package/build/src/tools/pages.js +5 -5
  21. package/build/src/tools/{inPage.js → thirdPartyDeveloper.js} +15 -15
  22. package/build/src/tools/tools.js +2 -2
  23. package/build/src/tools/webmcp.js +2 -4
  24. package/build/src/version.js +1 -1
  25. package/package.json +3 -4
@@ -0,0 +1,5 @@
1
+ # Missing tool description for a WebMCP declarative tool definition
2
+
3
+ This form is intended to be used as a WebMCP declarative tool definition, but it lacks a description explaining what the tool does. Descriptions are critical for AI models to decide when to use a given tool.
4
+
5
+ To fix this issue, provide a tool description via the `tooldescription` attribute.
@@ -0,0 +1,5 @@
1
+ # Missing tool name for a WebMCP declarative tool definition
2
+
3
+ This form is intended to be used as a WebMCP declarative tool definition, but it does not specify a name. A tool name is required for an AI model to correctly identify and invoke the tool.
4
+
5
+ To fix this issue, provide a tool name via the `toolname` attribute.
@@ -0,0 +1,5 @@
1
+ # Parameter missing name for a WebMCP declarative tool definition
2
+
3
+ An input element within this form lacks a `name` attribute. Without a name, the AI model cannot format the parameter payload correctly when invoking the tool.
4
+
5
+ To fix this issue, ensure form parameters have a `name` attribute.
@@ -0,0 +1,5 @@
1
+ # Missing parameter title and description for a WebMCP declarative tool definition
2
+
3
+ A parameter within this form (such as an `<input>` field) is missing both a title and a description. An AI model needs this metadata to understand what information should be passed to this parameter when invoking the tool.
4
+
5
+ To fix this issue, add a title and description to the form parameter.
@@ -0,0 +1,5 @@
1
+ # Required parameter missing name for a WebMCP declarative tool definition
2
+
3
+ A required input element within this form lacks a `name` attribute. Without a name, the AI model cannot format the parameter payload correctly when invoking the tool.
4
+
5
+ To fix this issue, ensure all required form parameters have a `name` attribute.
@@ -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"] = "experimentalInPage";
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,11 +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
31
  export const OFF_BY_DEFAULT_CATEGORIES = [
30
32
  ToolCategory.EXTENSIONS,
31
- ToolCategory.IN_PAGE,
33
+ ToolCategory.THIRD_PARTY,
34
+ ToolCategory.WEBMCP,
32
35
  ];
33
36
  //# sourceMappingURL=categories.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`,
@@ -44,8 +82,14 @@ export const click = definePageTool({
44
82
  handler: async (request, response) => {
45
83
  const uid = request.params.uid;
46
84
  const handle = await request.page.getElementByUid(uid);
85
+ const aXNode = request.page.getAXNodeByUid(uid);
86
+ const shouldSelectNativeOption = !request.params.dblClick && aXNode?.role === 'option';
47
87
  try {
48
88
  await request.page.waitForEventsAfterAction(async () => {
89
+ if (shouldSelectNativeOption &&
90
+ (await selectNativeSelectOption(handle))) {
91
+ return;
92
+ }
49
93
  await handle.asLocator().click({
50
94
  count: request.params.dblClick ? 2 : 1,
51
95
  });
@@ -64,7 +64,7 @@ export const listPages = defineTool(args => {
64
64
  blockedByDialog: false,
65
65
  handler: async (_request, response) => {
66
66
  response.setIncludePages(true);
67
- response.setListInPageTools();
67
+ response.setListThirdPartyDeveloperTools();
68
68
  response.setListWebMcpTools();
69
69
  },
70
70
  };
@@ -90,7 +90,7 @@ export const selectPage = defineTool({
90
90
  const page = context.getPageById(request.params.pageId);
91
91
  context.selectPage(page);
92
92
  response.setIncludePages(true);
93
- response.setListInPageTools();
93
+ response.setListThirdPartyDeveloperTools();
94
94
  response.setListWebMcpTools();
95
95
  if (request.params.bringToFront) {
96
96
  await page.pptrPage.bringToFront();
@@ -123,7 +123,7 @@ export const closePage = defineTool({
123
123
  }
124
124
  }
125
125
  response.setIncludePages(true);
126
- response.setListInPageTools();
126
+ response.setListThirdPartyDeveloperTools();
127
127
  },
128
128
  });
129
129
  export const newPage = defineTool(args => {
@@ -163,7 +163,7 @@ export const newPage = defineTool(args => {
163
163
  timeout: request.params.timeout,
164
164
  }), request.params.allowList, request.params.timeout);
165
165
  response.setIncludePages(true);
166
- response.setListInPageTools();
166
+ response.setListThirdPartyDeveloperTools();
167
167
  },
168
168
  };
169
169
  });
@@ -295,7 +295,7 @@ export const navigatePage = definePageTool(args => {
295
295
  }
296
296
  }
297
297
  response.setIncludePages(true);
298
- response.setListInPageTools();
298
+ response.setListThirdPartyDeveloperTools();
299
299
  response.setListWebMcpTools();
300
300
  },
301
301
  };
@@ -6,30 +6,30 @@
6
6
  import { zod, ajv } from '../third_party/index.js';
7
7
  import { ToolCategory } from './categories.js';
8
8
  import { definePageTool } from './ToolDefinition.js';
9
- export const listInPageTools = definePageTool({
10
- name: 'list_in_page_tools',
11
- description: `Lists all in-page tools the page exposes for providing runtime information.
12
- In-page tools can be called via the 'execute_in_page_tool()' MCP tool.
13
- Alternatively, in-page tools can be executed by calling 'evaluate_script' and adding the
9
+ export const listThirdPartyDeveloperTools = definePageTool({
10
+ name: 'list_3p_developer_tools',
11
+ description: `Lists all third-party developer tools the page exposes for providing runtime information.
12
+ Third-party developer tools can be called via the 'execute_3p_developer_tool()' MCP tool.
13
+ Alternatively, third-party developer tools can be executed by calling 'evaluate_script' and adding the
14
14
  following command to the script:
15
15
  'window.__dtmcp.executeTool(toolName, params)'
16
- This might be helpful when the in-page-tools return non-serializable values or when composing
17
- the in-page-tools with additional functionality.`,
16
+ This might be helpful when the third-party developer tools return non-serializable values or when composing
17
+ third-party developer tools with additional functionality.`,
18
18
  annotations: {
19
- category: ToolCategory.IN_PAGE,
19
+ category: ToolCategory.THIRD_PARTY,
20
20
  readOnlyHint: true,
21
21
  },
22
22
  schema: {},
23
23
  blockedByDialog: false,
24
24
  handler: async (_request, response, _context) => {
25
- response.setListInPageTools();
25
+ response.setListThirdPartyDeveloperTools();
26
26
  },
27
27
  });
28
- export const executeInPageTool = definePageTool({
29
- name: 'execute_in_page_tool',
28
+ export const executeThirdPartyDeveloperTool = definePageTool({
29
+ name: 'execute_3p_developer_tool',
30
30
  description: `Executes a tool exposed by the page.`,
31
31
  annotations: {
32
- category: ToolCategory.IN_PAGE,
32
+ category: ToolCategory.THIRD_PARTY,
33
33
  readOnlyHint: false,
34
34
  },
35
35
  schema: {
@@ -58,7 +58,7 @@ export const executeInPageTool = definePageTool({
58
58
  throw new Error(`Failed to parse params as JSON: ${errorMessage}`);
59
59
  }
60
60
  }
61
- const toolGroup = request.page.getInPageTools();
61
+ const toolGroup = request.page.getThirdPartyDeveloperTools();
62
62
  const tool = toolGroup?.tools.find(t => t.name === toolName);
63
63
  if (!tool) {
64
64
  throw new Error(`Tool ${toolName} not found`);
@@ -69,7 +69,7 @@ export const executeInPageTool = definePageTool({
69
69
  if (!valid) {
70
70
  throw new Error(`Invalid parameters for tool ${toolName}: ${ajvInstance.errorsText(validate.errors)}`);
71
71
  }
72
- await request.page.executeInPageTool(toolName, params, response);
72
+ await request.page.executeThirdPartyDeveloperTool(toolName, params, response);
73
73
  },
74
74
  });
75
- //# sourceMappingURL=inPage.js.map
75
+ //# sourceMappingURL=thirdPartyDeveloper.js.map
@@ -6,7 +6,6 @@
6
6
  import * as consoleTools from './console.js';
7
7
  import * as emulationTools from './emulation.js';
8
8
  import * as extensionTools from './extensions.js';
9
- import * as inPageTools from './inPage.js';
10
9
  import * as inputTools from './input.js';
11
10
  import * as lighthouseTools from './lighthouse.js';
12
11
  import * as memoryTools from './memory.js';
@@ -18,6 +17,7 @@ import * as screenshotTools from './screenshot.js';
18
17
  import * as scriptTools from './script.js';
19
18
  import * as slimTools from './slim/tools.js';
20
19
  import * as snapshotTools from './snapshot.js';
20
+ import * as thirdPartyDeveloperTools from './thirdPartyDeveloper.js';
21
21
  import * as webmcpTools from './webmcp.js';
22
22
  export const createTools = (args) => {
23
23
  const rawTools = args.slim
@@ -26,7 +26,6 @@ export const createTools = (args) => {
26
26
  ...Object.values(consoleTools),
27
27
  ...Object.values(emulationTools),
28
28
  ...Object.values(extensionTools),
29
- ...Object.values(inPageTools),
30
29
  ...Object.values(inputTools),
31
30
  ...Object.values(lighthouseTools),
32
31
  ...Object.values(memoryTools),
@@ -37,6 +36,7 @@ export const createTools = (args) => {
37
36
  ...Object.values(screenshotTools),
38
37
  ...Object.values(scriptTools),
39
38
  ...Object.values(snapshotTools),
39
+ ...Object.values(thirdPartyDeveloperTools),
40
40
  ...Object.values(webmcpTools),
41
41
  ];
42
42
  const tools = [];
@@ -10,9 +10,8 @@ export const listWebMcpTools = definePageTool({
10
10
  name: 'list_webmcp_tools',
11
11
  description: `Lists all WebMCP tools the page exposes.`,
12
12
  annotations: {
13
- category: ToolCategory.DEBUGGING,
13
+ category: ToolCategory.WEBMCP,
14
14
  readOnlyHint: true,
15
- conditions: ['experimentalWebmcp'],
16
15
  },
17
16
  schema: {},
18
17
  blockedByDialog: false,
@@ -24,9 +23,8 @@ export const executeWebMcpTool = definePageTool({
24
23
  name: 'execute_webmcp_tool',
25
24
  description: `Executes a WebMCP tool exposed by the page.`,
26
25
  annotations: {
27
- category: ToolCategory.DEBUGGING,
26
+ category: ToolCategory.WEBMCP,
28
27
  readOnlyHint: false,
29
- conditions: ['experimentalWebmcp'],
30
28
  },
31
29
  schema: {
32
30
  toolName: zod.string().describe('The name of the WebMCP tool to execute'),
@@ -5,6 +5,6 @@
5
5
  */
6
6
  // If moved update release-please config
7
7
  // x-release-please-start-version
8
- export const VERSION = '0.24.0';
8
+ export const VERSION = '0.25.0';
9
9
  // x-release-please-end
10
10
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chrome-devtools-mcp",
3
- "version": "0.24.0",
3
+ "version": "0.25.0",
4
4
  "description": "MCP server for Chrome DevTools",
5
5
  "type": "module",
6
6
  "bin": {
@@ -62,7 +62,7 @@
62
62
  "@types/yargs": "^17.0.33",
63
63
  "@typescript-eslint/eslint-plugin": "^8.43.0",
64
64
  "@typescript-eslint/parser": "^8.43.0",
65
- "chrome-devtools-frontend": "1.0.1618066",
65
+ "chrome-devtools-frontend": "1.0.1625079",
66
66
  "core-js": "3.49.0",
67
67
  "debug": "4.4.3",
68
68
  "eslint": "^9.35.0",
@@ -71,13 +71,12 @@
71
71
  "globals": "^17.0.0",
72
72
  "lighthouse": "13.2.0",
73
73
  "prettier": "^3.6.2",
74
- "puppeteer": "24.42.0",
74
+ "puppeteer": "24.43.0",
75
75
  "rollup": "4.60.2",
76
76
  "rollup-plugin-cleanup": "^3.2.1",
77
77
  "rollup-plugin-license": "^3.6.0",
78
78
  "semver": "^7.7.4",
79
79
  "sinon": "^21.0.0",
80
- "tiktoken": "^1.0.22",
81
80
  "typescript": "^6.0.2",
82
81
  "typescript-eslint": "^8.43.0",
83
82
  "urlpattern-polyfill": "^10.1.0",