Skip to content

Commit a7eb6f8

Browse files
committed
feat(@angular/cli): add --experimental-tool option to mcp command
This change introduces an `--experimental-tool` flag (with a `-E` alias) to the `ng mcp` command. This flag allows users to enable specific experimental tools by providing their names. Experimental tools are kept separate from the main toolset and are only registered if explicitly enabled via this option. This provides a mechanism for safely developing and testing new tools without exposing them to all users by default.
1 parent 8605249 commit a7eb6f8

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

packages/angular/cli/src/commands/mcp/cli.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,20 @@ export default class McpCommandModule extends CommandModule implements CommandMo
4343
type: 'boolean',
4444
default: false,
4545
describe: 'Only register tools that do not require internet access.',
46+
})
47+
.option('experimental-tool', {
48+
type: 'string',
49+
alias: 'E',
50+
array: true,
51+
describe: 'Enable an experimental tool.',
4652
});
4753
}
4854

49-
async run(options: { readOnly: boolean; localOnly: boolean }): Promise<void> {
55+
async run(options: {
56+
readOnly: boolean;
57+
localOnly: boolean;
58+
experimentalTool: string[] | undefined;
59+
}): Promise<void> {
5060
if (isTTY()) {
5161
this.context.logger.info(INTERACTIVE_MESSAGE);
5262

@@ -58,6 +68,7 @@ export default class McpCommandModule extends CommandModule implements CommandMo
5868
workspace: this.context.workspace,
5969
readOnly: options.readOnly,
6070
localOnly: options.localOnly,
71+
experimentalTools: options.experimentalTool,
6172
},
6273
this.context.logger,
6374
);

packages/angular/cli/src/commands/mcp/mcp-server.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ import { DOC_SEARCH_TOOL } from './tools/doc-search';
1616
import { FIND_EXAMPLE_TOOL } from './tools/examples';
1717
import { MODERNIZE_TOOL } from './tools/modernize';
1818
import { LIST_PROJECTS_TOOL } from './tools/projects';
19-
import { registerTools } from './tools/tool-registry';
19+
import { McpToolDeclaration, registerTools } from './tools/tool-registry';
2020

2121
export async function createMcpServer(
2222
context: {
2323
workspace?: AngularWorkspace;
2424
readOnly?: boolean;
2525
localOnly?: boolean;
26+
experimentalTools?: string[];
2627
},
2728
logger: { warn(text: string): void },
2829
): Promise<McpServer> {
@@ -53,6 +54,9 @@ export async function createMcpServer(
5354
FIND_EXAMPLE_TOOL,
5455
];
5556

57+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
58+
const experimentalToolDeclarations: McpToolDeclaration<any, any>[] = [];
59+
5660
if (context.readOnly) {
5761
toolDeclarations = toolDeclarations.filter((tool) => tool.isReadOnly);
5862
}
@@ -61,6 +65,21 @@ export async function createMcpServer(
6165
toolDeclarations = toolDeclarations.filter((tool) => tool.isLocalOnly);
6266
}
6367

68+
if (context.experimentalTools?.length) {
69+
const experimentalToolsMap = new Map(
70+
experimentalToolDeclarations.map((tool) => [tool.name, tool]),
71+
);
72+
73+
for (const toolName of context.experimentalTools) {
74+
const tool = experimentalToolsMap.get(toolName);
75+
if (tool) {
76+
toolDeclarations.push(tool);
77+
} else {
78+
logger.warn(`Unknown experimental tool: ${toolName}`);
79+
}
80+
}
81+
}
82+
6483
await registerTools(
6584
server,
6685
{

0 commit comments

Comments
 (0)