前言
做AI Agent开发最折磨人的是什么? 每接入一类外部能力,就要写一套胶水代码、适配一套接口、处理不同返回格式。
想让AI查地图,单独封装高德接口;想读写本地文件,重新写文件操作函数;想控制浏览器,又要对接Chrome调试协议。 代码冗余、维护成本爆炸,换个大模型还要重新适配一遍工具调用逻辑。
直到我用上 MCP(Model Context Protocol) 协议,彻底解决这个痛点。
读完本文你能学到:
- MCP协议核心价值,为什么它是AI工具统一标准
- Node.js+LangChain完整可运行代码,同时对接3种MCP服务
- 真实实战场景:AI自主查询酒店、生成文档、打开浏览器分页展示图片
- 开发中高频踩坑点与修复方案
- 多MCP服务协同Agent完整执行流程
一、先搞懂:MCP到底是什么?
MCP全称模型上下文协议,是AI领域标准化工具通信协议,业内俗称AI万能USB插头。
传统工具接入痛点
- 每个第三方服务、本地能力都要单独写适配层
- 返回格式不统一,每次调用都要手动做数据兼容
- 切换大模型、更换工具时,大量代码需要重构
MCP带来的改变
所有工具统一封装成MCP Server,通过stdio/HTTP两种方式通信。 客户端只需要一次配置,就能自动读取全部工具,交给LLM自由调用。
本文实战用到3套成熟MCP服务:
- amap-maps-streamableHTTP:远程HTTP服务,高德地图,查位置、酒店、路线
- filesystem:本地子进程服务,读写本地文件、创建目录、生成md文档
- chrome-devtools:本地子进程服务,操控Chrome浏览器,新开标签、修改页面标题、打开图片链接
二、项目前置依赖安装
新建项目,安装全部依赖包,复制执行:
bash
npm install dotenv @langchain/mcp-adapters @langchain/openai chalk langchain
.env环境变量配置
项目根目录新建.env文件,填入密钥:
env
DEEPSEEK_API_KEY=你的DeepSeek密钥
AMAP_KEY=你的高德地图key
三、完整可运行实战代码 mcp-test.js
javascript
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';
// 初始化DeepSeek大模型,兼容OpenAI调用格式
const model = new ChatOpenAI({
modelName:'deepseek-v4-pro',
apiKey: process.env.DEEPSEEK_API_KEY,
temperature: 0, // 设为0保证工具调用稳定,不随机发散
configuration: {
baseURL: 'https://api.deepseek.com/v1',
},
});
// 多MCP服务统一客户端配置
const mcpClient = new MultiServerMCPClient({
mcpServers: {
// 高德地图远程MCP服务,HTTP流式传输
'amap-maps-streamableHTTP': {
"url": `https://mcp.amap.com/mcp?key=${process.env.AMAP_KEY}`
},
// 本地文件系统MCP,npx启动子进程,限定访问目录
'filesystem': {
command: 'npx',
args: [
'-y',
'@modelcontextprotocol/server-filesystem',
'C:/Users/Administrator/Desktop/ai_doubao_ysw/ai/agent_in_action/remote-mcp'
]
},
// Chrome浏览器控制MCP,本地调试端口9222
'chrome-devtools': {
command: 'npx',
args: [
'-y',
'chrome-devtools-mcp@latest',
]
}
}
});
// 自动拉取全部MCP服务暴露的工具
const tools = await mcpClient.getTools();
// 将所有工具绑定到大模型,模型自动识别可用操作
const modelWithTools = model.bindTools(tools);
/**
* Agent循环执行核心函数
* @param {string} query 用户任务指令
* @param {number} maxIterations 最大迭代轮次,防止死循环
* @returns {string} 最终执行结果
*/
async function runAgentWithTools(query, maxIterations = 30) {
const messages = [
new HumanMessage(query)
];
// 循环执行:模型思考→调用工具→接收结果→再次思考
for (let i = 0; i < maxIterations; i++) {
console.log(chalk.bgGreen(`第${i+1}轮迭代 `));
const response = await modelWithTools.invoke(messages);
messages.push(response);
// 无工具调用,任务结束,返回最终回答
if (!response.tool_calls || response.tool_calls.length === 0) {
console.log(chalk.bgRed(`AI 最终回答: ${response.content}`));
return response.content
}
console.log(chalk.bgBlue(`本轮工具调用:
${response.tool_calls.map(t => t.name).join(', ')}
`));
// 逐个执行模型发起的工具调用
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两种返回格式:纯字符串 / {text: "内容"} 对象
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
}));
}
}
}
// 达到最大迭代次数,返回最后一条AI输出
return messages[messages.length-1].content;
}
// 实战任务:查询北京南站最近3家酒店、生成文档、浏览器分页打开酒店图片并修改标签标题
await runAgentWithTools("北京南站附近的酒店,最近的 3 个酒店,拿到酒店图片,打开浏览器,每个tab一个url展示,并且把页面标题改为酒店名,同时将酒店信息、步行/驾车路线保存为本地md文档");
// 关闭所有MCP进程连接
await mcpClient.close();
四、实战场景完整执行效果
需求拆解
- 调用高德MCP,定位北京南站,筛选距离最近3家酒店,获取坐标、地址、评分、图片链接、步行/驾车路线
- 调用FileSystem MCP,自动生成
北京南站附近酒店及路线指南.md保存全部数据 - 调用Chrome DevTools MCP,新开3个浏览器标签,分别加载酒店图片,修改每个Tab页面标题为对应酒店名称
生成文档核心内容节选
北京南站附近酒店及路线指南
📍 北京南站 | 坐标:
116.378059, 39.867679| 北京市丰台区
🏨 推荐酒店概览
| 序号 | 酒店名称 | 评分 | 步行距离 | 驾车距离 |
|---|---|---|---|---|
| 1 | 汉庭酒店(北京南站北广场店) | ⭐4.4 | 约403米 | 约1.2公里 |
| 2 | 海友酒店(北京南站南广场店) | ⭐4.4 | 约1.6公里 | 约1.8公里 |
| 3 | 桔子酒店(北京南站店) | ⭐4.6 | 约1.5公里 | 约1.6公里 |
酒店路线详情
每家酒店单独区块,包含完整步行分步指引、驾车路线、商圈信息,最后附带综合对比表格与入住推荐建议。
浏览器执行动作
Agent拿到每家酒店图片URL后,自动调用Chrome工具:
- 新建独立Tab页
- 跳转图片链接
- 修改页面document.title为酒店全称
- 3个酒店对应3个独立浏览器标签
五、开发高频踩坑提醒
坑1:Chrome MCP启动失败
报错:无法连接Chrome调试端口 解决:启动Chrome时开启远程调试端口
bash
chrome --remote-debugging-port=9222
必须先打开带调试端口的浏览器,再运行脚本。

坑2:FileSystem无权限读写文件
报错:文件夹访问拒绝 解决 :npx参数里的目录路径必须是绝对路径,Windows路径分隔符统一用/,不要用\。
坑3:工具调用频繁失效、模型乱输出
解决 :LLM配置temperature:0,降低随机度,保证工具调用逻辑稳定;最大迭代次数建议设置20~30,避免多轮工具调用中断。
坑4:MCP返回数据解析报错
部分MCP工具返回对象带text字段,部分直接返回纯字符串,代码中做了双重兼容,不要删除类型判断逻辑。
坑5:脚本运行结束进程残留
代码末尾必须执行await mcpClient.close(),否则npx启动的子进程会常驻后台占用端口。
六、MCP核心优势总结
- 统一工具标准:高德、文件、浏览器三类能力一套客户端管理,无需单独写接口适配
- 可复用生态:任何人开发MCP Server,直接接入项目,不用重构Agent逻辑
- 本地/远程双模式:高德HTTP远程服务、文件/浏览器本地子进程服务同时兼容
- Agent自动编排:大模型自主判断何时调用地图、何时写文件、何时操控浏览器,不用手动拆分任务
- 低维护成本:新增工具仅需在mcpServers配置新增节点,其余代码完全不用改动