@@ -8,6 +8,8 @@ import { Client } from '@modelcontextprotocol/sdk/client/index.js'
88import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'
99import fs from '../../../shared/fs/fs'
1010import { getLogger } from '../../../shared/logger/logger'
11+ import { tools } from '../../constants'
12+ import { ToolType } from '../toolUtils'
1113
1214export interface McpToolDefinition {
1315 serverName : string
@@ -21,7 +23,7 @@ export class McpManager {
2123 private clients : Map < string , Client > = new Map ( ) // key: serverName, val: MCP client
2224 private mcpTools : McpToolDefinition [ ] = [ ]
2325
24- private constructor ( private configPath : string ) { }
26+ private constructor ( private readonly configPath : string ) { }
2527
2628 public static async create ( configPath : string ) : Promise < McpManager > {
2729 const instance = new McpManager ( configPath )
@@ -79,6 +81,7 @@ export class McpManager {
7981 getLogger ( ) . info ( `Found MCP tool [${ toolDef . toolName } ] from server [${ serverName } ]` )
8082 }
8183 } catch ( err ) {
84+ // Log the error for this server but allow the initialization of others to continue.
8285 getLogger ( ) . error ( `Failed to init server [${ serverName } ]: ${ ( err as Error ) . message } ` )
8386 }
8487 }
@@ -101,4 +104,53 @@ export class McpManager {
101104 public findTool ( toolName : string ) : McpToolDefinition | undefined {
102105 return this . mcpTools . find ( ( t ) => t . toolName === toolName )
103106 }
107+
108+ public static async initMcpManager ( configPath : string ) : Promise < McpManager | undefined > {
109+ try {
110+ const manager = await McpManager . create ( configPath )
111+ const discovered = manager . getAllMcpTools ( )
112+ const builtInNames = new Set < string > ( Object . values ( ToolType ) )
113+ const discoveredNames = new Set ( discovered . map ( ( d ) => d . toolName ) )
114+
115+ for ( const def of discovered ) {
116+ const spec = {
117+ toolSpecification : {
118+ name : def . toolName ,
119+ description : def . description ,
120+ inputSchema : { json : def . inputSchema } ,
121+ } ,
122+ }
123+ const idx = tools . findIndex ( ( t ) => t . toolSpecification ! . name === def . toolName )
124+ if ( idx >= 0 ) {
125+ // replace existing entry
126+ tools [ idx ] = spec
127+ } else {
128+ // append new entry
129+ tools . push ( spec )
130+ }
131+ }
132+
133+ // Prune stale _dynamic_ tools (leave built‑ins intact)
134+ for ( let i = tools . length - 1 ; i >= 0 ; -- i ) {
135+ const name = tools [ i ] . toolSpecification ! . name
136+ if ( ! name || builtInNames . has ( name ) ) {
137+ continue
138+ }
139+ // if it wasn’t rediscovered in new MCP config, remove it
140+ if ( ! discoveredNames . has ( name ) ) {
141+ tools . splice ( i , 1 )
142+ }
143+ }
144+ getLogger ( ) . info ( `MCP: successfully discovered ${ discovered . length } new tools.` )
145+ return manager
146+ } catch ( err ) {
147+ getLogger ( ) . error ( `Failed to init MCP manager: ${ ( err as Error ) . message } ` )
148+ return undefined
149+ }
150+ }
151+
152+ // public async dispose(): Promise<void> {
153+ // this.clients.clear()
154+ // this.mcpTools = []
155+ // }
104156}
0 commit comments