豆豆友情提示:这是一个非官方 GitHub 代理镜像,主要用于网络测试或访问加速。请勿在此进行登录、注册或处理任何敏感信息。进行这些操作请务必访问官方网站 github.com。 Raw 内容也通过此代理提供。
Skip to content

Commit 28b545d

Browse files
committed
feat: --minimal mode with maximum token savings
1 parent 8d765c0 commit 28b545d

File tree

6 files changed

+148
-5
lines changed

6 files changed

+148
-5
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,11 @@ The Chrome DevTools MCP server supports the following configuration option:
525525
- **Type:** boolean
526526
- **Default:** `true`
527527

528+
- **`--minimal`, `-min`**
529+
Minimal set of tools (only 3).
530+
- **Type:** boolean
531+
- **Default:** `false`
532+
528533
<!-- END AUTO GENERATED OPTIONS -->
529534

530535
Pass them via the `args` property in the JSON configuration. For example:

src/MinimalMcpResponse.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* @license
3+
* Copyright 2026 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
import type {
8+
TextContent,
9+
ImageContent,
10+
} from '@modelcontextprotocol/sdk/types.js';
11+
12+
import type {McpContext} from './McpContext.js';
13+
import {McpResponse} from './McpResponse.js';
14+
15+
export class MinimalMcpResponse extends McpResponse {
16+
override async handle(
17+
_toolName: string,
18+
_context: McpContext,
19+
): Promise<{
20+
content: Array<TextContent | ImageContent>;
21+
structuredContent: object;
22+
}> {
23+
const text: TextContent = {
24+
type: 'text',
25+
text: this.responseLines.join('\n'),
26+
};
27+
return {
28+
content: [text],
29+
structuredContent: text,
30+
};
31+
}
32+
}

src/cli.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,11 @@ export const cliOptions = {
231231
hidden: true,
232232
describe: 'Include watchdog PID in Clearcut request headers (for testing).',
233233
},
234+
minimal: {
235+
type: 'boolean',
236+
describe: 'Minimal set of tools (only 3).',
237+
alias: 'min',
238+
},
234239
} satisfies Record<string, YargsOptions>;
235240

236241
export function parseArguments(version: string, argv = process.argv) {
@@ -307,6 +312,7 @@ export function parseArguments(version: string, argv = process.argv) {
307312
'$0 --no-performance-crux',
308313
'Disable CrUX (field data) integration in performance tools.',
309314
],
315+
['$0 --minimal', 'Only 3 tools: navigation, JavaScript and screenshot'],
310316
]);
311317

312318
return yargsInstance

src/main.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {loadIssueDescriptions} from './issue-descriptions.js';
1515
import {logger, saveLogsToFile} from './logger.js';
1616
import {McpContext} from './McpContext.js';
1717
import {McpResponse} from './McpResponse.js';
18+
import {MinimalMcpResponse} from './MinimalMcpResponse.js';
1819
import {Mutex} from './Mutex.js';
1920
import {ClearcutLogger} from './telemetry/ClearcutLogger.js';
2021
import {computeFlagUsage} from './telemetry/flagUtils.js';
@@ -26,6 +27,7 @@ import {
2627
SetLevelRequestSchema,
2728
} from './third_party/index.js';
2829
import {ToolCategory} from './tools/categories.js';
30+
import {tools as minimalTools} from './tools/minimal/tools.js';
2931
import type {ToolDefinition} from './tools/ToolDefinition.js';
3032
import {tools} from './tools/tools.js';
3133

@@ -128,13 +130,13 @@ debug, and modify any data in the browser or DevTools.
128130
Avoid sharing sensitive or personal information that you do not want to share with MCP clients.`,
129131
);
130132

131-
if (args.performanceCrux) {
133+
if (!args.minimal && args.performanceCrux) {
132134
console.error(
133135
`Performance tools may send trace URLs to the Google CrUX API to fetch real-user experience data. To disable, run with --no-performance-crux.`,
134136
);
135137
}
136138

137-
if (args.usageStatistics) {
139+
if (!args.minimal && args.usageStatistics) {
138140
console.error(
139141
`
140142
Google collects usage statistics to improve Chrome DevTools MCP. To opt-out, run with --no-usage-statistics.
@@ -198,7 +200,9 @@ function registerTool(tool: ToolDefinition): void {
198200
const context = await getContext();
199201
logger(`${tool.name} context: resolved`);
200202
await context.detectOpenDevToolsWindows();
201-
const response = new McpResponse();
203+
const response = args.minimal
204+
? new MinimalMcpResponse()
205+
: new McpResponse();
202206
await tool.handler(
203207
{
204208
params,
@@ -250,7 +254,7 @@ function registerTool(tool: ToolDefinition): void {
250254
);
251255
}
252256

253-
for (const tool of tools) {
257+
for (const tool of args.minimal ? minimalTools : tools) {
254258
registerTool(tool);
255259
}
256260

src/tools/minimal/tools.ts

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/**
2+
* @license
3+
* Copyright 2026 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
import type {Dialog} from '../../third_party/index.js';
8+
import {zod} from '../../third_party/index.js';
9+
import {ToolCategory} from '../categories.js';
10+
import type {ToolDefinition} from '../ToolDefinition.js';
11+
import {defineTool} from '../ToolDefinition.js';
12+
13+
export const screenshot = defineTool({
14+
name: 'screenshot',
15+
description: `Take page screenshot`,
16+
annotations: {
17+
category: ToolCategory.DEBUGGING,
18+
// Not read-only due to filePath param.
19+
readOnlyHint: false,
20+
},
21+
schema: {},
22+
handler: async (request, response, context) => {
23+
const page = context.getSelectedPage();
24+
const screenshot = await page.screenshot({
25+
type: 'png',
26+
optimizeForSpeed: true, // Bonus: optimize encoding for speed
27+
});
28+
const {filename} = await context.saveTemporaryFile(screenshot, `image/png`);
29+
response.appendResponseLine(filename);
30+
},
31+
});
32+
33+
export const navigatePage = defineTool({
34+
name: 'navigate',
35+
description: `Load URL in the browser`,
36+
annotations: {
37+
category: ToolCategory.NAVIGATION,
38+
readOnlyHint: false,
39+
},
40+
schema: {
41+
url: zod.string().describe('Page URL'),
42+
},
43+
handler: async (request, response, context) => {
44+
const page = context.getSelectedPage();
45+
const options = {
46+
timeout: 30_000,
47+
};
48+
49+
const dialogHandler = (dialog: Dialog) => {
50+
if (dialog.type() === 'beforeunload') {
51+
response.appendResponseLine(`Accepted a beforeunload dialog.`);
52+
void dialog.accept();
53+
// We are not going to report the dialog like regular dialogs.
54+
context.clearDialog();
55+
}
56+
};
57+
58+
page.on('dialog', dialogHandler);
59+
60+
try {
61+
await page.goto(request.params.url, options);
62+
} finally {
63+
page.off('dialog', dialogHandler);
64+
}
65+
},
66+
});
67+
68+
export const evaluateScript = defineTool({
69+
name: 'evaluate',
70+
description: `Evaluate a JavaScript function`,
71+
annotations: {
72+
category: ToolCategory.DEBUGGING,
73+
readOnlyHint: false,
74+
},
75+
schema: {
76+
fn: zod
77+
.string()
78+
.describe(`A JavaScript function to be executed on the active page`),
79+
},
80+
handler: async (request, response, context) => {
81+
const page = context.getSelectedPage();
82+
const fn = await page.evaluateHandle(`(${request.params.fn})`);
83+
const result = await page.evaluate(async fn => {
84+
// @ts-expect-error no types.
85+
return JSON.stringify(await fn());
86+
}, fn);
87+
response.appendResponseLine(result);
88+
void fn.dispose();
89+
},
90+
});
91+
92+
export const tools = [
93+
screenshot,
94+
evaluateScript,
95+
navigatePage,
96+
] as ToolDefinition[];

tests/index.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ describe('e2e', () => {
9292
const files = fs.readdirSync('build/src/tools');
9393
const definedNames = [];
9494
for (const file of files) {
95-
if (file === 'ToolDefinition.js') {
95+
if (file === 'ToolDefinition.js' || file === 'minimal') {
9696
continue;
9797
}
9898
const fileTools = await import(`../src/tools/${file}`);

0 commit comments

Comments
 (0)