From 8f266bea0d62d0ab2d2f7e2ad476440aad00622f Mon Sep 17 00:00:00 2001 From: kevin1sMe Date: Sun, 4 May 2025 23:33:07 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20MCP=20server=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E4=BD=BF=E7=94=A8sse=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/xiaozhi-server/core/mcp/MCPClient.py | 52 +++++++++++--------- main/xiaozhi-server/core/mcp/manager.py | 4 +- main/xiaozhi-server/mcp_server_settings.json | 3 ++ main/xiaozhi-server/requirements.txt | 2 +- 4 files changed, 36 insertions(+), 25 deletions(-) diff --git a/main/xiaozhi-server/core/mcp/MCPClient.py b/main/xiaozhi-server/core/mcp/MCPClient.py index 103ac645..7996ff67 100644 --- a/main/xiaozhi-server/core/mcp/MCPClient.py +++ b/main/xiaozhi-server/core/mcp/MCPClient.py @@ -4,6 +4,7 @@ from contextlib import AsyncExitStack import os, shutil from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client +from mcp.client.sse import sse_client from config.logger import setup_logging @@ -21,29 +22,36 @@ class MCPClient: async def initialize(self): args = self.config.get("args", []) - command = ( - shutil.which("npx") - if self.config["command"] == "npx" - else self.config["command"] - ) - - env={**os.environ} - if self.config.get("env"): - env.update(self.config["env"]) - - server_params = StdioServerParameters( - command=command, - args=args, - env=env - ) - - stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params)) - self.stdio, self.write = stdio_transport - time_out_delta = timedelta(seconds=15) - self.session = await self.exit_stack.enter_async_context(ClientSession(read_stream=self.stdio, write_stream=self.write, read_timeout_seconds=time_out_delta)) - + if "command" in self.config: + command = ( + shutil.which("npx") + if self.config["command"] == "npx" + else self.config["command"] + ) + env = {**os.environ} + if self.config.get("env"): + env.update(self.config["env"]) + server_params = StdioServerParameters( + command=command, + args=args, + env=env + ) + stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params)) + self.stdio, self.write = stdio_transport + time_out_delta = timedelta(seconds=15) + self.session = await self.exit_stack.enter_async_context( + ClientSession(read_stream=self.stdio, write_stream=self.write, read_timeout_seconds=time_out_delta) + ) + elif "url" in self.config: + sse_transport = await self.exit_stack.enter_async_context(sse_client(self.config["url"])) + self.sse_read, self.sse_write = sse_transport + self.session = await self.exit_stack.enter_async_context( + ClientSession(read_stream=self.sse_read, write_stream=self.sse_write) + ) + else: + raise ValueError("MCPClient config must have 'command' or 'url'.") + await self.session.initialize() - # List available tools response = await self.session.list_tools() tools = response.tools diff --git a/main/xiaozhi-server/core/mcp/manager.py b/main/xiaozhi-server/core/mcp/manager.py index f212b67a..a0e310fa 100644 --- a/main/xiaozhi-server/core/mcp/manager.py +++ b/main/xiaozhi-server/core/mcp/manager.py @@ -50,9 +50,9 @@ class MCPManager: """初始化所有MCP服务""" config = self.load_config() for name, srv_config in config.items(): - if not srv_config.get("command"): + if not srv_config.get("command") and not srv_config.get("url"): self.logger.bind(tag=TAG).warning( - f"Skipping server {name}: command not specified" + f"Skipping server {name}: neither command nor url specified" ) continue diff --git a/main/xiaozhi-server/mcp_server_settings.json b/main/xiaozhi-server/mcp_server_settings.json index a38bbdfb..26e2cf42 100644 --- a/main/xiaozhi-server/mcp_server_settings.json +++ b/main/xiaozhi-server/mcp_server_settings.json @@ -26,6 +26,9 @@ "command": "npx", "args": ["-y", "@simonb97/server-win-cli"], "link": "https://github.com/SimonB97/win-cli-mcp-server" + }, + "perplexity-ask": { + "url": "http://your-server-ip:your-port/sse" } } } diff --git a/main/xiaozhi-server/requirements.txt b/main/xiaozhi-server/requirements.txt index 7da31b6f..7b7237cf 100755 --- a/main/xiaozhi-server/requirements.txt +++ b/main/xiaozhi-server/requirements.txt @@ -22,7 +22,7 @@ mem0ai==0.1.62 bs4==0.0.2 modelscope==1.23.2 sherpa_onnx==1.11.0 -mcp==1.4.1 +mcp==1.7.1 cnlunar==0.2.0 PySocks==1.7.1 dashscope==1.23.1 \ No newline at end of file From 3fcfb65d45fefb086ecb6a375554dee29e6e25ec Mon Sep 17 00:00:00 2001 From: kevin1sMe Date: Sun, 4 May 2025 23:37:17 +0800 Subject: [PATCH 2/2] update: example --- main/xiaozhi-server/mcp_server_settings.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/main/xiaozhi-server/mcp_server_settings.json b/main/xiaozhi-server/mcp_server_settings.json index 26e2cf42..dc173f37 100644 --- a/main/xiaozhi-server/mcp_server_settings.json +++ b/main/xiaozhi-server/mcp_server_settings.json @@ -3,7 +3,8 @@ "在data目录下创建.mcp_server_settings.json文件,可以选择下面的MCP服务,也可以自行添加新的MCP服务。", "后面不断测试补充好用的mcp服务,欢迎大家一起补充。", "记得删除注释行,des属性仅为说明,不会被解析。", - "des和link属性,仅为说明安装方式,方便大家查看原始链接,不是必须项。" + "des和link属性,仅为说明安装方式,方便大家查看原始链接,不是必须项。", + "当前支持stdio/sse两种模式。" ], "mcpServers": { "filesystem": { @@ -26,9 +27,6 @@ "command": "npx", "args": ["-y", "@simonb97/server-win-cli"], "link": "https://github.com/SimonB97/win-cli-mcp-server" - }, - "perplexity-ask": { - "url": "http://your-server-ip:your-port/sse" } } }