摘要:从单一 stdio MCP 到同时接入高德地图、Chrome DevTools、FileSystem 四个 Server,一个北京南站酒店搜索加浏览器展示的实战,展示 MCP 多 Server 编排的完整流程。
上一篇文章拆解了 MCP 协议的核心机制------一个本地的 stdio MCP Server,通过跨进程通信让 Agent 调用外部工具。但 MCP 真正的威力不在于"一个 Server",而在于多个 Server 同时接入,让 Agent 获得跨越多个领域的能力组合。
MCP 本质上还是 tool,只不过包了一层进程,可以通过 stdio 和 HTTP 来访问。这个"包了一层"带来一个巨大的好处:任何人都可以开发基于 MCP 协议的 Server,然后直接被其他人复用。 高德地图的 MCP Server 可以做位置查询和路线规划,Chrome DevTools 的 MCP Server 可以控制浏览器打开网页和截图,FileSystem 的 MCP Server 可以读写本地文件。把这些 Server 同时接入一个 Agent,它就能完成"搜酒店 → 打开浏览器展示 → 保存截图到本地"这种跨领域的工作流。
本文用一个实际案例串联起来:查询北京南站附近最近的 3 个酒店,在浏览器中打开每个酒店的图片,并把页面标题改为酒店名。
四种 MCP Server 的接入方式
MultiServerMCPClient 支持同时配置多个 MCP Server,每个 Server 的接入方式不同------有的通过 HTTP 远程调用,有的通过本地 stdio 进程,有的通过 npx 拉取 npm 包后启动:
javascript
import { MultiServerMCPClient } from '@langchain/mcp-adapters';
import { ChatOpenAI } from '@langchain/openai';
const model = new ChatOpenAI({
modelName: 'deepseek-v4-pro',
apiKey: process.env.DEEPSEEK_API_KEY,
configuration: {
baseURL: process.env.DEEPSEEK_BASE_URL,
},
});
const mcpClient = new MultiServerMCPClient({
mcpServers: {
'amap-maps': {
// 远程 HTTP MCP ------ 高德地图
url: 'https://mcp.amap.com/mcp?key=f403bd38acafd014cffe95e54193a419',
},
'my-mcp-server': {
// 本地 stdio MCP ------ 自定义工具
command: 'node',
args: [
'F:/workspace/zzd_ai/ai/agent_in_action/mcp-demo/src/my-mcp-server.mjs',
],
},
'chrome-devtools': {
// npx MCP ------ 浏览器控制
command: 'npx',
args: ['-y', 'chrome-devtools-mcp@latest'],
},
'filesystem': {
// npx MCP ------ 文件系统操作
command: 'npx',
args: [
'-y',
'@modelcontextprotocol/server-filesystem',
'F:/workspace/zzd_ai/ai/agent_in_action/remote-mcp/src',
],
},
},
});
四种配置方式对应了四种不同的接入场景:
| Server | 接入方式 | 场景 |
|---|---|---|
| amap-maps | HTTP 远程 URL | 第三方服务提供的 MCP,无需本地安装,直接通过 HTTP 调用 |
| my-mcp-server | 本地 Node 进程 | 自己开发的 MCP Server,通过 stdio 与本机 Agent 通信 |
| chrome-devtools | npx 拉取 |
社区发布的 npm 包,npx -y 自动下载最新版并启动 |
| filesystem | npx 拉取 + 参数 |
同上,但额外传入工作目录参数,限制文件操作范围 |
npx -y 中的 -y 参数表示自动确认安装,避免交互式提示阻塞 Agent 的启动流程。chrome-devtools-mcp@latest 中的 @latest 确保每次启动都使用最新版本。
多 Server 并行:一个指令打通三个领域
配置好四个 Server 后,getTools() 会返回所有 Server 注册的工具集合。Agent 拿到这个工具列表后,就能在 ReAct 循环中自主选择调用哪个 Server 的哪个工具。
给 Agent 的任务指令:
javascript
await runAgentWithTools(`北京南站附近的酒店,最近的 3 个酒店,
拿到酒店图片,打开浏览器,展示每个酒店的图片,每个 tab 一个 url 展示,
并且在把那个页面标题改为酒店名`);
这个任务看似简单,实际上涉及三个完全不同领域的操作:
- 地理位置查询(高德 MCP):搜索"北京南站"附近的酒店,返回酒店名称、坐标和图片 URL
- 浏览器控制(Chrome DevTools MCP):打开浏览器,为每个酒店创建新标签页,导航到图片 URL,修改页面标题
- 文件读写(FileSystem MCP):可能将酒店信息保存为本地文件,作为后续步骤的输入
ReAct 循环会驱动 Agent 在"思考 → 行动 → 观察"之间反复迭代。Agent 需要先调用高德 MCP 获取酒店列表,拿到图片 URL 后,再调用 Chrome DevTools MCP 打开浏览器并操作标签页。每一步的观察结果会影响下一步的决策------比如高德返回了 3 个酒店的信息,Agent 才知道需要打开 3 个标签页。
工具返回值的处理:字符串还是对象
多 Server 场景下,不同 MCP Server 返回的工具结果格式不尽相同,这是一个容易被忽略的工程细节。有些 Server 返回纯字符串,有些返回结构化对象(如 { text: "..." }):
javascript
for (const toolCall of response.tool_calls) {
const foundTool = tools.find(t => t.name === toolCall.name);
if (foundTool) {
const toolResult = await foundTool.invoke(toolCall.args);
let contentStr;
// MCP tool 返回一般是字符串
if (typeof toolResult === 'string') {
contentStr = toolResult;
}
// 还有可能是对象,比如 filesystem 返回 { text: "..." }
else if (toolResult && toolResult.text) {
contentStr = toolResult.text;
}
messages.push(new ToolMessage({
content: contentStr,
tool_call_id: toolCall.id,
}));
}
}
这段兼容逻辑背后的原因是:MCP 协议规范了 Server 和 Client 之间的通信格式,但不同 Server 的实现者对返回值的封装方式不同。高德 MCP 可能直接返回纯文本的 JSON 字符串,而 FileSystem MCP 可能返回 { text: "文件内容" } 的结构化对象。Agent 端需要同时兼容两种格式,否则就会出现 [object Object] 被注入到 LLM 上下文中的情况。
ToolMessage 的 content 必须是字符串,因为 LLM 只能理解文本。如果工具返回的是对象,直接传给 LLM 会变成无意义的 [object Object]。
MCP 生态:从自己造轮子到直接复用
回到 MCP 协议的最大价值------复用。在 MCP 出现之前,如果你想在 Agent 中集成高德地图的能力,需要自己阅读高德 API 文档,写 HTTP 请求封装,定义 zod Schema,处理错误。如果你想控制浏览器,需要自己封装 Playwright 或 Puppeteer,暴露给 Agent 调用。
有了 MCP 协议之后,这些工作社区已经帮你做好了。你只需要在 MultiServerMCPClient 中配置一行 URL 或 npx 命令,Agent 就能直接获得这些能力。这种模式带来的变化可以用一个表格来对比:
| 维度 | 手写工具集成 | MCP 协议复用 |
|---|---|---|
| 高德地图集成 | 阅读 API 文档 → 写 HTTP 封装 → 定义 Schema → 注册工具 | 一行 url 配置 |
| 浏览器控制 | 封装 Playwright → 暴露工具 → 维护代码 | 一行 npx chrome-devtools-mcp@latest |
| 文件系统操作 | 用 fs 模块自己写 → 处理边界情况 |
一行 npx @modelcontextprotocol/server-filesystem |
| 跨项目复用 | 复制粘贴代码,手动适配 | 同一个配置,换项目直接用 |
MCP 正在催生一个类似 npm 生态的工具市场------高德地图 MCP、Chrome DevTools MCP、FileSystem MCP、GitHub MCP、Slack MCP,每个 Server 都是一个独立维护的"工具包",可以被任何 Agent 通过标准协议调用。
总结
MCP 多 Server 编排的核心价值,可以用一句话概括:把多个专业领域的工具能力通过标准协议聚合到一个 Agent 中,让 LLM 在 ReAct 循环中自主编排调用顺序,完成跨领域的复杂任务。
四个关键要点:
- 三种接入方式 :HTTP 远程(URL)、本地 stdio(
command+args)、npx拉取(npm 包),覆盖了从第三方服务到社区工具到自研 Server 的所有场景 - 多 Server 并行 :
getTools()返回所有 Server 的工具集合,Agent 在 ReAct 循环中自主选择调用哪个 Server 的哪个工具,无需人工编排调用顺序 - 返回值兼容:不同 MCP Server 的返回值格式可能不同(字符串 vs 对象),Agent 端需要做类型判断和格式转换,确保传给 LLM 的内容始终是文本
- 生态复用:MCP 让工具开发从"每个项目自己造轮子"变成"社区共享、一行配置即用",高德地图、Chrome DevTools、FileSystem 都是现成的例子
MCP 协议正在把 AI Agent 从"单工具"推向"多工具协同"的新阶段。一个 Agent 接入的 MCP Server 越多,它能完成的任务就越复杂,能跨越的领域就越广。 而这一切,只需要在配置文件中多加几行。**