mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-28 10:03:54 +08:00
fix(MCP): 重构MCPClient为后台协程 + AsyncExitStack管理,解决进程退出时的“Attempted to exit cancel scope in a different task”错误
# 变更 ---- - 将所有stdio_client与ClientSession的创建/销毁都放到同一个后台 task 中 - 使用AsyncExitStack托管异步资源,cleanup时在同一task内执行exit_stack.aclose() - 外部只通过事件通知后台task退出,避免跨协程调用cancel-scope异常
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
"""MCP服务管理器"""
|
||||
|
||||
import asyncio
|
||||
import os, json
|
||||
from typing import Dict, Any, List
|
||||
from .MCPClient import MCPClient
|
||||
@@ -94,8 +94,8 @@ class MCPManager:
|
||||
"""
|
||||
for tool in self.tools:
|
||||
if (
|
||||
tool.get("function") != None
|
||||
and tool["function"].get("name") == tool_name
|
||||
tool.get("function") != None
|
||||
and tool["function"].get("name") == tool_name
|
||||
):
|
||||
return True
|
||||
return False
|
||||
@@ -120,12 +120,13 @@ class MCPManager:
|
||||
raise ValueError(f"Tool {tool_name} not found in any MCP server")
|
||||
|
||||
async def cleanup_all(self) -> None:
|
||||
for name, client in self.client.items():
|
||||
"""依次关闭所有 MCPClient,不让异常阻断整体流程。"""
|
||||
for name, client in list(self.client.items()):
|
||||
try:
|
||||
await client.cleanup()
|
||||
self.logger.bind(tag=TAG).info(f"Cleaned up MCP client: {name}")
|
||||
except Exception as e:
|
||||
await asyncio.wait_for(client.cleanup(), timeout=20)
|
||||
self.logger.bind(tag=TAG).info(f"MCP client closed: {name}")
|
||||
except (asyncio.TimeoutError, Exception) as e:
|
||||
self.logger.bind(tag=TAG).error(
|
||||
f"Error cleaning up MCP client {name}: {e}"
|
||||
f"Error closing MCP client {name}: {e}"
|
||||
)
|
||||
self.client.clear()
|
||||
|
||||
Reference in New Issue
Block a user