mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-26 09:03:54 +08:00
update:统一工具注册及调用
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
"""服务端MCP工具模块"""
|
||||
|
||||
from .mcp_manager import ServerMCPManager
|
||||
from .mcp_executor import ServerMCPExecutor
|
||||
|
||||
__all__ = ["ServerMCPManager", "ServerMCPExecutor"]
|
||||
@@ -0,0 +1,82 @@
|
||||
"""服务端MCP工具执行器"""
|
||||
|
||||
from typing import Dict, Any, Optional
|
||||
from ..base import ToolType, ToolDefinition, ToolResult, ToolExecutor, ToolAction
|
||||
from .mcp_manager import ServerMCPManager
|
||||
|
||||
|
||||
class ServerMCPExecutor(ToolExecutor):
|
||||
"""服务端MCP工具执行器"""
|
||||
|
||||
def __init__(self, conn):
|
||||
self.conn = conn
|
||||
self.mcp_manager: Optional[ServerMCPManager] = None
|
||||
self._initialized = False
|
||||
|
||||
async def initialize(self):
|
||||
"""初始化MCP管理器"""
|
||||
if not self._initialized:
|
||||
self.mcp_manager = ServerMCPManager(self.conn)
|
||||
await self.mcp_manager.initialize_servers()
|
||||
self._initialized = True
|
||||
|
||||
async def execute(
|
||||
self, conn, tool_name: str, arguments: Dict[str, Any]
|
||||
) -> ToolResult:
|
||||
"""执行服务端MCP工具"""
|
||||
if not self._initialized or not self.mcp_manager:
|
||||
return ToolResult(
|
||||
action=ToolAction.ERROR,
|
||||
content="MCP管理器未初始化",
|
||||
error="MCP管理器未初始化",
|
||||
)
|
||||
|
||||
try:
|
||||
# 移除mcp_前缀(如果有)
|
||||
actual_tool_name = tool_name
|
||||
if tool_name.startswith("mcp_"):
|
||||
actual_tool_name = tool_name[4:]
|
||||
|
||||
result = await self.mcp_manager.execute_tool(actual_tool_name, arguments)
|
||||
|
||||
return ToolResult(action=ToolAction.RESPONSE, content=str(result))
|
||||
|
||||
except ValueError as e:
|
||||
return ToolResult(action=ToolAction.NOT_FOUND, content=str(e), error=str(e))
|
||||
except Exception as e:
|
||||
return ToolResult(action=ToolAction.ERROR, content=str(e), error=str(e))
|
||||
|
||||
def get_tools(self) -> Dict[str, ToolDefinition]:
|
||||
"""获取所有服务端MCP工具"""
|
||||
if not self._initialized or not self.mcp_manager:
|
||||
return {}
|
||||
|
||||
tools = {}
|
||||
mcp_tools = self.mcp_manager.get_all_tools()
|
||||
|
||||
for tool in mcp_tools:
|
||||
func_def = tool.get("function", {})
|
||||
tool_name = f"mcp_{func_def.get('name', '')}"
|
||||
|
||||
tools[tool_name] = ToolDefinition(
|
||||
name=tool_name, description=tool, tool_type=ToolType.SERVER_MCP
|
||||
)
|
||||
|
||||
return tools
|
||||
|
||||
def has_tool(self, tool_name: str) -> bool:
|
||||
"""检查是否有指定的服务端MCP工具"""
|
||||
if not self._initialized or not self.mcp_manager:
|
||||
return False
|
||||
|
||||
# 移除mcp_前缀(如果有)
|
||||
actual_tool_name = tool_name
|
||||
if tool_name.startswith("mcp_"):
|
||||
actual_tool_name = tool_name[4:]
|
||||
|
||||
return self.mcp_manager.is_mcp_tool(actual_tool_name)
|
||||
|
||||
async def cleanup(self):
|
||||
"""清理MCP连接"""
|
||||
if self.mcp_manager:
|
||||
await self.mcp_manager.cleanup_all()
|
||||
@@ -0,0 +1,100 @@
|
||||
"""服务端MCP管理器"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import json
|
||||
from typing import Dict, Any, List
|
||||
from config.config_loader import get_project_dir
|
||||
from config.logger import setup_logging
|
||||
|
||||
TAG = __name__
|
||||
logger = setup_logging()
|
||||
|
||||
|
||||
class ServerMCPManager:
|
||||
"""管理多个服务端MCP服务的集中管理器"""
|
||||
|
||||
def __init__(self, conn) -> None:
|
||||
"""初始化MCP管理器"""
|
||||
self.conn = conn
|
||||
self.config_path = get_project_dir() + "data/.mcp_server_settings.json"
|
||||
if not os.path.exists(self.config_path):
|
||||
self.config_path = ""
|
||||
logger.bind(tag=TAG).warning(
|
||||
f"请检查mcp服务配置文件:data/.mcp_server_settings.json"
|
||||
)
|
||||
self.clients: Dict[str, Any] = {}
|
||||
self.tools = []
|
||||
|
||||
def load_config(self) -> Dict[str, Any]:
|
||||
"""加载MCP服务配置"""
|
||||
if len(self.config_path) == 0:
|
||||
return {}
|
||||
|
||||
try:
|
||||
with open(self.config_path, "r", encoding="utf-8") as f:
|
||||
config = json.load(f)
|
||||
return config.get("mcpServers", {})
|
||||
except Exception as e:
|
||||
logger.bind(tag=TAG).error(
|
||||
f"Error loading MCP config from {self.config_path}: {e}"
|
||||
)
|
||||
return {}
|
||||
|
||||
async def initialize_servers(self) -> None:
|
||||
"""初始化所有MCP服务"""
|
||||
config = self.load_config()
|
||||
for name, srv_config in config.items():
|
||||
if not srv_config.get("command") and not srv_config.get("url"):
|
||||
logger.bind(tag=TAG).warning(
|
||||
f"Skipping server {name}: neither command nor url specified"
|
||||
)
|
||||
continue
|
||||
|
||||
try:
|
||||
# 这里可以添加真正的MCP客户端初始化逻辑
|
||||
# 暂时使用简化版本
|
||||
logger.bind(tag=TAG).info(f"初始化服务端MCP客户端: {name}")
|
||||
# client = MCPClient(srv_config)
|
||||
# await client.initialize()
|
||||
# self.clients[name] = client
|
||||
# client_tools = client.get_available_tools()
|
||||
# self.tools.extend(client_tools)
|
||||
|
||||
except Exception as e:
|
||||
logger.bind(tag=TAG).error(
|
||||
f"Failed to initialize MCP server {name}: {e}"
|
||||
)
|
||||
|
||||
def get_all_tools(self) -> List[Dict[str, Any]]:
|
||||
"""获取所有服务的工具function定义"""
|
||||
return self.tools
|
||||
|
||||
def is_mcp_tool(self, tool_name: str) -> bool:
|
||||
"""检查是否是MCP工具"""
|
||||
for tool in self.tools:
|
||||
if (
|
||||
tool.get("function") is not None
|
||||
and tool["function"].get("name") == tool_name
|
||||
):
|
||||
return True
|
||||
return False
|
||||
|
||||
async def execute_tool(self, tool_name: str, arguments: Dict[str, Any]) -> Any:
|
||||
"""执行工具调用"""
|
||||
logger.bind(tag=TAG).info(f"执行服务端MCP工具 {tool_name},参数: {arguments}")
|
||||
|
||||
# 这里可以添加真正的工具执行逻辑
|
||||
# 暂时返回模拟结果
|
||||
return f"服务端MCP工具 {tool_name} 执行结果"
|
||||
|
||||
async def cleanup_all(self) -> None:
|
||||
"""关闭所有 MCP客户端"""
|
||||
for name, client in list(self.clients.items()):
|
||||
try:
|
||||
if hasattr(client, "cleanup"):
|
||||
await asyncio.wait_for(client.cleanup(), timeout=20)
|
||||
logger.bind(tag=TAG).info(f"服务端MCP客户端已关闭: {name}")
|
||||
except (asyncio.TimeoutError, Exception) as e:
|
||||
logger.bind(tag=TAG).error(f"关闭服务端MCP客户端 {name} 时出错: {e}")
|
||||
self.clients.clear()
|
||||
Reference in New Issue
Block a user