chrome-devtools-mcp 0.24.0 → 0.26.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 +23 -6
- package/build/src/McpPage.js +4 -4
- package/build/src/McpResponse.js +18 -16
- package/build/src/TextSnapshot.js +2 -2
- package/build/src/ToolHandler.js +188 -0
- package/build/src/bin/chrome-devtools-cli-options.js +28 -5
- package/build/src/bin/chrome-devtools-mcp-cli-options.js +8 -5
- package/build/src/bin/chrome-devtools-mcp-main.js +4 -8
- package/build/src/bin/chrome-devtools.js +0 -2
- package/build/src/index.js +9 -164
- package/build/src/telemetry/ClearcutLogger.js +27 -0
- package/build/src/telemetry/errors.js +14 -0
- package/build/src/telemetry/types.js +0 -8
- package/build/src/third_party/THIRD_PARTY_NOTICES +12 -14
- package/build/src/third_party/bundled-packages.json +3 -3
- package/build/src/third_party/devtools-formatter-worker.js +49 -33
- package/build/src/third_party/devtools-heap-snapshot-worker.js +60 -44
- package/build/src/third_party/index.js +2138 -1352
- 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 +4236 -4219
- package/build/src/tools/categories.js +6 -3
- package/build/src/tools/input.js +72 -7
- package/build/src/tools/lighthouse.js +7 -7
- package/build/src/tools/pages.js +5 -5
- package/build/src/tools/{inPage.js → thirdPartyDeveloper.js} +15 -15
- package/build/src/tools/tools.js +2 -2
- package/build/src/tools/webmcp.js +2 -4
- package/build/src/version.js +1 -1
- package/package.json +7 -8
package/README.md
CHANGED
|
@@ -161,7 +161,7 @@ To install Chrome DevTools MCP with skills, add the marketplace registry in Clau
|
|
|
161
161
|
Then, install the plugin:
|
|
162
162
|
|
|
163
163
|
```sh
|
|
164
|
-
/plugin install chrome-devtools-mcp
|
|
164
|
+
/plugin install chrome-devtools-mcp@chrome-devtools-plugins
|
|
165
165
|
```
|
|
166
166
|
|
|
167
167
|
Restart Claude Code to have the MCP server and skills load (check with `/skills`).
|
|
@@ -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
|
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;
|
|
@@ -53,8 +53,8 @@ export class McpPage {
|
|
|
53
53
|
throw new Error(`A dialog is open (${this.#dialog.type()}: ${this.#dialog.message()}).`);
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
-
|
|
57
|
-
return this.
|
|
56
|
+
getThirdPartyDeveloperTools() {
|
|
57
|
+
return this.thirdPartyDeveloperTools;
|
|
58
58
|
}
|
|
59
59
|
getWebMcpTools() {
|
|
60
60
|
return this.pptrPage.webmcp.tools();
|
|
@@ -88,7 +88,7 @@ export class McpPage {
|
|
|
88
88
|
dispose() {
|
|
89
89
|
this.pptrPage.off('dialog', this.#dialogHandler);
|
|
90
90
|
}
|
|
91
|
-
async
|
|
91
|
+
async executeThirdPartyDeveloperTool(toolName, params, response) {
|
|
92
92
|
// Creates array of ElementHandles from the UIDs in the params.
|
|
93
93
|
// We do not replace the uids with the ElementsHandles yet, because
|
|
94
94
|
// the `evaluate` function only turns them into DOM elements if they
|
package/build/src/McpResponse.js
CHANGED
|
@@ -125,7 +125,7 @@ export class McpResponse {
|
|
|
125
125
|
#networkRequestsOptions;
|
|
126
126
|
#consoleDataOptions;
|
|
127
127
|
#listExtensions;
|
|
128
|
-
#
|
|
128
|
+
#listThirdPartyDeveloperTools;
|
|
129
129
|
#listWebMcpTools;
|
|
130
130
|
#devToolsData;
|
|
131
131
|
#tabId;
|
|
@@ -163,9 +163,9 @@ export class McpResponse {
|
|
|
163
163
|
setListExtensions() {
|
|
164
164
|
this.#listExtensions = true;
|
|
165
165
|
}
|
|
166
|
-
|
|
167
|
-
if (this.#args.
|
|
168
|
-
this.#
|
|
166
|
+
setListThirdPartyDeveloperTools() {
|
|
167
|
+
if (this.#args.categoryExperimentalThirdParty) {
|
|
168
|
+
this.#listThirdPartyDeveloperTools = true;
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
171
|
setListWebMcpTools() {
|
|
@@ -381,14 +381,14 @@ export class McpResponse {
|
|
|
381
381
|
if (this.#listExtensions) {
|
|
382
382
|
extensions = await context.listExtensions();
|
|
383
383
|
}
|
|
384
|
-
let
|
|
385
|
-
if (this.#
|
|
384
|
+
let thirdPartyDeveloperTools;
|
|
385
|
+
if (this.#listThirdPartyDeveloperTools) {
|
|
386
386
|
const page = this.#page ?? context.getSelectedMcpPage();
|
|
387
|
-
|
|
388
|
-
page.
|
|
387
|
+
thirdPartyDeveloperTools = await getToolGroup(page);
|
|
388
|
+
page.thirdPartyDeveloperTools = thirdPartyDeveloperTools;
|
|
389
389
|
}
|
|
390
390
|
let webmcpTools;
|
|
391
|
-
if (this.#listWebMcpTools && this.#args.
|
|
391
|
+
if (this.#listWebMcpTools && this.#args.categoryExperimentalWebmcp) {
|
|
392
392
|
const page = this.#page ?? context.getSelectedMcpPage();
|
|
393
393
|
webmcpTools = page.getWebMcpTools();
|
|
394
394
|
}
|
|
@@ -469,7 +469,7 @@ export class McpResponse {
|
|
|
469
469
|
traceSummary: this.#attachedTraceSummary,
|
|
470
470
|
extensions,
|
|
471
471
|
lighthouseResult: this.#attachedLighthouseResult,
|
|
472
|
-
|
|
472
|
+
thirdPartyDeveloperTools,
|
|
473
473
|
webmcpTools,
|
|
474
474
|
errorMessage: this.#error?.message,
|
|
475
475
|
});
|
|
@@ -700,14 +700,16 @@ Call ${handleDialog.name} to handle it before continuing.`);
|
|
|
700
700
|
response.push(extensionsMessage);
|
|
701
701
|
}
|
|
702
702
|
}
|
|
703
|
-
if (this.#
|
|
704
|
-
structuredContent.
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
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.');
|
|
708
710
|
}
|
|
709
711
|
else {
|
|
710
|
-
const toolGroup = data.
|
|
712
|
+
const toolGroup = data.thirdPartyDeveloperTools;
|
|
711
713
|
response.push(`${toolGroup.name}: ${toolGroup.description}`);
|
|
712
714
|
response.push('Available tools:');
|
|
713
715
|
const toolDefinitionsMessage = toolGroup.tools
|
|
@@ -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) => {
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { logger } from './logger.js';
|
|
7
|
+
import { McpResponse } from './McpResponse.js';
|
|
8
|
+
import { SlimMcpResponse } from './SlimMcpResponse.js';
|
|
9
|
+
import { ClearcutLogger } from './telemetry/ClearcutLogger.js';
|
|
10
|
+
import { bucketizeLatency } from './telemetry/metricUtils.js';
|
|
11
|
+
import { labels, OFF_BY_DEFAULT_CATEGORIES } from './tools/categories.js';
|
|
12
|
+
import { pageIdSchema } from './tools/ToolDefinition.js';
|
|
13
|
+
export function buildFlag(category) {
|
|
14
|
+
return `category${category.charAt(0).toUpperCase() + category.slice(1)}`;
|
|
15
|
+
}
|
|
16
|
+
function buildDisabledMessage(toolName, flag, categoryLabel) {
|
|
17
|
+
const reason = categoryLabel
|
|
18
|
+
? `is in category ${categoryLabel} which`
|
|
19
|
+
: `requires experimental feature ${flag} and`;
|
|
20
|
+
return `Tool ${toolName} ${reason} is currently disabled. Enable it by running chrome-devtools start ${flag}=true. For more information check the README.`;
|
|
21
|
+
}
|
|
22
|
+
function getCategoryStatus(category, serverArgs) {
|
|
23
|
+
const categoryFlag = buildFlag(category);
|
|
24
|
+
const flagValue = serverArgs[categoryFlag];
|
|
25
|
+
const isDisabled = OFF_BY_DEFAULT_CATEGORIES.includes(category)
|
|
26
|
+
? !flagValue
|
|
27
|
+
: flagValue === false;
|
|
28
|
+
if (isDisabled) {
|
|
29
|
+
return {
|
|
30
|
+
categoryFlag,
|
|
31
|
+
disabled: true,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
disabled: false,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function getConditionStatus(condition, serverArgs) {
|
|
39
|
+
if (condition && !serverArgs[condition]) {
|
|
40
|
+
return { conditionFlag: condition, disabled: true };
|
|
41
|
+
}
|
|
42
|
+
return { disabled: false };
|
|
43
|
+
}
|
|
44
|
+
function getToolStatusInfo(tool, serverArgs) {
|
|
45
|
+
const category = tool.annotations.category;
|
|
46
|
+
const categoryCheck = getCategoryStatus(category, serverArgs);
|
|
47
|
+
if (category && categoryCheck.disabled) {
|
|
48
|
+
if (!categoryCheck.categoryFlag) {
|
|
49
|
+
throw new Error('when the category is disabled there should always be a flag set');
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
disabled: true,
|
|
53
|
+
reason: buildDisabledMessage(tool.name, `--${categoryCheck.categoryFlag}`, labels[category]),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
for (const condition of tool.annotations.conditions || []) {
|
|
57
|
+
const conditionCheck = getConditionStatus(condition, serverArgs);
|
|
58
|
+
if (conditionCheck.disabled) {
|
|
59
|
+
if (!conditionCheck.conditionFlag) {
|
|
60
|
+
throw new Error('when the condition is disabled there should always be a flag set');
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
disabled: true,
|
|
64
|
+
reason: buildDisabledMessage(tool.name, `--${conditionCheck.conditionFlag}`),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return { disabled: false };
|
|
69
|
+
}
|
|
70
|
+
function isPageScopedTool(tool) {
|
|
71
|
+
return 'pageScoped' in tool && tool.pageScoped === true;
|
|
72
|
+
}
|
|
73
|
+
export class ToolHandler {
|
|
74
|
+
tool;
|
|
75
|
+
serverArgs;
|
|
76
|
+
getContext;
|
|
77
|
+
toolMutex;
|
|
78
|
+
inputSchema;
|
|
79
|
+
shouldRegister;
|
|
80
|
+
disabledReason;
|
|
81
|
+
constructor(tool, serverArgs, getContext, toolMutex) {
|
|
82
|
+
this.tool = tool;
|
|
83
|
+
this.serverArgs = serverArgs;
|
|
84
|
+
this.getContext = getContext;
|
|
85
|
+
this.toolMutex = toolMutex;
|
|
86
|
+
const { disabled, reason } = getToolStatusInfo(tool, serverArgs);
|
|
87
|
+
this.disabledReason = reason;
|
|
88
|
+
this.shouldRegister = !(disabled && !serverArgs.viaCli);
|
|
89
|
+
this.inputSchema =
|
|
90
|
+
'pageScoped' in tool &&
|
|
91
|
+
tool.pageScoped &&
|
|
92
|
+
serverArgs.experimentalPageIdRouting &&
|
|
93
|
+
!serverArgs.slim
|
|
94
|
+
? { ...tool.schema, ...pageIdSchema }
|
|
95
|
+
: tool.schema;
|
|
96
|
+
}
|
|
97
|
+
async handle(params) {
|
|
98
|
+
if (this.disabledReason) {
|
|
99
|
+
return {
|
|
100
|
+
content: [
|
|
101
|
+
{
|
|
102
|
+
type: 'text',
|
|
103
|
+
text: this.disabledReason,
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
isError: true,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
const guard = await this.toolMutex.acquire();
|
|
110
|
+
const startTime = Date.now();
|
|
111
|
+
let success = false;
|
|
112
|
+
try {
|
|
113
|
+
logger(`${this.tool.name} request: ${JSON.stringify(params, null, ' ')}`);
|
|
114
|
+
const context = await this.getContext();
|
|
115
|
+
logger(`${this.tool.name} context: resolved`);
|
|
116
|
+
await context.detectOpenDevToolsWindows();
|
|
117
|
+
const response = this.serverArgs.slim
|
|
118
|
+
? new SlimMcpResponse(this.serverArgs)
|
|
119
|
+
: new McpResponse(this.serverArgs);
|
|
120
|
+
response.setRedactNetworkHeaders(this.serverArgs.redactNetworkHeaders);
|
|
121
|
+
try {
|
|
122
|
+
if (isPageScopedTool(this.tool)) {
|
|
123
|
+
const pageId = typeof params.pageId === 'number' ? params.pageId : undefined;
|
|
124
|
+
const page = this.serverArgs.experimentalPageIdRouting &&
|
|
125
|
+
pageId !== undefined &&
|
|
126
|
+
!this.serverArgs.slim
|
|
127
|
+
? context.getPageById(pageId)
|
|
128
|
+
: context.getSelectedMcpPage();
|
|
129
|
+
response.setPage(page);
|
|
130
|
+
if (this.tool.blockedByDialog) {
|
|
131
|
+
page.throwIfDialogOpen();
|
|
132
|
+
}
|
|
133
|
+
await this.tool.handler({
|
|
134
|
+
params,
|
|
135
|
+
page,
|
|
136
|
+
}, response, context);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
await this.tool.handler({
|
|
140
|
+
params,
|
|
141
|
+
}, response, context);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
response.setError(err);
|
|
146
|
+
}
|
|
147
|
+
const { content, structuredContent } = await response.handle(this.tool.name, context);
|
|
148
|
+
const result = {
|
|
149
|
+
content,
|
|
150
|
+
};
|
|
151
|
+
if (response.error) {
|
|
152
|
+
result.isError = true;
|
|
153
|
+
}
|
|
154
|
+
success = true;
|
|
155
|
+
if (this.serverArgs.experimentalStructuredContent) {
|
|
156
|
+
result.structuredContent = structuredContent;
|
|
157
|
+
}
|
|
158
|
+
return result;
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
logger(`${this.tool.name} error:`, err, err?.stack);
|
|
162
|
+
let errorText = err && 'message' in err ? err.message : String(err);
|
|
163
|
+
if ('cause' in err && err.cause) {
|
|
164
|
+
errorText += `\nCause: ${err.cause.message}`;
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
content: [
|
|
168
|
+
{
|
|
169
|
+
type: 'text',
|
|
170
|
+
text: errorText,
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
isError: true,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
finally {
|
|
177
|
+
void ClearcutLogger.get()?.logToolInvocation({
|
|
178
|
+
toolName: this.tool.name,
|
|
179
|
+
params,
|
|
180
|
+
schema: this.inputSchema,
|
|
181
|
+
success,
|
|
182
|
+
latencyMs: bucketizeLatency(Date.now() - startTime),
|
|
183
|
+
});
|
|
184
|
+
guard.dispose();
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=ToolHandler.js.map
|
|
@@ -162,9 +162,27 @@ export const commands = {
|
|
|
162
162
|
},
|
|
163
163
|
},
|
|
164
164
|
},
|
|
165
|
+
execute_3p_developer_tool: {
|
|
166
|
+
description: 'Executes a tool exposed by the page. (requires flag: --categoryExperimentalThirdParty=true)',
|
|
167
|
+
category: 'Third-party',
|
|
168
|
+
args: {
|
|
169
|
+
toolName: {
|
|
170
|
+
name: 'toolName',
|
|
171
|
+
type: 'string',
|
|
172
|
+
description: 'The name of the tool to execute',
|
|
173
|
+
required: true,
|
|
174
|
+
},
|
|
175
|
+
params: {
|
|
176
|
+
name: 'params',
|
|
177
|
+
type: 'string',
|
|
178
|
+
description: 'The JSON-stringified parameters to pass to the tool',
|
|
179
|
+
required: false,
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
},
|
|
165
183
|
execute_webmcp_tool: {
|
|
166
|
-
description: 'Executes a WebMCP tool exposed by the page. (requires flag: --
|
|
167
|
-
category: '
|
|
184
|
+
description: 'Executes a WebMCP tool exposed by the page. (requires flag: --categoryExperimentalWebmcp=true)',
|
|
185
|
+
category: 'WebMCP',
|
|
168
186
|
args: {
|
|
169
187
|
toolName: {
|
|
170
188
|
name: 'toolName',
|
|
@@ -193,7 +211,7 @@ export const commands = {
|
|
|
193
211
|
value: {
|
|
194
212
|
name: 'value',
|
|
195
213
|
type: 'string',
|
|
196
|
-
description: 'The value to fill in',
|
|
214
|
+
description: 'The value to fill in. "true" or "false" for checkboxes and toggles, "true" for radio buttons.',
|
|
197
215
|
required: true,
|
|
198
216
|
},
|
|
199
217
|
includeSnapshot: {
|
|
@@ -371,6 +389,11 @@ export const commands = {
|
|
|
371
389
|
},
|
|
372
390
|
},
|
|
373
391
|
},
|
|
392
|
+
list_3p_developer_tools: {
|
|
393
|
+
description: "Lists all third-party developer tools the page exposes for providing runtime information.\n Third-party developer tools can be called via the 'execute_3p_developer_tool()' MCP tool.\n Alternatively, third-party developer tools can be executed by calling 'evaluate_script' and adding the\n following command to the script:\n 'window.__dtmcp.executeTool(toolName, params)'\n This might be helpful when the third-party developer tools return non-serializable values or when composing\n third-party developer tools with additional functionality. (requires flag: --categoryExperimentalThirdParty=true)",
|
|
394
|
+
category: 'Third-party',
|
|
395
|
+
args: {},
|
|
396
|
+
},
|
|
374
397
|
list_console_messages: {
|
|
375
398
|
description: 'List all console messages for the currently selected page since the last navigation.',
|
|
376
399
|
category: 'Debugging',
|
|
@@ -444,8 +467,8 @@ export const commands = {
|
|
|
444
467
|
args: {},
|
|
445
468
|
},
|
|
446
469
|
list_webmcp_tools: {
|
|
447
|
-
description: 'Lists all WebMCP tools the page exposes. (requires flag: --
|
|
448
|
-
category: '
|
|
470
|
+
description: 'Lists all WebMCP tools the page exposes. (requires flag: --categoryExperimentalWebmcp=true)',
|
|
471
|
+
category: 'WebMCP',
|
|
449
472
|
args: {},
|
|
450
473
|
},
|
|
451
474
|
load_memory_snapshot: {
|
|
@@ -183,7 +183,7 @@ export const cliOptions = {
|
|
|
183
183
|
describe: 'Path to ffmpeg executable for screencast recording.',
|
|
184
184
|
implies: 'experimentalScreencast',
|
|
185
185
|
},
|
|
186
|
-
|
|
186
|
+
categoryExperimentalWebmcp: {
|
|
187
187
|
type: 'boolean',
|
|
188
188
|
describe: 'Set to true to enable debugging WebMCP tools. Requires Chrome 149+ with the following flags: `--enable-features=WebMCPTesting,DevToolsWebMCPSupport`',
|
|
189
189
|
},
|
|
@@ -216,11 +216,10 @@ export const cliOptions = {
|
|
|
216
216
|
default: false,
|
|
217
217
|
describe: 'Set to true to include tools related to extensions. Note: This feature is currently only supported with a pipe connection. autoConnect, browserUrl, and wsEndpoint are not supported with this feature until 149 will be released.',
|
|
218
218
|
},
|
|
219
|
-
|
|
219
|
+
categoryExperimentalThirdParty: {
|
|
220
220
|
type: 'boolean',
|
|
221
|
-
hidden: true,
|
|
222
221
|
default: false,
|
|
223
|
-
describe: 'Set to true to enable tools exposed by the inspected page itself',
|
|
222
|
+
describe: 'Set to true to enable third-party developer tools exposed by the inspected page itself',
|
|
224
223
|
},
|
|
225
224
|
performanceCrux: {
|
|
226
225
|
type: 'boolean',
|
|
@@ -262,7 +261,7 @@ export const cliOptions = {
|
|
|
262
261
|
default: false,
|
|
263
262
|
},
|
|
264
263
|
};
|
|
265
|
-
export function parseArguments(version, argv = process.argv) {
|
|
264
|
+
export function parseArguments(version, argv = process.argv, env = process.env) {
|
|
266
265
|
const yargsInstance = yargs(hideBin(argv))
|
|
267
266
|
.scriptName('npx chrome-devtools-mcp@latest')
|
|
268
267
|
.options(cliOptions)
|
|
@@ -275,6 +274,10 @@ export function parseArguments(version, argv = process.argv) {
|
|
|
275
274
|
!args.executablePath) {
|
|
276
275
|
args.channel = 'stable';
|
|
277
276
|
}
|
|
277
|
+
if (env['CI'] || env['CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS']) {
|
|
278
|
+
console.error("turning off usage statistics. process.env['CI'] || process.env['CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS'] is set.");
|
|
279
|
+
args.usageStatistics = false;
|
|
280
|
+
}
|
|
278
281
|
return true;
|
|
279
282
|
})
|
|
280
283
|
.example([
|
|
@@ -7,6 +7,7 @@ import '../polyfill.js';
|
|
|
7
7
|
import process from 'node:process';
|
|
8
8
|
import { createMcpServer, logDisclaimers } from '../index.js';
|
|
9
9
|
import { logger, saveLogsToFile } from '../logger.js';
|
|
10
|
+
import { ClearcutLogger } from '../telemetry/ClearcutLogger.js';
|
|
10
11
|
import { computeFlagUsage } from '../telemetry/flagUtils.js';
|
|
11
12
|
import { StdioServerTransport } from '../third_party/index.js';
|
|
12
13
|
import { checkForUpdates } from '../utils/check-for-updates.js';
|
|
@@ -15,24 +16,19 @@ import { cliOptions, parseArguments } from './chrome-devtools-mcp-cli-options.js
|
|
|
15
16
|
await checkForUpdates('Run `npm install chrome-devtools-mcp@latest` to update.');
|
|
16
17
|
export const args = parseArguments(VERSION);
|
|
17
18
|
const logFile = args.logFile ? saveLogsToFile(args.logFile) : undefined;
|
|
18
|
-
if (process.env['CI'] ||
|
|
19
|
-
process.env['CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS']) {
|
|
20
|
-
console.error("turning off usage statistics. process.env['CI'] || process.env['CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS'] is set.");
|
|
21
|
-
args.usageStatistics = false;
|
|
22
|
-
}
|
|
23
19
|
if (process.env['CHROME_DEVTOOLS_MCP_CRASH_ON_UNCAUGHT'] !== 'true') {
|
|
24
20
|
process.on('unhandledRejection', (reason, promise) => {
|
|
25
21
|
logger('Unhandled promise rejection', promise, reason);
|
|
26
22
|
});
|
|
27
23
|
}
|
|
28
24
|
logger(`Starting Chrome DevTools MCP Server v${VERSION}`);
|
|
29
|
-
const { server
|
|
25
|
+
const { server } = await createMcpServer(args, {
|
|
30
26
|
logFile,
|
|
31
27
|
});
|
|
32
28
|
const transport = new StdioServerTransport();
|
|
33
29
|
await server.connect(transport);
|
|
34
30
|
logger('Chrome DevTools MCP Server connected');
|
|
35
31
|
logDisclaimers(args);
|
|
36
|
-
void
|
|
37
|
-
void
|
|
32
|
+
void ClearcutLogger.get()?.logDailyActiveIfNeeded();
|
|
33
|
+
void ClearcutLogger.get()?.logServerStart(computeFlagUsage(args, cliOptions));
|
|
38
34
|
//# sourceMappingURL=chrome-devtools-mcp-main.js.map
|
|
@@ -24,8 +24,6 @@ const defaultArgs = ['--viaCli', '--experimentalStructuredContent'];
|
|
|
24
24
|
const startCliOptions = {
|
|
25
25
|
...cliOptions,
|
|
26
26
|
};
|
|
27
|
-
// Not supported in CLI on purpose.
|
|
28
|
-
delete startCliOptions.autoConnect;
|
|
29
27
|
// Missing CLI serialization.
|
|
30
28
|
delete startCliOptions.viewport;
|
|
31
29
|
// Change the defaults for the CLI.
|