Skip to content

Commit 0fe2b8a

Browse files
authored
feat: allow configuring tool categories (#454)
This PR introduces a feature to disable some of the MCP server tool categories to tailor it to specific use cases. For example, ``` npx chrome-devtools-mcp@latest --no-category-emulation Disable tools in the emulation category npx chrome-devtools-mcp@latest --no-category-performance Disable tools in the performance category npx chrome-devtools-mcp@latest --no-category-network Disable tools in the network category ```
1 parent 6f24362 commit 0fe2b8a

File tree

16 files changed

+152
-52
lines changed

16 files changed

+152
-52
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,21 @@ The Chrome DevTools MCP server supports the following configuration option:
331331
Additional arguments for Chrome. Only applies when Chrome is launched by chrome-devtools-mcp.
332332
- **Type:** array
333333

334+
- **`--categoryEmulation`**
335+
Set to false to exlcude tools related to emulation.
336+
- **Type:** boolean
337+
- **Default:** `true`
338+
339+
- **`--categoryPerformance`**
340+
Set to false to exlcude tools related to performance.
341+
- **Type:** boolean
342+
- **Default:** `true`
343+
344+
- **`--categoryNetwork`**
345+
Set to false to exlcude tools related to network.
346+
- **Type:** boolean
347+
- **Default:** `true`
348+
334349
<!-- END AUTO GENERATED OPTIONS -->
335350

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

scripts/generate-docs.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {StdioClientTransport} from '@modelcontextprotocol/sdk/client/stdio.js';
1111
import type {Tool} from '@modelcontextprotocol/sdk/types.js';
1212

1313
import {cliOptions} from '../build/src/cli.js';
14-
import {ToolCategories} from '../build/src/tools/categories.js';
14+
import {ToolCategory, labels} from '../build/src/tools/categories.js';
1515

1616
const MCP_SERVER_PATH = 'build/src/index.js';
1717
const OUTPUT_PATH = './docs/tool-reference.md';
@@ -21,7 +21,7 @@ const README_PATH = './README.md';
2121
interface ToolWithAnnotations extends Tool {
2222
annotations?: {
2323
title?: string;
24-
category?: ToolCategories;
24+
category?: typeof ToolCategory;
2525
};
2626
}
2727

@@ -67,7 +67,7 @@ function generateToolsTOC(
6767

6868
for (const category of sortedCategories) {
6969
const categoryTools = categories[category];
70-
const categoryName = category;
70+
const categoryName = labels[category];
7171
toc += `- **${categoryName}** (${categoryTools.length} tools)\n`;
7272

7373
// Sort tools within category for TOC
@@ -209,7 +209,7 @@ async function generateToolDocumentation(): Promise<void> {
209209
});
210210

211211
// Sort categories using the enum order
212-
const categoryOrder = Object.values(ToolCategories);
212+
const categoryOrder = Object.values(ToolCategory);
213213
const sortedCategories = Object.keys(categories).sort((a, b) => {
214214
const aIndex = categoryOrder.indexOf(a);
215215
const bIndex = categoryOrder.indexOf(b);
@@ -223,8 +223,8 @@ async function generateToolDocumentation(): Promise<void> {
223223
// Generate table of contents
224224
for (const category of sortedCategories) {
225225
const categoryTools = categories[category];
226-
const categoryName = category;
227-
const anchorName = category.toLowerCase().replace(/\s+/g, '-');
226+
const categoryName = labels[category];
227+
const anchorName = categoryName.toLowerCase().replace(/\s+/g, '-');
228228
markdown += `- **[${categoryName}](#${anchorName})** (${categoryTools.length} tools)\n`;
229229

230230
// Sort tools within category for TOC
@@ -239,8 +239,9 @@ async function generateToolDocumentation(): Promise<void> {
239239

240240
for (const category of sortedCategories) {
241241
const categoryTools = categories[category];
242+
const categoryName = labels[category];
242243

243-
markdown += `## ${category}\n\n`;
244+
markdown += `## ${categoryName}\n\n`;
244245

245246
// Sort tools within category
246247
categoryTools.sort((a: Tool, b: Tool) => a.name.localeCompare(b.name));

src/cli.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,21 @@ export const cliOptions = {
139139
describe:
140140
'Additional arguments for Chrome. Only applies when Chrome is launched by chrome-devtools-mcp.',
141141
},
142+
categoryEmulation: {
143+
type: 'boolean',
144+
default: true,
145+
describe: 'Set to false to exlcude tools related to emulation.',
146+
},
147+
categoryPerformance: {
148+
type: 'boolean',
149+
default: true,
150+
describe: 'Set to false to exlcude tools related to performance.',
151+
},
152+
categoryNetwork: {
153+
type: 'boolean',
154+
default: true,
155+
describe: 'Set to false to exlcude tools related to network.',
156+
},
142157
} satisfies Record<string, YargsOptions>;
143158

144159
export function parseArguments(version: string, argv = process.argv) {
@@ -185,6 +200,12 @@ export function parseArguments(version: string, argv = process.argv) {
185200
`$0 --chrome-arg='--no-sandbox' --chrome-arg='--disable-setuid-sandbox'`,
186201
'Launch Chrome without sandboxes. Use with caution.',
187202
],
203+
['$0 --no-category-emulation', 'Disable tools in the emulation category'],
204+
[
205+
'$0 --no-category-performance',
206+
'Disable tools in the performance category',
207+
],
208+
['$0 --no-category-network', 'Disable tools in the network category'],
188209
]);
189210

190211
return yargsInstance

src/main.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
type CallToolResult,
2020
SetLevelRequestSchema,
2121
} from './third_party/index.js';
22+
import {ToolCategory} from './tools/categories.js';
2223
import * as consoleTools from './tools/console.js';
2324
import * as emulationTools from './tools/emulation.js';
2425
import * as inputTools from './tools/input.js';
@@ -96,6 +97,24 @@ Avoid sharing sensitive or personal information that you do not want to share wi
9697
const toolMutex = new Mutex();
9798

9899
function registerTool(tool: ToolDefinition): void {
100+
if (
101+
tool.annotations.category === ToolCategory.EMULATION &&
102+
args.categoryEmulation === false
103+
) {
104+
return;
105+
}
106+
if (
107+
tool.annotations.category === ToolCategory.PERFORMANCE &&
108+
args.categoryPerformance === false
109+
) {
110+
return;
111+
}
112+
if (
113+
tool.annotations.category === ToolCategory.NETWORK &&
114+
args.categoryNetwork === false
115+
) {
116+
return;
117+
}
99118
server.registerTool(
100119
tool.name,
101120
{

src/tools/ToolDefinition.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import type {Dialog, ElementHandle, Page} from '../third_party/index.js';
1010
import type {TraceResult} from '../trace-processing/parse.js';
1111
import type {PaginationOptions} from '../utils/types.js';
1212

13-
import type {ToolCategories} from './categories.js';
13+
import type {ToolCategory} from './categories.js';
1414

1515
export interface ToolDefinition<
1616
Schema extends zod.ZodRawShape = zod.ZodRawShape,
@@ -19,7 +19,7 @@ export interface ToolDefinition<
1919
description: string;
2020
annotations: {
2121
title?: string;
22-
category: ToolCategories;
22+
category: ToolCategory;
2323
/**
2424
* If true, the tool does not modify its environment.
2525
*/

src/tools/categories.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,20 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7-
export enum ToolCategories {
8-
INPUT_AUTOMATION = 'Input automation',
9-
NAVIGATION_AUTOMATION = 'Navigation automation',
10-
EMULATION = 'Emulation',
11-
PERFORMANCE = 'Performance',
12-
NETWORK = 'Network',
13-
DEBUGGING = 'Debugging',
7+
export enum ToolCategory {
8+
INPUT = 'input',
9+
NAVIGATION = 'navigation',
10+
EMULATION = 'emulation',
11+
PERFORMANCE = 'performance',
12+
NETWORK = 'network',
13+
DEBUGGING = 'debugging',
1414
}
15+
16+
export const labels = {
17+
[ToolCategory.INPUT]: 'Input automation',
18+
[ToolCategory.NAVIGATION]: 'Navigation automation',
19+
[ToolCategory.EMULATION]: 'Emulation',
20+
[ToolCategory.PERFORMANCE]: 'Performance',
21+
[ToolCategory.NETWORK]: 'Network',
22+
[ToolCategory.DEBUGGING]: 'Debugging',
23+
};

src/tools/console.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import {zod} from '../third_party/index.js';
88
import type {ConsoleMessageType} from '../third_party/index.js';
99

10-
import {ToolCategories} from './categories.js';
10+
import {ToolCategory} from './categories.js';
1111
import {defineTool} from './ToolDefinition.js';
1212

1313
const FILTERABLE_MESSAGE_TYPES: readonly [
@@ -40,7 +40,7 @@ export const listConsoleMessages = defineTool({
4040
description:
4141
'List all console messages for the currently selected page since the last navigation.',
4242
annotations: {
43-
category: ToolCategories.DEBUGGING,
43+
category: ToolCategory.DEBUGGING,
4444
readOnlyHint: true,
4545
},
4646
schema: {
@@ -86,7 +86,7 @@ export const getConsoleMessage = defineTool({
8686
name: 'get_console_message',
8787
description: `Gets a console message by its ID. You can get all messages by calling ${listConsoleMessages.name}.`,
8888
annotations: {
89-
category: ToolCategories.DEBUGGING,
89+
category: ToolCategory.DEBUGGING,
9090
readOnlyHint: true,
9191
},
9292
schema: {

src/tools/emulation.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import {zod, PredefinedNetworkConditions} from '../third_party/index.js';
88

9-
import {ToolCategories} from './categories.js';
9+
import {ToolCategory} from './categories.js';
1010
import {defineTool} from './ToolDefinition.js';
1111

1212
const throttlingOptions: [string, ...string[]] = [
@@ -19,7 +19,7 @@ export const emulateNetwork = defineTool({
1919
name: 'emulate_network',
2020
description: `Emulates network conditions such as throttling or offline mode on the selected page.`,
2121
annotations: {
22-
category: ToolCategories.EMULATION,
22+
category: ToolCategory.EMULATION,
2323
readOnlyHint: false,
2424
},
2525
schema: {
@@ -65,7 +65,7 @@ export const emulateCpu = defineTool({
6565
name: 'emulate_cpu',
6666
description: `Emulates CPU throttling by slowing down the selected page's execution.`,
6767
annotations: {
68-
category: ToolCategories.EMULATION,
68+
category: ToolCategory.EMULATION,
6969
readOnlyHint: false,
7070
},
7171
schema: {

src/tools/input.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ import type {McpContext, TextSnapshotNode} from '../McpContext.js';
88
import {zod} from '../third_party/index.js';
99
import type {ElementHandle} from '../third_party/index.js';
1010

11-
import {ToolCategories} from './categories.js';
11+
import {ToolCategory} from './categories.js';
1212
import {defineTool} from './ToolDefinition.js';
1313

1414
export const click = defineTool({
1515
name: 'click',
1616
description: `Clicks on the provided element`,
1717
annotations: {
18-
category: ToolCategories.INPUT_AUTOMATION,
18+
category: ToolCategory.INPUT,
1919
readOnlyHint: false,
2020
},
2121
schema: {
@@ -54,7 +54,7 @@ export const hover = defineTool({
5454
name: 'hover',
5555
description: `Hover over the provided element`,
5656
annotations: {
57-
category: ToolCategories.INPUT_AUTOMATION,
57+
category: ToolCategory.INPUT,
5858
readOnlyHint: false,
5959
},
6060
schema: {
@@ -138,7 +138,7 @@ export const fill = defineTool({
138138
name: 'fill',
139139
description: `Type text into a input, text area or select an option from a <select> element.`,
140140
annotations: {
141-
category: ToolCategories.INPUT_AUTOMATION,
141+
category: ToolCategory.INPUT,
142142
readOnlyHint: false,
143143
},
144144
schema: {
@@ -166,7 +166,7 @@ export const drag = defineTool({
166166
name: 'drag',
167167
description: `Drag an element onto another element`,
168168
annotations: {
169-
category: ToolCategories.INPUT_AUTOMATION,
169+
category: ToolCategory.INPUT,
170170
readOnlyHint: false,
171171
},
172172
schema: {
@@ -195,7 +195,7 @@ export const fillForm = defineTool({
195195
name: 'fill_form',
196196
description: `Fill out multiple form elements at once`,
197197
annotations: {
198-
category: ToolCategories.INPUT_AUTOMATION,
198+
category: ToolCategory.INPUT,
199199
readOnlyHint: false,
200200
},
201201
schema: {
@@ -227,7 +227,7 @@ export const uploadFile = defineTool({
227227
name: 'upload_file',
228228
description: 'Upload a file through a provided element.',
229229
annotations: {
230-
category: ToolCategories.INPUT_AUTOMATION,
230+
category: ToolCategory.INPUT,
231231
readOnlyHint: false,
232232
},
233233
schema: {

src/tools/network.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import {zod} from '../third_party/index.js';
88
import type {ResourceType} from '../third_party/index.js';
99

10-
import {ToolCategories} from './categories.js';
10+
import {ToolCategory} from './categories.js';
1111
import {defineTool} from './ToolDefinition.js';
1212

1313
const FILTERABLE_RESOURCE_TYPES: readonly [ResourceType, ...ResourceType[]] = [
@@ -36,7 +36,7 @@ export const listNetworkRequests = defineTool({
3636
name: 'list_network_requests',
3737
description: `List all requests for the currently selected page since the last navigation.`,
3838
annotations: {
39-
category: ToolCategories.NETWORK,
39+
category: ToolCategory.NETWORK,
4040
readOnlyHint: true,
4141
},
4242
schema: {
@@ -82,7 +82,7 @@ export const getNetworkRequest = defineTool({
8282
name: 'get_network_request',
8383
description: `Gets a network request by URL. You can get all requests by calling ${listNetworkRequests.name}.`,
8484
annotations: {
85-
category: ToolCategories.NETWORK,
85+
category: ToolCategory.NETWORK,
8686
readOnlyHint: true,
8787
},
8888
schema: {

0 commit comments

Comments
 (0)