游乐游手机版
首页/AI教程/文章详情

MCP客户端实战:两个服务器同时运行导致AI调用工具错误

时间:2026-07-21 14:50
同时运行两个MCP服务器时,因同名工具导致人工智能误选文件系统搜索而非数据库查询。通过添加命名空间前缀区分工具名称和描述,并结合独立超时与错误隔离机制,有效避免人工智能选错及单点故障。

在完成 MCP Server 相关文章后,一个实际需求随之而来:让一个 Agent 同时调用两个 MCP Server。一个用于查询 SQLite 数据库,另一个用于检索本地文件系统。Agent 运行一轮后返回了结果。核对答案时发现数据不太对,再比对原始数据——AI 返回了文件系统里的"张三",但用户实际询问的是数据库里张三的订单记录。

MCP Client实战翻车记:两个Server同时跑,AI调错了Tool

问题并非出在 Server 编写错误,也不是模型能力不足。真正的原因是 AI 选错了 Tool。

两个 Server 都提供了 search 方法,AI 最终选择了文件系统的 search,但正确做法应该是调用数据库的 query。这个场景让我深刻理解了 MCP Client 的真正职责——它不仅仅是简单的"连接器",更是一个"翻译官",将多组 Server 的能力转化为 AI 能够准确理解的语言。

MCP Client 的核心职责与作用

先用最短时间厘清角色分工。

MCP ServerMCP Client
职责提供 Tool 供外部调用将 Tool 翻译给 AI 理解
类比一个 API 接口API 文档 + 调用说明书
出问题的地方Tool 内部逻辑出错AI 选错了 Tool / 参数传不对
管理粒度每个 Server 独立运行一个 Client 可对接多个 Server

Server 只负责"我具备这个能力",Client 则负责"AI 如何知道该用哪个"。这个区分听起来简单,但只有当你手上同时管理两个以上 Server 时,才会真正体会到 Client 的设计直接决定了 AI 是否会出错。

翻车现场还原:MCP 多 Server 调用实战

先说场景。本地分别启动了 Node.js 编写的两个 Server,一个暴露了 search、query、insert 三个 Tool 来操作 SQLite,另一个暴露了 search、read、write 用于文件读写。然后编写了一个 Client 将它们连接起来。以下代码基于 @modelcontextprotocol/sdk 0.6.x 版本。

第一版 Client 代码如下:

import { Client } from '@modelcontextprotocol/sdk/client/index.js';import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';const dbClient = new Client({ name: 'database-client' });const fileClient = new Client({ name: 'filesystem-client' });await dbClient.connect(new StdioClientTransport({ command: 'node', args: ['db-server.mjs'] }));await fileClient.connect(new StdioClientTransport({ command: 'node', args: ['file-server.mjs'] }));// 列出各 Server 的 Toolconst dbTools = await dbClient.listTools();const fileTools = await fileClient.listTools();

代码看起来没毛病对吧?两个 Client 实例分别连接不同的 Server,各管各的。但问题出在 AI 这一侧——当把两个 Server 的 Tool 列表合并交给 LLM 时,AI 看到的工具列表是这样的:

可用工具:- search(来自 database-server)- query(来自 database-server)- insert(来自 database-server)- search(来自 filesystem-server)- read(来自 filesystem-server)- write(来自 filesystem-server)

两个 search 同名。LLM 在选 search 时,无法保证它一定选数据库的那个。

事实上进行了三组对话测试,其中有两次 AI 选了文件系统的 search。"张三"这个关键词在文件里确实有——某个文档里提到了这个名字——但用户问的是"张三的订单",应该在数据库里查 order 表。AI 拿到文件名和对应的内容片段,以为那就是答案。

这个场景其实挺典型。MCP 协议本身不限制 Tool 命名唯一性,Server 开发者各自命名自己的 Tool,撞名是常态。问题是,LLM 在做 Tool 选择时,依赖的是 Tool name + description 的语义匹配。当两个 Tool 的名字一模一样,description 又都跟"搜索"相关,模型大概率猜错。

翻车之后怎么修:MCP Tool 命名冲突解决方案

发现问题后第一个想法是:给 Tool 名字加上命名空间前缀。

class NamespaceClient {constructor(namespace, client) {this.namespace = namespace;this.client = client;}async listTools() {const tools = await this.client.listTools();return tools.map(tool => ({...tool,name: `${this.namespace}_${tool.name}`,description: `[${this.namespace}] ${tool.description}`}));}async callTool(name, args) {const originalName = name.replace(`${this.namespace}_`, '');return this.client.callTool(originalName, args);}}const dbClient = new NamespaceClient('db', originalDbClient);const fileClient = new NamespaceClient('fs', originalFileClient);// 现在 AI 看到的列表变成了:// - db_search// - db_query// - db_insert// - fs_search// - fs_read// - fs_write

加上前缀之后,AI 看到的就是 db_search 和 fs_search,名字不同,选错的概率降了很多。进行了七八轮测试,没有再出现调错 Tool 的情况。

不过这里有个细节值得说——description 也要改。光是改名字不够,因为 LLM 选 Tool 时 description 权重很高。在 description 前面加了 [db][fs] 标签,相当于给 AI 一个视觉锚点。后面一些文章提到,有人用 XML 标签、有人用 Emoji,试了一圈发现纯文本前缀最稳定,模型解析出错率最低。

翻车二:一个 Server 挂了,全链路卡死

修完命名冲突之后,以为这件事搞定了。直到第二个问题冒出来。

数据库 Server 那边有一次查询跑了很久——那张表数据量到了一定规模,索引没有建好,一次模糊查询拖了近两分钟。Client 一直在等 db_server 返回,file_server 的服务也跟着没法继续。

查了一下日志才发现问题:Client 是串行处理 Tool 调用的。一个 Server 的 Tool 没返回,后续的调用全部排队等着。

这是一个设计上的取舍。MCP Client 默认不隔离不同 Server 的超时行为,一个慢 Server 会拖慢整个链路。不是每次都会遇到,但遇到就卡死整条链路。

修复方式很直接——给每个 Server 配独立超时:

import { Client } from '@modelcontextprotocol/sdk/client/index.js';const dbClient = new Client({ name: 'database-client' },{ transportTimeout: 8000 } // 8秒超时);const fileClient = new Client({ name: 'filesystem-client' },{ transportTimeout: 3000 } // 文件操作一般快得多);

配了超时之后,db_server 那次慢查询在 8 秒后被 Client 主动中断,file_server 的调用正常执行。当然,超时本身不是完美的方案——超时意味着那个 Tool 调用失败了,AI 需要重试或者走 fallback。但至少不会让其他 Server 跟着陪葬。

后来加了一层更细的隔离:给每个 Server 的 Tool 调用包了一层 try/catch,让一个 Server 的失败不会传播到另一个。

async function safeCall(client, toolName, args) {try {return await client.callTool(toolName, args);} catch (err) {console.error(`[${client.id}] Tool ${toolName} failed:`, err.message);return { error: true, message: `暂无法访问 ${client.id}` };}}

其实就是加了个错误边界,但效果很明显——一个 Server 挂掉不会影响另一个。

多 Server 管理的决策框架与最佳实践

写完这个项目之后,自己整理了一个判断逻辑,什么场景下用什么策略:

场景推荐方案原因
两个 Server 功能完全不重叠命名空间前缀直接拆简单,互不干扰
Server 数量 >= 3 但功能有交集袋里聚合模式,统一入口减少 AI 选择成本
有 Server 偶尔超时/不稳定独立超时 + try/catch 隔离一个挂了不拖累全局
多个 Server 服务同一场景合并成一个 Server减少跨 Server 通信
外部不可控 Server(第三方)包装层 + 降级策略不能假设第三方永远可用

袋里聚合模式是什么?就是用一层袋里 Server 包装下面多个子 Server 的 Tool,对外只有一个入口。子 Server 的 Tool 全部通过袋里转发,Client 只需要连一个袋里 Server 就行。适合 Server 数量多的时候,减少 AI 面对的选择空间。

这个方案的边界与局限性

以上做法能解决大部分多 Server 集成问题,但不是银弹。

命名空间前缀有一类场景搞不定——当 LLM 需要跨两个 Server 的数据做推理时。比如"对比数据库里张三的订单和文件系统里张三的简历",AI 需要同时调 db_search 和 fs_search,两次结果合并做分析。前缀方案只能防选错,不能加速跨 Server 协作。

跨 Server 数据融合是另一个话题了,可能需要 Client 侧做一层缓存或结果聚合。这个还没完全想好,目前遇到的对比例子不多,方案还不够成熟。

另外超时配置的数值得根据实际场景调。设的 8 秒和 3 秒是基于本地测试的,放到线上环境网络延迟不同,要重新压测。具体设多少没有万能公式,自己的做法是先设成 5 秒,跑一周看日志,如果有 Tool 频繁超时就调大,如果服务器响应都很稳定就逐步缩紧。

你现在就可以做的一件事:检查 MCP 配置

打开你的 MCP 配置文件(一般是 mcp.jsonclaude_desktop_config.json),看看有没有配多个 Server。如果有,检查一下它们的 Tool 名字——有没有同名的?如果有,加个前缀,花不了五分钟,但能省掉后面排查"AI 为什么拿错数据"的时间。

当时就是觉得"两个 search 应该没关系吧"——结果查了接近两小时才发现是这个原因。这个亏吃一次就够了。

来源:https://juejin.cn/post/7664268452512841734
上一篇Dify工具调用失败:执行步骤超过500限制 下一篇前端转Agent第一周学习:Python FastAPI框架与Pydantic数据验证实战(TS/JS视角)
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
TalkVisions实时视频翻译应用,消除语言障碍
AI教程 · 2026-07-25

TalkVisions实时视频翻译应用,消除语言障碍

TalkVisions是一款实时视频翻译应用,能将视频中的口语实时转录为文本并翻译成用户所选语言,以字幕形式叠加在画面上,支持多语言、低延迟,还可保存录制视频,有效消除跨语言沟通障碍。

AI驱动的日历管理工具Ipso
AI教程 · 2026-07-25

AI驱动的日历管理工具Ipso

IpsoAI是一款专为专业人士及助手打造的AI日历管理工具,能够自动协调多方日程、智能草拟邮件,并通过快速安排会议、提供智能建议及自动化工作流程,显著减少琐碎操作,帮助用户高效管理时间、提升工作效率。

Spectate企业级专业高效监控与事故管理一体化平台
AI教程 · 2026-07-25

Spectate企业级专业高效监控与事故管理一体化平台

Spectate是一款高效监控和事故管理工具,能在30秒内检测故障并推送告警。它支持Slack、PagerDuty等主流集成,提供自定义状态页面和全球性能监控。系统自动更新状态并推送修复建议,帮助团队减少沟通成本,快速解决问题。

阿里云通义千问2.5大模型发布 多项能力赶超GPT-4
AI教程 · 2026-07-25

阿里云通义千问2.5大模型发布 多项能力赶超GPT-4

通义千问2 5大模型发布,多项能力宣称赶超GPT-4,中文语境下文本理解、生成、知识问答等表现优异。相比2 1版本,理解提升9%、逻辑推理提升16%、指令遵循提升19%。开源1100亿参数模型超越Llama-3-70B,获评开源最强。已服务超9万家企业,与小米、微博等达成合作。

万知个人AI工作站:一站式智能阅读创作分享平台
AI教程 · 2026-07-25

万知个人AI工作站:一站式智能阅读创作分享平台

万知是集成多种AI能力的个人工作站,支持自然语言交互、文档快速阅读与摘要生成、PPT自动设计与优化,覆盖学术研究、商务报告、写作辅助及日常问答等场景,全方位提升工作效率。