|
9 | 9 | import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
10 | 10 | import { readFile } from 'node:fs/promises';
|
11 | 11 | import path from 'node:path';
|
12 |
| -import { z } from 'zod'; |
13 | 12 | import type { AngularWorkspace } from '../../utilities/config';
|
14 | 13 | import { VERSION } from '../../utilities/version';
|
15 | 14 | import { registerBestPracticesTool } from './tools/best-practices';
|
16 | 15 | import { registerDocSearchTool } from './tools/doc-search';
|
| 16 | +import { registerListProjectsTool } from './tools/projects'; |
17 | 17 |
|
18 | 18 | export async function createMcpServer(context: {
|
19 | 19 | workspace?: AngularWorkspace;
|
@@ -50,88 +50,7 @@ export async function createMcpServer(context: {
|
50 | 50 | );
|
51 | 51 |
|
52 | 52 | registerBestPracticesTool(server);
|
53 |
| - |
54 |
| - server.registerTool( |
55 |
| - 'list_projects', |
56 |
| - { |
57 |
| - title: 'List Angular Projects', |
58 |
| - description: |
59 |
| - 'Lists the names of all applications and libraries defined within an Angular workspace. ' + |
60 |
| - 'It reads the `angular.json` configuration file to identify the projects. ', |
61 |
| - annotations: { |
62 |
| - readOnlyHint: true, |
63 |
| - }, |
64 |
| - outputSchema: { |
65 |
| - projects: z.array( |
66 |
| - z.object({ |
67 |
| - name: z |
68 |
| - .string() |
69 |
| - .describe('The name of the project, as defined in the `angular.json` file.'), |
70 |
| - type: z |
71 |
| - .enum(['application', 'library']) |
72 |
| - .optional() |
73 |
| - .describe(`The type of the project, either 'application' or 'library'.`), |
74 |
| - root: z |
75 |
| - .string() |
76 |
| - .describe('The root directory of the project, relative to the workspace root.'), |
77 |
| - sourceRoot: z |
78 |
| - .string() |
79 |
| - .describe( |
80 |
| - `The root directory of the project's source files, relative to the workspace root.`, |
81 |
| - ), |
82 |
| - selectorPrefix: z |
83 |
| - .string() |
84 |
| - .optional() |
85 |
| - .describe( |
86 |
| - 'The prefix to use for component selectors.' + |
87 |
| - ` For example, a prefix of 'app' would result in selectors like '<app-my-component>'.`, |
88 |
| - ), |
89 |
| - }), |
90 |
| - ), |
91 |
| - }, |
92 |
| - }, |
93 |
| - async () => { |
94 |
| - const { workspace } = context; |
95 |
| - |
96 |
| - if (!workspace) { |
97 |
| - return { |
98 |
| - content: [ |
99 |
| - { |
100 |
| - type: 'text' as const, |
101 |
| - text: |
102 |
| - 'No Angular workspace found.' + |
103 |
| - ' An `angular.json` file, which marks the root of a workspace,' + |
104 |
| - ' could not be located in the current directory or any of its parent directories.', |
105 |
| - }, |
106 |
| - ], |
107 |
| - }; |
108 |
| - } |
109 |
| - |
110 |
| - const projects = []; |
111 |
| - // Convert to output format |
112 |
| - for (const [name, project] of workspace.projects.entries()) { |
113 |
| - projects.push({ |
114 |
| - name, |
115 |
| - type: project.extensions['projectType'] as 'application' | 'library' | undefined, |
116 |
| - root: project.root, |
117 |
| - sourceRoot: project.sourceRoot ?? path.posix.join(project.root, 'src'), |
118 |
| - selectorPrefix: project.extensions['prefix'] as string, |
119 |
| - }); |
120 |
| - } |
121 |
| - |
122 |
| - // The structuredContent field is newer and may not be supported by all hosts. |
123 |
| - // A text representation of the content is also provided for compatibility. |
124 |
| - return { |
125 |
| - content: [ |
126 |
| - { |
127 |
| - type: 'text' as const, |
128 |
| - text: `Projects in the Angular workspace:\n${JSON.stringify(projects)}`, |
129 |
| - }, |
130 |
| - ], |
131 |
| - structuredContent: { projects }, |
132 |
| - }; |
133 |
| - }, |
134 |
| - ); |
| 53 | + registerListProjectsTool(server, context); |
135 | 54 |
|
136 | 55 | await registerDocSearchTool(server);
|
137 | 56 |
|
|
0 commit comments