chrome-devtools-mcp 1.4.0 → 1.5.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.
@@ -4,7 +4,6 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import { zod } from '../third_party/index.js';
7
- import { ensureExtension } from '../utils/files.js';
8
7
  import { ToolCategory } from './categories.js';
9
8
  import { definePageTool, defineTool } from './ToolDefinition.js';
10
9
  export const takeHeapSnapshot = definePageTool({
@@ -21,12 +20,13 @@ export const takeHeapSnapshot = definePageTool({
21
20
  },
22
21
  blockedByDialog: true,
23
22
  verifyFilesSchema: ['filePath'],
24
- handler: async (request, response) => {
23
+ handler: async (request, response, context) => {
25
24
  const page = request.page;
25
+ const snapshotPath = await context.ensureExtension(request.params.filePath, '.heapsnapshot');
26
26
  await page.pptrPage.captureHeapSnapshot({
27
- path: ensureExtension(request.params.filePath, '.heapsnapshot'),
27
+ path: snapshotPath,
28
28
  });
29
- response.appendResponseLine(`Heap snapshot saved to ${request.params.filePath}`);
29
+ response.appendResponseLine(`Heap snapshot saved to ${snapshotPath}`);
30
30
  },
31
31
  });
32
32
  export const getHeapSnapshotSummary = defineTool({
@@ -224,4 +224,60 @@ export const getHeapSnapshotDominators = defineTool({
224
224
  response.setHeapSnapshotDominators(dominators);
225
225
  },
226
226
  });
227
+ export const compareHeapSnapshots = defineTool({
228
+ name: 'compare_heapsnapshots',
229
+ description: 'Loads two memory heapsnapshots and returns the comparison. If classIndex is provided, returns detailed diff for that class, otherwise returns summary diff.',
230
+ annotations: {
231
+ category: ToolCategory.MEMORY,
232
+ readOnlyHint: true,
233
+ conditions: ['memoryDebugging'],
234
+ },
235
+ verifyFilesSchema: ['baseFilePath', 'currentFilePath'],
236
+ schema: {
237
+ baseFilePath: zod
238
+ .string()
239
+ .describe('A path to the base .heapsnapshot file (earlier snapshot).'),
240
+ currentFilePath: zod
241
+ .string()
242
+ .describe('A path to the current .heapsnapshot file (later snapshot).'),
243
+ classIndex: zod
244
+ .number()
245
+ .optional()
246
+ .describe('Optional 0-based index of the class in the summary list to filter results, showing individual objects.'),
247
+ },
248
+ blockedByDialog: false,
249
+ handler: async (request, response, context) => {
250
+ if (request.params.classIndex !== undefined) {
251
+ const classDiffResult = await context.getHeapSnapshotDetailedClassDiff(request.params.baseFilePath, request.params.currentFilePath, request.params.classIndex);
252
+ response.setHeapSnapshotDetailedClassDiff(classDiffResult);
253
+ }
254
+ else {
255
+ const diff = await context.getHeapSnapshotClassDiffs(request.params.baseFilePath, request.params.currentFilePath);
256
+ response.setHeapSnapshotClassDiffs(diff);
257
+ }
258
+ },
259
+ });
260
+ export const getHeapSnapshotDuplicateStrings = defineTool({
261
+ name: 'get_heapsnapshot_duplicate_strings',
262
+ description: 'Loads a memory heapsnapshot and returns duplicate strings grouped by their value.',
263
+ annotations: {
264
+ category: ToolCategory.MEMORY,
265
+ readOnlyHint: true,
266
+ conditions: ['memoryDebugging'],
267
+ },
268
+ blockedByDialog: false,
269
+ verifyFilesSchema: ['filePath'],
270
+ schema: {
271
+ filePath: zod.string().describe('A path to a .heapsnapshot file to read.'),
272
+ pageIdx: zod.number().optional().describe('The page index for pagination.'),
273
+ pageSize: zod.number().optional().describe('The page size for pagination.'),
274
+ },
275
+ handler: async (request, response, context) => {
276
+ const duplicateStrings = await context.getHeapSnapshotDuplicateStrings(request.params.filePath);
277
+ response.setHeapSnapshotDuplicateStrings(duplicateStrings, {
278
+ pageIdx: request.params.pageIdx,
279
+ pageSize: request.params.pageSize,
280
+ });
281
+ },
282
+ });
227
283
  //# sourceMappingURL=memory.js.map
@@ -7,7 +7,6 @@ import fs from 'node:fs/promises';
7
7
  import os from 'node:os';
8
8
  import path from 'node:path';
9
9
  import { zod } from '../third_party/index.js';
10
- import { ensureExtension } from '../utils/files.js';
11
10
  import { ToolCategory } from './categories.js';
12
11
  import { definePageTool } from './ToolDefinition.js';
13
12
  async function generateTempFilePath() {
@@ -53,7 +52,7 @@ export const startScreencast = definePageTool(args => ({
53
52
  const enforcedExtension = matchedExtension ?? '.mp4';
54
53
  const format = (matchedExtension?.substring(1) ??
55
54
  'mp4');
56
- const resolvedPath = ensureExtension(path.resolve(filePath), enforcedExtension);
55
+ const resolvedPath = await context.ensureExtension(filePath, enforcedExtension);
57
56
  const page = request.page;
58
57
  let recorder;
59
58
  try {
@@ -9,8 +9,7 @@ import { defineTool, pageIdSchema } from './ToolDefinition.js';
9
9
  export const evaluateScript = defineTool(cliArgs => {
10
10
  return {
11
11
  name: 'evaluate_script',
12
- description: `Evaluate a JavaScript function inside the currently selected page${cliArgs?.categoryExtensions ? ' or service worker' : ''}. Returns the response as JSON,
13
- so returned values have to be JSON-serializable.`,
12
+ description: `Evaluate a JavaScript function inside the currently selected page${cliArgs?.categoryExtensions ? ' or service worker' : ''}. Returns the response as JSON, so returned values have to be JSON-serializable.`,
14
13
  annotations: {
15
14
  category: ToolCategory.DEBUGGING,
16
15
  readOnlyHint: false,
@@ -18,14 +17,8 @@ so returned values have to be JSON-serializable.`,
18
17
  schema: {
19
18
  ...(cliArgs?.experimentalPageIdRouting ? pageIdSchema : {}),
20
19
  function: zod.string().describe(`A JavaScript function declaration to be executed by the tool in the currently selected page.
21
- Example without arguments: \`() => {
22
- return document.title
23
- }\` or \`async () => {
24
- return await fetch("example.com")
25
- }\`.
26
- Example with arguments: \`(el) => {
27
- return el.innerText;
28
- }\`
20
+ Example without arguments: \`() => document.title\` or \`async () => await fetch("example.com")\`.
21
+ Example with arguments: \`(el) => el.innerText\`
29
22
  `),
30
23
  args: zod
31
24
  .array(zod
@@ -9,12 +9,12 @@ import { definePageTool } from './ToolDefinition.js';
9
9
  export const listThirdPartyDeveloperTools = definePageTool({
10
10
  name: 'list_3p_developer_tools',
11
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
- following command to the script:
15
- 'window.__dtmcp.executeTool(toolName, params)'
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.`,
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
+ following command to the script:
15
+ \`window.__dtmcp.executeTool(toolName, params)\`
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
19
  category: ToolCategory.THIRD_PARTY,
20
20
  readOnlyHint: true,
@@ -11,10 +11,6 @@ export async function getTempFilePath(filename) {
11
11
  const filepath = path.join(dir, filename);
12
12
  return filepath;
13
13
  }
14
- export function ensureExtension(filepath, extension) {
15
- const ext = path.extname(filepath);
16
- return filepath.slice(0, filepath.length - ext.length) + extension;
17
- }
18
14
  export async function resolveCanonicalPath(filePath) {
19
15
  const absolutePath = path.resolve(filePath);
20
16
  try {
@@ -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 = '1.4.0';
8
+ export const VERSION = '1.5.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": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "MCP server for Chrome DevTools",
5
5
  "type": "module",
6
6
  "bin": {
@@ -64,7 +64,7 @@
64
64
  "@types/yargs": "^17.0.33",
65
65
  "@typescript-eslint/eslint-plugin": "^8.43.0",
66
66
  "@typescript-eslint/parser": "^8.43.0",
67
- "chrome-devtools-frontend": "1.0.1650035",
67
+ "chrome-devtools-frontend": "1.0.1652307",
68
68
  "core-js": "3.49.0",
69
69
  "debug": "4.4.3",
70
70
  "eslint": "^9.35.0",
@@ -73,7 +73,7 @@
73
73
  "globals": "^17.0.0",
74
74
  "lighthouse": "13.4.0",
75
75
  "prettier": "^3.6.2",
76
- "puppeteer": "25.2.0",
76
+ "puppeteer": "25.2.1",
77
77
  "rollup": "4.62.2",
78
78
  "rollup-plugin-cleanup": "^3.2.1",
79
79
  "rollup-plugin-license": "^3.6.0",
@@ -84,6 +84,14 @@
84
84
  "urlpattern-polyfill": "^10.1.0",
85
85
  "yargs": "18.0.0"
86
86
  },
87
+ "peerDependencies": {
88
+ "@toon-format/toon": "^2.2.0"
89
+ },
90
+ "peerDependenciesMeta": {
91
+ "@toon-format/toon": {
92
+ "optional": true
93
+ }
94
+ },
87
95
  "engines": {
88
96
  "node": "^20.19.0 || ^22.12.0 || >=23"
89
97
  },