Skip to content

Commit 8890fac

Browse files
committed
feat: Enable dynamic tool definition based on CLI arguments
1 parent b5d01b5 commit 8890fac

5 files changed

Lines changed: 76 additions & 24 deletions

File tree

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: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import {
2929
import {ToolCategory} from './tools/categories.js';
3030
import {tools as slimTools} from './tools/slim/tools.js';
3131
import type {ToolDefinition} from './tools/ToolDefinition.js';
32-
import {tools} from './tools/tools.js';
32+
import {createTools} from './tools/tools.js';
3333

3434
// If moved update release-please config
3535
// x-release-please-start-version
@@ -260,6 +260,7 @@ function registerTool(tool: ToolDefinition): void {
260260
);
261261
}
262262

263+
const tools = createTools(args);
263264
for (const tool of args.slim ? slimTools : tools) {
264265
registerTool(tool);
265266
}

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 {
@@ -166,6 +167,20 @@ export type Context = Readonly<{
166167

167168
export function defineTool<Schema extends zod.ZodRawShape>(
168169
definition: ToolDefinition<Schema>,
170+
): ToolDefinition<Schema>;
171+
172+
export function defineTool<
173+
Schema extends zod.ZodRawShape,
174+
Args extends ParsedArguments = ParsedArguments,
175+
>(
176+
definition: (args: Args) => ToolDefinition<Schema>,
177+
): (args: Args) => ToolDefinition<Schema>;
178+
179+
export function defineTool<
180+
Schema extends zod.ZodRawShape,
181+
Args extends ParsedArguments = ParsedArguments,
182+
>(
183+
definition: ToolDefinition<Schema> | ((args: Args) => ToolDefinition<Schema>),
169184
) {
170185
return definition;
171186
}

src/tools/tools.ts

Lines changed: 33 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';
@@ -18,23 +20,36 @@ import * as scriptTools from './script.js';
1820
import * as snapshotTools from './snapshot.js';
1921
import type {ToolDefinition} from './ToolDefinition.js';
2022

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

36-
tools.sort((a, b) => {
37-
return a.name.localeCompare(b.name);
38-
});
50+
tools.sort((a, b) => {
51+
return a.name.localeCompare(b.name);
52+
});
3953

40-
export {tools};
54+
return tools;
55+
};

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)