远程 MCP 实战:一行代码接入高德地图、文件系统、浏览器控制,打造 AI 工作流
文章目录
一、回顾:MCP 本质上是什么?
在开始之前,先快速回顾一下 MCP 的核心概念——如果你已经看过上一篇基础入门,这一节能帮你巩固;如果你是第一次接触,也能快速建立认知。
MCP(Model Context Protocol)本质上是 Tool(工具),只不过在 Tool 外面包了一层"进程"。
- 普通的 Tool:在 Agent 进程内部执行,定义在同一个代码文件里,直接调用函数
- MCP Tool:在独立的进程(MCP Server)中执行,Agent 通过协议和它通信
两种访问方式:
| 方式 | 适用场景 | 配置写法 |
|---|---|---|
| stdio | 本地子进程,适合个人开发工具 | { command: 'node', args: ['server.js'] } |
| HTTP | 远程服务,适合团队共享、第三方服务 | { url: 'https://xxx.com/mcp' } |
有了这个基础,我们来看今天的重点——如何在实际项目中组合多个 MCP Server,让 AI 完成一条完整的工作流。
二、应用场景:三个 MCP Server 协同工作
假设你有一个需求:查询北京南站附近的酒店,获取路线规划,把结果保存成 Markdown 文件。
这需要三种能力:
- 🌍 地理信息查询 → 高德地图 MCP(HTTP 远程)
- 📂 文件读写 → FileSystem MCP(npx 本地子进程)
- 🌐 浏览器控制 → Chrome DevTools MCP(npx 本地子进程)
恰好,这三种能力都有现成的 MCP Server 可以直接用。这就是 MCP 生态最大的价值:任何人都可以开发基于 MCP 协议的 Server,然后其他人直接复用。

2.1 高德地图 MCP(HTTP 远程方式)
高德地图提供了官方的 MCP Server,通过 HTTP 暴露。这是典型的"远程 MCP"使用方式——你不需要下载任何代码,只要在配置里填入 URL 和 API Key 即可。
注册和获取 Key:高德开放平台
提供的核心工具:
| 工具名 | 功能 | 示例 |
|---|---|---|
maps_geo |
地理编码(地址 → 经纬度) | “北京南站” → 116.379, 39.865 |
maps_around_search |
周边搜索(经纬度 + 关键词 → 结果列表) | 附近 3km 内的酒店 |
maps_direction |
路线规划(起点 → 终点) | 北京南站 → 酒店的驾车/公交路线 |
💡 关键理解:高德 MCP Server 是部署在高德服务器上的,你的 Agent 通过 HTTP 请求去调用它。这和调一个普通 HTTP API 表面类似,但本质区别在于——MCP 返回的不是"业务数据",而是"Tool 定义 + 执行结果",Agent 能自动发现它有哪些工具、工具需要什么参数、然后自动调用。
2.2 Chrome DevTools MCP(npx 本地方式)
这个 MCP Server 让你能通过 AI 控制 Chrome 浏览器:打开网页、点击按钮、截屏、甚至修改页面标题。
前提条件:Chrome 需要以远程调试模式启动:
chrome --remote-debugging-port=9222
提供的核心工具:
| 工具名 | 功能 |
|---|---|
navigate_page |
导航到指定 URL |
take_screenshot |
截取页面截图 |
click |
点击页面元素 |
evaluate_script |
执行 JavaScript 代码 |
list_pages |
列出当前打开的所有页面 |
2.3 FileSystem MCP(npx 本地方式)
这个 MCP Server 提供文件系统的读写能力,由 @modelcontextprotocol/server-filesystem 这个 npm 包提供。
关键配置:启动时必须指定允许访问的目录(安全限制),否则无法读写:
'filesystem': {
command: 'npx',
args: [
'-y',
'@modelcontextprotocol/server-filesystem',
'D:\\workspace\\zmt_ai\\ai\\agent_in_action\\remote-mcp' // 允许访问的目录
]
}
⚠️ 安全提示:FileSystem MCP 只能访问配置中指定的目录,不能随意访问系统任意路径。这是一个重要的安全边界——MCP Server 不能"越狱"访问你未授权的文件夹。
三、完整实战:一个 AI 工作流的诞生
现在把三个 MCP Server 组合起来,实现一个完整的 AI 工作流:查询酒店 → 路线规划 → 保存文档。
3.1 完整代码(带详细注释)
// mcp-test.mjs —— 远程 MCP 多 Server 协同工作流
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. 初始化 LLM ====================
const model = new ChatOpenAI({
modelName: 'deepseek-v4-pro',
apiKey: process.env.DEEPSEEK_API_KEY,
temperature: 0, // 设为 0 确保结果稳定
configuration: {
baseURL: 'https://api.deepseek.com/v1',
},
});
// ==================== 2. 配置多个 MCP Server ====================
const mcpClient = new MultiServerMCPClient({
mcpServers: {
// ① 高德地图 —— HTTP 远程方式
'amap-mcp-streamableHTTP': {
"url": "https://mcp.amap.com/mcp?key=你的高德APIkey"
},
// ② 自建用户查询 —— stdio 本地子进程
'my-mcp-server': {
command: "node",
args: [
// 你自己写的用户查询工具的路径
'D:\\workspace\\zmt_ai\\ai\\agent_in_action\\mcp-demo\\src\\my-mcp-server.mjs'
]
},
// ③ 文件系统 —— npx 启动第三方 MCP Server
'filesystem': {
command: 'npx',
args: [
'-y',
'@modelcontextprotocol/server-filesystem',
'D:\\workspace\\zmt_ai\\ai\\agent_in_action\\remote-mcp' // 白名单目录
]
},
// ④ Chrome DevTools —— 控制浏览器
// 使用前需执行:chrome --remote-debugging-port=9222
'chrome-devtools': {
command: 'npx',
args: [
'-y',
'chrome-devtools-mcp@latest',
]
}
}
});
// ==================== 3. 获取所有工具并绑定到模型 ====================
const tools = await mcpClient.getTools();
console.log(tools); // 打印看看总共有哪些工具可用
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(`第${i + 1}轮对话`));
// 4.1 让 LLM 思考下一步
const response = await modelWithTools.invoke(messages);
messages.push(response);
// 4.2 如果 LLM 不再调用工具 → 说明已经得出最终答案
if (!response.tool_calls || response.tool_calls.length === 0) {
console.log(chalk.bgRed(`AI 回答:${response.content}`));
return response.content;
}
// 4.3 打印本轮调用了哪些工具
console.log(chalk.bgBlue(`工具调用: ${response.tool_calls.map(t => t.name).join(', ')}`));
// 4.4 逐个执行工具,收集结果
for (const toolCall of response.tool_calls) {
const foundTool = tools.find(t => t.name === toolCall.name);
if (foundTool) {
// 执行工具(跨进程:stdio 或 HTTP)
const toolResult = await foundTool.invoke(toolCall.args);
// 解析工具返回的内容
let contentStr;
if (typeof toolResult === 'string') {
contentStr = toolResult;
} else if (toolResult && toolResult.result) {
contentStr = toolResult.text;
}
// 将工具执行结果反馈给 LLM
messages.push(new ToolMessage({
content: contentStr,
tool_call_id: toolCall.id
}));
}
}
}
// 达到最大轮数仍无结果,返回最后一轮内容
return messages[messages.length - 1].content;
}
// ==================== 5. 启动工作流 ====================
// 任务:查酒店 → 规划路线 → 保存 Markdown 文件
await runAgentWithTools(
'北京南站附近的 2 个酒店,以及去的路线,路线规划生成文档保存到当前目录的一个 md 文件'
);
// 备选任务(需要 Chrome 调试模式):
// await runAgentWithTools(
// '北京南站附近的酒店,最近的 3 个酒店,拿到酒店图片,打开浏览器,
// 展示每个酒店的图片,每个 tab 一个 url 展示,并且把那个页面标题改为酒店名'
// );
// ==================== 6. 关闭所有 MCP 连接 ====================
await mcpClient.close();
执行结果:
1.2.
3.2 代码执行流程图
当 AI 收到"查询北京南站附近的酒店并保存文档"这个任务时,内部发生了如下过程:
关键观察:AI 自动规划了 4 步操作(地理编码 → 周边搜索 → 路线规划 → 保存文件),每一步调用了不同的 MCP Server,完全无需人工干预。这就是 MCP 工作流的威力。
四、MCP 生态:最大的价值在于复用
4.1 核心认知转变
有了 MCP 协议之后,AI 工具开发发生了根本性的认知转变:
| 之前(无 MCP) | 之后(有 MCP) |
|---|---|
| 每个项目自己写工具函数 | 直接引入现成的 MCP Server |
| Node.js 项目只能用 JS 工具 | 可以调用任何语言编写的 MCP Server |
| 工具和 Agent 代码耦合 | 工具独立部署、独立升级 |
| 个人造轮子,质量参差不齐 | 社区共建,专业团队维护(如高德官方 MCP) |
4.2 三种典型的 MCP Server 来源
4.3 各 Server 能力速查
| MCP Server | 通信方式 | 启动方式 | 核心能力 |
|---|---|---|---|
| 高德地图 | HTTP | 配置 URL | 地理编码、周边搜索、路线规划 |
| FileSystem | stdio | npx @modelcontextprotocol/server-filesystem |
读写文件、创建目录、搜索文件 |
| Chrome DevTools | stdio | npx chrome-devtools-mcp@latest |
控制浏览器:导航、截图、点击、执行 JS |
| 自建 Server | stdio | node my-server.js |
查询内部数据库、调用内部 API 等 |
五、全文总结
远程 MCP 的核心思想就一句话:Tool 还是那个 Tool,但通过 MCP 协议,它可以从"项目里的一段代码"变成"一个独立、可复用、跨语言、跨网络的服务"。
本文展示了三种接入方式的实际应用:
- HTTP 远程(高德地图)—— 第三方服务直接提供 MCP URL,一行配置即可接入
- npx 本地包(FileSystem、Chrome DevTools)—— npm 社区提供的 MCP Server,一行命令即可启动
- 自建 stdio(my-mcp-server)—— 自己开发的 MCP Server,用 Node.js 编写,查询内部数据
当这些 Server 组合在一起时,AI Agent 就能完成一条完整的工作流——自动规划步骤、跨 Server 调用工具、最终交付结果。你只需要用自然语言描述需求。
六、核心知识点复盘
| 知识点 | 要点 |
|---|---|
| MCP 本质 | Tool + 进程包装,通过 stdio 或 HTTP 提供跨进程调用 |
| stdio vs HTTP | stdio 用于本地子进程,HTTP 用于远程服务 |
| MultiServerMCPClient | 可以同时配置多个 MCP Server,Agent 自动发现所有工具 |
| 高德 MCP | HTTP 远程方式,提供地理编码、周边搜索、路线规划 |
| FileSystem MCP | 需要指定允许访问的目录(安全白名单) |
| Chrome DevTools MCP | 需要 Chrome 以 --remote-debugging-port=9222 启动 |
| MCP 生态价值 | 任何语言的工具都能封装成 MCP Server,跨项目、跨团队复用 |
| Agent 循环 | LLM 决定调用什么工具 → Agent 执行 → 结果反馈 → 循环,直到得出最终答案 |
七、常见问题与避坑指南
Q1:Tool names must be unique 错误
现象:启动时 DeepSeek API 返回 400 错误。
原因:多个 MCP Server 注册了同名工具。比如 filesystem 和自建的 my-mcp-server 都提供了 read_file 工具,绑定给 LLM 时名称冲突。
解决:只保留功能更全的那个 Server,或者修改其中一个 Server 注册的工具名。
Q2:Instances of "undefined" type are not supported 错误
现象:Agent 执行工具时报 schema 校验错误。
原因:toolCall.arguments 从 LLM 返回时是 JSON 字符串(如 '{"userId":"001"}'),而 invoke() 期望接收 JS 对象(如 {userId: "001"})。
解决:调用前先做类型判断和转换:
const args = typeof toolCall.arguments === 'string'
? JSON.parse(toolCall.arguments)
: toolCall.arguments;
const toolResult = await foundTool.invoke(args);
Q3:Chrome DevTools MCP 连接不上
现象:getTools() 阶段一直卡住不返回。
原因:Chrome DevTools MCP 需要连接本地 Chrome 的调试端口。如果 Chrome 没有以 --remote-debugging-port=9222 参数启动,MCP Server 会一直等待连接。
解决:
# Windows:先关闭所有 Chrome 窗口,然后用调试模式启动
chrome --remote-debugging-port=9222
# 如果暂时用不到,直接注释掉这个 Server 的配置即可
Q4:FileSystem MCP 无法写入文件
现象:工具返回权限错误。
原因:FileSystem MCP 只能访问启动时配置的"白名单目录",不能越界。
解决:检查 args 中指定的目录路径是否正确,确保目标文件在该目录下。
Q5:脚本执行完一直不退出
原因:通过 stdio 启动的子进程(MCP Server)没有被关闭。
解决:Agent 脚本末尾必须调用 await mcpClient.close(),这会关闭所有 stdio 连接并终止子进程。忘记这行代码会导致脚本"假死"。
Q6:如何获取高德地图 MCP 的 API Key?
访问 高德开放平台 注册账号 → 创建应用 → 选择"Web 服务" → 获取 Key。注意:高德 MCP 是 HTTP 远程服务,Key 会明文出现在 URL 中,不要把带 Key 的代码提交到公开仓库。
💡 最佳实践:将 API Key 放在
.env文件中,通过process.env.AMAP_KEY引用,并在.gitignore中添加.env。
更多推荐
2.


所有评论(0)