瀏覽代碼

隔离mcp服务,采用api形式调用mcp

关习习 1 月之前
父節點
當前提交
29b2ac05c1
共有 4 個文件被更改,包括 470 次插入367 次删除
  1. 417 0
      mcp_api_server.py
  2. 0 247
      mcp_tools.py
  3. 0 77
      test_mcp_services.py
  4. 53 43
      tools.py

+ 417 - 0
mcp_api_server.py

@@ -0,0 +1,417 @@
+import json
+import subprocess
+import asyncio
+import sys
+from mcp import ClientSession, StdioServerParameters
+from mcp.client.stdio import stdio_client
+from pydantic import BaseModel
+from http.server import HTTPServer, BaseHTTPRequestHandler
+from urllib.parse import urlparse, parse_qs
+
+class MCPServerManager:
+    def __init__(self, config_file="mcp_config.json"):
+        # 从配置文件加载MCP服务配置
+        self.mcp_servers = self._load_config(config_file)
+        # 缓存每个服务的工具列表
+        self._tools_cache = {}
+        # 存储活动的会话
+        self._active_sessions = {}
+
+    def _load_config(self, config_file):
+        """
+        从配置文件加载MCP服务配置
+        
+        Args:
+            config_file (str): 配置文件路径
+            
+        Returns:
+            dict: MCP服务配置
+        """
+        try:
+            # 加载配置文件
+            with open(config_file, 'r', encoding='utf-8') as f:
+                config = json.load(f)
+            return config.get("mcpServers", {})
+        except Exception as e:
+            print(f"加载MCP配置文件时出错: {e}")
+            # 返回空配置
+            return {}
+
+    async def _test_server_command(self, server_name):
+        """
+        测试服务器命令是否可用
+        
+        Args:
+            server_name (str): 服务器名称
+            
+        Returns:
+            bool: 命令是否可用
+        """
+        if server_name not in self.mcp_servers:
+            return False
+
+        server_config = self.mcp_servers[server_name]
+        
+        try:
+            # 检查命令是否存在
+            process = subprocess.Popen([server_config["command"]] + server_config["args"], 
+                                     stdout=subprocess.PIPE, 
+                                     stderr=subprocess.PIPE,
+                                     shell=(sys.platform == 'win32'))
+            # 给进程一点时间启动
+            await asyncio.sleep(0.5)
+            
+            # 检查进程是否仍在运行
+            if process.poll() is None:
+                # 进程仍在运行,终止它
+                process.terminate()
+                try:
+                    process.wait(timeout=1)
+                except subprocess.TimeoutExpired:
+                    process.kill()
+                return True
+            else:
+                # 进程已退出,检查返回码
+                _, stderr = process.communicate()
+                if process.returncode == 0 or process.returncode == 1:
+                    # 返回码为0(成功)或1(一般错误)表示命令存在
+                    return True
+                else:
+                    print(f"命令执行失败 {server_name}: {stderr.decode()}")
+                    return False
+        except FileNotFoundError:
+            print(f"命令未找到: {server_config['command']}")
+            return False
+        except Exception as e:
+            print(f"测试命令时出错 {server_name}: {e}")
+            return False
+
+    async def call_mcp_server(self, server_name, method, params=None):
+        """
+        调用指定的MCP服务器
+        
+        Args:
+            server_name (str): 服务器名称
+            method (str): 要调用的方法
+            params (dict): 方法参数
+            
+        Returns:
+            dict: MCP服务器的响应
+        """
+        if server_name not in self.mcp_servers:
+            return {"error": f"MCP server '{server_name}' not found"}
+
+        # 检查命令是否可用
+        if not await self._test_server_command(server_name):
+            return {"error": f"MCP server '{server_name}' 命令不可用"}
+
+        try:
+            # 创建临时会话(每次调用都创建新会话)
+            server_config = self.mcp_servers[server_name]
+            
+            async with stdio_client(
+                StdioServerParameters(
+                    command=server_config["command"],
+                    args=server_config["args"],
+                    env=None
+                )
+            ) as (read, write):
+                async with ClientSession(read, write) as session:
+                    # 初始化MCP服务器
+                    await session.initialize()
+                    
+                    # 调用指定方法
+                    if method == "prompts/list":
+                        result = await session.list_prompts()
+                    elif method == "prompts/get" and params:
+                        result = await session.get_prompt(params["name"])
+                    elif method == "resources/list":
+                        result = await session.list_resources()
+                    elif method == "resources/read" and params:
+                        result = await session.read_resource(params["uri"])
+                    elif method == "tools/list":
+                        result = await session.list_tools()
+                    elif method == "tools/call" and params:
+                        result = await session.call_tool(params["name"], params.get("arguments", {}))
+                    else:
+                        # 通用方法调用
+                        result = await session.send_request(method, params or {})
+                    
+                    # 将结果转换为可序列化的字典
+                    return self._serialize_result(result)
+        except Exception as e:
+            return {"error": f"调用MCP服务时出错: {str(e)}"}
+
+    def _serialize_result(self, result):
+        """
+        将MCP结果转换为可JSON序列化的格式
+        """
+        if isinstance(result, BaseModel):
+            return result.model_dump()
+        elif isinstance(result, dict):
+            return {key: self._serialize_result(value) for key, value in result.items()}
+        elif isinstance(result, list):
+            return [self._serialize_result(item) for item in result]
+        else:
+            return result
+
+    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:
+                # 缓存工具列表
+                self._tools_cache[server_name] = result["tools"]
+                return result["tools"]
+            return []
+        except Exception as e:
+            print(f"获取 {server_name} 工具列表时出错: {e}")
+            return []
+
+    async def get_all_mcp_tools(self):
+        """
+        获取所有MCP服务的实际工具列表
+        
+        Returns:
+            list: 所有MCP服务的工具列表,每个工具名称后缀添加_mcp
+        """
+        all_tools = []
+        for server_name in self.mcp_servers.keys():
+            try:
+                tools = await self.get_actual_mcp_tools(server_name)
+                # 为每个工具名称添加_mcp后缀以区分
+                for tool in tools:
+                    # 创建工具副本并修改名称
+                    tool_copy = tool.copy()
+                    tool_copy['name'] = f"{tool['name']}_mcp"
+                    all_tools.append(tool_copy)
+            except Exception as e:
+                print(f"获取 {server_name} 工具列表时出错: {e}")
+        return all_tools
+
+    async def call_mcp_tool(self, tool_name, arguments):
+        """
+        执行MCP工具调用
+        
+        Args:
+            tool_name (str): 工具名称(需要以_mcp结尾)
+            arguments (dict): 工具参数
+            
+        Returns:
+            dict: 工具执行结果
+        """
+        try:
+            # 验证工具名称格式
+            if not tool_name.endswith("_mcp"):
+                return {"error": f"无效的工具名称格式: {tool_name}"}
+            
+            # 移除_mcp后缀获取原始工具名称
+            original_tool_name = tool_name[:-4]
+            
+            # 查找工具所属的服务器
+            server_name = self._find_server_for_tool(original_tool_name)
+            if not server_name:
+                return {"error": f"未找到工具 {tool_name} 对应的MCP服务器"}
+            
+            # 调用工具
+            result = await self.call_mcp_server(
+                server_name, 
+                "tools/call", 
+                {
+                    "name": original_tool_name,
+                    "arguments": arguments
+                }
+            )
+            
+            return result
+        except Exception as e:
+            return {"error": f"MCP工具调用失败: {str(e)}"}
+
+    def _find_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
+
+    async def initialize_all_servers(self):
+        """
+        初始化所有MCP服务器并获取工具列表
+        """
+        print("正在测试MCP服务器连接...")
+        for server_name in self.mcp_servers.keys():
+            if await self._test_server_command(server_name):
+                print(f"✓ {server_name} 命令可用")
+            else:
+                print(f"✗ {server_name} 命令不可用")
+
+class MCPAPIHandler(BaseHTTPRequestHandler):
+    """
+    MCP API HTTP请求处理器
+    """
+    
+    # 类变量,用于存储MCPServerManager实例
+    server_manager = None
+    
+    def _set_headers(self, status_code=200, content_type='application/json'):
+        """
+        设置HTTP响应头
+        """
+        self.send_response(status_code)
+        self.send_header('Content-type', content_type)
+        self.send_header('Access-Control-Allow-Origin', '*')
+        self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
+        self.send_header('Access-Control-Allow-Headers', 'Content-Type')
+        self.end_headers()
+    
+    def do_OPTIONS(self):
+        """
+        处理CORS预检请求
+        """
+        self._set_headers()
+    
+    def do_GET(self):
+        """
+        处理GET请求
+        """
+        parsed_path = urlparse(self.path)
+        
+        # 处理 /tools 接口
+        if parsed_path.path == '/tools':
+            self._handle_tools_request()
+        else:
+            self._set_headers(404)
+            self.wfile.write(json.dumps({"error": "未找到接口"}).encode('utf-8'))
+    
+    def do_POST(self):
+        """
+        处理POST请求
+        """
+        parsed_path = urlparse(self.path)
+        
+        # 处理 /call 接口
+        if parsed_path.path == '/call':
+            self._handle_call_request()
+        else:
+            self._set_headers(404)
+            self.wfile.write(json.dumps({"error": "未找到接口"}).encode('utf-8'))
+    
+    def _handle_tools_request(self):
+        """
+        处理 /tools 请求,返回所有MCP工具列表
+        """
+        try:
+            # 在新的事件循环中运行异步代码
+            loop = asyncio.new_event_loop()
+            asyncio.set_event_loop(loop)
+            
+            tools = loop.run_until_complete(
+                self.server_manager.get_all_mcp_tools()
+            )
+            loop.close()
+            
+            self._set_headers()
+            self.wfile.write(json.dumps(tools, ensure_ascii=False).encode('utf-8'))
+        except Exception as e:
+            self._set_headers(500)
+            self.wfile.write(json.dumps({"error": str(e)}).encode('utf-8'))
+    
+    def _handle_call_request(self):
+        """
+        处理 /call 请求,调用指定的MCP工具
+        """
+        try:
+            # 读取请求体
+            content_length = int(self.headers['Content-Length'])
+            post_data = self.rfile.read(content_length)
+            
+            # 解析JSON数据
+            data = json.loads(post_data.decode('utf-8'))
+            
+            # 获取必要参数
+            tool_name = data.get('name')
+            arguments = data.get('arguments', {})
+            
+            if not tool_name:
+                self._set_headers(400)
+                self.wfile.write(json.dumps({"error": "缺少工具名称"}).encode('utf-8'))
+                return
+            
+            # 在新的事件循环中运行异步代码
+            loop = asyncio.new_event_loop()
+            asyncio.set_event_loop(loop)
+            
+            result = loop.run_until_complete(
+                self.server_manager.call_mcp_tool(tool_name, arguments)
+            )
+            loop.close()
+            
+            # 检查是否有错误
+            if isinstance(result, dict) and "error" in result:
+                self._set_headers(500)
+            else:
+                self._set_headers()
+            
+            self.wfile.write(json.dumps(result, ensure_ascii=False).encode('utf-8'))
+        except json.JSONDecodeError:
+            self._set_headers(400)
+            self.wfile.write(json.dumps({"error": "无效的JSON格式"}).encode('utf-8'))
+        except Exception as e:
+            self._set_headers(500)
+            self.wfile.write(json.dumps({"error": str(e)}).encode('utf-8'))
+
+class MCPAPIServer:
+    """
+    MCP API服务器主类
+    """
+    
+    def __init__(self, host='localhost', port=8000, config_file='mcp_config.json'):
+        self.host = host
+        self.port = port
+        self.server_manager = MCPServerManager(config_file)
+        # 将server_manager设置为请求处理器的类变量
+        MCPAPIHandler.server_manager = self.server_manager
+    
+    def start(self):
+        """
+        启动MCP API服务器
+        """
+        # 初始化所有服务器
+        print("正在初始化MCP服务器...")
+        loop = asyncio.new_event_loop()
+        asyncio.set_event_loop(loop)
+        loop.run_until_complete(self.server_manager.initialize_all_servers())
+        loop.close()
+        print("MCP服务器初始化完成")
+        
+        # 启动HTTP服务器
+        server_address = (self.host, self.port)
+        httpd = HTTPServer(server_address, MCPAPIHandler)
+        print(f"启动MCP API服务器: http://{self.host}:{self.port}")
+        httpd.serve_forever()
+
+if __name__ == "__main__":
+    # 创建并启动MCP API服务器
+    api_server = MCPAPIServer()
+    api_server.start()

+ 0 - 247
mcp_tools.py

@@ -1,247 +0,0 @@
-import json
-import subprocess
-import asyncio
-import sys
-import os
-from mcp import ClientSession, StdioServerParameters
-from mcp.client.stdio import stdio_client
-from pydantic import BaseModel
-
-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):
-        """
-        从配置文件加载MCP服务配置
-        
-        Args:
-            config_file (str): 配置文件路径
-            
-        Returns:
-            dict: MCP服务配置
-        """
-        try:
-            # 加载配置文件
-            with open(config_file, 'r', encoding='utf-8') as f:
-                config = json.load(f)
-            return config.get("mcpServers", {})
-        except Exception as e:
-            print(f"加载MCP配置文件时出错: {e}")
-            # 返回空配置
-            return {}
-
-    async def call_mcp_server(self, server_name, method, params=None):
-        """
-        调用指定的MCP服务器
-        
-        Args:
-            server_name (str): 服务器名称
-            method (str): 要调用的方法
-            params (dict): 方法参数
-            
-        Returns:
-            dict: MCP服务器的响应
-        """
-        if server_name not in self.mcp_servers:
-            return {"error": f"MCP server '{server_name}' not found"}
-
-        server_config = self.mcp_servers[server_name]
-        
-        try:
-            # 检查命令是否存在
-            try:
-                process = subprocess.Popen([server_config["command"]] + server_config["args"], 
-                                         stdout=subprocess.PIPE, 
-                                         stderr=subprocess.PIPE,
-                                         shell=(sys.platform == 'win32'))
-                process.terminate()  # 立即终止,只是检查命令是否存在
-            except FileNotFoundError:
-                return {"error": f"命令未找到: {server_config['command']}"}
-            
-            # 检查service_mcp脚本是否存在 (仅当它是配置中的服务时)
-            if server_name == "service_mcp" and server_config.get("args"):
-                script_path = server_config["args"][0] if server_config["args"] else None
-                if script_path and not os.path.exists(script_path):
-                    return {"error": f"Service MCP脚本不存在: {script_path}"}
-            
-            async with stdio_client(
-                StdioServerParameters(
-                    command=server_config["command"],
-                    args=server_config["args"],
-                    env=None
-                )
-            ) as (read, write):
-                async with ClientSession(read, write) as session:
-                    # 初始化MCP服务器
-                    await session.initialize()
-                    
-                    # 调用指定方法
-                    if method == "prompts/list":
-                        result = await session.list_prompts()
-                    elif method == "prompts/get" and params:
-                        result = await session.get_prompt(params["name"])
-                    elif method == "resources/list":
-                        result = await session.list_resources()
-                    elif method == "resources/read" and params:
-                        result = await session.read_resource(params["uri"])
-                    elif method == "tools/list":
-                        result = await session.list_tools()
-                    elif method == "tools/call" and params:
-                        result = await session.call_tool(params["name"], params.get("arguments", {}))
-                    else:
-                        # 通用方法调用
-                        result = await session.send_request(method, params or {})
-                    
-                    # 将结果转换为可序列化的字典
-                    return self._serialize_result(result)
-        except Exception as e:
-            return {"error": f"调用MCP服务时出错: {str(e)}"}
-
-    def _serialize_result(self, result):
-        """
-        将MCP结果转换为可JSON序列化的格式
-        """
-        if isinstance(result, BaseModel):
-            return result.model_dump()
-        elif isinstance(result, dict):
-            return {key: self._serialize_result(value) for key, value in result.items()}
-        elif isinstance(result, list):
-            return [self._serialize_result(item) for item in result]
-        else:
-            return result
-
-    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工具调用
-        
-        Args:
-            tool_name (str): 工具名称
-            parameters (dict): 工具参数
-            
-        Returns:
-            str: 工具执行结果
-        """
-        try:
-            # 从工具名称中提取服务器名称
-            if tool_name.startswith("call_") and tool_name.endswith("_mcp"):
-                server_name = tool_name[5:-4]  # 移除 "call_" 前缀和 "_mcp" 后缀
-            else:
-                return f"未知的MCP工具格式: {tool_name}"
-
-            if server_name not in self.mcp_servers:
-                return f"未配置的MCP服务: {server_name}"
-
-            # 在异步环境中运行
-            result = asyncio.run(
-                self.call_mcp_server(
-                    server_name, 
-                    parameters.get("method", ""), 
-                    parameters.get("params")
-                )
-            )
-            
-            return json.dumps(result, ensure_ascii=False)
-        except Exception as e:
-            return f"MCP工具调用失败: {str(e)}"
-
-    async def test_mcp_connection(self, server_name):
-        """
-        测试MCP服务连接
-        
-        Args:
-            server_name (str): 服务器名称
-            
-        Returns:
-            dict: 测试结果
-        """
-        if server_name not in self.mcp_servers:
-            return {"error": f"MCP server '{server_name}' not found"}
-            
-        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,
-                "tools_available": len(result.get("tools", [])) if isinstance(result, dict) else 0,
-                "result": result
-            }
-        except Exception as e:
-            return {
-                "status": "error",
-                "server": server_name,
-                "error": str(e)
-            }
-            
-    def get_available_servers(self):
-        """
-        获取所有可用的MCP服务器名称
-        
-        Returns:
-            list: 可用的MCP服务器名称列表
-        """
-        return list(self.mcp_servers.keys())

+ 0 - 77
test_mcp_services.py

@@ -1,77 +0,0 @@
-import asyncio
-from mcp_tools import MCPTools
-
-async def test_all_mcp_services():
-    """
-    测试所有配置的MCP服务
-    """
-    print("开始测试MCP服务...")
-    print("=" * 50)
-    
-    # 初始化MCP工具
-    mcp_tools = MCPTools()
-    
-    # 获取所有配置的服务器
-    servers = mcp_tools.get_available_servers()
-    
-    if not servers:
-        print("未找到任何配置的MCP服务")
-        return
-    
-    print(f"找到 {len(servers)} 个MCP服务: {', '.join(servers)}")
-    print()
-    
-    # 测试每个服务器
-    results = []
-    for server_name in servers:
-        print(f"正在测试服务: {server_name}")
-        try:
-            result = await mcp_tools.test_mcp_connection(server_name)
-            results.append(result)
-            
-            if result.get("status") == "success":
-                tools_count = result.get("tools_available", 0)
-                print(f"  ✓ 连接成功 - 可用工具数: {tools_count}")
-            else:
-                print(f"  ✗ 连接失败 - 错误: {result.get('error', '未知错误')}")
-        except Exception as e:
-            error_result = {
-                "status": "error",
-                "server": server_name,
-                "error": str(e)
-            }
-            results.append(error_result)
-            print(f"  ✗ 测试异常 - 错误: {str(e)}")
-        print()
-    
-    # 输出汇总结果
-    print("=" * 50)
-    print("测试结果汇总:")
-    success_count = sum(1 for r in results if r.get("status") == "success")
-    print(f"总服务数: {len(servers)}")
-    print(f"成功连接: {success_count}")
-    print(f"连接失败: {len(servers) - success_count}")
-    
-    # 详细结果
-    print("\n详细结果:")
-    for result in results:
-        server = result.get("server", "未知")
-        status = result.get("status", "未知")
-        if status == "success":
-            print(f"  {server}: ✓ 成功")
-        else:
-            print(f"  {server}: ✗ 失败 - {result.get('error', '未知错误')}")
-def main():
-    """
-    主函数
-    """
-    try:
-        asyncio.run(test_all_mcp_services())
-    except KeyboardInterrupt:
-        print("\n测试被用户中断")
-    except Exception as e:
-        print(f"测试过程中发生错误: {e}")
-
-
-if __name__ == "__main__":
-    main()

+ 53 - 43
tools.py

@@ -1,8 +1,8 @@
 import json
 import urllib.request
 import urllib.parse
+import urllib.error
 from html.parser import HTMLParser
-from mcp_tools import MCPTools
 
 class MLStripper(HTMLParser):
     def __init__(self):
@@ -22,8 +22,8 @@ def strip_tags(html):
     return s.get_data()
 
 class Tools:
-    def __init__(self):
-        self.mcp_tools = MCPTools()
+    def __init__(self, mcp_api_url="http://localhost:8000"):
+        self.mcp_api_url = mcp_api_url
 
     def get_tool_list(self):
         # 基础工具
@@ -39,22 +39,27 @@ class Tools:
         ]
 
         # 获取所有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": []
-                    })
-                }
-            })
+        try:
+            req = urllib.request.Request(f"{self.mcp_api_url}/tools")
+            with urllib.request.urlopen(req) as response:
+                mcp_tools = json.loads(response.read().decode('utf-8'))
+            
+            # 为每个MCP工具创建独立的工具定义
+            for tool in mcp_tools:
+                tools.append({
+                    "type": "function",
+                    "function": {
+                        "name": tool.get("name"),  # 工具名称已经带有_mcp后缀
+                        "description": tool.get("description", "未知工具"),
+                        "parameters": tool.get("inputSchema", {
+                            "type": "object",
+                            "properties": {},
+                            "required": []
+                        })
+                    }
+                })
+        except Exception as e:
+            print(f"获取MCP工具列表时出错: {e}")
         
         return tools
 
@@ -77,33 +82,38 @@ class Tools:
                 return f"读取网页错误: {str(e)}"
         
         # 处理MCP工具
-        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
-                    }
+        elif tool_name.endswith("_mcp"):
+            # 调用MCP API服务器
+            try:
+                # 构造请求数据
+                data = {
+                    "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)
+                # 发送POST请求到MCP API服务器
+                req = urllib.request.Request(
+                    f"{self.mcp_api_url}/call",
+                    data=json.dumps(data).encode('utf-8'),
+                    headers={'Content-Type': 'application/json'}
+                )
+                
+                with urllib.request.urlopen(req) as response:
+                    result = json.loads(response.read().decode('utf-8'))
                 
-                # 解析结果并检查是否有错误
-                try:
-                    result_dict = json.loads(result)
-                    if "error" in result_dict:
-                        error_msg = result_dict['error']
-                        return f"MCP调用错误: {error_msg}"
-                except json.JSONDecodeError:
-                    pass  # 如果不是JSON格式,直接返回原始结果
-                return result
-            else:
-                return f"未知工具: {tool_name}"
+                # 检查是否有错误
+                if "error" in result:
+                    error_msg = result['error']
+                    return f"MCP调用错误: {error_msg}"
+                
+                # 返回结果
+                return json.dumps(result, ensure_ascii=False)
+            except urllib.error.HTTPError as e:
+                return f"MCP调用HTTP错误: {e.code} - {e.reason}"
+            except Exception as e:
+                return f"MCP调用失败: {str(e)}"
+        else:
+            return f"未知工具: {tool_name}"
 
 if __name__ == "__main__":
     tools = Tools()