Skip to content

Commit ec9f740

Browse files
committed
perf: add timeout and better error handling for MCP initialization
- Add 20-second total timeout to prevent slow MCP servers from blocking startup - Show detailed configuration info when MCP initialization fails - List all failed services in a summary warning - Gracefully handle timeout by using already-completed services This ensures that even if some MCP servers are slow or unreachable, the system will start within a reasonable time and provide clear feedback about which services failed and why.
1 parent 0de7ae8 commit ec9f740

1 file changed

Lines changed: 38 additions & 3 deletions

File tree

astrbot/core/provider/func_tool_manager.py

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,17 +229,52 @@ async def init_mcp_clients(self) -> None:
229229
# 等待所有 MCP 客户端初始化完成(或失败)
230230
if init_futures:
231231
logger.info(f"等待 {len(init_futures)} 个 MCP 服务初始化...")
232-
results = await asyncio.gather(
233-
*init_futures.values(), return_exceptions=True
234-
)
232+
233+
try:
234+
# 设置总超时时间为 20 秒,避免慢速 MCP 服务器阻塞启动过久
235+
results = await asyncio.wait_for(
236+
asyncio.gather(*init_futures.values(), return_exceptions=True),
237+
timeout=20.0,
238+
)
239+
except asyncio.TimeoutError:
240+
logger.warning(
241+
"MCP 服务初始化超时(20秒),部分服务可能未完全加载。"
242+
"建议检查 MCP 服务器配置和网络连接。"
243+
)
244+
# 即使超时也继续,已完成的服务仍然可用
245+
results = []
246+
for name, future in zip(init_futures.keys(), init_futures.values()):
247+
if future.done():
248+
try:
249+
results.append(future.result())
250+
except Exception as e:
251+
results.append(e)
252+
else:
253+
results.append(TimeoutError(f"MCP 服务 {name} 初始化超时"))
235254

236255
success_count = 0
256+
failed_services = []
237257
for name, result in zip(init_futures.keys(), results):
238258
if isinstance(result, Exception):
239259
logger.error(f"MCP 服务 {name} 初始化失败: {result}")
260+
# 显示配置信息以便调试
261+
cfg = mcp_server_json_obj.get(name, {})
262+
if "command" in cfg:
263+
logger.error(f" 命令: {cfg['command']}")
264+
if "args" in cfg:
265+
logger.error(f" 参数: {cfg['args']}")
266+
elif "url" in cfg:
267+
logger.error(f" URL: {cfg['url']}")
268+
failed_services.append(name)
240269
else:
241270
success_count += 1
242271

272+
if failed_services:
273+
logger.warning(
274+
f"以下 MCP 服务初始化失败: {', '.join(failed_services)}。"
275+
f"请检查配置文件 mcp_server.json 和服务器可用性。"
276+
)
277+
243278
logger.info(f"MCP 服务初始化完成: {success_count}/{len(init_futures)} 成功")
244279

245280
async def _init_mcp_client_task_wrapper(

0 commit comments

Comments
 (0)