从零掌握 MCP 多服务器架构:让 AI 同时操控地图、浏览器和文件系统
前言
想象一下:你只需要用自然语言说一句"帮我查北京南站附近的酒店,把结果截图保存到本地",AI 就能自动调用高德地图查酒店、操控浏览器截图、再写入本地文件------全程无需你手动操作任何工具。
这就是 MCP(Model Context Protocol,模型上下文协议) 带来的变革。本文基于一个实际项目,带你从零理解 MCP 的多服务器架构,并手把手实现一个 AI Agent 同时连接 4 个 MCP Server。
一、什么是 MCP?为什么它很重要?
1.1 一句话理解
MCP 就是 AI 的"USB 接口协议"。就像 USB 让电脑能连接键盘、鼠标、U盘等各种外设一样,MCP 让 AI 能连接地图、浏览器、文件系统、数据库等各种工具。
1.2 核心价值:可复用
有了 MCP 协议后,任何人都可以开发基于这个协议的 MCP Server,然后可以直接复用。
这就是 MCP 最大的魅力------一次开发,到处使用。高德官方开发了地图 MCP Server,你不需要自己封装地图 API,直接拿来用就行。
1.3 两种连接方式
| 连接方式 | 传输协议 | 适用场景 | 示例 |
|---|---|---|---|
| 远程 HTTP | HTTP/SSE | 第三方服务、云端API | 高德地图 MCP |
| 本地 stdio | 标准输入输出 | 本地工具、浏览器控制 | Chrome DevTools、FileSystem |
知识点 1:MCP 协议
MCP 是什么:Model Context Protocol,是 Anthropic 开源的一套标准协议,定义了 AI 模型与外部工具之间的通信规范。它让 LLM 能够以统一的方式发现、调用各种外部工具,而不需要为每个工具写定制化的胶水代码。
核心概念:
- Server:提供工具的进程(可以是本地程序,也可以是远程服务)
- Client:连接 Server 并获取工具列表的客户端
- Tool:Server 暴露的具体能力(如"查询经纬度"、"打开网页"、"写文件")
为什么重要:在 MCP 出现之前,让 AI 调用外部工具需要为每个工具单独写适配代码。MCP 统一了这个过程------就像 USB 统一了外设连接标准。
二、项目架构总览
scss
┌─────────────────────────────────────────────────────┐
│ AI Agent (DeepSeek) │
│ 理解自然语言 → 决策调用哪些工具 │
└──────────────────────┬──────────────────────────────┘
│ bindTools()
┌──────────────────────▼──────────────────────────────┐
│ MultiServerMCPClient │
│ (LangChain MCP Adapter) │
│ 统一管理多个 MCP Server 的工具 │
└──┬──────────┬──────────────┬──────────────┬─────────┘
│ HTTP │ stdio │ stdio │ stdio
┌──▼────┐ ┌───▼──────┐ ┌────▼──────┐ ┌───▼─────────┐
│ 高德地图 │ │ 自定义MCP │ │Chrome │ │ FileSystem │
│ MCP │ │ Server │ │DevTools MCP│ │ MCP │
│ (远程) │ │ (本地) │ │ (本地) │ │ (本地) │
└────────┘ └──────────┘ └────────────┘ └─────────────┘
核心依赖(package.json):
@langchain/mcp-adapters:LangChain 的 MCP 适配层,提供MultiServerMCPClient@langchain/openai:兼容 OpenAI 协议的模型调用(这里连的是 DeepSeek)@modelcontextprotocol/sdk:MCP 官方 SDK,用于自定义 MCP Server
三、创建你自己的 MCP Server
先从最简单的开始------用 MCP SDK 写一个本地 Server。代码见 my-mcp-server.mjs:
javascript
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';
// 1. 创建 Server 实例
const server = new McpServer({
name: 'my-mcp-server',
version: '1.0.0',
});
// 2. 注册工具:加法
server.tool(
'add',
'计算两个数字的和',
{
a: z.number().describe('第一个数字'), // ← zod 定义参数 schema
b: z.number().describe('第二个数字'),
},
async ({ a, b }) => ({
content: [{ type: 'text', text: String(a + b) }], // ← 返回标准格式
})
);
// 3. 通过 stdio 启动,等待客户端连接
const transport = new StdioServerTransport();
await server.connect(transport);
知识点 2:MCP Server 的三要素
每个 MCP 工具都包含三个核心部分:
1. 名称(name) :唯一标识,如
'add'。AI 通过名称来区分和选择工具。2. 参数 Schema(input schema) :用 Zod 定义参数类型和描述。Zod 是 TypeScript/JavaScript 的 schema 校验库。AI 会读取这个 schema 来理解"这个工具需要什么参数"。
javascript{ a: z.number().describe('第一个数字') }
z.number()表示参数类型是数字,.describe()是给 AI 看的参数说明。3. 回调函数(handler) :实际执行业务逻辑的函数,返回
{ content: [{ type: 'text', text: '...' }] }格式。stdio 传输:客户端通过启动子进程的方式运行 MCP Server,两者通过标准输入/输出(stdin/stdout)交换 JSON 消息。这意味着 MCP Server 可以是任何语言写的命令行程序。
四、AI Agent 客户端:同时连接多个 MCP Server
最精彩的部分在这里------mcp-test.mjs。它用一个 MultiServerMCPClient 统一管理所有 MCP Server:
javascript
const mcpClient = new MultiServerMCPClient({
mcpServers: {
// 类型1:远程 HTTP MCP
'amap': {
"url": "https://mcp.amap.com/mcp?key=YOUR_KEY"
},
// 类型2:本地 stdio MCP(运行 JS 文件)
'my-mcp-server': {
command: 'node',
args: ['./src/my-mcp-server.mjs']
},
// 类型3:本地 stdio MCP(通过 npx 运行 npm 包)
'chrome-devtools': {
command: 'npx',
args: ['-y', 'chrome-devtools-mcp']
},
// 类型4:文件系统 MCP
'filesystem': {
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-filesystem', './output']
}
}
});
// 一行代码获取所有 Server 的全部工具!
const tools = await mcpClient.getTools();
四类 Server 的配置对比:
| MCP Server | 类型 | 配置方式 |
|---|---|---|
| 高德地图 | HTTP 远程 | 直接填 URL,SDK 自动处理连接 |
| 自定义 Server | stdio 本地 | command: 'node' + 脚本路径 |
| Chrome DevTools | stdio 本地 | npx -y 拉取 npm 包运行 |
| FileSystem | stdio 本地 | 同上,后面跟允许访问的目录 |
知识点 3:MultiServerMCPClient 如何工作
MultiServerMCPClient 是 LangChain MCP Adapter 提供的聚合客户端。
工作流程:
- 读取配置中的每个 MCP Server
- 对 HTTP 类型 → 发 HTTP 请求获取工具列表
- 对 stdio 类型 → 启动子进程,通过 stdin/stdout 通信
- 将所有 Server 的工具合并成一个统一的工具列表
- 通过
model.bindTools(tools)把工具注入给 AI 模型关键优势:AI 不需要知道每个工具来自哪个 Server------它只看到一个统一的工具列表,直接按需调用即可。这就像操作系统的"设备抽象层"。
五、AI Agent 循环:让模型自主决策
有了工具列表后,怎么让 AI 自主调用它们?核心是 Agent Loop(代理循环):
javascript
async function runAgentWithTools(query, maxIterations = 10) {
const messages = [new HumanMessage(query)];
for (let i = 0; i < maxIterations; i++) {
// 第1步:把对话历史发给模型
const response = await modelWithTools.invoke(messages);
messages.push(response);
// 第2步:如果模型直接返回文本 → 任务完成!
if (!response.tool_calls || response.tool_calls.length === 0) {
return response.content;
}
// 第3步:模型说要调用工具 → 逐个执行
for (const tool_call of response.tool_calls) {
const foundTool = tools.find(t => t.name === tool_call.name);
const result = await foundTool.invoke(tool_call.args);
// 第4步:把工具执行结果告诉模型,让它决定下一步
messages.push(new ToolMessage({
content: result,
tool_call_id: tool_call.id,
}));
}
// 回到第1步,模型根据结果继续推理...
}
}
知识点 4:Agent Loop 的执行流程
整个过程就像一个"智能 while 循环":
css用户: "查北京南站附近酒店,写入文件" ↓ 第1轮: AI 调用 amap.search("北京南站附近酒店") ← 我需要位置数据 ↓ (工具返回:酒店列表) 第2轮: AI 调用 amap.get_detail(酒店1_id) ← 我需要详细信息 ↓ (工具返回:名称、地址、评分) 第3轮: AI 调用 filesystem.write("hotels.txt", 结果) ← 数据够了,写文件 ↓ (工具返回:写入成功) 第4轮: AI 返回 "已完成!酒店信息已写入 hotels.txt" ← 任务完成,停止循环关键设计:
- ToolMessage:工具执行结果被包装成 ToolMessage 追加到消息历史,这样模型能看到"上次调用工具的结果"
- maxIterations:防止无限循环的安全阀(比如工具一直失败)
- 模型自主决策:每一步调用哪个工具、传什么参数,全部由模型判断
六、实战演示
场景1:地图 + 文件联动
javascript
await runAgentWithTools(`
帮我查询北京南站附近的酒店,找最近的 3 个。
对每个酒店,把名称、地址、评分等信息,
写入 hotels_near_beijing_south_station.txt 文件中。
`);
AI 会自动:调用高德地图 MCP 搜索 → 获取详情 → 调用 FileSystem MCP 写入文件。
场景2:浏览器操控
javascript
await runAgentWithTools('打开百度首页,告诉我页面标题是什么');
AI 自动调用 Chrome DevTools MCP 的 navigate_page → take_snapshot 工具。
知识点 5:Chrome DevTools MCP 的作用
chrome-devtools-mcp 是一个 npm 包,提供了 29 个浏览器操控工具:
分类 工具 页面导航 navigate_page,new_page,close_page,select_page元素交互 click,fill,hover,drag,type_text,press_key数据获取 take_screenshot,take_snapshot,evaluate_script调试分析 list_console_messages,list_network_requests,performance_start_trace它让你用自然语言就能操控浏览器------"打开淘宝搜 iPhone"、"截图并保存"、"查看控制台报错",AI 都能帮你完成。
注意:需要本机装有 Chrome 或 Edge 浏览器(Chromium 内核即可)。
知识点 6:环境变量管理
iniDEEPSEEK_API_KEY=sk-xxx DEEPSEEK_API_BASE_URL=https://api.deepseek.com/v1 DEEPSEEK_MODEL=deepseek-v4-flash代码中通过
import 'dotenv/config'自动加载,然后用process.env.XXX读取。永远不要把 API Key 硬编码在代码里。
七、总结
核心要点回顾
- MCP 是 AI 的工具协议:统一了 AI 与外部工具的通信方式,让工具可以复用
- 两种传输方式:HTTP(远程服务)和 stdio(本地进程)
- MultiServerMCPClient:一个客户端同时管理多个 MCP Server,AI 无需关心工具来源
- Agent Loop:AI 在循环中"思考→调工具→看结果→再思考",直到完成任务
- 自定义 MCP Server 只需三步:创建 Server → 注册 tool(name + zod schema + handler)→ 连接 transport
文件索引
| 文件 | 作用 |
|---|---|
| readme.md | 项目笔记,记录应用场景和设计思路 |
| my-mcp-server.mjs | 自定义 MCP Server 示例(add/get_current_time/reverse_string) |
| mcp-test.mjs | AI Agent 客户端,连接多个 MCP Server + Agent Loop |
| package.json | 项目依赖 |
| .env | 环境变量(API Key) |
一句话记住 MCP:它让 AI 从"只会聊天"变成了"什么都能干"------而你要做的,只是把 MCP Server 的配置填进去。
欢迎评论区交流!如果你也写了有趣的 MCP Server,欢迎分享 🚀