chrome-devtools-mcp 0.20.3 → 0.22.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 +97 -20
- package/build/src/HeapSnapshotManager.js +94 -0
- package/build/src/McpContext.js +26 -49
- package/build/src/McpPage.js +16 -0
- package/build/src/McpResponse.js +220 -12
- package/build/src/PageCollector.js +14 -28
- package/build/src/WaitForHelper.js +31 -0
- package/build/src/bin/check-latest-version.js +25 -0
- package/build/src/bin/chrome-devtools-mcp-cli-options.js +28 -9
- package/build/src/bin/chrome-devtools-mcp-main.js +2 -0
- package/build/src/bin/chrome-devtools-mcp.js +1 -0
- package/build/src/bin/chrome-devtools.js +9 -3
- package/build/src/bin/cliDefinitions.js +15 -9
- package/build/src/daemon/client.js +1 -1
- package/build/src/daemon/daemon.js +2 -6
- package/build/src/daemon/utils.js +1 -0
- package/build/src/formatters/HeapSnapshotFormatter.js +38 -0
- package/build/src/formatters/NetworkFormatter.js +24 -7
- package/build/src/index.js +22 -1
- package/build/src/telemetry/ClearcutLogger.js +145 -6
- package/build/src/telemetry/flagUtils.js +46 -4
- package/build/src/telemetry/toolMetricsUtils.js +88 -0
- package/build/src/telemetry/types.js +5 -0
- package/build/src/telemetry/watchdog/ClearcutSender.js +4 -3
- package/build/src/third_party/THIRD_PARTY_NOTICES +1400 -483
- package/build/src/third_party/bundled-packages.json +6 -5
- package/build/src/third_party/devtools-formatter-worker.js +61 -66
- package/build/src/third_party/devtools-heap-snapshot-worker.js +9690 -0
- package/build/src/third_party/index.js +61622 -52803
- package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorCrossOriginNoCorsRequest.md +1 -0
- package/build/src/third_party/lighthouse-devtools-mcp-bundle.js +10589 -4647
- package/build/src/tools/categories.js +5 -0
- package/build/src/tools/console.js +42 -39
- package/build/src/tools/emulation.js +1 -1
- package/build/src/tools/extensions.js +5 -11
- package/build/src/tools/inPage.js +105 -0
- package/build/src/tools/input.js +18 -16
- package/build/src/tools/lighthouse.js +3 -3
- package/build/src/tools/memory.js +50 -5
- package/build/src/tools/network.js +2 -2
- package/build/src/tools/pages.js +14 -6
- package/build/src/tools/performance.js +1 -1
- package/build/src/tools/screencast.js +2 -1
- package/build/src/tools/screenshot.js +3 -3
- package/build/src/tools/script.js +22 -16
- package/build/src/tools/tools.js +4 -0
- package/build/src/tools/webmcp.js +63 -0
- package/build/src/utils/check-for-updates.js +73 -0
- package/build/src/utils/files.js +4 -0
- package/build/src/utils/id.js +15 -0
- package/build/src/version.js +1 -1
- package/package.json +13 -9
- package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorNoCorpCrossOriginNoCorsRequest.md +0 -3
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNoCorpCossOriginNoCorsRequest.md +0 -3
- package/build/src/utils/ExtensionRegistry.js +0 -35
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"@modelcontextprotocol/sdk": "1.
|
|
3
|
-
"chrome-devtools-frontend": "1.0.
|
|
4
|
-
"core-js": "3.
|
|
2
|
+
"@modelcontextprotocol/sdk": "1.29.0",
|
|
3
|
+
"chrome-devtools-frontend": "1.0.1613625",
|
|
4
|
+
"core-js": "3.49.0",
|
|
5
5
|
"debug": "4.4.3",
|
|
6
|
-
"lighthouse": "13.0
|
|
6
|
+
"lighthouse": "13.1.0",
|
|
7
|
+
"semver": "^7.7.4",
|
|
7
8
|
"yargs": "18.0.0",
|
|
8
|
-
"puppeteer-core": "24.
|
|
9
|
+
"puppeteer-core": "24.42.0"
|
|
9
10
|
}
|
|
@@ -26,36 +26,36 @@ function arrayDoesNotContainNullOrUndefined(arr) {
|
|
|
26
26
|
const EmptyUrlString = '';
|
|
27
27
|
|
|
28
28
|
// Copyright 2025 The Chromium Authors
|
|
29
|
-
class
|
|
29
|
+
class WebWorkerScope {
|
|
30
30
|
postMessage(message) {
|
|
31
|
-
|
|
31
|
+
self.postMessage(message);
|
|
32
32
|
}
|
|
33
33
|
set onmessage(listener) {
|
|
34
|
-
|
|
35
|
-
listener({ data });
|
|
36
|
-
});
|
|
34
|
+
self.addEventListener('message', listener);
|
|
37
35
|
}
|
|
38
36
|
}
|
|
39
|
-
class
|
|
37
|
+
class WebWorker {
|
|
40
38
|
#workerPromise;
|
|
41
|
-
#disposed
|
|
39
|
+
#disposed;
|
|
42
40
|
#rejectWorkerPromise;
|
|
43
|
-
constructor(
|
|
44
|
-
this.#workerPromise = new Promise((
|
|
41
|
+
constructor(workerLocation) {
|
|
42
|
+
this.#workerPromise = new Promise((fulfill, reject) => {
|
|
45
43
|
this.#rejectWorkerPromise = reject;
|
|
46
|
-
const worker = new
|
|
47
|
-
worker.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
44
|
+
const worker = new Worker(new URL(workerLocation), { type: 'module' });
|
|
45
|
+
worker.onerror = event => {
|
|
46
|
+
console.error(`Failed to load worker for ${workerLocation}:`, event);
|
|
47
|
+
};
|
|
48
|
+
worker.onmessage = (event) => {
|
|
49
|
+
console.assert(event.data === 'workerReady');
|
|
50
|
+
worker.onmessage = null;
|
|
51
|
+
fulfill(worker);
|
|
52
|
+
};
|
|
53
53
|
});
|
|
54
54
|
}
|
|
55
|
-
postMessage(message) {
|
|
55
|
+
postMessage(message, transfer) {
|
|
56
56
|
void this.#workerPromise.then(worker => {
|
|
57
57
|
if (!this.#disposed) {
|
|
58
|
-
worker.postMessage(message);
|
|
58
|
+
worker.postMessage(message, transfer ?? []);
|
|
59
59
|
}
|
|
60
60
|
});
|
|
61
61
|
}
|
|
@@ -63,7 +63,7 @@ class NodeWorker {
|
|
|
63
63
|
this.#disposed = true;
|
|
64
64
|
void this.#workerPromise.then(worker => worker.terminate());
|
|
65
65
|
}
|
|
66
|
-
terminate(immediately) {
|
|
66
|
+
terminate(immediately = false) {
|
|
67
67
|
if (immediately) {
|
|
68
68
|
this.#rejectWorkerPromise?.(new Error('Worker terminated'));
|
|
69
69
|
}
|
|
@@ -71,28 +71,20 @@ class NodeWorker {
|
|
|
71
71
|
}
|
|
72
72
|
set onmessage(listener) {
|
|
73
73
|
void this.#workerPromise.then(worker => {
|
|
74
|
-
worker.
|
|
75
|
-
if (!this.#disposed) {
|
|
76
|
-
listener({ data });
|
|
77
|
-
}
|
|
78
|
-
});
|
|
74
|
+
worker.onmessage = listener;
|
|
79
75
|
});
|
|
80
76
|
}
|
|
81
77
|
set onerror(listener) {
|
|
82
78
|
void this.#workerPromise.then(worker => {
|
|
83
|
-
worker.
|
|
84
|
-
if (!this.#disposed) {
|
|
85
|
-
listener({ type: 'error', ...error });
|
|
86
|
-
}
|
|
87
|
-
});
|
|
79
|
+
worker.onerror = listener;
|
|
88
80
|
});
|
|
89
81
|
}
|
|
90
82
|
}
|
|
91
83
|
const HOST_RUNTIME$2 = {
|
|
92
84
|
createWorker(url) {
|
|
93
|
-
return new
|
|
85
|
+
return new WebWorker(url);
|
|
94
86
|
},
|
|
95
|
-
workerScope: new
|
|
87
|
+
workerScope: new WebWorkerScope(),
|
|
96
88
|
};
|
|
97
89
|
|
|
98
90
|
var HostRuntime$1 = /*#__PURE__*/Object.freeze({
|
|
@@ -102,42 +94,42 @@ var HostRuntime$1 = /*#__PURE__*/Object.freeze({
|
|
|
102
94
|
|
|
103
95
|
// Copyright 2025 The Chromium Authors
|
|
104
96
|
|
|
105
|
-
var
|
|
97
|
+
var browser = /*#__PURE__*/Object.freeze({
|
|
106
98
|
__proto__: null,
|
|
107
99
|
HostRuntime: HostRuntime$1
|
|
108
100
|
});
|
|
109
101
|
|
|
110
102
|
// Copyright 2025 The Chromium Authors
|
|
111
|
-
class
|
|
103
|
+
class NodeWorkerScope {
|
|
112
104
|
postMessage(message) {
|
|
113
|
-
|
|
105
|
+
WorkerThreads.parentPort?.postMessage(message);
|
|
114
106
|
}
|
|
115
107
|
set onmessage(listener) {
|
|
116
|
-
|
|
108
|
+
WorkerThreads.parentPort?.addEventListener('message', msg => {
|
|
109
|
+
listener(msg);
|
|
110
|
+
});
|
|
117
111
|
}
|
|
118
112
|
}
|
|
119
|
-
class
|
|
113
|
+
class NodeWorker {
|
|
120
114
|
#workerPromise;
|
|
121
|
-
#disposed;
|
|
115
|
+
#disposed = false;
|
|
122
116
|
#rejectWorkerPromise;
|
|
123
|
-
constructor(
|
|
124
|
-
this.#workerPromise = new Promise((
|
|
117
|
+
constructor(url) {
|
|
118
|
+
this.#workerPromise = new Promise((resolve, reject) => {
|
|
125
119
|
this.#rejectWorkerPromise = reject;
|
|
126
|
-
const worker = new Worker(new URL(
|
|
127
|
-
worker.
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
fulfill(worker);
|
|
134
|
-
};
|
|
120
|
+
const worker = new WorkerThreads.Worker(new URL(url));
|
|
121
|
+
worker.once('message', (message) => {
|
|
122
|
+
if (message === 'workerReady') {
|
|
123
|
+
resolve(worker);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
worker.on('error', reject);
|
|
135
127
|
});
|
|
136
128
|
}
|
|
137
129
|
postMessage(message, transfer) {
|
|
138
130
|
void this.#workerPromise.then(worker => {
|
|
139
131
|
if (!this.#disposed) {
|
|
140
|
-
worker.postMessage(message, transfer
|
|
132
|
+
worker.postMessage(message, transfer);
|
|
141
133
|
}
|
|
142
134
|
});
|
|
143
135
|
}
|
|
@@ -145,7 +137,7 @@ class WebWorker {
|
|
|
145
137
|
this.#disposed = true;
|
|
146
138
|
void this.#workerPromise.then(worker => worker.terminate());
|
|
147
139
|
}
|
|
148
|
-
terminate(immediately
|
|
140
|
+
terminate(immediately) {
|
|
149
141
|
if (immediately) {
|
|
150
142
|
this.#rejectWorkerPromise?.(new Error('Worker terminated'));
|
|
151
143
|
}
|
|
@@ -153,20 +145,28 @@ class WebWorker {
|
|
|
153
145
|
}
|
|
154
146
|
set onmessage(listener) {
|
|
155
147
|
void this.#workerPromise.then(worker => {
|
|
156
|
-
worker.
|
|
148
|
+
worker.on('message', (data) => {
|
|
149
|
+
if (!this.#disposed) {
|
|
150
|
+
listener({ data, ports: [] });
|
|
151
|
+
}
|
|
152
|
+
});
|
|
157
153
|
});
|
|
158
154
|
}
|
|
159
155
|
set onerror(listener) {
|
|
160
156
|
void this.#workerPromise.then(worker => {
|
|
161
|
-
worker.
|
|
157
|
+
worker.on('error', (error) => {
|
|
158
|
+
if (!this.#disposed) {
|
|
159
|
+
listener({ type: 'error', ...error });
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
162
|
});
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
165
|
const HOST_RUNTIME$1 = {
|
|
166
166
|
createWorker(url) {
|
|
167
|
-
return new
|
|
167
|
+
return new NodeWorker(url);
|
|
168
168
|
},
|
|
169
|
-
workerScope: new
|
|
169
|
+
workerScope: new NodeWorkerScope(),
|
|
170
170
|
};
|
|
171
171
|
|
|
172
172
|
var HostRuntime = /*#__PURE__*/Object.freeze({
|
|
@@ -176,7 +176,7 @@ var HostRuntime = /*#__PURE__*/Object.freeze({
|
|
|
176
176
|
|
|
177
177
|
// Copyright 2025 The Chromium Authors
|
|
178
178
|
|
|
179
|
-
var
|
|
179
|
+
var node = /*#__PURE__*/Object.freeze({
|
|
180
180
|
__proto__: null,
|
|
181
181
|
HostRuntime: HostRuntime
|
|
182
182
|
});
|
|
@@ -186,12 +186,12 @@ const IS_NODE = typeof process !== 'undefined' && process.versions?.node !== nul
|
|
|
186
186
|
const IS_BROWSER =
|
|
187
187
|
typeof window !== 'undefined' || (typeof self !== 'undefined' && typeof self.postMessage === 'function');
|
|
188
188
|
const HOST_RUNTIME = await (async () => {
|
|
189
|
-
if (IS_NODE) {
|
|
190
|
-
return (await Promise.resolve().then(function () { return node; })).HostRuntime.HOST_RUNTIME;
|
|
191
|
-
}
|
|
192
189
|
if (IS_BROWSER) {
|
|
193
190
|
return (await Promise.resolve().then(function () { return browser; })).HostRuntime.HOST_RUNTIME;
|
|
194
191
|
}
|
|
192
|
+
if (IS_NODE) {
|
|
193
|
+
return (await Promise.resolve().then(function () { return node; })).HostRuntime.HOST_RUNTIME;
|
|
194
|
+
}
|
|
195
195
|
throw new Error('Unknown runtime!');
|
|
196
196
|
})();
|
|
197
197
|
|
|
@@ -3114,16 +3114,10 @@ var ExperimentName;
|
|
|
3114
3114
|
ExperimentName["LIVE_HEAP_PROFILE"] = "live-heap-profile";
|
|
3115
3115
|
ExperimentName["PROTOCOL_MONITOR"] = "protocol-monitor";
|
|
3116
3116
|
ExperimentName["SAMPLING_HEAP_PROFILER_TIMELINE"] = "sampling-heap-profiler-timeline";
|
|
3117
|
-
ExperimentName["SHOW_OPTION_TO_EXPOSE_INTERNALS_IN_HEAP_SNAPSHOT"] = "show-option-to-expose-internals-in-heap-snapshot";
|
|
3118
3117
|
ExperimentName["TIMELINE_INVALIDATION_TRACKING"] = "timeline-invalidation-tracking";
|
|
3119
|
-
ExperimentName["TIMELINE_SHOW_ALL_EVENTS"] = "timeline-show-all-events";
|
|
3120
3118
|
ExperimentName["APCA"] = "apca";
|
|
3121
3119
|
ExperimentName["FONT_EDITOR"] = "font-editor";
|
|
3122
|
-
ExperimentName["FULL_ACCESSIBILITY_TREE"] = "full-accessibility-tree";
|
|
3123
|
-
ExperimentName["EXPERIMENTAL_COOKIE_FEATURES"] = "experimental-cookie-features";
|
|
3124
3120
|
ExperimentName["INSTRUMENTATION_BREAKPOINTS"] = "instrumentation-breakpoints";
|
|
3125
|
-
ExperimentName["AUTHORED_DEPLOYED_GROUPING"] = "authored-deployed-grouping";
|
|
3126
|
-
ExperimentName["JUST_MY_CODE"] = "just-my-code";
|
|
3127
3121
|
ExperimentName["USE_SOURCE_MAP_SCOPES"] = "use-source-map-scopes";
|
|
3128
3122
|
ExperimentName["TIMELINE_DEBUG_MODE"] = "timeline-debug-mode";
|
|
3129
3123
|
ExperimentName["DURABLE_MESSAGES"] = "durable-messages";
|
|
@@ -9113,6 +9107,7 @@ function hsva2rgba(hsva) {
|
|
|
9113
9107
|
}
|
|
9114
9108
|
const EPSILON = 0.01;
|
|
9115
9109
|
const WIDE_RANGE_EPSILON = 1;
|
|
9110
|
+
const STRICT_EPSILON = 1e-4;
|
|
9116
9111
|
function equals(a, b, accuracy = EPSILON) {
|
|
9117
9112
|
if (Array.isArray(a) && Array.isArray(b)) {
|
|
9118
9113
|
if (a.length !== b.length) {
|
|
@@ -9351,7 +9346,7 @@ class LCH {
|
|
|
9351
9346
|
return false;
|
|
9352
9347
|
}
|
|
9353
9348
|
isHuePowerless() {
|
|
9354
|
-
return equals(this.c, 0);
|
|
9349
|
+
return equals(this.c, 0, STRICT_EPSILON);
|
|
9355
9350
|
}
|
|
9356
9351
|
static fromSpec(spec, text) {
|
|
9357
9352
|
const L = parsePercentage(spec[0], [0, 100]) ?? parseNumber(spec[0]);
|
|
@@ -9823,7 +9818,7 @@ class HSL {
|
|
|
9823
9818
|
this.l = clamp(l, { min: 0, max: 1 });
|
|
9824
9819
|
s = equals(this.l, 0) || equals(this.l, 1) ? 0 : s;
|
|
9825
9820
|
this.s = clamp(s, { min: 0, max: 1 });
|
|
9826
|
-
h = equals(this.s, 0) ? 0 : h;
|
|
9821
|
+
h = equals(this.s, 0, STRICT_EPSILON) ? 0 : h;
|
|
9827
9822
|
this.h = normalizeHue(h * 360) / 360;
|
|
9828
9823
|
this.alpha = clamp(alpha ?? null, { min: 0, max: 1 });
|
|
9829
9824
|
this.#authoredText = authoredText;
|