forked from angular/angular-cli
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathmcp-server.ts
More file actions
96 lines (85 loc) · 2.89 KB
/
mcp-server.ts
File metadata and controls
96 lines (85 loc) · 2.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import path from 'node:path';
import type { AngularWorkspace } from '../../utilities/config';
import { VERSION } from '../../utilities/version';
import { registerInstructionsResource } from './resources/instructions';
import { BEST_PRACTICES_TOOL } from './tools/best-practices';
import { DOC_SEARCH_TOOL } from './tools/doc-search';
import { FIND_EXAMPLE_TOOL } from './tools/examples';
import { MODERNIZE_TOOL } from './tools/modernize';
import { LIST_PROJECTS_TOOL } from './tools/projects';
import { McpToolDeclaration, registerTools } from './tools/tool-registry';
export async function createMcpServer(
context: {
workspace?: AngularWorkspace;
readOnly?: boolean;
localOnly?: boolean;
experimentalTools?: string[];
},
logger: { warn(text: string): void },
): Promise<McpServer> {
const server = new McpServer(
{
name: 'angular-cli-server',
version: VERSION.full,
},
{
capabilities: {
resources: {},
tools: {},
logging: {},
},
instructions:
'For Angular development, this server provides tools to adhere to best practices, search documentation, and find code examples. ' +
'When writing or modifying Angular code, use the MCP server and its tools instead of direct shell commands where possible.',
},
);
registerInstructionsResource(server);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let toolDeclarations: McpToolDeclaration<any, any>[] = [
BEST_PRACTICES_TOOL,
DOC_SEARCH_TOOL,
LIST_PROJECTS_TOOL,
];
const experimentalToolDeclarations = [FIND_EXAMPLE_TOOL, MODERNIZE_TOOL];
if (context.readOnly) {
toolDeclarations = toolDeclarations.filter((tool) => tool.isReadOnly);
}
if (context.localOnly) {
toolDeclarations = toolDeclarations.filter((tool) => tool.isLocalOnly);
}
const enabledExperimentalTools = new Set(context.experimentalTools);
if (process.env['NG_MCP_CODE_EXAMPLES'] === '1') {
enabledExperimentalTools.add('find_examples');
}
if (enabledExperimentalTools.size > 0) {
const experimentalToolsMap = new Map(
experimentalToolDeclarations.map((tool) => [tool.name, tool]),
);
for (const toolName of enabledExperimentalTools) {
const tool = experimentalToolsMap.get(toolName);
if (tool) {
toolDeclarations.push(tool);
} else {
logger.warn(`Unknown experimental tool: ${toolName}`);
}
}
}
await registerTools(
server,
{
workspace: context.workspace,
logger,
exampleDatabasePath: path.join(__dirname, '../../../lib/code-examples.db'),
},
toolDeclarations,
);
return server;
}