大疆无人机:如何革新雪崩救援行动
2026-07-14 3398501
2026-07-14 0
2026 年最火的 AI 协议是什么?

MCP(Model Context Protocol)——模型上下文协议。
几乎所有 AI 产品都在接入:Cursor、Claude、豆包、Trae...
今天我们从原理出发,实战接入高德地图 MCP、文件系统 MCP、浏览器控制 MCP,彻底搞懂 MCP 的本质。
复制代码豆包手机 AI Agent 的全新体验:
- 不再只是 chat
- 帮我们把活干了
传统 AI 的局限:
| 能力 | 传统 AI | MCP 加持后 |
|---|---|---|
| 聊天 | 可以 | 可以 |
| 查地图 | 不能 | 调用高德地图 |
| 读写文件 | 不能 | 操作本地文件 |
| 控制浏览器 | 不能 | 打开 Chrome |
| 查数据库 | 不能 | 查询 MySQL |
MCP 的本质:
复制代码MCP = AI 的"USB 接口"
就像 USB 让各种设备可以连接电脑一样,MCP 让 AI 可以连接各种外部服务。
复制代码Model Context Protocol(模型上下文协议)25 年最火的协议,定义了模型和外界服务之间的通信标准。
核心思想:
MCP 的架构:
复制代码┌─────────────┐
│ AI 模型 │ ← 大脑(LLM)
└──────┬──────┘
│
▼
┌─────────────┐
│ MCP Client │ ← 客户端(Cursor/Trae/你的代码)
└──────┬──────┘
│
├──────────────┬──────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 高德地图 │ │ 文件系统 │ │ 浏览器 │
│ MCP │ │ MCP │ │ MCP │
└──────────┘ └──────────┘ └──────────┘
三个角色:
| 角色 | 职责 | 例子 |
|---|---|---|
| AI 模型 | 思考和决策 | GPT-4、Claude、Qwen |
| MCP Client | 协议适配、工具调用 | Cursor、你的代码 |
| MCP Server | 提供具体能力 | 高德地图、文件系统 |
复制代码{
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"]
}
特点:
复制代码{
url: "https://mcp.amap.com/mcp?key=YOUR_API_KEY"
}
特点:
对比:
| 方式 | 通信方式 | 适用场景 | 性能 |
|---|---|---|---|
| Stdio | 本地进程 | 本地工具 | 快 |
| HTTP | 网络请求 | 云服务 | 受网络影响 |
复制代码mcp-test/
├── main.mjs # 主程序
├── package.json
├── .env # 环境变量(API Key)
└── beijing_south_station_hotels.md # AI 生成的文档
复制代码// 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:\workspace\lesson_zp\ai\agent\mcp_in_action\mcp-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();
复制代码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,
.env 文件 复制代码configuration: {
baseURL: process.env.OPENAI_BASE_URL,
}
为什么用环境变量?
复制代码const mcpClient = new MultiServerMCPClient({
mcpServers: {
"amap-maps-streamableHTTP": {
url: `${process.env.AMAP_MAPS_API_KEY}`,
},
filesystem: {
command: "npx",
args: [
"-y",
"@modelcontextprotocol/server-filesystem",
"D:\workspace\lesson_zp\ai\agent\mcp_in_action\mcp-test",
],
},
"chrome-devtools": {
command: "npx",
args: ["-y", "chrome-devtools-mcp@latest"],
},
},
});
逐行解析:
复制代码"amap-maps-streamableHTTP": {
url: `${process.env.AMAP_MAPS_API_KEY}`,
}
url:MCP Server 的地址key:高德地图 API Key,需要在高德开放平台申请 复制代码filesystem: {
command: "npx",
args: [
"-y",
"@modelcontextprotocol/server-filesystem",
"D:\workspace\lesson_zp\ai\agent\mcp_in_action\mcp-test",
],
}
command: "npx":使用 npx 运行args:
-y:自动确认安装@modelcontextprotocol/server-filesystem:官方文件系统 MCP 包 复制代码"chrome-devtools": {
command: "npx",
args: ["-y", "chrome-devtools-mcp@latest"],
}
chrome-devtools-mcp@latest:使用最新版本三个 MCP Server 对比:
| Server | 方式 | 功能 | 用途 |
|---|---|---|---|
| 高德地图 | HTTP | 查地点、路线、POI | 地理信息查询 |
| 文件系统 | Stdio | 读写文件 | 生成文档、保存结果 |
| 浏览器控制 | Stdio | 控制 Chrome | 展示内容、自动化操作 |
复制代码const tools = await mcpClient.getTools();
const modelWithTools = model.bindTools(tools);
逐行解析:
复制代码const tools = await mcpClient.getTools();
maps_geo(地理编码)、maps_direction(路线规划)等 复制代码const modelWithTools = model.bindTools(tools);
Function Calling 流程:
复制代码用户:北京南站附近的酒店
↓
AI 思考:需要调用地图工具
↓
AI 输出:调用 maps_search_around 工具
↓
MCP Client:执行工具,返回结果
↓
AI 思考:根据结果生成回复
↓
最终回复:推荐 3 个酒店...
复制代码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:用户消息 复制代码for (let i = 0; i < maxIterations; i++) {
复制代码const response = await modelWithTools.invoke(messages);
messages.push(response);
复制代码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) {
复制代码console.log(`n AI 最终回复:n ${response.content}n`);
return response.content;
复制代码console.log(
chalk.bgBlue(` 检测到 ${response.tool_calls.length} 个工具调用`)
);
console.log(
chalk.bgBlue(
` 工具调用: ${response.tool_calls.map((t) => t.name).join(", ")}`
)
);
解析:
chalk 库给日志上色,便于调试 复制代码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) {
复制代码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:关联到对应的工具调用消息类型:
| 类型 | 用途 | 例子 |
|---|---|---|
HumanMessage | 用户输入 | "北京南站附近的酒店" |
AIMessage | AI 回复 | "我来帮你查询..." |
ToolMessage | 工具结果 | "找到 3 个酒店..." |
SystemMessage | 系统提示 | "你是一个助手..." |
复制代码await runAgentWithTools(`
北京南站附近的3个酒店,拿到酒店照片,展开浏览器,展示每个酒店的图片
每个tab一个url展示,并且把那个页面标题改为酒店名
`);await mcpClient.close();
逐行解析:
复制代码await runAgentWithTools(`...`);
复制代码await mcpClient.close();
复制代码用户输入:北京南站附近的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 个酒店...
复制代码⏳正在等待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分钟
这个文档是怎么生成的?
复制代码MCP Server 生态(部分):官方提供:
- filesystem(文件系统)
- postgres(数据库)
- sqlite(数据库)
- puppeteer(浏览器自动化)第三方提供:
- 高德地图(地理信息)
- 百度搜索(搜索引擎)
- GitHub(代码仓库)
- Slack(即时通讯)
- Notion(笔记)
- ...
| 特性 | 传统 API | MCP |
|---|---|---|
| 标准化 | 每个 API 不同 | 统一协议 |
| 开发成本 | 需要适配每个 API | 一次开发,到处使用 |
| AI 集成 | 需要手动编写调用逻辑 | AI 自动选择工具 |
| 生态 | 分散 | 统一生态 |
复制代码1. AI 编程助手(Cursor/Trae)
- 读写文件
- 执行命令
- 搜索代码2. AI 办公助手
- 查地图、订酒店
- 发邮件、发消息
- 操作 Excel、PPT3. AI 数据分析
- 查询数据库
- 生成报表
- 可视化图表4. AI 自动化
- 控制浏览器
- 操作手机 App
- 定时任务
通过这个项目,我们实现了:
复制代码传统 AI:只能聊天
MCP 加持:可以干活从"Chat AI"到"Agent AI"的跨越