brave-mcp 0.1.2 → 0.2.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 +10 -0
- package/build/src/McpContext.js +4 -4
- package/build/src/McpPage.js +3 -0
- package/build/src/McpResponse.js +43 -4
- package/build/src/PageCollector.js +4 -5
- package/build/src/bin/brave-devtools-mcp-cli-options.js +9 -0
- package/build/src/bin/brave-devtools.js +1 -0
- package/build/src/formatters/NetworkFormatter.js +23 -6
- package/build/src/index.js +7 -0
- package/build/src/telemetry/ClearcutLogger.js +15 -8
- package/build/src/telemetry/watchdog/ClearcutSender.js +4 -3
- package/build/src/third_party/devtools-formatter-worker.js +6 -15432
- package/build/src/third_party/index.js +23 -182509
- package/build/src/tools/lighthouse.js +2 -2
- package/build/src/tools/memory.js +2 -1
- package/build/src/tools/pages.js +4 -1
- package/build/src/tools/performance.js +1 -1
- package/build/src/tools/screencast.js +2 -1
- package/build/src/tools/screenshot.js +2 -2
- package/build/src/tools/tools.js +2 -0
- package/build/src/tools/webmcp.js +63 -0
- package/build/src/utils/files.js +4 -0
- package/package.json +3 -3
|
@@ -86,8 +86,8 @@ export const lighthouseAudit = definePageTool({
|
|
|
86
86
|
const report = generateReport(lhr, format);
|
|
87
87
|
const data = encoder.encode(report);
|
|
88
88
|
if (outputDirPath) {
|
|
89
|
-
const reportPath = path.join(outputDirPath, `report
|
|
90
|
-
const { filename } = await context.saveFile(data, reportPath);
|
|
89
|
+
const reportPath = path.join(outputDirPath, `report`);
|
|
90
|
+
const { filename } = await context.saveFile(data, reportPath, `.${format}`);
|
|
91
91
|
reportPaths.push(filename);
|
|
92
92
|
}
|
|
93
93
|
else {
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
import { zod } from '../third_party/index.js';
|
|
7
|
+
import { ensureExtension } from '../utils/files.js';
|
|
7
8
|
import { ToolCategory } from './categories.js';
|
|
8
9
|
import { definePageTool } from './ToolDefinition.js';
|
|
9
10
|
export const takeMemorySnapshot = definePageTool({
|
|
@@ -21,7 +22,7 @@ export const takeMemorySnapshot = definePageTool({
|
|
|
21
22
|
handler: async (request, response, _context) => {
|
|
22
23
|
const page = request.page;
|
|
23
24
|
await page.pptrPage.captureHeapSnapshot({
|
|
24
|
-
path: request.params.filePath,
|
|
25
|
+
path: ensureExtension(request.params.filePath, '.heapsnapshot'),
|
|
25
26
|
});
|
|
26
27
|
response.appendResponseLine(`Heap snapshot saved to ${request.params.filePath}`);
|
|
27
28
|
},
|
package/build/src/tools/pages.js
CHANGED
|
@@ -19,6 +19,7 @@ export const listPages = defineTool(args => {
|
|
|
19
19
|
handler: async (_request, response) => {
|
|
20
20
|
response.setIncludePages(true);
|
|
21
21
|
response.setListInPageTools();
|
|
22
|
+
response.setListWebMcpTools();
|
|
22
23
|
},
|
|
23
24
|
};
|
|
24
25
|
});
|
|
@@ -43,6 +44,7 @@ export const selectPage = defineTool({
|
|
|
43
44
|
context.selectPage(page);
|
|
44
45
|
response.setIncludePages(true);
|
|
45
46
|
response.setListInPageTools();
|
|
47
|
+
response.setListWebMcpTools();
|
|
46
48
|
if (request.params.bringToFront) {
|
|
47
49
|
await page.pptrPage.bringToFront();
|
|
48
50
|
}
|
|
@@ -179,7 +181,7 @@ export const navigatePage = definePageTool({
|
|
|
179
181
|
response.appendResponseLine(`Successfully navigated to ${request.params.url}.`);
|
|
180
182
|
}
|
|
181
183
|
catch (error) {
|
|
182
|
-
response.appendResponseLine(`Unable to navigate in the
|
|
184
|
+
response.appendResponseLine(`Unable to navigate in the selected page: ${error.message}.`);
|
|
183
185
|
}
|
|
184
186
|
break;
|
|
185
187
|
case 'back':
|
|
@@ -227,6 +229,7 @@ export const navigatePage = definePageTool({
|
|
|
227
229
|
}
|
|
228
230
|
response.setIncludePages(true);
|
|
229
231
|
response.setListInPageTools();
|
|
232
|
+
response.setListWebMcpTools();
|
|
230
233
|
},
|
|
231
234
|
});
|
|
232
235
|
export const resizePage = definePageTool({
|
|
@@ -142,7 +142,7 @@ async function stopTracingAndAppendOutput(page, response, context, filePath) {
|
|
|
142
142
|
});
|
|
143
143
|
});
|
|
144
144
|
}
|
|
145
|
-
const file = await context.saveFile(dataToWrite, filePath);
|
|
145
|
+
const file = await context.saveFile(dataToWrite, filePath, filePath.endsWith('.gz') ? '.json.gz' : '.json');
|
|
146
146
|
response.appendResponseLine(`The raw trace data was saved to ${file.filename}.`);
|
|
147
147
|
}
|
|
148
148
|
const result = await parseRawTraceBuffer(traceEventsBuffer);
|
|
@@ -7,6 +7,7 @@ import fs from 'node:fs/promises';
|
|
|
7
7
|
import os from 'node:os';
|
|
8
8
|
import path from 'node:path';
|
|
9
9
|
import { zod } from '../third_party/index.js';
|
|
10
|
+
import { ensureExtension } from '../utils/files.js';
|
|
10
11
|
import { ToolCategory } from './categories.js';
|
|
11
12
|
import { definePageTool } from './ToolDefinition.js';
|
|
12
13
|
async function generateTempFilePath() {
|
|
@@ -33,7 +34,7 @@ export const startScreencast = definePageTool({
|
|
|
33
34
|
return;
|
|
34
35
|
}
|
|
35
36
|
const filePath = request.params.path ?? (await generateTempFilePath());
|
|
36
|
-
const resolvedPath = path.resolve(filePath);
|
|
37
|
+
const resolvedPath = ensureExtension(path.resolve(filePath), '.mp4');
|
|
37
38
|
const page = request.page;
|
|
38
39
|
let recorder;
|
|
39
40
|
try {
|
|
@@ -67,8 +67,8 @@ export const screenshot = definePageTool({
|
|
|
67
67
|
response.appendResponseLine("Took a screenshot of the current page's viewport.");
|
|
68
68
|
}
|
|
69
69
|
if (request.params.filePath) {
|
|
70
|
-
const
|
|
71
|
-
response.appendResponseLine(`Saved screenshot to ${
|
|
70
|
+
const result = await context.saveFile(screenshot, request.params.filePath, `.${format}`);
|
|
71
|
+
response.appendResponseLine(`Saved screenshot to ${result.filename}.`);
|
|
72
72
|
}
|
|
73
73
|
else if (screenshot.length >= 2_000_000) {
|
|
74
74
|
const { filepath } = await context.saveTemporaryFile(screenshot, `screenshot.${request.params.format}`);
|
package/build/src/tools/tools.js
CHANGED
|
@@ -18,6 +18,7 @@ import * as screenshotTools from './screenshot.js';
|
|
|
18
18
|
import * as scriptTools from './script.js';
|
|
19
19
|
import * as slimTools from './slim/tools.js';
|
|
20
20
|
import * as snapshotTools from './snapshot.js';
|
|
21
|
+
import * as webmcpTools from './webmcp.js';
|
|
21
22
|
export const createTools = (args) => {
|
|
22
23
|
const rawTools = args.slim
|
|
23
24
|
? Object.values(slimTools)
|
|
@@ -36,6 +37,7 @@ export const createTools = (args) => {
|
|
|
36
37
|
...Object.values(screenshotTools),
|
|
37
38
|
...Object.values(scriptTools),
|
|
38
39
|
...Object.values(snapshotTools),
|
|
40
|
+
...Object.values(webmcpTools),
|
|
39
41
|
];
|
|
40
42
|
const tools = [];
|
|
41
43
|
for (const tool of rawTools) {
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { zod } from '../third_party/index.js';
|
|
7
|
+
import { ToolCategory } from './categories.js';
|
|
8
|
+
import { definePageTool } from './ToolDefinition.js';
|
|
9
|
+
export const listWebMcpTools = definePageTool({
|
|
10
|
+
name: 'list_webmcp_tools',
|
|
11
|
+
description: `Lists all WebMCP tools the page exposes.`,
|
|
12
|
+
annotations: {
|
|
13
|
+
category: ToolCategory.DEBUGGING,
|
|
14
|
+
readOnlyHint: true,
|
|
15
|
+
conditions: ['experimentalWebmcp'],
|
|
16
|
+
},
|
|
17
|
+
schema: {},
|
|
18
|
+
handler: async (_request, response, _context) => {
|
|
19
|
+
response.setListWebMcpTools();
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
export const executeWebMcpTool = definePageTool({
|
|
23
|
+
name: 'execute_webmcp_tool',
|
|
24
|
+
description: `Executes a WebMCP tool exposed by the page.`,
|
|
25
|
+
annotations: {
|
|
26
|
+
category: ToolCategory.DEBUGGING,
|
|
27
|
+
readOnlyHint: false,
|
|
28
|
+
conditions: ['experimentalWebmcp'],
|
|
29
|
+
},
|
|
30
|
+
schema: {
|
|
31
|
+
toolName: zod.string().describe('The name of the WebMCP tool to execute'),
|
|
32
|
+
input: zod
|
|
33
|
+
.string()
|
|
34
|
+
.optional()
|
|
35
|
+
.describe('The JSON-stringified parameters to pass to the WebMCP tool'),
|
|
36
|
+
},
|
|
37
|
+
handler: async (request, response) => {
|
|
38
|
+
const toolName = request.params.toolName;
|
|
39
|
+
let input = {};
|
|
40
|
+
if (request.params.input) {
|
|
41
|
+
try {
|
|
42
|
+
const parsed = JSON.parse(request.params.input);
|
|
43
|
+
if (typeof parsed === 'object' && parsed !== null) {
|
|
44
|
+
input = parsed;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
throw new Error('Parsed input is not an object');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch (e) {
|
|
51
|
+
const errorMessage = e instanceof Error ? e.message : String(e);
|
|
52
|
+
throw new Error(`Failed to parse input as JSON: ${errorMessage}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const tools = request.page.pptrPage.webmcp.tools();
|
|
56
|
+
const tool = tools.find(t => t.name === toolName);
|
|
57
|
+
if (!tool) {
|
|
58
|
+
throw new Error(`Tool ${toolName} not found`);
|
|
59
|
+
}
|
|
60
|
+
const { status, output, errorText } = await tool.execute(input);
|
|
61
|
+
response.appendResponseLine(JSON.stringify({ status, output, errorText }, null, 2));
|
|
62
|
+
},
|
|
63
|
+
});
|
package/build/src/utils/files.js
CHANGED
|
@@ -17,3 +17,7 @@ export async function saveTemporaryFile(data, filename) {
|
|
|
17
17
|
throw new Error('Could not save a file', { cause: err });
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
|
+
export function ensureExtension(filepath, extension) {
|
|
21
|
+
const ext = path.extname(filepath);
|
|
22
|
+
return filepath.slice(0, filepath.length - ext.length) + extension;
|
|
23
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brave-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "MCP server for Brave 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.1613625",
|
|
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.1.0",
|
|
73
73
|
"prettier": "^3.6.2",
|
|
74
|
-
"puppeteer": "24.
|
|
74
|
+
"puppeteer": "24.41.0",
|
|
75
75
|
"rollup": "4.60.1",
|
|
76
76
|
"rollup-plugin-cleanup": "^3.2.1",
|
|
77
77
|
"rollup-plugin-license": "^3.6.0",
|