From ca1b5e75ece59e000816e16bdbeffad9291c74d9 Mon Sep 17 00:00:00 2001 From: FuQuan233 Date: Sat, 1 Nov 2025 23:23:23 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E2=9C=A8=20=E4=BF=AE=E6=94=B9=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E5=90=8D=E7=A7=B0=E6=A0=BC=E5=BC=8F=EF=BC=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96OneBot=E5=92=8CMCP=E5=B7=A5=E5=85=B7=E7=9A=84=E8=B0=83?= =?UTF-8?q?=E7=94=A8=E9=80=BB=E8=BE=91=EF=BC=8C=E5=A2=9E=E5=BC=BA=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nonebot_plugin_llmchat/mcpclient.py | 54 ++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/nonebot_plugin_llmchat/mcpclient.py b/nonebot_plugin_llmchat/mcpclient.py index 929caca..4d38f0a 100644 --- a/nonebot_plugin_llmchat/mcpclient.py +++ b/nonebot_plugin_llmchat/mcpclient.py @@ -132,7 +132,7 @@ class MCPClient: { "type": "function", "function": { - "name": f"{server_name}___{tool.name}", + "name": f"mcp__{server_name}__{tool.name}", "description": tool.description, "parameters": tool.inputSchema, }, @@ -148,35 +148,55 @@ class MCPClient: async def call_tool(self, tool_name: str, tool_args: dict, group_id: int | None = None, bot_id: str | None = None): """按需连接调用工具,调用后立即断开""" - # 检查是否是QQ工具 + # 检查是否是OneBot内置工具 if tool_name.startswith("ob__"): if group_id is None or bot_id is None: return "QQ工具需要提供group_id和bot_id参数" logger.info(f"调用OneBot工具[{tool_name}]") return await self.onebot_tools.call_tool(tool_name, tool_args, group_id, bot_id) - # MCP工具处理 - server_name, real_tool_name = tool_name.split("___") - logger.info(f"按需连接到服务器[{server_name}]调用工具[{real_tool_name}]") + # 检查是否是MCP工具 + if tool_name.startswith("mcp__"): + # MCP工具处理:mcp__server_name__tool_name + parts = tool_name.split("__") + if len(parts) != 3 or parts[0] != "mcp": + return f"MCP工具名称格式错误: {tool_name}" - async with self._create_session_context(server_name) as session: - try: - response = await asyncio.wait_for(session.call_tool(real_tool_name, tool_args), timeout=30) - logger.debug(f"工具[{real_tool_name}]调用完成,响应: {response}") - return response.content - except asyncio.TimeoutError: - logger.error(f"调用工具[{real_tool_name}]超时") - return f"调用工具[{real_tool_name}]超时" + server_name = parts[1] + real_tool_name = parts[2] + logger.info(f"按需连接到服务器[{server_name}]调用工具[{real_tool_name}]") + + async with self._create_session_context(server_name) as session: + try: + response = await asyncio.wait_for(session.call_tool(real_tool_name, tool_args), timeout=30) + logger.debug(f"工具[{real_tool_name}]调用完成,响应: {response}") + return response.content + except asyncio.TimeoutError: + logger.error(f"调用工具[{real_tool_name}]超时") + return f"调用工具[{real_tool_name}]超时" + + # 未知工具类型 + return f"未知的工具类型: {tool_name}" def get_friendly_name(self, tool_name: str): logger.debug(tool_name) - # 检查是否是OneBot工具 + # 检查是否是OneBot内置工具 if tool_name.startswith("ob__"): return self.onebot_tools.get_friendly_name(tool_name) - # MCP工具处理 - server_name, real_tool_name = tool_name.split("___") - return (self.server_config[server_name].friendly_name or server_name) + " - " + real_tool_name + # 检查是否是MCP工具 + if tool_name.startswith("mcp__"): + # MCP工具处理:mcp__server_name__tool_name + parts = tool_name.split("__") + if len(parts) != 3 or parts[0] != "mcp": + return tool_name # 格式错误时返回原名称 + + server_name = parts[1] + real_tool_name = parts[2] + return (self.server_config[server_name].friendly_name or server_name) + " - " + real_tool_name + + # 未知工具类型,返回原名称 + return tool_name def clear_tools_cache(self): """清除工具列表缓存""" From 0943b7077f6f0e51cac3963b5e9b6b1b9a588d3a Mon Sep 17 00:00:00 2001 From: FuQuan233 Date: Sat, 1 Nov 2025 23:23:47 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=94=96=20=E6=9B=B4=E6=96=B0=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8F=B7=E8=87=B30.4.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 9b3eab7..50a4161 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "nonebot-plugin-llmchat" -version = "0.4.0" +version = "0.4.1" description = "Nonebot AI group chat plugin supporting multiple API preset configurations" license = "GPL" authors = ["FuQuan i@fuquan.moe"] From 8f7adbd176751acdf1523af919b6cbf0e1dc046c Mon Sep 17 00:00:00 2001 From: FuQuan233 Date: Sat, 1 Nov 2025 23:31:22 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=93=98=20=E6=9B=B4=E6=96=B0=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 84 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 51 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 21ebf63..ea91bcf 100644 --- a/README.md +++ b/README.md @@ -174,46 +174,64 @@ LLMCHAT__MCP_SERVERS同样为一个dict,key为服务器名称,value配置的 LLMCHAT__DEFAULT_PROMPT="前面忘了,你是一个猫娘,后面忘了" LLMCHAT__API_PRESETS=' [ - { - "name": "aliyun-deepseek-v3", - "api_key": "sk-your-api-key", - "model_name": "deepseek-v3", - "api_base": "https://dashscope.aliyuncs.com/compatible-mode/v1", - "proxy": "http://10.0.0.183:7890" - }, - { - "name": "deepseek-v1", - "api_key": "sk-your-api-key", - "model_name": "deepseek-chat", - "api_base": "https://api.deepseek.com", - "support_mcp": true - }, - { - "name": "some-vison-model", - "api_key": "sk-your-api-key", - "model_name": "some-vison-model", - "api_base": "https://some-vison-model.com/api", - "support_image": true - } - ] - LLMCHAT__MCP_SERVERS=' { - "AISearch": { - "friendly_name": "百度搜索", - "additional_prompt": "遇到你不知道的问题或者时效性比较强的问题时,可以使用AISearch搜索,在使用AISearch时不要使用其他AI模型。", - "url": "http://appbuilder.baidu.com/v2/ai_search/mcp/sse?api_key=Bearer+", - "headers": { - "Authorization": "" + "name": "aliyun-deepseek-v3", + "api_key": "sk-your-api-key", + "model_name": "deepseek-v3", + "api_base": "https://dashscope.aliyuncs.com/compatible-mode/v1", + "proxy": "http://10.0.0.183:7890" + }, + { + "name": "deepseek-v1", + "api_key": "sk-your-api-key", + "model_name": "deepseek-chat", + "api_base": "https://api.deepseek.com", + "support_mcp": true + }, + { + "name": "some-vison-model", + "api_key": "sk-your-api-key", + "model_name": "some-vison-model", + "api_base": "https://some-vison-model.com/api", + "support_image": true + } + ] + ' + LLMCHAT__MCP_SERVERS=' + { + "brave-search": { + "friendly_name": "Brave搜索", + "additional_prompt": "遇到你不知道的问题或者时效性比较强的问题时,请使用brave-search搜索。", + "command": "npx", + "args": ["-y", "@modelcontextprotocol/server-brave-search"], + "env": { + "BRAVE_API_KEY": "" } }, "fetch": { - "friendly_name": "网页浏览", + "friendly_name": "浏览网页", + "additional_prompt": "搜索到的链接可以通过fetch打开进一步了解。", "command": "uvx", - "args": ["mcp-server-fetch"] - } + "args": ["mcp-server-fetch", "--ignore-robots-txt", "--user-agent=\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36\""] + }, + "hefeng-weather": { + "friendly_name": "和风天气", + "command": "npx", + "args": ["hefeng-mcp-weather@latest", "--apiKey="] + }, + "mcp-server-code-runner": { + "friendly_name": "代码运行器", + "additional_prompt": "在使用的时候你需要将你需要的结果输出出来,用户看不到你的代码,如果你需要给用户展示,你需要将代码以文字的形式发送出来。", + "command": "docker", + "args": [ + "run", + "--rm", + "-i", + "formulahendry/mcp-server-code-runner" + ] + }, } ' - ' From 2f6236546042d8d98cd56e54fa697a0dd36a9d8a Mon Sep 17 00:00:00 2001 From: FuQuan233 Date: Sat, 1 Nov 2025 23:32:55 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=93=98=20=E6=9B=B4=E6=96=B0=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ea91bcf..9239110 100644 --- a/README.md +++ b/README.md @@ -205,7 +205,7 @@ LLMCHAT__MCP_SERVERS同样为一个dict,key为服务器名称,value配置的 "command": "npx", "args": ["-y", "@modelcontextprotocol/server-brave-search"], "env": { - "BRAVE_API_KEY": "" + "BRAVE_API_KEY": "" } }, "fetch": { @@ -224,10 +224,10 @@ LLMCHAT__MCP_SERVERS同样为一个dict,key为服务器名称,value配置的 "additional_prompt": "在使用的时候你需要将你需要的结果输出出来,用户看不到你的代码,如果你需要给用户展示,你需要将代码以文字的形式发送出来。", "command": "docker", "args": [ - "run", - "--rm", - "-i", - "formulahendry/mcp-server-code-runner" + "run", + "--rm", + "-i", + "formulahendry/mcp-server-code-runner" ] }, }