@@ -8,6 +8,7 @@ import { Client } from '@modelcontextprotocol/sdk/client/index.js'
88import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'
99import type { MCPServerConfig , McpToolDefinition , ListToolsResponse } from './mcpTypes'
1010import { loadMcpServerConfigs } from './mcpUtils'
11+ import { AgenticChatError } from '../../errors'
1112
1213/**
1314 * Manages MCP servers and their tools
@@ -71,8 +72,10 @@ export class McpManager {
7172 * Errors are logged but do not stop discovery of other servers.
7273 */
7374 private async initOneServer ( serverName : string , cfg : MCPServerConfig ) : Promise < void > {
75+ const DEFAULT_SERVER_INIT_TIMEOUT_MS = 60_000
7476 try {
7577 this . features . logging . debug ( `MCP: initializing server [${ serverName } ]` )
78+
7679 const mergedEnv = {
7780 ...( process . env as Record < string , string > ) ,
7881 ...( cfg . env ?? { } ) ,
@@ -86,9 +89,32 @@ export class McpManager {
8689 name : `mcp-client-${ serverName } ` ,
8790 version : '1.0.0' ,
8891 } )
89- await client . connect ( transport )
90- this . clients . set ( serverName , client )
9192
93+ const connectPromise = client . connect ( transport )
94+ const timeoutMs = cfg . initializationTimeout ?? DEFAULT_SERVER_INIT_TIMEOUT_MS
95+ const timeoutPromise = new Promise < never > ( ( _ , reject ) =>
96+ setTimeout (
97+ ( ) =>
98+ reject (
99+ new AgenticChatError (
100+ `MCP: server '${ serverName } ' initialization timed out after ${ timeoutMs } ms` ,
101+ 'MCPServerInitTimeout'
102+ )
103+ ) ,
104+ timeoutMs
105+ )
106+ )
107+
108+ try {
109+ await Promise . race ( [ connectPromise , timeoutPromise ] )
110+ } catch ( err : unknown ) {
111+ if ( err instanceof AgenticChatError && err . code === 'MCPServerInitTimeout' ) {
112+ this . features . logging . error ( err . message )
113+ }
114+ throw err
115+ }
116+
117+ this . clients . set ( serverName , client )
92118 this . mcpTools = this . mcpTools . filter ( t => t . serverName !== serverName )
93119 const resp = ( await client . listTools ( ) ) as ListToolsResponse
94120 for ( const t of resp . tools ) {
@@ -161,6 +187,7 @@ export class McpManager {
161187
162188 const client = this . clients . get ( server )
163189 if ( ! client ) throw new Error ( `MCP: server '${ server } ' not connected` )
190+
164191 return client . callTool ( { name : tool , arguments : args } )
165192 }
166193
@@ -177,6 +204,7 @@ export class McpManager {
177204 command : cfg . command ,
178205 args : cfg . args ,
179206 env : cfg . env ,
207+ initializationTimeout : cfg . initializationTimeout ,
180208 disabled : cfg . disabled ,
181209 autoApprove : cfg . autoApprove ,
182210 toolOverrides : cfg . toolOverrides ,
0 commit comments