Prechádzať zdrojové kódy

实现mcp集成至tools中

关习习 1 mesiac pred
rodič
commit
37f63a8099
2 zmenil súbory, kde vykonal 112 pridanie a 18 odobranie
  1. 64 1
      mcp_tools.py
  2. 48 17
      tools.py

+ 64 - 1
mcp_tools.py

@@ -11,6 +11,8 @@ class MCPTools:
     def __init__(self, config_file="mcp_config.json"):
         # 从配置文件加载MCP服务配置
         self.mcp_servers = self._load_config(config_file)
+        # 缓存每个服务的工具列表
+        self._tools_cache = {}
 
     def _load_config(self, config_file):
         """
@@ -134,7 +136,7 @@ class MCPTools:
                         "properties": {
                             "method": {
                                 "type": "string",
-                                "description": "要调用的MCP方法,如tools/list, resources/list等"
+                                "description": "要调用的MCP方法,如tools/list, tools/call等"
                             },
                             "params": {
                                 "type": "object",
@@ -148,6 +150,63 @@ class MCPTools:
         
         return tools
 
+    async def get_actual_mcp_tools(self, server_name):
+        """
+        获取指定MCP服务的实际工具列表
+        
+        Args:
+            server_name (str): 服务器名称
+            
+        Returns:
+            list: 实际的工具列表
+        """
+        if server_name not in self.mcp_servers:
+            return []
+            
+        try:
+            result = await self.call_mcp_server(server_name, "tools/list")
+            if isinstance(result, dict) and "tools" in result:
+                return result["tools"]
+            return []
+        except Exception as e:
+            print(f"获取 {server_name} 工具列表时出错: {e}")
+            return []
+
+    def get_all_mcp_tools_sync(self):
+        """
+        同步获取所有MCP服务的实际工具列表
+        
+        Returns:
+            list: 所有MCP服务的工具列表
+        """
+        all_tools = []
+        for server_name in self.mcp_servers.keys():
+            try:
+                tools = asyncio.run(self.get_actual_mcp_tools(server_name))
+                # 缓存工具列表及对应的服务器名称
+                self._tools_cache[server_name] = tools
+                all_tools.extend(tools)
+            except Exception as e:
+                print(f"获取 {server_name} 工具列表时出错: {e}")
+        return all_tools
+
+    def get_server_for_tool(self, tool_name):
+        """
+        根据工具名称获取对应的服务器名称
+        
+        Args:
+            tool_name (str): 工具名称
+            
+        Returns:
+            str or None: 服务器名称或None
+        """
+        # 遍历缓存的工具列表查找对应的服务器
+        for server_name, tools in self._tools_cache.items():
+            for tool in tools:
+                if tool.get("name") == tool_name:
+                    return server_name
+        return None
+
     def call_mcp_tool(self, tool_name, parameters):
         """
         执行MCP工具调用
@@ -197,6 +256,10 @@ class MCPTools:
             
         try:
             result = await self.call_mcp_server(server_name, "tools/list")
+            # 缓存工具列表
+            if isinstance(result, dict) and "tools" in result:
+                self._tools_cache[server_name] = result["tools"]
+                
             return {
                 "status": "success",
                 "server": server_name,

+ 48 - 17
tools.py

@@ -26,6 +26,7 @@ class Tools:
         self.mcp_tools = MCPTools()
 
     def get_tool_list(self):
+        # 基础工具
         tools = [
             {
                 "type": "function",
@@ -37,8 +38,23 @@ class Tools:
             }
         ]
 
-        # 添加MCP工具
-        tools.extend(self.mcp_tools.get_mcp_tool_list())
+        # 获取所有MCP服务的实际工具
+        mcp_tools = self.mcp_tools.get_all_mcp_tools_sync()
+        
+        # 为每个MCP工具创建独立的工具定义
+        for tool in mcp_tools:
+            tools.append({
+                "type": "function",
+                "function": {
+                    "name": tool.get("name", "unknown_tool"),
+                    "description": tool.get("description", "未知工具"),
+                    "parameters": tool.get("inputSchema", {
+                        "type": "object",
+                        "properties": {},
+                        "required": []
+                    })
+                }
+            })
         
         return tools
 
@@ -61,21 +77,36 @@ class Tools:
                 return f"读取网页错误: {str(e)}"
         
         # 处理MCP工具
-        elif tool_name.endswith("_mcp"):
-            result = self.mcp_tools.call_mcp_tool(tool_name, parameters)
-            # 解析结果并检查是否有错误
-            try:
-                result_dict = json.loads(result)
-                if "error" in result_dict:
-                    error_msg = result_dict['error']
-                    # 提供更详细的错误信息和建议
-                    if "unhandled errors in a TaskGroup" in error_msg:
-                        server_name = tool_name[5:-4]  # 提取服务名
-                        return f"MCP调用错误: {server_name}服务内部出现未处理的异常。这通常表示服务端存在问题。错误详情: {error_msg}"
-                    return f"MCP调用错误: {error_msg}"
-            except json.JSONDecodeError:
-                pass  # 如果不是JSON格式,直接返回原始结果
-            return result
+        else:
+            # 根据工具名称确定所属的MCP服务
+            server_name = self.mcp_tools.get_server_for_tool(tool_name)
+            if server_name:
+                # 构造正确的MCP调用参数
+                mcp_params = {
+                    "method": "tools/call",
+                    "params": {
+                        "name": tool_name,
+                        "arguments": parameters
+                    }
+                }
+                
+                mcp_tool_name = f"call_{server_name}_mcp"
+                result = self.mcp_tools.call_mcp_tool(mcp_tool_name, mcp_params)
+                
+                # 解析结果并检查是否有错误
+                try:
+                    result_dict = json.loads(result)
+                    if "error" in result_dict:
+                        error_msg = result_dict['error']
+                        # 提供更详细的错误信息和建议
+                        if "unhandled errors in a TaskGroup" in error_msg:
+                            return f"MCP调用错误: {server_name}服务内部出现未处理的异常。这通常表示服务端存在问题。错误详情: {error_msg}"
+                        return f"MCP调用错误: {error_msg}"
+                except json.JSONDecodeError:
+                    pass  # 如果不是JSON格式,直接返回原始结果
+                return result
+            else:
+                return f"未知工具: {tool_name}"
 
         return f"工具 {tool_name} 执行完成"