目前最火AI协议 - MCP 协议实战:从原理到落地:让 AI 拥有“超能力”
前言
2026 年最火的 AI 协议是什么?

MCP(Model Context Protocol)——模型上下文协议。
几乎所有 AI 产品都在接入:Cursor、Claude、豆包、Trae...
今天我们从原理出发,实战接入高德地图 MCP、文件系统 MCP、浏览器控制 MCP,彻底搞懂 MCP 的本质。
一、MCP 是什么?
1.1 从"聊天"到"干活"
复制代码豆包手机 AI Agent 的全新体验:
- 不再只是 chat
- 帮我们把活干了
传统 AI 的局限:
| 能力 | 传统 AI | MCP 加持后 |
|---|---|---|
| 聊天 | 可以 | 可以 |
| 查地图 | 不能 | 调用高德地图 |
| 读写文件 | 不能 | 操作本地文件 |
| 控制浏览器 | 不能 | 打开 Chrome |
| 查数据库 | 不能 | 查询 MySQL |
MCP 的本质:
复制代码MCP = AI 的"USB 接口"
就像 USB 让各种设备可以连接电脑一样,MCP 让 AI 可以连接各种外部服务。
1.2 MCP 的定义
复制代码Model Context Protocol(模型上下文协议)25 年最火的协议,定义了模型和外界服务之间的通信标准。
核心思想:
- 标准化:统一的协议格式,一次开发,到处使用
- 可扩展:任何人都可以开发 MCP Server
- 安全:权限控制,用户授权
MCP 的架构:
复制代码┌─────────────┐
│ AI 模型 │ ← 大脑(LLM)
└──────┬──────┘
│
▼
┌─────────────┐
│ MCP Client │ ← 客户端(Cursor/Trae/你的代码)
└──────┬──────┘
│
├──────────────┬──────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 高德地图 │ │ 文件系统 │ │ 浏览器 │
│ MCP │ │ MCP │ │ MCP │
└──────────┘ └──────────┘ └──────────┘
三个角色:
| 角色 | 职责 | 例子 |
|---|---|---|
| AI 模型 | 思考和决策 | GPT-4、Claude、Qwen |
| MCP Client | 协议适配、工具调用 | Cursor、你的代码 |
| MCP Server | 提供具体能力 | 高德地图、文件系统 |
二、MCP 的两种接入方式
2.1 Stdio 方式(本地进程)
复制代码{
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"]
}
特点:
- 启动一个本地进程
- 通过标准输入/输出(stdin/stdout)通信
- 适合本地工具(文件系统、数据库等)
2.2 HTTP 方式(远程服务)
复制代码{
url: "https://mcp.amap.com/mcp?key=YOUR_API_KEY"
}
特点:
- 连接远程服务
- 通过 HTTP 请求通信
- 适合云服务(地图、天气、API 等)
对比:
| 方式 | 通信方式 | 适用场景 | 性能 |
|---|---|---|---|
| Stdio | 本地进程 | 本地工具 | 快 |
| HTTP | 网络请求 | 云服务 | 受网络影响 |
三、实战:接入三个 MCP Server
3.1 项目结构
复制代码mcp-test/
├── main.mjs # 主程序
├── package.json
├── .env # 环境变量(API Key)
└── beijing_south_station_hotels.md # AI 生成的文档
3.2 完整代码
复制代码// main.mjs
import "dotenv/config";
import { MultiServerMCPClient } from "@langchain/mcp-adapters";
import { ChatOpenAI } from "@langchain/openai";
import chalk from "chalk";
import {
HumanMessage,
SystemMessage,
ToolMessage,
} from "@langchain/core/messages";// 1. 初始化 AI 模型
const model = new ChatOpenAI({
modelName: process.env.MODEL_NAME,
apiKey: process.env.OPENAI_API_KEY,
configuration: {
baseURL: process.env.OPENAI_BASE_URL,
},
});// 2. 配置多个 MCP Server
const mcpClient = new MultiServerMCPClient({
mcpServers: {
// 高德地图 MCP(HTTP 方式)
"amap-maps-streamableHTTP": {
url: `${process.env.AMAP_MAPS_API_KEY}`,
},
// 文件系统 MCP(Stdio 方式)
filesystem: {
command: "npx",
args: [
"-y",
"@modelcontextprotocol/server-filesystem",
"D:workspacelesson_zpaiagentmcp_in_actionmcp-test",
],
},
// 浏览器控制 MCP(Stdio 方式)
"chrome-devtools": {
command: "npx",
args: ["-y", "chrome-devtools-mcp@latest"],
},
},
});// 3. 获取所有工具
const tools = await mcpClient.getTools();
const modelWithTools = model.bindTools(tools);// 4. Agent 循环
async function runAgentWithTools(query, maxIterations = 30) {
const messages = [new HumanMessage(query)];
for (let i = 0; i < maxIterations; i++) {
console.log(chalk.bgGreen("⏳正在等待AI思考..."));
const response = await modelWithTools.invoke(messages);
messages.push(response); // 5. 如果没有工具调用,返回最终结果
if (!response.tool_calls || response.tool_calls.length === 0) {
console.log(`n AI 最终回复:n ${response.content}n`);
return response.content;
} // 6. 处理工具调用
console.log(
chalk.bgBlue(` 检测到 ${response.tool_calls.length} 个工具调用`)
);
console.log(
chalk.bgBlue(
` 工具调用: ${response.tool_calls.map((t) => t.name).join(", ")}`
)
); // 7. 执行每个工具
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;
if (typeof toolResult === "string") {
contentStr = toolResult;
} else if (toolResult && toolResult.text) {
contentStr = toolResult.text;
}
messages.push(
new ToolMessage({
content: contentStr,
tool_call_id: toolCall.id,
})
);
}
}
}
return messages[messages.length - 1].content;
}// 8. 执行任务
await runAgentWithTools(`
北京南站附近的3个酒店,拿到酒店照片,展开浏览器,展示每个酒店的图片
每个tab一个url展示,并且把那个页面标题改为酒店名
`);await mcpClient.close();
四、逐行解析
4.1 初始化 AI 模型
复制代码const model = new ChatOpenAI({
modelName: process.env.MODEL_NAME,
apiKey: process.env.OPENAI_API_KEY,
configuration: {
baseURL: process.env.OPENAI_BASE_URL,
},
});
逐行解析:
复制代码modelName: process.env.MODEL_NAME,
- 从环境变量读取模型名称
- 可以是
gpt-4、qwen-max、deepseek-chat等
复制代码apiKey: process.env.OPENAI_API_KEY,
- API 密钥,用于身份验证
- 不要硬编码在代码中,使用
.env文件
复制代码configuration: {
baseURL: process.env.OPENAI_BASE_URL,
}
- API 基础 URL
- 如果使用国内模型(如 Qwen),需要修改为对应的 baseURL
为什么用环境变量?
- 安全性:API Key 不会泄露到代码仓库
- 灵活性:不同环境使用不同配置
- 标准化:12-Factor App 最佳实践
4.2 配置 MCP Server
复制代码const mcpClient = new MultiServerMCPClient({
mcpServers: {
"amap-maps-streamableHTTP": {
url: `${process.env.AMAP_MAPS_API_KEY}`,
},
filesystem: {
command: "npx",
args: [
"-y",
"@modelcontextprotocol/server-filesystem",
"D:workspacelesson_zpaiagentmcp_in_actionmcp-test",
],
},
"chrome-devtools": {
command: "npx",
args: ["-y", "chrome-devtools-mcp@latest"],
},
},
});
逐行解析:
复制代码"amap-maps-streamableHTTP": {
url: `${process.env.AMAP_MAPS_API_KEY}`,
}
- 高德地图 MCP,使用 HTTP 方式
url:MCP Server 的地址key:高德地图 API Key,需要在高德开放平台申请
复制代码filesystem: {
command: "npx",
args: [
"-y",
"@modelcontextprotocol/server-filesystem",
"D:workspacelesson_zpaiagentmcp_in_actionmcp-test",
],
}
- 文件系统 MCP,使用 Stdio 方式
command: "npx":使用 npx 运行args:-y:自动确认安装@modelcontextprotocol/server-filesystem:官方文件系统 MCP 包- 最后一个参数:允许访问的目录路径
复制代码"chrome-devtools": {
command: "npx",
args: ["-y", "chrome-devtools-mcp@latest"],
}
- 浏览器控制 MCP
chrome-devtools-mcp@latest:使用最新版本- 可以控制 Chrome 浏览器(打开页面、点击、输入等)
三个 MCP Server 对比:
| Server | 方式 | 功能 | 用途 |
|---|---|---|---|
| 高德地图 | HTTP | 查地点、路线、POI | 地理信息查询 |
| 文件系统 | Stdio | 读写文件 | 生成文档、保存结果 |
| 浏览器控制 | Stdio | 控制 Chrome | 展示内容、自动化操作 |
4.3 获取工具并绑定
复制代码const tools = await mcpClient.getTools();
const modelWithTools = model.bindTools(tools);
逐行解析:
复制代码const tools = await mcpClient.getTools();
- 从所有 MCP Server 获取工具列表
- 每个工具包含:名称、描述、参数 schema
- 例如:
maps_geo(地理编码)、maps_direction(路线规划)等
复制代码const modelWithTools = model.bindTools(tools);
- 将工具绑定到 AI 模型
- AI 可以根据用户请求,自动选择调用哪个工具
- 这就是 Function Calling(函数调用)机制
Function Calling 流程:
复制代码用户:北京南站附近的酒店
↓
AI 思考:需要调用地图工具
↓
AI 输出:调用 maps_search_around 工具
↓
MCP Client:执行工具,返回结果
↓
AI 思考:根据结果生成回复
↓
最终回复:推荐 3 个酒店...
4.4 Agent 循环
复制代码async function runAgentWithTools(query, maxIterations = 30) {
const messages = [new HumanMessage(query)];
for (let i = 0; i < maxIterations; i++) {
console.log(chalk.bgGreen("⏳正在等待AI思考..."));
const response = await modelWithTools.invoke(messages);
messages.push(response);
逐行解析:
复制代码const messages = [new HumanMessage(query)];
- 创建消息数组,初始包含用户的问题
HumanMessage:用户消息- 后续会不断追加 AI 回复和工具结果
复制代码for (let i = 0; i < maxIterations; i++) {
- Agent 循环,最多执行 30 次
- 防止无限循环(AI 一直调用工具)
复制代码const response = await modelWithTools.invoke(messages);
messages.push(response);
- 调用 AI 模型,传入所有历史消息
- AI 会返回:
- 纯文本回复(结束)
- 工具调用(继续循环)
4.5 判断是否结束
复制代码if (!response.tool_calls || response.tool_calls.length === 0) {
console.log(`n AI 最终回复:n ${response.content}n`);
return response.content;
}
逐行解析:
复制代码if (!response.tool_calls || response.tool_calls.length === 0) {
- 检查 AI 是否调用了工具
- 如果没有工具调用,说明 AI 已经给出最终答案
复制代码console.log(`n AI 最终回复:n ${response.content}n`);
return response.content;
- 输出最终回复
- 返回结果,结束函数
4.6 处理工具调用
复制代码console.log(
chalk.bgBlue(` 检测到 ${response.tool_calls.length} 个工具调用`)
);
console.log(
chalk.bgBlue(
` 工具调用: ${response.tool_calls.map((t) => t.name).join(", ")}`
)
);
解析:
- 输出检测到的工具调用数量
- 输出工具名称列表
- 使用
chalk库给日志上色,便于调试
4.7 执行工具
复制代码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;
if (typeof toolResult === "string") {
contentStr = toolResult;
} else if (toolResult && toolResult.text) {
contentStr = toolResult.text;
}
messages.push(
new ToolMessage({
content: contentStr,
tool_call_id: toolCall.id,
})
);
}
}
逐行解析:
复制代码for (const toolCall of response.tool_calls) {
- 遍历所有工具调用
- AI 可能一次调用多个工具
复制代码const foundTool = tools.find((t) => t.name === toolCall.name);
- 根据工具名称找到对应的工具实例
复制代码const toolResult = await foundTool.invoke(toolCall.args);
- 执行工具,传入参数
- 返回工具执行结果
复制代码let contentStr;
if (typeof toolResult === "string") {
contentStr = toolResult;
} else if (toolResult && toolResult.text) {
contentStr = toolResult.text;
}
- 处理工具返回结果
- 可能是字符串,也可能是对象(包含
text属性)
复制代码messages.push(
new ToolMessage({
content: contentStr,
tool_call_id: toolCall.id,
})
);
- 创建
ToolMessage,包含工具结果 tool_call_id:关联到对应的工具调用- 追加到消息历史,供 AI 继续思考
消息类型:
| 类型 | 用途 | 例子 |
|---|---|---|
HumanMessage | 用户输入 | "北京南站附近的酒店" |
AIMessage | AI 回复 | "我来帮你查询..." |
ToolMessage | 工具结果 | "找到 3 个酒店..." |
SystemMessage | 系统提示 | "你是一个助手..." |
4.8 执行任务
复制代码await runAgentWithTools(`
北京南站附近的3个酒店,拿到酒店照片,展开浏览器,展示每个酒店的图片
每个tab一个url展示,并且把那个页面标题改为酒店名
`);await mcpClient.close();
逐行解析:
复制代码await runAgentWithTools(`...`);
- 执行 Agent,传入复杂任务
- 任务包含多个步骤:
- 查询北京南站附近的酒店
- 获取酒店照片
- 打开浏览器展示
- 修改页面标题
复制代码await mcpClient.close();
- 关闭 MCP Client
- 释放资源,断开连接
五、执行流程
5.1 完整流程图
复制代码用户输入:北京南站附近的3个酒店...
↓
AI 思考:需要调用地图工具
↓
调用 maps_search_around(高德地图 MCP)
↓
返回:3 个酒店信息
↓
AI 思考:需要获取酒店照片
↓
调用 maps_photo(高德地图 MCP)
↓
返回:照片 URL
↓
AI 思考:需要打开浏览器展示
↓
调用 chrome_navigate(浏览器 MCP)
↓
打开 3 个 Tab,展示照片
↓
调用 chrome_set_document_title(浏览器 MCP)
↓
修改页面标题
↓
AI 思考:任务完成
↓
最终回复:已完成,展示了 3 个酒店...
5.2 实际输出示例
复制代码⏳正在等待AI思考...
检测到 1 个工具调用
工具调用: maps_search_around⏳正在等待AI思考...
检测到 3 个工具调用
工具调用: maps_photo, maps_photo, maps_photo⏳正在等待AI思考...
检测到 3 个工具调用
工具调用: chrome_navigate, chrome_navigate, chrome_navigate⏳正在等待AI思考...
检测到 3 个工具调用
工具调用: chrome_set_document_title, chrome_set_document_title, chrome_set_document_title⏳正在等待AI思考...AI 最终回复:
已完成,展示了 3 个酒店的图片:
1. 米家青年酒店(北京南站店)
2. 汉庭酒店(北京南站护城河店)
3. 如家酒店(北京南站店)
六、生成的文档
AI 还会自动生成一个 Markdown 文档:
复制代码# 北京南站附近酒店及交通指南## 北京南站位置信息- **名称**: 北京南站
- **地址**: 北京市丰台区
- **坐标**: 116.378059, 39.867679## 推荐酒店### 1. 米家青年酒店(北京南站店)- **地址**: 右外东庄21号楼
- **坐标**: 116.377765, 39.868995
- **评分**: 3.6分
- **距离北京南站**: 约304米步行
- **步行时间**: 约4分钟### 2. 汉庭酒店(北京南站护城河店)- **地址**: 开阳路6号院1号楼
- **评分**: 4.6分
- **距离北京南站**: 约851米步行
- **步行时间**: 约11分钟
这个文档是怎么生成的?
- AI 调用高德地图 MCP,获取酒店信息
- AI 调用文件系统 MCP,创建 Markdown 文件
- AI 将信息整理成结构化文档
七、扩展:MCP 的未来
7.1 MCP 生态
复制代码MCP Server 生态(部分):官方提供:
- filesystem(文件系统)
- postgres(数据库)
- sqlite(数据库)
- puppeteer(浏览器自动化)第三方提供:
- 高德地图(地理信息)
- 百度搜索(搜索引擎)
- GitHub(代码仓库)
- Slack(即时通讯)
- Notion(笔记)
- ...
7.2 MCP vs 传统 API
| 特性 | 传统 API | MCP |
|---|---|---|
| 标准化 | 每个 API 不同 | 统一协议 |
| 开发成本 | 需要适配每个 API | 一次开发,到处使用 |
| AI 集成 | 需要手动编写调用逻辑 | AI 自动选择工具 |
| 生态 | 分散 | 统一生态 |
7.3 MCP 的应用场景
复制代码1. AI 编程助手(Cursor/Trae)
- 读写文件
- 执行命令
- 搜索代码2. AI 办公助手
- 查地图、订酒店
- 发邮件、发消息
- 操作 Excel、PPT3. AI 数据分析
- 查询数据库
- 生成报表
- 可视化图表4. AI 自动化
- 控制浏览器
- 操作手机 App
- 定时任务
八、总结
核心要点
- MCP = AI 的"USB 接口",让 AI 可以连接各种外部服务
- 两种接入方式:Stdio(本地)和 HTTP(远程)
- 三个角色:AI 模型、MCP Client、MCP Server
- Function Calling:AI 自动选择并调用工具
- Agent 循环:思考 → 调用工具 → 获取结果 → 继续思考
实战收获
通过这个项目,我们实现了:
- 接入高德地图 MCP(HTTP 方式)
- 接入文件系统 MCP(Stdio 方式)
- 接入浏览器控制 MCP(Stdio 方式)
- 实现 Agent 循环,自动调用多个工具
- 完成复杂任务:查酒店 → 获取照片 → 打开浏览器 → 修改标题
MCP 的价值
复制代码传统 AI:只能聊天
MCP 加持:可以干活从"Chat AI"到"Agent AI"的跨越
-
07.14
无期迷途怦怦电波放送中活动详解 无期迷途心动互动玩法与奖励指南
-
07.14
永远的蔚蓝星球全新英雄皮肤效果介绍-火焰法师与闪电之子介绍
-
07.14
永远的蔚蓝星球新坐骑瞌睡小飞象介绍-技能效果详解
-
07.14
永远的蔚蓝星球戒指图腾选择推荐指南
-
07.14
永远的蔚蓝星球111-115关如何通关
-
07.14
永恒的蔚蓝星球漫游奇境活动攻略
推荐专题
热门阅读
-
- AI 编程普及:初学者还要不要学习基础语法?
- 07.14
-
- LLM 推理究竟是怎么跑起来的?
- 07.14
-
-
-
下载
- |
-
-
下载
- 《行尸走肉第一章》免安装中文汉化硬盘版下载
- 单机|436 MB
- 一款以动作冒险为主题的游戏
-
-
下载
- 《街头霸王X铁拳》免安装中文汉化硬盘版下载
- 单机|111MB
- 一款非常好玩的格斗游戏
-
-
下载
- |
-
-
下载
- 《暗黑破坏神3》免安装繁体中文正式版下载
- 单机|7630 MB
- 一款以角色扮演为主题的游戏
-
-
下载
- 《马克思佩恩3》免安装硬盘版下载
- 单机|27033 MB
- 一款以第三人称射击为主题的游戏