@@ -16,10 +16,22 @@ import { DOC_SEARCH_TOOL } from './tools/doc-search';
1616import { FIND_EXAMPLE_TOOL } from './tools/examples' ;
1717import { MODERNIZE_TOOL } from './tools/modernize' ;
1818import { LIST_PROJECTS_TOOL } from './tools/projects' ;
19- import { McpToolDeclaration , registerTools } from './tools/tool-registry' ;
19+ import { AnyMcpToolDeclaration , registerTools } from './tools/tool-registry' ;
20+
21+ /**
22+ * The set of tools that are enabled by default for the MCP server.
23+ * These tools are considered stable and suitable for general use.
24+ */
25+ const STABLE_TOOLS = [ BEST_PRACTICES_TOOL , DOC_SEARCH_TOOL , LIST_PROJECTS_TOOL ] as const ;
26+
27+ /**
28+ * The set of tools that are available but not enabled by default.
29+ * These tools are considered experimental and may have limitations.
30+ */
31+ const EXPERIMENTAL_TOOLS = [ FIND_EXAMPLE_TOOL , MODERNIZE_TOOL ] as const ;
2032
2133export async function createMcpServer (
22- context : {
34+ options : {
2335 workspace ?: AngularWorkspace ;
2436 readOnly ?: boolean ;
2537 localOnly ?: boolean ;
@@ -46,51 +58,61 @@ export async function createMcpServer(
4658
4759 registerInstructionsResource ( server ) ;
4860
49- // eslint-disable-next-line @typescript-eslint/no-explicit-any
50- let toolDeclarations : McpToolDeclaration < any , any > [ ] = [
51- BEST_PRACTICES_TOOL ,
52- DOC_SEARCH_TOOL ,
53- LIST_PROJECTS_TOOL ,
54- ] ;
55- const experimentalToolDeclarations = [ FIND_EXAMPLE_TOOL , MODERNIZE_TOOL ] ;
61+ const toolDeclarations = assembleToolDeclarations ( STABLE_TOOLS , EXPERIMENTAL_TOOLS , {
62+ ...options ,
63+ logger,
64+ } ) ;
5665
57- if ( context . readOnly ) {
66+ await registerTools (
67+ server ,
68+ {
69+ workspace : options . workspace ,
70+ logger,
71+ exampleDatabasePath : path . join ( __dirname , '../../../lib/code-examples.db' ) ,
72+ } ,
73+ toolDeclarations ,
74+ ) ;
75+
76+ return server ;
77+ }
78+
79+ export function assembleToolDeclarations (
80+ stableDeclarations : readonly AnyMcpToolDeclaration [ ] ,
81+ experimentalDeclarations : readonly AnyMcpToolDeclaration [ ] ,
82+ options : {
83+ readOnly ?: boolean ;
84+ localOnly ?: boolean ;
85+ experimentalTools ?: string [ ] ;
86+ logger : { warn ( text : string ) : void } ;
87+ } ,
88+ ) : AnyMcpToolDeclaration [ ] {
89+ let toolDeclarations = [ ...stableDeclarations ] ;
90+
91+ if ( options . readOnly ) {
5892 toolDeclarations = toolDeclarations . filter ( ( tool ) => tool . isReadOnly ) ;
5993 }
6094
61- if ( context . localOnly ) {
95+ if ( options . localOnly ) {
6296 toolDeclarations = toolDeclarations . filter ( ( tool ) => tool . isLocalOnly ) ;
6397 }
6498
65- const enabledExperimentalTools = new Set ( context . experimentalTools ) ;
99+ const enabledExperimentalTools = new Set ( options . experimentalTools ) ;
66100 if ( process . env [ 'NG_MCP_CODE_EXAMPLES' ] === '1' ) {
67101 enabledExperimentalTools . add ( 'find_examples' ) ;
68102 }
69103
70104 if ( enabledExperimentalTools . size > 0 ) {
71- const experimentalToolsMap = new Map (
72- experimentalToolDeclarations . map ( ( tool ) => [ tool . name , tool ] ) ,
73- ) ;
105+ const experimentalToolsMap = new Map ( experimentalDeclarations . map ( ( tool ) => [ tool . name , tool ] ) ) ;
74106
75107 for ( const toolName of enabledExperimentalTools ) {
76108 const tool = experimentalToolsMap . get ( toolName ) ;
77109 if ( tool ) {
78110 toolDeclarations . push ( tool ) ;
79111 } else {
80- logger . warn ( `Unknown experimental tool: ${ toolName } ` ) ;
112+ options . logger . warn ( `Unknown experimental tool: ${ toolName } ` ) ;
81113 }
82114 }
83115 }
84116
85- await registerTools (
86- server ,
87- {
88- workspace : context . workspace ,
89- logger,
90- exampleDatabasePath : path . join ( __dirname , '../../../lib/code-examples.db' ) ,
91- } ,
92- toolDeclarations ,
93- ) ;
94-
95- return server ;
117+ return toolDeclarations ;
96118}
0 commit comments