chrome-devtools-mcp 1.0.1 → 1.1.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 +7 -7
- package/build/src/DevtoolsUtils.js +1 -1
- package/build/src/HeapSnapshotManager.js +16 -16
- package/build/src/McpContext.js +58 -23
- package/build/src/McpResponse.js +1 -1
- package/build/src/bin/chrome-devtools-cli-options.js +55 -49
- package/build/src/bin/chrome-devtools-mcp-main.js +38 -0
- package/build/src/browser.js +36 -2
- package/build/src/daemon/daemon.js +62 -5
- package/build/src/formatters/HeapSnapshotFormatter.js +7 -7
- package/build/src/third_party/THIRD_PARTY_NOTICES +4 -4
- package/build/src/third_party/bundled-packages.json +2 -2
- package/build/src/third_party/devtools-formatter-worker.js +2 -0
- package/build/src/third_party/devtools-heap-snapshot-worker.js +2 -0
- package/build/src/third_party/index.js +197 -75
- package/build/src/tools/ToolDefinition.js +1 -1
- package/build/src/tools/emulation.js +25 -0
- package/build/src/tools/extensions.js +2 -0
- package/build/src/tools/input.js +1 -1
- package/build/src/tools/lighthouse.js +1 -1
- package/build/src/tools/memory.js +19 -21
- package/build/src/tools/network.js +2 -2
- package/build/src/tools/performance.js +9 -6
- package/build/src/tools/screencast.js +1 -1
- package/build/src/tools/screenshot.js +1 -1
- package/build/src/tools/script.js +1 -1
- package/build/src/tools/snapshot.js +1 -1
- package/build/src/trace-processing/parse.js +2 -2
- package/build/src/utils/files.js +43 -0
- package/build/src/version.js +1 -1
- package/package.json +3 -3
|
@@ -30,7 +30,7 @@ export function definePageTool(definition) {
|
|
|
30
30
|
}
|
|
31
31
|
export const CLOSE_PAGE_ERROR = 'The last open page cannot be closed. It is fine to keep it open.';
|
|
32
32
|
export const pageIdSchema = {
|
|
33
|
-
pageId: zod.number().
|
|
33
|
+
pageId: zod.number().describe('Targets a specific page by ID.'),
|
|
34
34
|
};
|
|
35
35
|
export const timeoutSchema = {
|
|
36
36
|
timeout: zod
|
|
@@ -7,6 +7,26 @@
|
|
|
7
7
|
import { zod, PredefinedNetworkConditions } from '../third_party/index.js';
|
|
8
8
|
import { ToolCategory } from './categories.js';
|
|
9
9
|
import { definePageTool, geolocationTransform, viewportTransform, } from './ToolDefinition.js';
|
|
10
|
+
function headerStringTransform(value) {
|
|
11
|
+
if (value === undefined) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
if (value === '') {
|
|
15
|
+
return {};
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
const parsed = JSON.parse(value);
|
|
19
|
+
if (typeof parsed !== 'object' ||
|
|
20
|
+
parsed === null ||
|
|
21
|
+
Array.isArray(parsed)) {
|
|
22
|
+
throw new Error('Headers must be a JSON object');
|
|
23
|
+
}
|
|
24
|
+
return parsed;
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
throw new Error(`Invalid JSON for headers: ${error instanceof Error ? error.message : String(error)}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
10
30
|
const throttlingOptions = [
|
|
11
31
|
'Offline',
|
|
12
32
|
...Object.keys(PredefinedNetworkConditions),
|
|
@@ -47,6 +67,11 @@ export const emulate = definePageTool({
|
|
|
47
67
|
.optional()
|
|
48
68
|
.transform(viewportTransform)
|
|
49
69
|
.describe(`Emulate device viewports '<width>x<height>x<devicePixelRatio>[,mobile][,touch][,landscape]'. 'touch' and 'mobile' to emulate mobile devices. 'landscape' to emulate landscape mode.`),
|
|
70
|
+
extraHttpHeaders: zod
|
|
71
|
+
.string()
|
|
72
|
+
.optional()
|
|
73
|
+
.transform(headerStringTransform)
|
|
74
|
+
.describe('Extra HTTP headers as a JSON string object, e.g. {"X-Custom": "value", "Authorization": "Bearer token"}. Headers are included into every HTTP request originating from the page and persist across navigations until cleared. Pass an empty string to clear all extra headers.'),
|
|
50
75
|
},
|
|
51
76
|
blockedByDialog: true,
|
|
52
77
|
handler: async (request, response, context) => {
|
|
@@ -21,6 +21,7 @@ export const installExtension = defineTool({
|
|
|
21
21
|
blockedByDialog: false,
|
|
22
22
|
handler: async (request, response, context) => {
|
|
23
23
|
const { path } = request.params;
|
|
24
|
+
await context.validatePath(path);
|
|
24
25
|
const id = await context.installExtension(path);
|
|
25
26
|
response.appendResponseLine(`Extension installed. Id: ${id}`);
|
|
26
27
|
},
|
|
@@ -72,6 +73,7 @@ export const reloadExtension = defineTool({
|
|
|
72
73
|
if (!extension) {
|
|
73
74
|
throw new Error(`Extension with ID ${id} not found.`);
|
|
74
75
|
}
|
|
76
|
+
await context.validatePath(extension.path);
|
|
75
77
|
await context.installExtension(extension.path);
|
|
76
78
|
response.appendResponseLine('Extension reloaded.');
|
|
77
79
|
},
|
package/build/src/tools/input.js
CHANGED
|
@@ -393,7 +393,7 @@ export const uploadFile = definePageTool({
|
|
|
393
393
|
blockedByDialog: true,
|
|
394
394
|
handler: async (request, response, context) => {
|
|
395
395
|
const { uid, filePath } = request.params;
|
|
396
|
-
context.validatePath(filePath);
|
|
396
|
+
await context.validatePath(filePath);
|
|
397
397
|
const handle = (await request.page.getElementByUid(uid));
|
|
398
398
|
try {
|
|
399
399
|
try {
|
|
@@ -40,7 +40,7 @@ export const lighthouseAudit = definePageTool({
|
|
|
40
40
|
];
|
|
41
41
|
const formats = ['json', 'html'];
|
|
42
42
|
const { mode = 'navigation', device = 'desktop', outputDirPath, } = request.params;
|
|
43
|
-
context.validatePath(outputDirPath);
|
|
43
|
+
await context.validatePath(outputDirPath);
|
|
44
44
|
const flags = {
|
|
45
45
|
onlyCategories: categories,
|
|
46
46
|
output: formats,
|
|
@@ -7,8 +7,8 @@ import { zod } from '../third_party/index.js';
|
|
|
7
7
|
import { ensureExtension } from '../utils/files.js';
|
|
8
8
|
import { ToolCategory } from './categories.js';
|
|
9
9
|
import { definePageTool, defineTool } from './ToolDefinition.js';
|
|
10
|
-
export const
|
|
11
|
-
name: '
|
|
10
|
+
export const takeHeapSnapshot = definePageTool({
|
|
11
|
+
name: 'take_heapsnapshot',
|
|
12
12
|
description: `Capture a heap snapshot of the currently selected page. Use to analyze the memory distribution of JavaScript objects and debug memory leaks.`,
|
|
13
13
|
annotations: {
|
|
14
14
|
category: ToolCategory.MEMORY,
|
|
@@ -22,15 +22,15 @@ export const takeMemorySnapshot = definePageTool({
|
|
|
22
22
|
blockedByDialog: true,
|
|
23
23
|
handler: async (request, response, context) => {
|
|
24
24
|
const page = request.page;
|
|
25
|
-
context.validatePath(request.params.filePath);
|
|
25
|
+
await context.validatePath(request.params.filePath);
|
|
26
26
|
await page.pptrPage.captureHeapSnapshot({
|
|
27
27
|
path: ensureExtension(request.params.filePath, '.heapsnapshot'),
|
|
28
28
|
});
|
|
29
29
|
response.appendResponseLine(`Heap snapshot saved to ${request.params.filePath}`);
|
|
30
30
|
},
|
|
31
31
|
});
|
|
32
|
-
export const
|
|
33
|
-
name: '
|
|
32
|
+
export const getHeapSnapshotSummary = defineTool({
|
|
33
|
+
name: 'get_heapsnapshot_summary',
|
|
34
34
|
description: 'Loads a memory heapsnapshot and returns snapshot summary stats.',
|
|
35
35
|
annotations: {
|
|
36
36
|
category: ToolCategory.MEMORY,
|
|
@@ -42,14 +42,14 @@ export const exploreMemorySnapshot = defineTool({
|
|
|
42
42
|
},
|
|
43
43
|
blockedByDialog: false,
|
|
44
44
|
handler: async (request, response, context) => {
|
|
45
|
-
context.validatePath(request.params.filePath);
|
|
45
|
+
await context.validatePath(request.params.filePath);
|
|
46
46
|
const stats = await context.getHeapSnapshotStats(request.params.filePath);
|
|
47
47
|
const staticData = await context.getHeapSnapshotStaticData(request.params.filePath);
|
|
48
48
|
response.setHeapSnapshotStats(stats, staticData);
|
|
49
49
|
},
|
|
50
50
|
});
|
|
51
|
-
export const
|
|
52
|
-
name: '
|
|
51
|
+
export const getHeapSnapshotDetails = defineTool({
|
|
52
|
+
name: 'get_heapsnapshot_details',
|
|
53
53
|
description: 'Loads a memory heapsnapshot and returns all available information including statistics, static data, and aggregated node information. Supports pagination for aggregates.',
|
|
54
54
|
annotations: {
|
|
55
55
|
category: ToolCategory.MEMORY,
|
|
@@ -69,7 +69,7 @@ export const getMemorySnapshotDetails = defineTool({
|
|
|
69
69
|
},
|
|
70
70
|
blockedByDialog: false,
|
|
71
71
|
handler: async (request, response, context) => {
|
|
72
|
-
context.validatePath(request.params.filePath);
|
|
72
|
+
await context.validatePath(request.params.filePath);
|
|
73
73
|
const aggregates = await context.getHeapSnapshotAggregates(request.params.filePath);
|
|
74
74
|
response.setHeapSnapshotAggregates(aggregates, {
|
|
75
75
|
pageIdx: request.params.pageIdx,
|
|
@@ -77,9 +77,9 @@ export const getMemorySnapshotDetails = defineTool({
|
|
|
77
77
|
});
|
|
78
78
|
},
|
|
79
79
|
});
|
|
80
|
-
export const
|
|
81
|
-
name: '
|
|
82
|
-
description: 'Loads a memory heapsnapshot and returns instances of a specific class with their
|
|
80
|
+
export const getHeapSnapshotClassNodes = defineTool({
|
|
81
|
+
name: 'get_heapsnapshot_class_nodes',
|
|
82
|
+
description: 'Loads a memory heapsnapshot and returns instances of a specific class with their IDs.',
|
|
83
83
|
annotations: {
|
|
84
84
|
category: ToolCategory.MEMORY,
|
|
85
85
|
readOnlyHint: true,
|
|
@@ -87,24 +87,22 @@ export const getNodesByClass = defineTool({
|
|
|
87
87
|
},
|
|
88
88
|
schema: {
|
|
89
89
|
filePath: zod.string().describe('A path to a .heapsnapshot file to read.'),
|
|
90
|
-
|
|
91
|
-
.number()
|
|
92
|
-
.describe('The unique UID for the class, obtained from aggregates listing.'),
|
|
90
|
+
id: zod.number().describe('The ID for the class, obtained from details.'),
|
|
93
91
|
pageIdx: zod.number().optional().describe('The page index for pagination.'),
|
|
94
92
|
pageSize: zod.number().optional().describe('The page size for pagination.'),
|
|
95
93
|
},
|
|
96
94
|
blockedByDialog: false,
|
|
97
95
|
handler: async (request, response, context) => {
|
|
98
|
-
context.validatePath(request.params.filePath);
|
|
99
|
-
const nodes = await context.
|
|
96
|
+
await context.validatePath(request.params.filePath);
|
|
97
|
+
const nodes = await context.getHeapSnapshotNodesById(request.params.filePath, request.params.id);
|
|
100
98
|
response.setHeapSnapshotNodes(nodes, {
|
|
101
99
|
pageIdx: request.params.pageIdx,
|
|
102
100
|
pageSize: request.params.pageSize,
|
|
103
101
|
});
|
|
104
102
|
},
|
|
105
103
|
});
|
|
106
|
-
export const
|
|
107
|
-
name: '
|
|
104
|
+
export const getHeapSnapshotRetainers = defineTool({
|
|
105
|
+
name: 'get_heapsnapshot_retainers',
|
|
108
106
|
description: 'Loads a memory heapsnapshot and returns retainers for a specific node ID.',
|
|
109
107
|
annotations: {
|
|
110
108
|
category: ToolCategory.MEMORY,
|
|
@@ -114,12 +112,12 @@ export const getNodeRetainers = defineTool({
|
|
|
114
112
|
blockedByDialog: false,
|
|
115
113
|
schema: {
|
|
116
114
|
filePath: zod.string().describe('A path to a .heapsnapshot file to read.'),
|
|
117
|
-
nodeId: zod.number().describe('The
|
|
115
|
+
nodeId: zod.number().describe('The node ID to get retainers for.'),
|
|
118
116
|
pageIdx: zod.number().optional().describe('The page index for pagination.'),
|
|
119
117
|
pageSize: zod.number().optional().describe('The page size for pagination.'),
|
|
120
118
|
},
|
|
121
119
|
handler: async (request, response, context) => {
|
|
122
|
-
context.validatePath(request.params.filePath);
|
|
120
|
+
await context.validatePath(request.params.filePath);
|
|
123
121
|
const retainers = await context.getHeapSnapshotRetainers(request.params.filePath, request.params.nodeId);
|
|
124
122
|
response.setHeapSnapshotNodes(retainers, {
|
|
125
123
|
pageIdx: request.params.pageIdx,
|
|
@@ -96,8 +96,8 @@ export const getNetworkRequest = definePageTool({
|
|
|
96
96
|
},
|
|
97
97
|
blockedByDialog: true,
|
|
98
98
|
handler: async (request, response, context) => {
|
|
99
|
-
context.validatePath(request.params.requestFilePath);
|
|
100
|
-
context.validatePath(request.params.responseFilePath);
|
|
99
|
+
await context.validatePath(request.params.requestFilePath);
|
|
100
|
+
await context.validatePath(request.params.responseFilePath);
|
|
101
101
|
if (request.params.reqid) {
|
|
102
102
|
response.attachNetworkRequest(request.params.reqid, {
|
|
103
103
|
requestFilePath: request.params.requestFilePath,
|
|
@@ -33,7 +33,7 @@ export const startTrace = definePageTool({
|
|
|
33
33
|
},
|
|
34
34
|
blockedByDialog: true,
|
|
35
35
|
handler: async (request, response, context) => {
|
|
36
|
-
context.validatePath(request.params.filePath);
|
|
36
|
+
await context.validatePath(request.params.filePath);
|
|
37
37
|
if (context.isRunningPerformanceTrace()) {
|
|
38
38
|
response.appendResponseLine('Error: a performance trace is already running. Use performance_stop_trace to stop it. Only one trace can be running at any given time.');
|
|
39
39
|
return;
|
|
@@ -78,7 +78,7 @@ export const startTrace = definePageTool({
|
|
|
78
78
|
}
|
|
79
79
|
if (request.params.autoStop) {
|
|
80
80
|
await new Promise(resolve => setTimeout(resolve, 5_000));
|
|
81
|
-
await stopTracingAndAppendOutput(page
|
|
81
|
+
await stopTracingAndAppendOutput(page, response, context, request.params.filePath);
|
|
82
82
|
}
|
|
83
83
|
else {
|
|
84
84
|
response.appendResponseLine(`The performance trace is being recorded. Use performance_stop_trace to stop it.`);
|
|
@@ -97,12 +97,12 @@ export const stopTrace = definePageTool({
|
|
|
97
97
|
},
|
|
98
98
|
blockedByDialog: true,
|
|
99
99
|
handler: async (request, response, context) => {
|
|
100
|
-
context.validatePath(request.params.filePath);
|
|
100
|
+
await context.validatePath(request.params.filePath);
|
|
101
101
|
if (!context.isRunningPerformanceTrace()) {
|
|
102
102
|
return;
|
|
103
103
|
}
|
|
104
104
|
const page = request.page;
|
|
105
|
-
await stopTracingAndAppendOutput(page
|
|
105
|
+
await stopTracingAndAppendOutput(page, response, context, request.params.filePath);
|
|
106
106
|
},
|
|
107
107
|
});
|
|
108
108
|
export const analyzeInsight = definePageTool({
|
|
@@ -132,7 +132,7 @@ export const analyzeInsight = definePageTool({
|
|
|
132
132
|
});
|
|
133
133
|
async function stopTracingAndAppendOutput(page, response, context, filePath) {
|
|
134
134
|
try {
|
|
135
|
-
const traceEventsBuffer = await page.tracing.stop();
|
|
135
|
+
const traceEventsBuffer = await page.pptrPage.tracing.stop();
|
|
136
136
|
if (filePath && traceEventsBuffer) {
|
|
137
137
|
let dataToWrite = traceEventsBuffer;
|
|
138
138
|
if (filePath.endsWith('.gz')) {
|
|
@@ -150,7 +150,10 @@ async function stopTracingAndAppendOutput(page, response, context, filePath) {
|
|
|
150
150
|
const file = await context.saveFile(dataToWrite, filePath, filePath.endsWith('.gz') ? '.json.gz' : '.json');
|
|
151
151
|
response.appendResponseLine(`The raw trace data was saved to ${file.filename}.`);
|
|
152
152
|
}
|
|
153
|
-
const result = await parseRawTraceBuffer(traceEventsBuffer
|
|
153
|
+
const result = await parseRawTraceBuffer(traceEventsBuffer, {
|
|
154
|
+
cpuThrottling: page.cpuThrottlingRate,
|
|
155
|
+
networkThrottling: page.networkConditions ?? undefined,
|
|
156
|
+
});
|
|
154
157
|
response.appendResponseLine('The performance trace has been stopped.');
|
|
155
158
|
if (traceResultIsSuccess(result)) {
|
|
156
159
|
if (context.isCruxEnabled()) {
|
|
@@ -31,7 +31,7 @@ export const startScreencast = definePageTool(args => ({
|
|
|
31
31
|
},
|
|
32
32
|
blockedByDialog: false,
|
|
33
33
|
handler: async (request, response, context) => {
|
|
34
|
-
context.validatePath(request.params.filePath);
|
|
34
|
+
await context.validatePath(request.params.filePath);
|
|
35
35
|
if (context.getScreenRecorder() !== null) {
|
|
36
36
|
response.appendResponseLine('Error: a screencast recording is already in progress. Use screencast_stop to stop it before starting a new one.');
|
|
37
37
|
return;
|
|
@@ -40,7 +40,7 @@ export const screenshot = definePageTool({
|
|
|
40
40
|
},
|
|
41
41
|
blockedByDialog: true,
|
|
42
42
|
handler: async (request, response, context) => {
|
|
43
|
-
context.validatePath(request.params.filePath);
|
|
43
|
+
await context.validatePath(request.params.filePath);
|
|
44
44
|
if (request.params.uid && request.params.fullPage) {
|
|
45
45
|
throw new Error('Providing both "uid" and "fullPage" is not allowed.');
|
|
46
46
|
}
|
|
@@ -53,7 +53,7 @@ Example with arguments: \`(el) => {
|
|
|
53
53
|
blockedByDialog: true,
|
|
54
54
|
handler: async (request, response, context) => {
|
|
55
55
|
const { serviceWorkerId, args: uidArgs, function: fnString, pageId, dialogAction, filePath, } = request.params;
|
|
56
|
-
context.validatePath(filePath);
|
|
56
|
+
await context.validatePath(filePath);
|
|
57
57
|
if (cliArgs?.categoryExtensions && serviceWorkerId) {
|
|
58
58
|
if (uidArgs && uidArgs.length > 0) {
|
|
59
59
|
throw new Error('args (element uids) cannot be used when evaluating in a service worker.');
|
|
@@ -28,7 +28,7 @@ in the DevTools Elements panel (if any).`,
|
|
|
28
28
|
},
|
|
29
29
|
blockedByDialog: true,
|
|
30
30
|
handler: async (request, response, context) => {
|
|
31
|
-
context.validatePath(request.params.filePath);
|
|
31
|
+
await context.validatePath(request.params.filePath);
|
|
32
32
|
response.includeSnapshot({
|
|
33
33
|
verbose: request.params.verbose ?? false,
|
|
34
34
|
filePath: request.params.filePath,
|
|
@@ -9,7 +9,7 @@ const engine = DevTools.TraceEngine.TraceModel.Model.createWithAllHandlers();
|
|
|
9
9
|
export function traceResultIsSuccess(x) {
|
|
10
10
|
return 'parsedTrace' in x;
|
|
11
11
|
}
|
|
12
|
-
export async function parseRawTraceBuffer(buffer) {
|
|
12
|
+
export async function parseRawTraceBuffer(buffer, metadata) {
|
|
13
13
|
engine.resetProcessor();
|
|
14
14
|
if (!buffer) {
|
|
15
15
|
return {
|
|
@@ -25,7 +25,7 @@ export async function parseRawTraceBuffer(buffer) {
|
|
|
25
25
|
try {
|
|
26
26
|
const data = JSON.parse(asString);
|
|
27
27
|
const events = Array.isArray(data) ? data : data.traceEvents;
|
|
28
|
-
await engine.parse(events);
|
|
28
|
+
await engine.parse(events, { metadata });
|
|
29
29
|
const parsedTrace = engine.parsedTrace();
|
|
30
30
|
if (!parsedTrace) {
|
|
31
31
|
return {
|
package/build/src/utils/files.js
CHANGED
|
@@ -15,4 +15,47 @@ export function ensureExtension(filepath, extension) {
|
|
|
15
15
|
const ext = path.extname(filepath);
|
|
16
16
|
return filepath.slice(0, filepath.length - ext.length) + extension;
|
|
17
17
|
}
|
|
18
|
+
export async function resolveCanonicalPath(filePath) {
|
|
19
|
+
const absolutePath = path.resolve(filePath);
|
|
20
|
+
try {
|
|
21
|
+
// Get the true canonical path, resolving all symlinks.
|
|
22
|
+
return await fs.realpath(absolutePath);
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
if (err &&
|
|
26
|
+
typeof err === 'object' &&
|
|
27
|
+
'code' in err &&
|
|
28
|
+
err.code === 'ENOENT') {
|
|
29
|
+
// Find the nearest existing ancestor directory on the filesystem.
|
|
30
|
+
let current = absolutePath;
|
|
31
|
+
const missingSegments = [];
|
|
32
|
+
while (true) {
|
|
33
|
+
const parent = path.dirname(current);
|
|
34
|
+
if (parent === current) {
|
|
35
|
+
// Reached root directory but still couldn't resolve anything.
|
|
36
|
+
throw err;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const canonicalParent = await fs.realpath(parent);
|
|
40
|
+
return path.join(canonicalParent, path.basename(current), ...missingSegments);
|
|
41
|
+
}
|
|
42
|
+
catch (parentErr) {
|
|
43
|
+
if (parentErr &&
|
|
44
|
+
typeof parentErr === 'object' &&
|
|
45
|
+
'code' in parentErr &&
|
|
46
|
+
parentErr.code === 'ENOENT') {
|
|
47
|
+
missingSegments.unshift(path.basename(current));
|
|
48
|
+
current = parent;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
throw parentErr;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
throw err;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
18
61
|
//# sourceMappingURL=files.js.map
|
package/build/src/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chrome-devtools-mcp",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "MCP server for Chrome DevTools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"@types/yargs": "^17.0.33",
|
|
63
63
|
"@typescript-eslint/eslint-plugin": "^8.43.0",
|
|
64
64
|
"@typescript-eslint/parser": "^8.43.0",
|
|
65
|
-
"chrome-devtools-frontend": "1.0.
|
|
65
|
+
"chrome-devtools-frontend": "1.0.1632065",
|
|
66
66
|
"core-js": "3.49.0",
|
|
67
67
|
"debug": "4.4.3",
|
|
68
68
|
"eslint": "^9.35.0",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"globals": "^17.0.0",
|
|
72
72
|
"lighthouse": "13.3.0",
|
|
73
73
|
"prettier": "^3.6.2",
|
|
74
|
-
"puppeteer": "25.0
|
|
74
|
+
"puppeteer": "25.1.0",
|
|
75
75
|
"rollup": "4.60.4",
|
|
76
76
|
"rollup-plugin-cleanup": "^3.2.1",
|
|
77
77
|
"rollup-plugin-license": "^3.6.0",
|