chrome-devtools-mcp 0.20.2 → 0.21.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.
@@ -12,6 +12,7 @@ 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
16
  })(ToolCategory || (ToolCategory = {}));
16
17
  export const labels = {
17
18
  [ToolCategory.INPUT]: 'Input automation',
@@ -21,4 +22,5 @@ export const labels = {
21
22
  [ToolCategory.NETWORK]: 'Network',
22
23
  [ToolCategory.DEBUGGING]: 'Debugging',
23
24
  [ToolCategory.EXTENSIONS]: 'Extensions',
25
+ [ToolCategory.IN_PAGE]: 'In-page tools',
24
26
  };
@@ -0,0 +1,84 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { zod, ajv } from '../third_party/index.js';
7
+ import { ToolCategory } from './categories.js';
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
14
+ following command to the script:
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.`,
18
+ annotations: {
19
+ category: ToolCategory.IN_PAGE,
20
+ readOnlyHint: true,
21
+ conditions: ['inPageTools'],
22
+ },
23
+ schema: {},
24
+ handler: async (_request, response, _context) => {
25
+ response.setListInPageTools();
26
+ },
27
+ });
28
+ export const executeInPageTool = definePageTool({
29
+ name: 'execute_in_page_tool',
30
+ description: `Executes a tool exposed by the page.`,
31
+ annotations: {
32
+ category: ToolCategory.IN_PAGE,
33
+ readOnlyHint: false,
34
+ conditions: ['inPageTools'],
35
+ },
36
+ schema: {
37
+ toolName: zod.string().describe('The name of the tool to execute'),
38
+ params: zod
39
+ .string()
40
+ .optional()
41
+ .describe('The JSON-stringified parameters to pass to the tool'),
42
+ },
43
+ handler: async (request, response, context) => {
44
+ const page = context.getSelectedMcpPage();
45
+ const toolName = request.params.toolName;
46
+ let params = {};
47
+ if (request.params.params) {
48
+ try {
49
+ const parsed = JSON.parse(request.params.params);
50
+ if (typeof parsed === 'object' && parsed !== null) {
51
+ params = parsed;
52
+ }
53
+ else {
54
+ throw new Error('Parsed params is not an object');
55
+ }
56
+ }
57
+ catch (e) {
58
+ const errorMessage = e instanceof Error ? e.message : String(e);
59
+ throw new Error(`Failed to parse params as JSON: ${errorMessage}`);
60
+ }
61
+ }
62
+ const toolGroup = context.getInPageTools();
63
+ const tool = toolGroup?.tools.find(t => t.name === toolName);
64
+ if (!tool) {
65
+ throw new Error(`Tool ${toolName} not found`);
66
+ }
67
+ const ajvInstance = new ajv();
68
+ const validate = ajvInstance.compile(tool.inputSchema);
69
+ const valid = validate(params);
70
+ if (!valid) {
71
+ throw new Error(`Invalid parameters for tool ${toolName}: ${ajvInstance.errorsText(validate.errors)}`);
72
+ }
73
+ const result = await page.pptrPage.evaluate(async (name, args) => {
74
+ if (!window.__dtmcp?.executeTool) {
75
+ throw new Error('No tools found on the page');
76
+ }
77
+ const toolResult = await window.__dtmcp.executeTool(name, args);
78
+ return {
79
+ result: toolResult,
80
+ };
81
+ }, toolName, params);
82
+ response.appendResponseLine(JSON.stringify(result, null, 2));
83
+ },
84
+ });
@@ -186,6 +186,7 @@ async function fillFormElement(uid, value, context, page) {
186
186
  void handle.dispose();
187
187
  }
188
188
  }
189
+ // here
189
190
  export const fill = definePageTool({
190
191
  name: 'fill',
191
192
  description: `Type text into a input, text area or select an option from a <select> element.`,
@@ -274,7 +275,9 @@ export const fillForm = definePageTool({
274
275
  },
275
276
  schema: {
276
277
  elements: zod
277
- .array(zod.object({
278
+ .array(
279
+ // eslint-disable-next-line @local/enforce-zod-schema
280
+ zod.object({
278
281
  uid: zod.string().describe('The uid of the element to fill out'),
279
282
  value: zod.string().describe('Value for the element'),
280
283
  }))
@@ -13,7 +13,7 @@ export const lighthouseAudit = definePageTool({
13
13
  description: `Get Lighthouse score and reports for accessibility, SEO and best practices. This excludes performance. For performance audits, run ${startTrace.name}`,
14
14
  annotations: {
15
15
  category: ToolCategory.DEBUGGING,
16
- readOnlyHint: true,
16
+ readOnlyHint: false,
17
17
  },
18
18
  schema: {
19
19
  mode: zod
@@ -8,10 +8,10 @@ import { ToolCategory } from './categories.js';
8
8
  import { definePageTool } from './ToolDefinition.js';
9
9
  export const takeMemorySnapshot = definePageTool({
10
10
  name: 'take_memory_snapshot',
11
- description: `Capture a memory heapsnapshot of the currently selected page to memory leak debugging`,
11
+ description: `Capture a heap snapshot of the currently selected page. Use to analyze the memory distribution of JavaScript objects and debug memory leaks.`,
12
12
  annotations: {
13
13
  category: ToolCategory.PERFORMANCE,
14
- readOnlyHint: true,
14
+ readOnlyHint: false,
15
15
  },
16
16
  schema: {
17
17
  filePath: zod
@@ -7,7 +7,7 @@ import { logger } from '../logger.js';
7
7
  import { zod } from '../third_party/index.js';
8
8
  import { ToolCategory } from './categories.js';
9
9
  import { CLOSE_PAGE_ERROR, definePageTool, defineTool, timeoutSchema, } from './ToolDefinition.js';
10
- export const listPages = definePageTool(args => {
10
+ export const listPages = defineTool(args => {
11
11
  return {
12
12
  name: 'list_pages',
13
13
  description: `Get a list of pages ${args?.categoryExtensions ? 'including extension service workers' : ''} open in the browser.`,
@@ -18,6 +18,7 @@ export const listPages = definePageTool(args => {
18
18
  schema: {},
19
19
  handler: async (_request, response) => {
20
20
  response.setIncludePages(true);
21
+ response.setListInPageTools();
21
22
  },
22
23
  };
23
24
  });
@@ -41,6 +42,7 @@ export const selectPage = defineTool({
41
42
  const page = context.getPageById(request.params.pageId);
42
43
  context.selectPage(page);
43
44
  response.setIncludePages(true);
45
+ response.setListInPageTools();
44
46
  if (request.params.bringToFront) {
45
47
  await page.pptrPage.bringToFront();
46
48
  }
@@ -71,6 +73,7 @@ export const closePage = defineTool({
71
73
  }
72
74
  }
73
75
  response.setIncludePages(true);
76
+ response.setListInPageTools();
74
77
  },
75
78
  });
76
79
  export const newPage = defineTool({
@@ -102,6 +105,7 @@ export const newPage = defineTool({
102
105
  });
103
106
  }, { timeout: request.params.timeout });
104
107
  response.setIncludePages(true);
108
+ response.setListInPageTools();
105
109
  },
106
110
  });
107
111
  export const navigatePage = definePageTool({
@@ -222,6 +226,7 @@ export const navigatePage = definePageTool({
222
226
  }
223
227
  }
224
228
  response.setIncludePages(true);
229
+ response.setListInPageTools();
225
230
  },
226
231
  });
227
232
  export const resizePage = definePageTool({
@@ -6,6 +6,7 @@
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';
9
10
  import * as inputTools from './input.js';
10
11
  import * as lighthouseTools from './lighthouse.js';
11
12
  import * as memoryTools from './memory.js';
@@ -24,6 +25,7 @@ export const createTools = (args) => {
24
25
  ...Object.values(consoleTools),
25
26
  ...Object.values(emulationTools),
26
27
  ...Object.values(extensionTools),
28
+ ...Object.values(inPageTools),
27
29
  ...Object.values(inputTools),
28
30
  ...Object.values(lighthouseTools),
29
31
  ...Object.values(memoryTools),
@@ -5,5 +5,5 @@
5
5
  */
6
6
  // If moved update release-please config
7
7
  // x-release-please-start-version
8
- export const VERSION = '0.20.2';
8
+ export const VERSION = '0.21.0';
9
9
  // x-release-please-end
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chrome-devtools-mcp",
3
- "version": "0.20.2",
3
+ "version": "0.21.0",
4
4
  "description": "MCP server for Chrome DevTools",
5
5
  "type": "module",
6
6
  "bin": {
@@ -47,7 +47,7 @@
47
47
  "devDependencies": {
48
48
  "@eslint/js": "^9.35.0",
49
49
  "@google/genai": "^1.37.0",
50
- "@modelcontextprotocol/sdk": "1.27.1",
50
+ "@modelcontextprotocol/sdk": "1.28.0",
51
51
  "@rollup/plugin-commonjs": "^29.0.0",
52
52
  "@rollup/plugin-json": "^6.1.0",
53
53
  "@rollup/plugin-node-resolve": "^16.0.3",
@@ -59,8 +59,8 @@
59
59
  "@types/yargs": "^17.0.33",
60
60
  "@typescript-eslint/eslint-plugin": "^8.43.0",
61
61
  "@typescript-eslint/parser": "^8.43.0",
62
- "chrome-devtools-frontend": "1.0.1596260",
63
- "core-js": "3.48.0",
62
+ "chrome-devtools-frontend": "1.0.1602348",
63
+ "core-js": "3.49.0",
64
64
  "debug": "4.4.3",
65
65
  "eslint": "^9.35.0",
66
66
  "eslint-import-resolver-typescript": "^4.4.4",
@@ -68,8 +68,8 @@
68
68
  "globals": "^17.0.0",
69
69
  "lighthouse": "13.0.3",
70
70
  "prettier": "^3.6.2",
71
- "puppeteer": "24.39.1",
72
- "rollup": "4.59.0",
71
+ "puppeteer": "24.40.0",
72
+ "rollup": "4.59.1",
73
73
  "rollup-plugin-cleanup": "^3.2.1",
74
74
  "rollup-plugin-license": "^3.6.0",
75
75
  "sinon": "^21.0.0",