fix: prevent initialized MCP clients from being cleaned up on timeout
- Do not cancel pending tasks on timeout; let them continue running in the background waiting for the termination signal (event.set()), so successfully initialized services remain available - Track initialization state with a flag to distinguish init failures from post-init cancellations in _init_mcp_client_task_wrapper
This commit is contained in:
@@ -234,8 +234,6 @@ class FunctionToolManager:
|
|||||||
"MCP 服务初始化超时(20秒),部分服务可能未完全加载。"
|
"MCP 服务初始化超时(20秒),部分服务可能未完全加载。"
|
||||||
"建议检查 MCP 服务器配置和网络连接。"
|
"建议检查 MCP 服务器配置和网络连接。"
|
||||||
)
|
)
|
||||||
for task in pending:
|
|
||||||
task.cancel()
|
|
||||||
|
|
||||||
success_count = 0
|
success_count = 0
|
||||||
failed_services: list[str] = []
|
failed_services: list[str] = []
|
||||||
@@ -277,17 +275,19 @@ class FunctionToolManager:
|
|||||||
event: asyncio.Event,
|
event: asyncio.Event,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""初始化 MCP 客户端的包装函数,用于捕获异常"""
|
"""初始化 MCP 客户端的包装函数,用于捕获异常"""
|
||||||
|
initialized = False
|
||||||
try:
|
try:
|
||||||
await self._init_mcp_client(name, cfg)
|
await self._init_mcp_client(name, cfg)
|
||||||
tools = await self.mcp_client_dict[name].list_tools_and_save()
|
initialized = True
|
||||||
logger.debug(f"MCP 服务 {name} 初始化完成,工具: {tools}")
|
|
||||||
await event.wait()
|
await event.wait()
|
||||||
logger.info(f"收到 MCP 客户端 {name} 终止信号")
|
logger.info(f"收到 MCP 客户端 {name} 终止信号")
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.error(f"初始化 MCP 客户端 {name} 失败", exc_info=True)
|
if not initialized:
|
||||||
raise
|
# 初始化阶段失败,记录错误并向上抛出让 task.exception() 捕获
|
||||||
|
logger.error(f"初始化 MCP 客户端 {name} 失败", exc_info=True)
|
||||||
|
raise
|
||||||
|
# 初始化已成功,此处异常来自 event.wait() 被取消,属于正常终止流程
|
||||||
finally:
|
finally:
|
||||||
# 无论如何都能清理
|
|
||||||
await self._terminate_mcp_client(name)
|
await self._terminate_mcp_client(name)
|
||||||
|
|
||||||
async def _init_mcp_client(self, name: str, config: dict) -> None:
|
async def _init_mcp_client(self, name: str, config: dict) -> None:
|
||||||
|
|||||||
Reference in New Issue
Block a user