feat: memory debugging tools (#2169)
Updates the flag for the memory tooling to remove the experimental bit (keep alias for backwards compatibility). And updates the SKILLs to reflected the update names and point to the available tools. Q: Should it be called `take_heapsnapshot` or `take_heap_snapshot`?
This commit is contained in:
@@ -609,8 +609,8 @@ The Chrome DevTools MCP server supports the following configuration option:
|
||||
Whether to enable coordinate-based tools such as click_at(x,y). Usually requires a computer-use model able to produce accurate coordinates by looking at screenshots.
|
||||
- **Type:** boolean
|
||||
|
||||
- **`--experimentalMemory`/ `--experimental-memory`**
|
||||
Whether to enable experimental memory tools.
|
||||
- **`--memoryDebugging`/ `--memory-debugging`, `-experimentalMemory`**
|
||||
Whether to enable memory debugging tools.
|
||||
- **Type:** boolean
|
||||
|
||||
- **`--experimentalStructuredContent`/ `--experimental-structured-content`**
|
||||
|
||||
@@ -457,7 +457,7 @@ in the DevTools Elements panel (if any).
|
||||
|
||||
### `close_heapsnapshot`
|
||||
|
||||
**Description:** Closes a previously loaded memory heapsnapshot, freeing its memory. (requires flag: --experimentalMemory=true)
|
||||
**Description:** Closes a previously loaded memory heapsnapshot, freeing its memory. (requires flag: --memoryDebugging=true)
|
||||
|
||||
**Parameters:**
|
||||
|
||||
@@ -467,7 +467,7 @@ in the DevTools Elements panel (if any).
|
||||
|
||||
### `get_heapsnapshot_class_nodes`
|
||||
|
||||
**Description:** Loads a memory heapsnapshot and returns instances of a specific class with their IDs. (requires flag: --experimentalMemory=true)
|
||||
**Description:** Loads a memory heapsnapshot and returns instances of a specific class with their IDs. (requires flag: --memoryDebugging=true)
|
||||
|
||||
**Parameters:**
|
||||
|
||||
@@ -480,7 +480,7 @@ in the DevTools Elements panel (if any).
|
||||
|
||||
### `get_heapsnapshot_details`
|
||||
|
||||
**Description:** Loads a memory heapsnapshot and returns all available information including statistics, static data, and aggregated node information. Supports pagination for aggregates. (requires flag: --experimentalMemory=true)
|
||||
**Description:** Loads a memory heapsnapshot and returns all available information including statistics, static data, and aggregated node information. Supports pagination for aggregates. (requires flag: --memoryDebugging=true)
|
||||
|
||||
**Parameters:**
|
||||
|
||||
@@ -492,7 +492,7 @@ in the DevTools Elements panel (if any).
|
||||
|
||||
### `get_heapsnapshot_retainers`
|
||||
|
||||
**Description:** Loads a memory heapsnapshot and returns retainers for a specific node ID. (requires flag: --experimentalMemory=true)
|
||||
**Description:** Loads a memory heapsnapshot and returns retainers for a specific node ID. (requires flag: --memoryDebugging=true)
|
||||
|
||||
**Parameters:**
|
||||
|
||||
@@ -505,7 +505,7 @@ in the DevTools Elements panel (if any).
|
||||
|
||||
### `get_heapsnapshot_summary`
|
||||
|
||||
**Description:** Loads a memory heapsnapshot and returns snapshot summary stats. (requires flag: --experimentalMemory=true)
|
||||
**Description:** Loads a memory heapsnapshot and returns snapshot summary stats. (requires flag: --memoryDebugging=true)
|
||||
|
||||
**Parameters:**
|
||||
|
||||
|
||||
@@ -5,9 +5,13 @@ description: Uses Chrome DevTools via MCP for efficient debugging, troubleshooti
|
||||
|
||||
## Core Concepts
|
||||
|
||||
**Browser lifecycle**: Browser starts automatically on first tool call using a persistent Chrome profile. Configure via CLI args in the MCP server configuration: `npx chrome-devtools-mcp@latest --help`. To enable extensions, use `--categoryExtensions`.
|
||||
**Page selection**: Tools operate on the currently selected page. Use `list_pages` to see available pages, then `select_page` to switch context.
|
||||
**Browser lifecycle**: Browser starts automatically on first tool call using a persistent Chrome profile. Configure via CLI args in the MCP server configuration: `npx chrome-devtools-mcp@latest --help`.
|
||||
Addional tooling can be enabled by providing the following flags:
|
||||
|
||||
- For extension tooling, use the `--categoryExtensions` flag.
|
||||
- For memory tooling, use the `--memoryDebugging` flag.
|
||||
|
||||
**Page selection**: Tools operate on the currently selected page. Use `list_pages` to see available pages, then `select_page` to switch context.
|
||||
**Element interaction**: Use `take_snapshot` to get page structure with element `uid`s. Each element has a unique `uid` for interaction. If an element isn't found, take a fresh snapshot - the element may have been removed or the page changed.
|
||||
|
||||
## Workflow Patterns
|
||||
|
||||
@@ -22,11 +22,11 @@ When investigating a frontend web application memory leak, utilize the `chrome-d
|
||||
- Use tools like `click`, `navigate_page`, `fill`, etc., to manipulate the page into the desired state.
|
||||
- Revert the page back to the original state after interactions to see if memory is released.
|
||||
- Repeat the same user interactions 10 times to amplify the leak.
|
||||
- Use `take_memory_snapshot` to save `.heapsnapshot` files to disk at baseline, target (after actions), and final (after reverting actions) states.
|
||||
- Use `take_heapsnapshot` to save `.heapsnapshot` files to disk at baseline, target (after actions), and final (after reverting actions) states.
|
||||
|
||||
### 2. Using Memlab to Find Leaks (Recommended)
|
||||
|
||||
Once you have generated `.heapsnapshot` files using `take_memory_snapshot`, use `memlab` to automatically find memory leaks.
|
||||
Once you have generated `.heapsnapshot` files using `take_heapsnapshot`, use `memlab` to automatically find memory leaks.
|
||||
|
||||
- Read [references/memlab.md](references/memlab.md) for how to use `memlab` to analyze the generated heapsnapshots.
|
||||
- Do **not** read raw `.heapsnapshot` files using `read_file` or `cat`.
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
## Analyzing Snapshots
|
||||
|
||||
You can use the `take_memory_snapshot` tool provided by the `chrome-devtools-mcp` extension to generate heap snapshots during an investigation. To find leaks, you generally need 3 snapshots:
|
||||
You can use the `take_heapsnapshot` tool provided by the `chrome-devtools-mcp` extension to generate heap snapshots during an investigation. To find leaks, you generally need 3 snapshots:
|
||||
|
||||
1. **Baseline:** Before the suspect action.
|
||||
2. **Target:** After the suspect action.
|
||||
|
||||
@@ -43,7 +43,7 @@ If the server starts successfully but `list_pages` returns an empty list or crea
|
||||
|
||||
#### Symptom: Missing Tools / Only 9 tools available
|
||||
|
||||
If the server starts successfully but only a limited subset of tools (like `list_pages`, `get_console_message`, `lighthouse_audit`, `take_memory_snapshot`) are available, this is likely because the MCP client is enforcing a **read-only mode**.
|
||||
If the server starts successfully but only a limited subset of tools (like `list_pages`, `get_console_message`, `lighthouse_audit`, `take_heapsnapshot`) are available, this is likely because the MCP client is enforcing a **read-only mode**.
|
||||
|
||||
All tools in `chrome-devtools-mcp` are annotated with `readOnlyHint: true` (for safe, non-modifying tools) or `readOnlyHint: false` (for tools that modify browser state, like `emulate`, `click`, `navigate_page`). To access the full suite of tools, the user must disable read-only mode in their MCP client (e.g., by exiting "Plan Mode" in Gemini CLI or adjusting their client's tool safety settings).
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ export const commands: Commands = {
|
||||
},
|
||||
close_heapsnapshot: {
|
||||
description:
|
||||
'Closes a previously loaded memory heapsnapshot, freeing its memory. (requires flag: --experimentalMemory=true)',
|
||||
'Closes a previously loaded memory heapsnapshot, freeing its memory. (requires flag: --memoryDebugging=true)',
|
||||
category: 'Memory',
|
||||
args: {
|
||||
filePath: {
|
||||
@@ -306,7 +306,7 @@ export const commands: Commands = {
|
||||
},
|
||||
get_heapsnapshot_class_nodes: {
|
||||
description:
|
||||
'Loads a memory heapsnapshot and returns instances of a specific class with their IDs. (requires flag: --experimentalMemory=true)',
|
||||
'Loads a memory heapsnapshot and returns instances of a specific class with their IDs. (requires flag: --memoryDebugging=true)',
|
||||
category: 'Memory',
|
||||
args: {
|
||||
filePath: {
|
||||
@@ -337,7 +337,7 @@ export const commands: Commands = {
|
||||
},
|
||||
get_heapsnapshot_details: {
|
||||
description:
|
||||
'Loads a memory heapsnapshot and returns all available information including statistics, static data, and aggregated node information. Supports pagination for aggregates. (requires flag: --experimentalMemory=true)',
|
||||
'Loads a memory heapsnapshot and returns all available information including statistics, static data, and aggregated node information. Supports pagination for aggregates. (requires flag: --memoryDebugging=true)',
|
||||
category: 'Memory',
|
||||
args: {
|
||||
filePath: {
|
||||
@@ -362,7 +362,7 @@ export const commands: Commands = {
|
||||
},
|
||||
get_heapsnapshot_retainers: {
|
||||
description:
|
||||
'Loads a memory heapsnapshot and returns retainers for a specific node ID. (requires flag: --experimentalMemory=true)',
|
||||
'Loads a memory heapsnapshot and returns retainers for a specific node ID. (requires flag: --memoryDebugging=true)',
|
||||
category: 'Memory',
|
||||
args: {
|
||||
filePath: {
|
||||
@@ -393,7 +393,7 @@ export const commands: Commands = {
|
||||
},
|
||||
get_heapsnapshot_summary: {
|
||||
description:
|
||||
'Loads a memory heapsnapshot and returns snapshot summary stats. (requires flag: --experimentalMemory=true)',
|
||||
'Loads a memory heapsnapshot and returns snapshot summary stats. (requires flag: --memoryDebugging=true)',
|
||||
category: 'Memory',
|
||||
args: {
|
||||
filePath: {
|
||||
|
||||
@@ -161,9 +161,10 @@ export const cliOptions = {
|
||||
describe:
|
||||
'Whether to enable coordinate-based tools such as click_at(x,y). Usually requires a computer-use model able to produce accurate coordinates by looking at screenshots.',
|
||||
},
|
||||
experimentalMemory: {
|
||||
memoryDebugging: {
|
||||
type: 'boolean',
|
||||
describe: 'Whether to enable experimental memory tools.',
|
||||
describe: 'Whether to enable memory debugging tools.',
|
||||
alias: 'experimentalMemory',
|
||||
},
|
||||
experimentalStructuredContent: {
|
||||
type: 'boolean',
|
||||
|
||||
@@ -222,11 +222,13 @@
|
||||
},
|
||||
{
|
||||
"name": "experimental_memory",
|
||||
"flagType": "boolean"
|
||||
"flagType": "boolean",
|
||||
"isDeprecated": true
|
||||
},
|
||||
{
|
||||
"name": "experimental_memory_present",
|
||||
"flagType": "boolean"
|
||||
"flagType": "boolean",
|
||||
"isDeprecated": true
|
||||
},
|
||||
{
|
||||
"name": "experimental_navigation_allowlist",
|
||||
@@ -295,5 +297,13 @@
|
||||
{
|
||||
"name": "category_experimental_third_party",
|
||||
"flagType": "boolean"
|
||||
},
|
||||
{
|
||||
"name": "memory_debugging_present",
|
||||
"flagType": "boolean"
|
||||
},
|
||||
{
|
||||
"name": "memory_debugging",
|
||||
"flagType": "boolean"
|
||||
}
|
||||
]
|
||||
|
||||
+5
-5
@@ -44,7 +44,7 @@ export const getHeapSnapshotSummary = defineTool({
|
||||
annotations: {
|
||||
category: ToolCategory.MEMORY,
|
||||
readOnlyHint: true,
|
||||
conditions: ['experimentalMemory'],
|
||||
conditions: ['memoryDebugging'],
|
||||
},
|
||||
schema: {
|
||||
filePath: zod.string().describe('A path to a .heapsnapshot file to read.'),
|
||||
@@ -68,7 +68,7 @@ export const getHeapSnapshotDetails = defineTool({
|
||||
annotations: {
|
||||
category: ToolCategory.MEMORY,
|
||||
readOnlyHint: true,
|
||||
conditions: ['experimentalMemory'],
|
||||
conditions: ['memoryDebugging'],
|
||||
},
|
||||
schema: {
|
||||
filePath: zod.string().describe('A path to a .heapsnapshot file to read.'),
|
||||
@@ -102,7 +102,7 @@ export const getHeapSnapshotClassNodes = defineTool({
|
||||
annotations: {
|
||||
category: ToolCategory.MEMORY,
|
||||
readOnlyHint: true,
|
||||
conditions: ['experimentalMemory'],
|
||||
conditions: ['memoryDebugging'],
|
||||
},
|
||||
schema: {
|
||||
filePath: zod.string().describe('A path to a .heapsnapshot file to read.'),
|
||||
@@ -132,7 +132,7 @@ export const getHeapSnapshotRetainers = defineTool({
|
||||
annotations: {
|
||||
category: ToolCategory.MEMORY,
|
||||
readOnlyHint: true,
|
||||
conditions: ['experimentalMemory'],
|
||||
conditions: ['memoryDebugging'],
|
||||
},
|
||||
blockedByDialog: false,
|
||||
verifyFilesSchema: ['filePath'],
|
||||
@@ -162,7 +162,7 @@ export const closeHeapSnapshot = defineTool({
|
||||
annotations: {
|
||||
category: ToolCategory.MEMORY,
|
||||
readOnlyHint: false,
|
||||
conditions: ['experimentalMemory'],
|
||||
conditions: ['memoryDebugging'],
|
||||
},
|
||||
verifyFilesSchema: ['filePath'],
|
||||
schema: {
|
||||
|
||||
@@ -171,6 +171,19 @@ describe('e2e', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('has memory debugging tools', async () => {
|
||||
await withClient(
|
||||
async client => {
|
||||
const {tools} = await client.listTools();
|
||||
const getHeapSnapshotSummary = tools.find(
|
||||
t => t.name === 'get_heapsnapshot_summary',
|
||||
);
|
||||
assert.ok(getHeapSnapshotSummary);
|
||||
},
|
||||
['--memoryDebugging'],
|
||||
);
|
||||
});
|
||||
|
||||
it('updates roots when client notifies', async () => {
|
||||
const roots = [{uri: 'file:///test-root', name: 'test-root'}];
|
||||
let resolvePromise: () => void;
|
||||
|
||||
Reference in New Issue
Block a user