chrome-devtools-mcp 0.23.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.
- package/README.md +22 -5
- package/build/src/DevToolsConnectionAdapter.js +1 -0
- package/build/src/DevtoolsUtils.js +1 -0
- package/build/src/HeapSnapshotManager.js +16 -0
- package/build/src/McpContext.js +57 -4
- package/build/src/McpPage.js +10 -4
- package/build/src/McpResponse.js +55 -19
- package/build/src/Mutex.js +1 -0
- package/build/src/PageCollector.js +1 -0
- package/build/src/SlimMcpResponse.js +1 -0
- package/build/src/TextSnapshot.js +13 -7
- package/build/src/WaitForHelper.js +6 -0
- package/build/src/bin/check-latest-version.js +1 -0
- package/build/src/bin/chrome-devtools-cli-options.js +229 -46
- package/build/src/bin/chrome-devtools-mcp-cli-options.js +10 -5
- package/build/src/bin/chrome-devtools-mcp-main.js +1 -5
- package/build/src/bin/chrome-devtools-mcp.js +1 -0
- package/build/src/bin/chrome-devtools.js +5 -13
- package/build/src/browser.js +1 -0
- package/build/src/daemon/client.js +4 -2
- package/build/src/daemon/daemon.js +1 -0
- package/build/src/daemon/types.js +1 -0
- package/build/src/daemon/utils.js +1 -0
- package/build/src/formatters/ConsoleFormatter.js +48 -1
- package/build/src/formatters/HeapSnapshotFormatter.js +18 -2
- package/build/src/formatters/IssueFormatter.js +1 -0
- package/build/src/formatters/NetworkFormatter.js +1 -0
- package/build/src/formatters/SnapshotFormatter.js +2 -1
- package/build/src/index.js +114 -51
- package/build/src/issue-descriptions.js +1 -0
- package/build/src/logger.js +1 -0
- package/build/src/polyfill.js +1 -0
- package/build/src/telemetry/ClearcutLogger.js +13 -1
- package/build/src/telemetry/WatchdogClient.js +1 -0
- package/build/src/telemetry/flagUtils.js +1 -0
- package/build/src/telemetry/metricUtils.js +1 -0
- package/build/src/telemetry/persistence.js +1 -0
- package/build/src/telemetry/toolMetricsUtils.js +2 -1
- package/build/src/telemetry/types.js +1 -0
- package/build/src/telemetry/watchdog/ClearcutSender.js +1 -0
- package/build/src/telemetry/watchdog/main.js +1 -0
- package/build/src/third_party/THIRD_PARTY_NOTICES +8 -8
- package/build/src/third_party/bundled-packages.json +3 -3
- package/build/src/third_party/devtools-formatter-worker.js +2469 -2933
- package/build/src/third_party/devtools-heap-snapshot-worker.js +50 -26
- package/build/src/third_party/index.js +1107 -407
- package/build/src/third_party/issue-descriptions/genericFormModelContextMissingToolDescription.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormModelContextMissingToolName.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormModelContextParameterMissingName.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormModelContextParameterMissingTitleAndDescription.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormModelContextRequiredParameterMissingName.md +5 -0
- package/build/src/third_party/lighthouse-devtools-mcp-bundle.js +21717 -20261
- package/build/src/tools/ToolDefinition.js +1 -0
- package/build/src/tools/categories.js +10 -3
- package/build/src/tools/console.js +3 -0
- package/build/src/tools/emulation.js +2 -0
- package/build/src/tools/extensions.js +6 -0
- package/build/src/tools/input.js +57 -2
- package/build/src/tools/lighthouse.js +17 -9
- package/build/src/tools/memory.js +34 -1
- package/build/src/tools/network.js +5 -0
- package/build/src/tools/pages.js +14 -5
- package/build/src/tools/performance.js +6 -0
- package/build/src/tools/screencast.js +6 -2
- package/build/src/tools/screenshot.js +3 -0
- package/build/src/tools/script.js +2 -0
- package/build/src/tools/slim/tools.js +4 -0
- package/build/src/tools/snapshot.js +5 -1
- package/build/src/tools/{inPage.js → thirdPartyDeveloper.js} +17 -16
- package/build/src/tools/tools.js +3 -2
- package/build/src/tools/webmcp.js +5 -4
- package/build/src/trace-processing/parse.js +1 -0
- package/build/src/types.js +1 -0
- package/build/src/utils/check-for-updates.js +1 -0
- package/build/src/utils/files.js +5 -10
- package/build/src/utils/id.js +1 -0
- package/build/src/utils/keyboard.js +1 -0
- package/build/src/utils/pagination.js +1 -0
- package/build/src/utils/string.js +1 -0
- package/build/src/utils/types.js +1 -0
- package/build/src/version.js +2 -1
- package/package.json +10 -11
- package/build/src/bin/cliDefinitions.js +0 -621
package/README.md
CHANGED
|
@@ -477,7 +477,7 @@ If you run into any issues, checkout our [troubleshooting guide](./docs/troubles
|
|
|
477
477
|
|
|
478
478
|
<!-- BEGIN AUTO GENERATED TOOLS -->
|
|
479
479
|
|
|
480
|
-
- **Input automation** (
|
|
480
|
+
- **Input automation** (10 tools)
|
|
481
481
|
- [`click`](docs/tool-reference.md#click)
|
|
482
482
|
- [`drag`](docs/tool-reference.md#drag)
|
|
483
483
|
- [`fill`](docs/tool-reference.md#fill)
|
|
@@ -487,6 +487,7 @@ If you run into any issues, checkout our [troubleshooting guide](./docs/troubles
|
|
|
487
487
|
- [`press_key`](docs/tool-reference.md#press_key)
|
|
488
488
|
- [`type_text`](docs/tool-reference.md#type_text)
|
|
489
489
|
- [`upload_file`](docs/tool-reference.md#upload_file)
|
|
490
|
+
- [`click_at`](docs/tool-reference.md#click_at)
|
|
490
491
|
- **Navigation automation** (6 tools)
|
|
491
492
|
- [`close_page`](docs/tool-reference.md#close_page)
|
|
492
493
|
- [`list_pages`](docs/tool-reference.md#list_pages)
|
|
@@ -504,21 +505,32 @@ If you run into any issues, checkout our [troubleshooting guide](./docs/troubles
|
|
|
504
505
|
- **Network** (2 tools)
|
|
505
506
|
- [`get_network_request`](docs/tool-reference.md#get_network_request)
|
|
506
507
|
- [`list_network_requests`](docs/tool-reference.md#list_network_requests)
|
|
507
|
-
- **Debugging** (
|
|
508
|
+
- **Debugging** (8 tools)
|
|
508
509
|
- [`evaluate_script`](docs/tool-reference.md#evaluate_script)
|
|
509
510
|
- [`get_console_message`](docs/tool-reference.md#get_console_message)
|
|
510
511
|
- [`lighthouse_audit`](docs/tool-reference.md#lighthouse_audit)
|
|
511
512
|
- [`list_console_messages`](docs/tool-reference.md#list_console_messages)
|
|
512
513
|
- [`take_screenshot`](docs/tool-reference.md#take_screenshot)
|
|
513
514
|
- [`take_snapshot`](docs/tool-reference.md#take_snapshot)
|
|
515
|
+
- [`screencast_start`](docs/tool-reference.md#screencast_start)
|
|
516
|
+
- [`screencast_stop`](docs/tool-reference.md#screencast_stop)
|
|
517
|
+
- **Memory** (4 tools)
|
|
518
|
+
- [`take_memory_snapshot`](docs/tool-reference.md#take_memory_snapshot)
|
|
519
|
+
- [`get_memory_snapshot_details`](docs/tool-reference.md#get_memory_snapshot_details)
|
|
520
|
+
- [`get_nodes_by_class`](docs/tool-reference.md#get_nodes_by_class)
|
|
521
|
+
- [`load_memory_snapshot`](docs/tool-reference.md#load_memory_snapshot)
|
|
514
522
|
- **Extensions** (5 tools)
|
|
515
523
|
- [`install_extension`](docs/tool-reference.md#install_extension)
|
|
516
524
|
- [`list_extensions`](docs/tool-reference.md#list_extensions)
|
|
517
525
|
- [`reload_extension`](docs/tool-reference.md#reload_extension)
|
|
518
526
|
- [`trigger_extension_action`](docs/tool-reference.md#trigger_extension_action)
|
|
519
527
|
- [`uninstall_extension`](docs/tool-reference.md#uninstall_extension)
|
|
520
|
-
- **
|
|
521
|
-
- [`
|
|
528
|
+
- **Third-party** (2 tools)
|
|
529
|
+
- [`execute_3p_developer_tool`](docs/tool-reference.md#execute_3p_developer_tool)
|
|
530
|
+
- [`list_3p_developer_tools`](docs/tool-reference.md#list_3p_developer_tools)
|
|
531
|
+
- **WebMCP** (2 tools)
|
|
532
|
+
- [`execute_webmcp_tool`](docs/tool-reference.md#execute_webmcp_tool)
|
|
533
|
+
- [`list_webmcp_tools`](docs/tool-reference.md#list_webmcp_tools)
|
|
522
534
|
|
|
523
535
|
<!-- END AUTO GENERATED TOOLS -->
|
|
524
536
|
|
|
@@ -595,7 +607,7 @@ The Chrome DevTools MCP server supports the following configuration option:
|
|
|
595
607
|
Path to ffmpeg executable for screencast recording.
|
|
596
608
|
- **Type:** string
|
|
597
609
|
|
|
598
|
-
- **`--
|
|
610
|
+
- **`--categoryExperimentalWebmcp`/ `--category-experimental-webmcp`**
|
|
599
611
|
Set to true to enable debugging WebMCP tools. Requires Chrome 149+ with the following flags: `--enable-features=WebMCPTesting,DevToolsWebMCPSupport`
|
|
600
612
|
- **Type:** boolean
|
|
601
613
|
|
|
@@ -627,6 +639,11 @@ The Chrome DevTools MCP server supports the following configuration option:
|
|
|
627
639
|
- **Type:** boolean
|
|
628
640
|
- **Default:** `false`
|
|
629
641
|
|
|
642
|
+
- **`--categoryExperimentalThirdParty`/ `--category-experimental-third-party`**
|
|
643
|
+
Set to true to enable third-party developer tools exposed by the inspected page itself
|
|
644
|
+
- **Type:** boolean
|
|
645
|
+
- **Default:** `false`
|
|
646
|
+
|
|
630
647
|
- **`--performanceCrux`/ `--performance-crux`**
|
|
631
648
|
Set to false to disable sending URLs from performance traces to CrUX API to get field performance data.
|
|
632
649
|
- **Type:** boolean
|
|
@@ -56,6 +56,17 @@ export class HeapSnapshotManager {
|
|
|
56
56
|
}
|
|
57
57
|
return uid;
|
|
58
58
|
}
|
|
59
|
+
async getNodesByUid(filePath, uid) {
|
|
60
|
+
const snapshot = await this.getSnapshot(filePath);
|
|
61
|
+
const filter = new DevTools.HeapSnapshotModel.HeapSnapshotModel.NodeFilter();
|
|
62
|
+
const className = await this.resolveClassKeyFromUid(filePath, uid);
|
|
63
|
+
if (!className) {
|
|
64
|
+
throw new Error(`Class with UID ${uid} not found in heap snapshot`);
|
|
65
|
+
}
|
|
66
|
+
const provider = snapshot.createNodesProviderForClass(className, filter);
|
|
67
|
+
const range = await provider.serializeItemsRange(0, 1);
|
|
68
|
+
return await provider.serializeItemsRange(0, range.totalLength);
|
|
69
|
+
}
|
|
59
70
|
#getCachedSnapshot(filePath) {
|
|
60
71
|
const absolutePath = path.resolve(filePath);
|
|
61
72
|
const cached = this.#snapshots.get(absolutePath);
|
|
@@ -64,6 +75,10 @@ export class HeapSnapshotManager {
|
|
|
64
75
|
}
|
|
65
76
|
return cached;
|
|
66
77
|
}
|
|
78
|
+
async resolveClassKeyFromUid(filePath, uid) {
|
|
79
|
+
const cached = this.#getCachedSnapshot(filePath);
|
|
80
|
+
return cached.uidToClassKey.get(uid);
|
|
81
|
+
}
|
|
67
82
|
async #loadSnapshot(absolutePath) {
|
|
68
83
|
const workerProxy = new DevTools.HeapSnapshotModel.HeapSnapshotProxy.HeapSnapshotWorkerProxy(() => {
|
|
69
84
|
/* noop */
|
|
@@ -92,3 +107,4 @@ export class HeapSnapshotManager {
|
|
|
92
107
|
}
|
|
93
108
|
}
|
|
94
109
|
}
|
|
110
|
+
//# sourceMappingURL=HeapSnapshotManager.js.map
|
package/build/src/McpContext.js
CHANGED
|
@@ -4,16 +4,17 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
import fs from 'node:fs/promises';
|
|
7
|
+
import os from 'node:os';
|
|
7
8
|
import path from 'node:path';
|
|
9
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
8
10
|
import { UniverseManager } from './DevtoolsUtils.js';
|
|
9
11
|
import { HeapSnapshotManager } from './HeapSnapshotManager.js';
|
|
10
12
|
import { McpPage } from './McpPage.js';
|
|
11
13
|
import { NetworkCollector, ConsoleCollector, } from './PageCollector.js';
|
|
12
|
-
import { Locator } from './third_party/index.js';
|
|
13
|
-
import { PredefinedNetworkConditions } from './third_party/index.js';
|
|
14
|
+
import { Locator, PredefinedNetworkConditions, } from './third_party/index.js';
|
|
14
15
|
import { listPages } from './tools/pages.js';
|
|
15
16
|
import { CLOSE_PAGE_ERROR } from './tools/ToolDefinition.js';
|
|
16
|
-
import { ensureExtension,
|
|
17
|
+
import { ensureExtension, getTempFilePath } from './utils/files.js';
|
|
17
18
|
import { getNetworkMultiplierFromString } from './WaitForHelper.js';
|
|
18
19
|
const DEFAULT_TIMEOUT = 5_000;
|
|
19
20
|
const NAVIGATION_TIMEOUT = 10_000;
|
|
@@ -41,6 +42,7 @@ export class McpContext {
|
|
|
41
42
|
#locatorClass;
|
|
42
43
|
#options;
|
|
43
44
|
#heapSnapshotManager = new HeapSnapshotManager();
|
|
45
|
+
#roots = undefined;
|
|
44
46
|
constructor(browser, logger, options, locatorClass) {
|
|
45
47
|
this.browser = browser;
|
|
46
48
|
this.logger = logger;
|
|
@@ -89,6 +91,39 @@ export class McpContext {
|
|
|
89
91
|
await context.#init();
|
|
90
92
|
return context;
|
|
91
93
|
}
|
|
94
|
+
roots() {
|
|
95
|
+
if (this.#roots === undefined) {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
return [
|
|
99
|
+
...this.#roots,
|
|
100
|
+
{
|
|
101
|
+
uri: pathToFileURL(os.tmpdir()).href,
|
|
102
|
+
name: 'temp',
|
|
103
|
+
},
|
|
104
|
+
];
|
|
105
|
+
}
|
|
106
|
+
setRoots(roots) {
|
|
107
|
+
this.#roots = roots;
|
|
108
|
+
}
|
|
109
|
+
validatePath(filePath) {
|
|
110
|
+
if (filePath === undefined) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const roots = this.roots();
|
|
114
|
+
if (roots === undefined) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const absolutePath = path.resolve(filePath);
|
|
118
|
+
for (const root of roots) {
|
|
119
|
+
const rootPath = path.resolve(fileURLToPath(root.uri));
|
|
120
|
+
if (absolutePath === rootPath ||
|
|
121
|
+
absolutePath.startsWith(rootPath + path.sep)) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
throw new Error(`Access denied: path ${filePath} is not within any of the workspace roots ${JSON.stringify(roots)}.`);
|
|
126
|
+
}
|
|
92
127
|
resolveCdpRequestId(page, cdpRequestId) {
|
|
93
128
|
if (!cdpRequestId) {
|
|
94
129
|
this.logger('no network request');
|
|
@@ -463,9 +498,18 @@ export class McpContext {
|
|
|
463
498
|
return this.#mcpPages.get(page)?.isolatedContextName;
|
|
464
499
|
}
|
|
465
500
|
async saveTemporaryFile(data, filename) {
|
|
466
|
-
|
|
501
|
+
const filepath = await getTempFilePath(filename);
|
|
502
|
+
this.validatePath(filepath);
|
|
503
|
+
try {
|
|
504
|
+
await fs.writeFile(filepath, data);
|
|
505
|
+
}
|
|
506
|
+
catch (err) {
|
|
507
|
+
throw new Error('Could not save a file', { cause: err });
|
|
508
|
+
}
|
|
509
|
+
return { filepath };
|
|
467
510
|
}
|
|
468
511
|
async saveFile(data, clientProvidedFilePath, extension) {
|
|
512
|
+
this.validatePath(clientProvidedFilePath);
|
|
469
513
|
try {
|
|
470
514
|
const filePath = ensureExtension(path.resolve(clientProvidedFilePath), extension);
|
|
471
515
|
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
@@ -518,6 +562,7 @@ export class McpContext {
|
|
|
518
562
|
await this.#networkCollector.init(pages);
|
|
519
563
|
}
|
|
520
564
|
async installExtension(extensionPath) {
|
|
565
|
+
this.validatePath(extensionPath);
|
|
521
566
|
const id = await this.browser.installExtension(extensionPath);
|
|
522
567
|
return id;
|
|
523
568
|
}
|
|
@@ -541,12 +586,20 @@ export class McpContext {
|
|
|
541
586
|
return pptrExtensions.get(id);
|
|
542
587
|
}
|
|
543
588
|
async getHeapSnapshotAggregates(filePath) {
|
|
589
|
+
this.validatePath(filePath);
|
|
544
590
|
return await this.#heapSnapshotManager.getAggregates(filePath);
|
|
545
591
|
}
|
|
546
592
|
async getHeapSnapshotStats(filePath) {
|
|
593
|
+
this.validatePath(filePath);
|
|
547
594
|
return await this.#heapSnapshotManager.getStats(filePath);
|
|
548
595
|
}
|
|
549
596
|
async getHeapSnapshotStaticData(filePath) {
|
|
597
|
+
this.validatePath(filePath);
|
|
550
598
|
return await this.#heapSnapshotManager.getStaticData(filePath);
|
|
551
599
|
}
|
|
600
|
+
async getHeapSnapshotNodesByUid(filePath, uid) {
|
|
601
|
+
this.validatePath(filePath);
|
|
602
|
+
return await this.#heapSnapshotManager.getNodesByUid(filePath, uid);
|
|
603
|
+
}
|
|
552
604
|
}
|
|
605
|
+
//# sourceMappingURL=McpContext.js.map
|
package/build/src/McpPage.js
CHANGED
|
@@ -30,7 +30,7 @@ export class McpPage {
|
|
|
30
30
|
// Dialog
|
|
31
31
|
#dialog;
|
|
32
32
|
#dialogHandler;
|
|
33
|
-
|
|
33
|
+
thirdPartyDeveloperTools;
|
|
34
34
|
constructor(page, id) {
|
|
35
35
|
this.pptrPage = page;
|
|
36
36
|
this.id = id;
|
|
@@ -48,8 +48,13 @@ export class McpPage {
|
|
|
48
48
|
clearDialog() {
|
|
49
49
|
this.#dialog = undefined;
|
|
50
50
|
}
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
throwIfDialogOpen() {
|
|
52
|
+
if (this.#dialog) {
|
|
53
|
+
throw new Error(`A dialog is open (${this.#dialog.type()}: ${this.#dialog.message()}).`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
getThirdPartyDeveloperTools() {
|
|
57
|
+
return this.thirdPartyDeveloperTools;
|
|
53
58
|
}
|
|
54
59
|
getWebMcpTools() {
|
|
55
60
|
return this.pptrPage.webmcp.tools();
|
|
@@ -83,7 +88,7 @@ export class McpPage {
|
|
|
83
88
|
dispose() {
|
|
84
89
|
this.pptrPage.off('dialog', this.#dialogHandler);
|
|
85
90
|
}
|
|
86
|
-
async
|
|
91
|
+
async executeThirdPartyDeveloperTool(toolName, params, response) {
|
|
87
92
|
// Creates array of ElementHandles from the UIDs in the params.
|
|
88
93
|
// We do not replace the uids with the ElementsHandles yet, because
|
|
89
94
|
// the `evaluate` function only turns them into DOM elements if they
|
|
@@ -307,3 +312,4 @@ export class McpPage {
|
|
|
307
312
|
return {};
|
|
308
313
|
}
|
|
309
314
|
}
|
|
315
|
+
//# sourceMappingURL=McpPage.js.map
|
package/build/src/McpResponse.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { ConsoleFormatter } from './formatters/ConsoleFormatter.js';
|
|
7
7
|
import { HeapSnapshotFormatter } from './formatters/HeapSnapshotFormatter.js';
|
|
8
|
+
import { isNodeLike } from './formatters/HeapSnapshotFormatter.js';
|
|
8
9
|
import { IssueFormatter } from './formatters/IssueFormatter.js';
|
|
9
10
|
import { NetworkFormatter } from './formatters/NetworkFormatter.js';
|
|
10
11
|
import { SnapshotFormatter } from './formatters/SnapshotFormatter.js';
|
|
@@ -124,13 +125,14 @@ export class McpResponse {
|
|
|
124
125
|
#networkRequestsOptions;
|
|
125
126
|
#consoleDataOptions;
|
|
126
127
|
#listExtensions;
|
|
127
|
-
#
|
|
128
|
+
#listThirdPartyDeveloperTools;
|
|
128
129
|
#listWebMcpTools;
|
|
129
130
|
#devToolsData;
|
|
130
131
|
#tabId;
|
|
131
132
|
#args;
|
|
132
133
|
#page;
|
|
133
134
|
#redactNetworkHeaders = true;
|
|
135
|
+
#error;
|
|
134
136
|
constructor(args) {
|
|
135
137
|
this.#args = args;
|
|
136
138
|
}
|
|
@@ -161,9 +163,9 @@ export class McpResponse {
|
|
|
161
163
|
setListExtensions() {
|
|
162
164
|
this.#listExtensions = true;
|
|
163
165
|
}
|
|
164
|
-
|
|
165
|
-
if (this.#args.
|
|
166
|
-
this.#
|
|
166
|
+
setListThirdPartyDeveloperTools() {
|
|
167
|
+
if (this.#args.categoryExperimentalThirdParty) {
|
|
168
|
+
this.#listThirdPartyDeveloperTools = true;
|
|
167
169
|
}
|
|
168
170
|
}
|
|
169
171
|
setListWebMcpTools() {
|
|
@@ -204,6 +206,9 @@ export class McpResponse {
|
|
|
204
206
|
includePreservedMessages: options?.includePreservedMessages,
|
|
205
207
|
};
|
|
206
208
|
}
|
|
209
|
+
setError(error) {
|
|
210
|
+
this.#error = error;
|
|
211
|
+
}
|
|
207
212
|
attachNetworkRequest(reqId, options) {
|
|
208
213
|
this.#attachedNetworkRequestId = reqId;
|
|
209
214
|
this.#attachedNetworkRequestOptions = options;
|
|
@@ -254,6 +259,9 @@ export class McpResponse {
|
|
|
254
259
|
get consoleMessagesTypes() {
|
|
255
260
|
return this.#consoleDataOptions?.types;
|
|
256
261
|
}
|
|
262
|
+
get error() {
|
|
263
|
+
return this.#error;
|
|
264
|
+
}
|
|
257
265
|
appendResponseLine(value) {
|
|
258
266
|
this.#textResponseLines.push(value);
|
|
259
267
|
}
|
|
@@ -273,6 +281,14 @@ export class McpResponse {
|
|
|
273
281
|
staticData,
|
|
274
282
|
};
|
|
275
283
|
}
|
|
284
|
+
setHeapSnapshotNodes(nodes, options) {
|
|
285
|
+
this.#heapSnapshotOptions = {
|
|
286
|
+
...this.#heapSnapshotOptions,
|
|
287
|
+
include: true,
|
|
288
|
+
nodes,
|
|
289
|
+
pagination: options,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
276
292
|
attachImage(value) {
|
|
277
293
|
this.#images.push(value);
|
|
278
294
|
}
|
|
@@ -365,14 +381,14 @@ export class McpResponse {
|
|
|
365
381
|
if (this.#listExtensions) {
|
|
366
382
|
extensions = await context.listExtensions();
|
|
367
383
|
}
|
|
368
|
-
let
|
|
369
|
-
if (this.#
|
|
384
|
+
let thirdPartyDeveloperTools;
|
|
385
|
+
if (this.#listThirdPartyDeveloperTools) {
|
|
370
386
|
const page = this.#page ?? context.getSelectedMcpPage();
|
|
371
|
-
|
|
372
|
-
page.
|
|
387
|
+
thirdPartyDeveloperTools = await getToolGroup(page);
|
|
388
|
+
page.thirdPartyDeveloperTools = thirdPartyDeveloperTools;
|
|
373
389
|
}
|
|
374
390
|
let webmcpTools;
|
|
375
|
-
if (this.#listWebMcpTools && this.#args.
|
|
391
|
+
if (this.#listWebMcpTools && this.#args.categoryExperimentalWebmcp) {
|
|
376
392
|
const page = this.#page ?? context.getSelectedMcpPage();
|
|
377
393
|
webmcpTools = page.getWebMcpTools();
|
|
378
394
|
}
|
|
@@ -453,8 +469,9 @@ export class McpResponse {
|
|
|
453
469
|
traceSummary: this.#attachedTraceSummary,
|
|
454
470
|
extensions,
|
|
455
471
|
lighthouseResult: this.#attachedLighthouseResult,
|
|
456
|
-
|
|
472
|
+
thirdPartyDeveloperTools,
|
|
457
473
|
webmcpTools,
|
|
474
|
+
errorMessage: this.#error?.message,
|
|
458
475
|
});
|
|
459
476
|
}
|
|
460
477
|
format(toolName, context, data) {
|
|
@@ -645,6 +662,17 @@ Call ${handleDialog.name} to handle it before continuing.`);
|
|
|
645
662
|
response.push(formatter.toString());
|
|
646
663
|
structuredContent.heapSnapshotData = formatter.toJSON();
|
|
647
664
|
}
|
|
665
|
+
const nodes = this.#heapSnapshotOptions.nodes;
|
|
666
|
+
if (nodes) {
|
|
667
|
+
const sortedItems = nodes.items
|
|
668
|
+
.filter(isNodeLike)
|
|
669
|
+
.sort((a, b) => b.retainedSize - a.retainedSize);
|
|
670
|
+
const paginationData = this.#dataWithPagination(sortedItems, this.#heapSnapshotOptions.pagination);
|
|
671
|
+
response.push(HeapSnapshotFormatter.formatNodes(paginationData.items));
|
|
672
|
+
structuredContent.pagination = paginationData.pagination;
|
|
673
|
+
response.push(...paginationData.info);
|
|
674
|
+
structuredContent.heapSnapshotNodes = paginationData.items;
|
|
675
|
+
}
|
|
648
676
|
}
|
|
649
677
|
if (data.detailedNetworkRequest) {
|
|
650
678
|
response.push(data.detailedNetworkRequest.toStringDetailed());
|
|
@@ -672,14 +700,16 @@ Call ${handleDialog.name} to handle it before continuing.`);
|
|
|
672
700
|
response.push(extensionsMessage);
|
|
673
701
|
}
|
|
674
702
|
}
|
|
675
|
-
if (this.#
|
|
676
|
-
structuredContent.
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
703
|
+
if (this.#listThirdPartyDeveloperTools) {
|
|
704
|
+
structuredContent.thirdPartyDeveloperTools =
|
|
705
|
+
data.thirdPartyDeveloperTools ?? undefined;
|
|
706
|
+
response.push('## Third-party developer tools');
|
|
707
|
+
if (!data.thirdPartyDeveloperTools ||
|
|
708
|
+
!data.thirdPartyDeveloperTools.tools) {
|
|
709
|
+
response.push('No third-party developer tools available.');
|
|
680
710
|
}
|
|
681
711
|
else {
|
|
682
|
-
const toolGroup = data.
|
|
712
|
+
const toolGroup = data.thirdPartyDeveloperTools;
|
|
683
713
|
response.push(`${toolGroup.name}: ${toolGroup.description}`);
|
|
684
714
|
response.push('Available tools:');
|
|
685
715
|
const toolDefinitionsMessage = toolGroup.tools
|
|
@@ -733,16 +763,21 @@ Call ${handleDialog.name} to handle it before continuing.`);
|
|
|
733
763
|
const messages = data.consoleMessages ?? [];
|
|
734
764
|
response.push('## Console messages');
|
|
735
765
|
if (messages.length) {
|
|
736
|
-
const
|
|
766
|
+
const grouped = ConsoleFormatter.groupConsecutive(messages);
|
|
767
|
+
const paginationData = this.#dataWithPagination(grouped, this.#consoleDataOptions.pagination);
|
|
737
768
|
structuredContent.pagination = paginationData.pagination;
|
|
738
769
|
response.push(...paginationData.info);
|
|
739
|
-
response.push(...paginationData.items.map(
|
|
740
|
-
structuredContent.consoleMessages = paginationData.items.map(
|
|
770
|
+
response.push(...paginationData.items.map(item => item.toString()));
|
|
771
|
+
structuredContent.consoleMessages = paginationData.items.map(item => item.toJSON());
|
|
741
772
|
}
|
|
742
773
|
else {
|
|
743
774
|
response.push('<no console messages found>');
|
|
744
775
|
}
|
|
745
776
|
}
|
|
777
|
+
if (data.errorMessage) {
|
|
778
|
+
response.push(`Error: ${data.errorMessage}`);
|
|
779
|
+
structuredContent.errorMessage = data.errorMessage;
|
|
780
|
+
}
|
|
746
781
|
const text = {
|
|
747
782
|
type: 'text',
|
|
748
783
|
text: response.join('\n'),
|
|
@@ -804,3 +839,4 @@ function createStructuredPage(page, context) {
|
|
|
804
839
|
}
|
|
805
840
|
return entry;
|
|
806
841
|
}
|
|
842
|
+
//# sourceMappingURL=McpResponse.js.map
|
package/build/src/Mutex.js
CHANGED
|
@@ -99,8 +99,8 @@ export class TextSnapshot {
|
|
|
99
99
|
return snapshot;
|
|
100
100
|
}
|
|
101
101
|
// ExtraHandles represent DOM nodes which might not be part of the accessibility tree, e.g. DOM nodes
|
|
102
|
-
// returned by
|
|
103
|
-
// tree and inserting the node as a child. The ancestor's child nodes are re-parented if necessary.
|
|
102
|
+
// returned by third-party developer tools. We insert them into the tree by finding the closest ancestor
|
|
103
|
+
// in the tree and inserting the node as a child. The ancestor's child nodes are re-parented if necessary.
|
|
104
104
|
static async insertExtraNodes(page, idToNode, seenUniqueIds, snapshotId, idCounter, rootNodeWithId, seenBackendNodeIds, extraHandles) {
|
|
105
105
|
const { uniqueBackendNodeIdToMcpId } = page;
|
|
106
106
|
const createExtraNode = async (handle) => {
|
|
@@ -160,6 +160,9 @@ export class TextSnapshot {
|
|
|
160
160
|
};
|
|
161
161
|
const findDescendantNodes = async (backendNodeId) => {
|
|
162
162
|
const descendantIds = new Set();
|
|
163
|
+
if (!backendNodeId) {
|
|
164
|
+
return descendantIds;
|
|
165
|
+
}
|
|
163
166
|
try {
|
|
164
167
|
// @ts-expect-error internal API
|
|
165
168
|
const client = page.pptrPage._client();
|
|
@@ -213,6 +216,7 @@ export class TextSnapshot {
|
|
|
213
216
|
if (extraHandles.length) {
|
|
214
217
|
page.extraHandles = extraHandles;
|
|
215
218
|
}
|
|
219
|
+
const reorgInfo = [];
|
|
216
220
|
for (const handle of page.extraHandles) {
|
|
217
221
|
const extraNode = await createExtraNode(handle);
|
|
218
222
|
if (!extraNode) {
|
|
@@ -220,11 +224,13 @@ export class TextSnapshot {
|
|
|
220
224
|
}
|
|
221
225
|
idToNode.set(extraNode.id, extraNode);
|
|
222
226
|
const attachTarget = (await findAncestorNode(handle)) || rootNodeWithId;
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
227
|
+
const descendantIds = await findDescendantNodes(extraNode.backendNodeId);
|
|
228
|
+
reorgInfo.push({ extraNode, attachTarget, descendantIds });
|
|
229
|
+
}
|
|
230
|
+
for (const { extraNode, attachTarget, descendantIds } of reorgInfo) {
|
|
231
|
+
const index = moveChildNodes(attachTarget, extraNode, descendantIds);
|
|
232
|
+
attachTarget.children.splice(index, 0, extraNode);
|
|
228
233
|
}
|
|
229
234
|
}
|
|
230
235
|
}
|
|
236
|
+
//# sourceMappingURL=TextSnapshot.js.map
|
|
@@ -104,8 +104,10 @@ export class WaitForHelper {
|
|
|
104
104
|
});
|
|
105
105
|
}
|
|
106
106
|
async waitForEventsAfterAction(action, options) {
|
|
107
|
+
let dialogOpened = false;
|
|
107
108
|
if (options?.handleDialog) {
|
|
108
109
|
const dialogHandler = (dialog) => {
|
|
110
|
+
dialogOpened = true;
|
|
109
111
|
if (options.handleDialog === 'dismiss') {
|
|
110
112
|
void dialog.dismiss();
|
|
111
113
|
}
|
|
@@ -142,6 +144,9 @@ export class WaitForHelper {
|
|
|
142
144
|
}
|
|
143
145
|
try {
|
|
144
146
|
await navigationFinished;
|
|
147
|
+
if (dialogOpened) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
145
150
|
// Wait for stable dom after navigation so we execute in
|
|
146
151
|
// the correct context
|
|
147
152
|
await this.waitForStableDom();
|
|
@@ -168,3 +173,4 @@ export function getNetworkMultiplierFromString(condition) {
|
|
|
168
173
|
}
|
|
169
174
|
return 1;
|
|
170
175
|
}
|
|
176
|
+
//# sourceMappingURL=WaitForHelper.js.map
|