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

Commit 25638f0

Browse files
authored
chore: enable dynamic tool definition based on CLI arguments (#1031)
This PR allows tools to be created dynamically based on the provided cli arguments
1 parent b9f65e6 commit 25638f0

File tree

7 files changed

+83
-33
lines changed

7 files changed

+83
-33
lines changed

scripts/generate-docs.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ import type {Tool} from '@modelcontextprotocol/sdk/types.js';
1212
import {get_encoding} from 'tiktoken';
1313

1414
import {cliOptions} from '../build/src/cli.js';
15+
import type {ParsedArguments} from '../build/src/cli.js';
1516
import {ToolCategory, labels} from '../build/src/tools/categories.js';
16-
import {tools as slimTools} from '../build/src/tools/slim/tools.js';
17-
import {tools} from '../build/src/tools/tools.js';
17+
import {createTools} from '../build/src/tools/tools.js';
1818

1919
const OUTPUT_PATH = './docs/tool-reference.md';
2020
const SLIM_OUTPUT_PATH = './docs/slim-tool-reference.md';
@@ -504,7 +504,7 @@ async function generateToolDocumentation(): Promise<void> {
504504

505505
{
506506
const {toolsWithAnnotations, categories, sortedCategories} =
507-
getToolsAndCategories(tools);
507+
getToolsAndCategories(createTools({slim: false} as ParsedArguments));
508508
await generateReference(
509509
'Chrome DevTools MCP Tool Reference',
510510
OUTPUT_PATH,
@@ -521,7 +521,7 @@ async function generateToolDocumentation(): Promise<void> {
521521

522522
{
523523
const {toolsWithAnnotations, categories, sortedCategories} =
524-
getToolsAndCategories(slimTools);
524+
getToolsAndCategories(createTools({slim: true} as ParsedArguments));
525525
await generateReference(
526526
'Chrome DevTools MCP Slim Tool Reference',
527527
SLIM_OUTPUT_PATH,

src/cli.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,8 @@ export const cliOptions = {
243243
},
244244
} satisfies Record<string, YargsOptions>;
245245

246+
export type ParsedArguments = ReturnType<typeof parseArguments>;
247+
246248
export function parseArguments(version: string, argv = process.argv) {
247249
const yargsInstance = yargs(hideBin(argv))
248250
.scriptName('npx chrome-devtools-mcp@latest')

src/main.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,8 @@ import {
2727
SetLevelRequestSchema,
2828
} from './third_party/index.js';
2929
import {ToolCategory} from './tools/categories.js';
30-
import {tools as slimTools} from './tools/slim/tools.js';
3130
import type {ToolDefinition} from './tools/ToolDefinition.js';
32-
import {tools} from './tools/tools.js';
31+
import {createTools} from './tools/tools.js';
3332
import {VERSION} from './version.js';
3433

3534
export const args = parseArguments(VERSION);
@@ -256,7 +255,8 @@ function registerTool(tool: ToolDefinition): void {
256255
);
257256
}
258257

259-
for (const tool of args.slim ? slimTools : tools) {
258+
const tools = createTools(args);
259+
for (const tool of tools) {
260260
registerTool(tool);
261261
}
262262

src/tools/ToolDefinition.ts

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

7+
import type {ParsedArguments} from '../cli.js';
78
import type {TextSnapshotNode, GeolocationOptions} from '../McpContext.js';
89
import {zod} from '../third_party/index.js';
910
import type {
@@ -157,6 +158,20 @@ export type Context = Readonly<{
157158

158159
export function defineTool<Schema extends zod.ZodRawShape>(
159160
definition: ToolDefinition<Schema>,
161+
): ToolDefinition<Schema>;
162+
163+
export function defineTool<
164+
Schema extends zod.ZodRawShape,
165+
Args extends ParsedArguments = ParsedArguments,
166+
>(
167+
definition: (args: Args) => ToolDefinition<Schema>,
168+
): (args: Args) => ToolDefinition<Schema>;
169+
170+
export function defineTool<
171+
Schema extends zod.ZodRawShape,
172+
Args extends ParsedArguments = ParsedArguments,
173+
>(
174+
definition: ToolDefinition<Schema> | ((args: Args) => ToolDefinition<Schema>),
160175
) {
161176
return definition;
162177
}

src/tools/slim/tools.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import type {Dialog} from '../../third_party/index.js';
88
import {zod} from '../../third_party/index.js';
99
import {ToolCategory} from '../categories.js';
10-
import type {ToolDefinition} from '../ToolDefinition.js';
1110
import {defineTool} from '../ToolDefinition.js';
1211

1312
export const screenshot = defineTool({
@@ -86,5 +85,3 @@ export const evaluate = defineTool({
8685
}
8786
},
8887
});
89-
90-
export const tools = [screenshot, evaluate, navigate] as ToolDefinition[];

src/tools/tools.ts

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7+
import type {ParsedArguments} from '../cli.js';
8+
79
import * as consoleTools from './console.js';
810
import * as emulationTools from './emulation.js';
911
import * as extensionTools from './extensions.js';
@@ -15,26 +17,41 @@ import * as performanceTools from './performance.js';
1517
import * as screencastTools from './screencast.js';
1618
import * as screenshotTools from './screenshot.js';
1719
import * as scriptTools from './script.js';
20+
import * as slimTools from './slim/tools.js';
1821
import * as snapshotTools from './snapshot.js';
1922
import type {ToolDefinition} from './ToolDefinition.js';
2023

21-
const tools = [
22-
...Object.values(consoleTools),
23-
...Object.values(emulationTools),
24-
...Object.values(extensionTools),
25-
...Object.values(inputTools),
26-
...Object.values(memoryTools),
27-
...Object.values(networkTools),
28-
...Object.values(pagesTools),
29-
...Object.values(performanceTools),
30-
...Object.values(screencastTools),
31-
...Object.values(screenshotTools),
32-
...Object.values(scriptTools),
33-
...Object.values(snapshotTools),
34-
] as ToolDefinition[];
24+
export const createTools = (args: ParsedArguments) => {
25+
const rawTools = args.slim
26+
? Object.values(slimTools)
27+
: [
28+
...Object.values(consoleTools),
29+
...Object.values(emulationTools),
30+
...Object.values(extensionTools),
31+
...Object.values(inputTools),
32+
...Object.values(memoryTools),
33+
...Object.values(networkTools),
34+
...Object.values(pagesTools),
35+
...Object.values(performanceTools),
36+
...Object.values(screencastTools),
37+
...Object.values(screenshotTools),
38+
...Object.values(scriptTools),
39+
...Object.values(snapshotTools),
40+
];
41+
42+
const tools: ToolDefinition[] = [];
43+
for (const tool of rawTools) {
44+
if (typeof tool === 'function') {
45+
// @ts-expect-error none of the tools for now implement the function type tool has type "never"
46+
tools.push(tool(args) as ToolDefinition);
47+
} else {
48+
tools.push(tool as ToolDefinition);
49+
}
50+
}
3551

36-
tools.sort((a, b) => {
37-
return a.name.localeCompare(b.name);
38-
});
52+
tools.sort((a, b) => {
53+
return a.name.localeCompare(b.name);
54+
});
3955

40-
export {tools};
56+
return tools;
57+
};

tests/index.test.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,16 +92,35 @@ describe('e2e', () => {
9292
const files = fs.readdirSync('build/src/tools');
9393
const definedNames = [];
9494
for (const file of files) {
95-
if (file === 'ToolDefinition.js' || file === 'slim') {
95+
if (
96+
file === 'ToolDefinition.js' ||
97+
file === 'tools.js' ||
98+
file === 'slim'
99+
) {
96100
continue;
97101
}
98102
const fileTools = await import(`../src/tools/${file}`);
99-
for (const maybeTool of Object.values<ToolDefinition>(fileTools)) {
100-
if ('name' in maybeTool) {
101-
if (maybeTool.annotations?.conditions) {
103+
for (const maybeTool of Object.values<unknown>(fileTools)) {
104+
if (typeof maybeTool === 'function') {
105+
const tool = (maybeTool as (val: boolean) => ToolDefinition)(false);
106+
if (tool && typeof tool === 'object' && 'name' in tool) {
107+
if (tool.annotations?.conditions) {
108+
continue;
109+
}
110+
definedNames.push(tool.name);
111+
}
112+
continue;
113+
}
114+
if (
115+
typeof maybeTool === 'object' &&
116+
maybeTool !== null &&
117+
'name' in maybeTool
118+
) {
119+
const tool = maybeTool as ToolDefinition;
120+
if (tool.annotations?.conditions) {
102121
continue;
103122
}
104-
definedNames.push(maybeTool.name);
123+
definedNames.push(tool.name);
105124
}
106125
}
107126
}

0 commit comments

Comments
 (0)