当前位置: 首页 > news >正文

Agent 智能体开发实战 · 第七课:Remote MCP —— 从本地工具到远程服务

上节回顾:第六课我们用 MCP 协议让 Agent 跨进程调用本地工具——通过 stdio 启动自己的 MCP Server 子进程。

本课聚焦:MCP 不止 stdio 本地调用,还支持HTTP 远程调用npm 包直接拉起。本课让 Agent 同时连接高德地图(远程)、Chrome DevTools(远程调试)、FileSystem(npm 包)和自己的 my-mcp-server(本地)——四个不同来源的 MCP Server 协同工作,完成一个真实的AI 工作流


📖 本课目录

  • 一、从本地 MCP 到远程 MCP
  • 二、四种 MCP Server 连接方式
  • 三、核心改造:兼容多种 Tool 返回格式
  • 四、完整代码拆解
  • 五、AI 工作流实战:查酒店 → 开浏览器 → 保存结果
  • 六、本课学习总结

一、从本地 MCP 到远程 MCP

🔙 第六课的 MCP 架构

Agent ──stdio──► my-mcp-server(本地子进程) └─ query-user Tool

第六课只用了 stdio 本地通信,MCP Server 是自己写的 Node.js 脚本。

🚀 本课的 MCP 架构

┌─────────────┐ │ amap-mcp │ 高德地图(HTTP 远程) │ URL 连接 │ → 位置查询、路线规划 └─────────────┘ │ HTTP ┌─────┴───────┐ Agent ──stdio──►│ my-mcp-server│ 本地子进程(复用第六课) └─────────────┘ │ stdio ┌─────┴───────┐ │ filesystem │ npm 包(npx 拉起) │ 读写文件 │ → @modelcontextprotocol/server-filesystem └─────────────┘ │ stdio ┌─────┴───────┐ │ chrome-devtools│ npm 包(npx 拉起) │ 操控浏览器 │ → 打开 Tab、点击、截图 └─────────────┘

🎯核心突破:一个 Agent 同时连接 4 个 MCP Server——2 个远程/包、1 个本地自己写的、1 个 npm 的——工具从"自己造"变成了"接入现成的生态"。


二、四种 MCP Server 连接方式

MultiServerMCPClient的配置字典中,每个 Server 用 key 标识,value 可以是两种格式:

连接方式配置格式原理
🔗HTTP 远程{ url: "https://..." }直接 HTTP 请求,不需要启动子进程
🖥️stdio 本地{ command: "...", args: [...] }同第六课,spawn 子进程,stdin/stdout 通信

基于这个配置,来看本课连接的 4 个 Server:

1. 高德地图 MCP(HTTP 远程)

'amap-mcp':{url:"https://mcp.amap.com/mcp?key=f0259c6adf20e8543e0773baxxxxx"}

URL 里带 API key(需要去 developer.amap.com 申请),连接后可以调用位置查询、路线规划等工具。这是远程 MCP——不需要本地启动任何进程。

2. 自己的 MCP Server(stdio 本地)

'my-mcp-server':{command:'node',args:['C:/Users/yihao/Desktop/workspace/yh_ai/ai/ai/agent_in_action/mcp-demo/src/my-mcp-server.mjs']}

复用第六课写的query-user工具,通过node+ 脚本路径拉起。

3. FileSystem MCP(npm 包,npx 拉起)

'filesystem':{command:'npx',args:['-y','@modelcontextprotocol/server-filesystem',// 允许访问的文件夹,可以配置多个,用空格隔开'C:/Users/yihao/Desktop/workspace/yh_ai/ai/ai/agent_in_action/remote-mcp']}
要点说明
command: 'npx'不是 node,是 npx——直接运行 npm 包
-y自动确认,跳过安装确认提示
@modelcontextprotocol/server-filesystemnpm 上发布的 MCP Server 包
文件夹路径参数传给 Server,限制它只能操作这个文件夹

💡不用自己写工具了。FileSystem 是社区已有的 MCP Server,提供read_filewrite_filelist_directory等——跟第四课的all-tools.mjs功能一样,但它是独立进程、独立语言实现。

4. Chrome DevTools MCP(npm 包,npx 拉起)

// Chrome‑DevTools MCP,默认连接本地打开的Chrome// (开启远程调试:chrome --remote-debugging-port=9222)'chrome-devtools':{command:'npx',args:['-y','chrome-devtools-mcp@latest',]}

连接已打开的 Chrome 浏览器(需以chrome --remote-debugging-port=9222启动),提供打开页面、点击元素、截图、修改标题等浏览器操控能力。

🔑 四种 Server 对比

Server连接方式来源提供的能力
🗺️ amap-mcpHTTP URL高德开放平台位置查询、路线规划
🏠 my-mcp-serverstdio (node)自己写的(第六课)用户信息查询
📁 filesystemstdio (npx)npm 包读写文件、列目录
🌐 chrome-devtoolsstdio (npx)npm 包操控浏览器 Tab、截图

三、核心改造:兼容多种 Tool 返回格式

第六课的 Tool 返回格式是固定的——自己写的 Server,返回的content格式可控。但远程 MCP Server(高德、Chrome DevTools 等)的返回格式五花八门:

返回类型示例来源
纯字符串"查询结果:xxx"多数 stdio Server
content 数组[{ type: 'text', text: '...' }]标准 MCP 返回
对象{ text: '...', result: '...' }某些第三方 Server

本课的invoke部分做了格式兼容处理

letcontentStr;try{consttoolResult=awaitselectedTool.invoke(tool_call.args);// mcp tool 返回一般是字符串// 还可能是 content 数组if(typeoftoolResult==='string'){contentStr=toolResult;}elseif(Array.isArray(toolResult)){contentStr=toolResult.map(item=>item.text||JSON.stringify(item)).join('\n');}elseif(toolResult&&typeoftoolResult==='object'){contentStr=toolResult.text||toolResult.result||JSON.stringify(toolResult);}else{contentStr=String(toolResult);}}catch(err){console.log(chalk.red(`工具调用失败${tool_call.name}:${err.message}`));contentStr=`Error:${err.message}`;}messages.push(newToolMessage({tool_call_id:tool_call.id,content:contentStr}));
处理分支逻辑
typeof === 'string'直接使用
Array.isArray提取每个元素的.text,拼接
typeof === 'object'优先取.text.result→ JSON 序列化
兜底String()强制转字符串
try-catch工具调用失败也不崩溃,返回错误信息

🎯 这是工程化的关键细节——你控制不了远程 Server 的返回格式,必须做兼容处理


四、完整代码拆解

第1步:导入 + LLM 初始化

import'dotenv/config';import{MultiServerMCPClient}from'@langchain/mcp-adapters';import{ChatOpenAI}from'@langchain/openai';importchalkfrom'chalk';importfsfrom'node:fs';importpathfrom'node:path';import{HumanMessage,SystemMessage,ToolMessage}from'@langchain/core/messages';constmodel=newChatOpenAI({modelName:'deepseek-v4-pro',apiKey:process.env.DEEPSEEK_API_KEY,temperature:0,configuration:{baseURL:'https://api.deepseek.com/v1',},});

第2步:配置 4 个 MCP Server

constmcpClient=newMultiServerMCPClient({mcpServers:{'amap-mcp':{url:"https://mcp.amap.com/mcp?key=f0259c6adf20e8543e0773baxxxxxx"},'my-mcp-server':{command:'node',args:['C:/Users/yihao/Desktop/workspace/yh_ai/ai/ai/agent_in_action/mcp-demo/src/my-mcp-server.mjs']},'filesystem':{command:'npx',args:['-y','@modelcontextprotocol/server-filesystem',// 允许访问的文件夹,可以配置多个,用空格隔开'C:/Users/yihao/Desktop/workspace/yh_ai/ai/ai/agent_in_action/remote-mcp']},// Chrome‑DevTools MCP,默认连接本地打开的Chrome// (开启远程调试:chrome --remote-debugging-port=9222)'chrome-devtools':{command:'npx',args:['-y','chrome-devtools-mcp@latest',]}}})

🎯 4 个 Server 配置在一个对象里,MultiServerMCPClient统一管理连接、获取工具、关闭连接。Agent 不用知道哪个 Tool 来自哪个 Server。

第3步:获取工具 + bindTools

consttools=awaitmcpClient.getTools();console.log(tools);// 打印所有可用工具,看看4个Server总共提供了多少constmodelWithTools=model.bindTools(tools);

第4步:Agent Loop

asyncfunctionrunAgentWithTools(query,maxIterations=30){constmessages=[newHumanMessage(query)];for(leti=0;i<maxIterations;i++){console.log(chalk.bgGreen(`${i+1}轮迭代`));constresponse=awaitmodelWithTools.invoke(messages);messages.push(response);if(!response.tool_calls||response.tool_calls.length===0){console.log(chalk.green(`AI 回答:${response.content}`));returnresponse.content;}console.log(chalk.bgBlue(`工具调用${response.tool_calls.map(t=>t.name).join(', ')}`))for(consttool_callofresponse.tool_calls){constselectedTool=tools.find(t=>t.name===tool_call.name);if(!selectedTool){console.log(chalk.red(`未找到工具:${tool_call.name}`));continue;}// 格式兼容处理(见第三节)// ...messages.push(newToolMessage({tool_call_id:tool_call.id,content:contentStr}));}}// 最后一次消息是AI的回复returnmessages[messages.length-1].content;}

第5步:启动 + 保存结果

constresult=awaitrunAgentWithTools("北京南站附近的酒店,最近的 3 个酒店,拿到酒店图片,打开浏览器,展示每个酒店的图片,每个 tab 一个 url 展示,并且在把那个页面标题改为酒店名");// 保存结果到 md 文件constoutputDir=path.resolve(import.meta.dirname,'../output');fs.mkdirSync(outputDir,{recursive:true});constoutputPath=path.join(outputDir,`hotel-result-${Date.now()}.md`);fs.writeFileSync(outputPath,`# 北京南站附近酒店查询结果\n\n${result}\n`);console.log(chalk.cyan(`\n✅ 结果已保存到:${outputPath}`));

📂 运行一次就生成一个带时间戳的.md文件在remote-mcp/output/,记录完整结果。


五、AI 工作流实战:查酒店 → 开浏览器 → 保存结果

🎬 任务拆解

Agent 收到一个复杂任务:“北京南站附近的酒店,最近的 3 个酒店,拿到酒店图片,展示在浏览器,图片标题改为酒店名”

这不是一个单一操作,而是一个多步骤工作流

┌─────────────────────────────────────────────────┐ │ 🗺️ Step 1: amap-mcp │ │ 搜索"北京南站"坐标 → 查询附近酒店 → │ │ 返回酒店列表(名称、距离、评分) │ └─────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────┐ │ 🗺️ Step 2: amap-mcp │ │ 根据酒店名称搜索图片 URL │ │ 拿到每个酒店的图片链接 │ └─────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────┐ │ 🌐 Step 3: chrome-devtools │ │ 为每个酒店开一个 Chrome Tab │ │ 修改每个 Tab 的标题为酒店名 │ │ 设置 page title 方便用户识别 │ └─────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────┐ │ 📁 Step 4: filesystem │ │ 将结果写入 output/hotel-result-xxx.md │ │ 保存完整的查询结果 │ └─────────────────────────────────────────────────┘

🎯 实际产出

运行node src/mcp-test.mjs后,Agent 自动完成了所有步骤,在output/生成了结果文件:

# 北京南站附近酒店查询结果 | 排名 | 酒店名称 | 步行距离 | 评分 | Tab | |------|----------|----------|------|-----| | 🥇 | **北京永鑫宾馆** | **228米** | ⭐4.2 | Tab 2 | | 🥈 | **轻羽精品酒店(北京南站北广场店)** | **257米** | ⭐3.2 | Tab 3 | | 🥉 | **米家青年酒店(北京南站店)** | **304米** | ⭐3.6 | Tab 4 |

🤯 人工只做了一件事——描述需求。Agent 自动调度 3 个 MCP Server(高德、Chrome DevTools、FileSystem)完成了整个工作流。

🧩 MCP 生态的核心价值

有了 MCP 协议后:

以前:想用高德地图?→ 读 API 文档 → 写 fetch 调用 → 自己封 Tool 现在:高德提供了 MCP Server → url 配上去 → getTools() → 直接用 以前:想操控浏览器?→ 学 Puppeteer/Playwright → 写脚本 现在:chrome-devtools-mcp → npx 拉起 → getTools() → 直接用 以前:跨团队共享工具?→ 写成 npm 包 → 对方 import → 还是得同语言 现在:写成 MCP Server → 任何语言 → 任何项目 → getTools() → 直接用

🎯MCP 把 Tool 从"自己造"变成了"接入生态"——任何人都可以开发基于这个协议的 MCP Server,然后直接复用。高德地图、Chrome DevTools、FileSystem 这些不是我们自己写的,但它们提供的 Tool 跟我们自己写的一样用。


六、本课学习总结

🧠 知识点

📋 Remote MCP · 知识点 │ ├── 🚀 从本地到远程 │ ├── 第六课:只有 stdio 本地 │ └── 本课:HTTP 远程 + npx 包 + stdio 本地 混合 │ ├── 🔗 四种 MCP Server 连接方式 │ ├── 🗺️ amap-mcp(HTTP URL) │ │ └── 高德地图 API,纯远程调用,不需本地进程 │ ├── 🏠 my-mcp-server(stdio · node) │ │ └── 复用第六课自己的 Server │ ├── 📁 filesystem(stdio · npx) │ │ └── npm 包 @modelcontextprotocol/server-filesystem │ └── 🌐 chrome-devtools(stdio · npx) │ └── npm 包 chrome-devtools-mcp@latest │ ├── 🔧 格式兼容处理 │ ├── string → 直接用 │ ├── Array → 提取 .text 拼接 │ ├── object → .text → .result → JSON │ ├── 兜底 → String() │ └── try-catch → 不崩溃 │ ├── 🔄 Agent Loop │ ├── for + ToolMessage(同第五课) │ ├── 多 Server 统一管理 │ └── tools 来自 4 个不同来源 │ ├── 💾 结果持久化 │ ├── fs.mkdirSync + recursive │ ├── fs.writeFileSync │ ├── 带时间戳的文件名 │ └── 保存在 output/ 目录 │ └── 🧩 MCP 生态价值 ├── 工具从"自己造" → "接入生态" ├── 任何人开发 → 任何人复用 ├── 高德/Chrome/FileSystem 即插即用 └── Agent 的能力 = 接入的 MCP Server 数量

✅ 知识清单

编号掌握项核心要点
1HTTP 远程 MCP{ url: "https://..." }连接远程 Server,不需本地进程
2npx 拉起 MCP{ command: 'npx', args: ['-y', 'package-name'] }
3混合连接一个MultiServerMCPClient同时连 HTTP + stdio + npx
4返回格式兼容string / array / object 三种类型都要处理
5高德 MCP 接入URL 带 API Key,提供位置查询、路线规划
6Chrome DevTools MCP操控浏览器:打开 Tab、截图、修改标题
7FileSystem MCPnpm 包读写文件,限制访问目录
8AI 工作流Agent 自动编排多个 Server 完成多步骤任务
9结果保存fs.writeFileSync+ 时间戳文件名,持久化到 output/
10MCP 生态工具不再自己写,接入现成 MCP Server 即可

📊 基础 Agent → MCP 优化 → Remote MCP

维度前五课 · 基础 Agent第六课 · MCP 本地第七课 · Remote MCP
工具来源本地定义 / importMCP stdio 动态获取HTTP + npx + stdio 混合
Server 类型自己写的 Node 脚本自己写的 + npm 包 + 远程服务
连接方式stdiostdio + HTTP URL
工具数量1 → 4N(本地 Server 提供)N×M(M 个 Server 各提供 N 个)
生态复用✅ 高德/Chrome/FileSystem 即插即用
返回格式固定字符串自己控制的格式需兼容 string/array/object

🎯本课定位:第六课证明了 MCP 能让工具脱离 Agent 进程。本课进一步证明——工具不需要自己写。高德地图、Chrome DevTools、FileSystem 这些成熟的 MCP Server 直接接入,Agent 的能力不再受限于你写工具的能力,而取决于你接入了多少个 MCP Server。


📅 2026-07-13 | 🏷️ Agent · MCP · Remote MCP · HTTP · AI工作流 · 第七课

http://www.jsqmd.com/news/1183939/

相关文章:

  • EldenRingSaveCopier终极指南:3步安全迁移你的艾尔登法环存档
  • 北京本地正规汽车空调系统维保店联系方式实用指南 - 热点品牌推荐
  • 2026 重庆权威优选正规婚恋|余生婚恋(2013 年本土老牌)实名一对一高端相亲完整版 FAQ - 星际AI
  • 天津地区职业卫生检测机构实测评测:资质与经验对比 - 起跑123
  • 2026年大庆本地车主车膜线下门店怎么选更靠谱 - 热点品牌推荐
  • 2026年济南散酒加盟靠谱品牌选型参考指南 - 起跑123
  • 滨湖新区回收空调公司服务全指南 本地旧空调处置实用攻略 - 热点品牌推荐
  • 2026年四川区域实验室植物培养原料工厂找哪家更省心 - 热点品牌推荐
  • 2026年正负极弹簧批发哪家强 珠三角源头厂选购全指南 - 热点品牌推荐
  • 2026年襄阳本地福特车轮胎轮毂靠谱门店选购参考 - 热点品牌推荐
  • 萧邦售后维修基本多少钱?手表保养与维修费用指南权威公示(2026年7月最新) - 萧邦中国官方服务中心
  • 合肥买手机哪里便宜又好?排名前三实测,第一名果然没让我失望…… - 安徽胡歌
  • 我用了3个月AI数字人直播,省下12万人力成本,但这3个坑差点让我放弃——真实账本公开!
  • 石家庄这家大飞汽车音响改装店太强了 - 烈焰猫科技
  • 2026年毕节陶粒混凝土定制厂家高性价比企业梳理参考 - 热点品牌推荐
  • 2026年冀鲁辽地区制氢充电工程企业哪家性价比高 - 热点品牌推荐
  • 2026年7月国内主流eHR系统服务商名录参考 - 起跑123
  • 2026宁波口碑好的 宁波高考复读学校资源汇总 中立评测参考指南 - 起跑123
  • 百达翡丽中国官方售后服务中心|服务电话和详细网点地址权威信息通告(2026年7月最新) - 百达翡丽服务中心
  • HarmonyOS APP实战-画图APP - 第12篇:离线图像处理与保存
  • 重庆向前冲商业管理旗下向前冲公寓大学生租房体验全解析 - 起跑123
  • 一个服装店老板的自述:从月亏3万到净利润8万,我只是换了种直播方式!
  • DeepSeek逻辑推理题实战精讲:从零构建推理链,7步拿下95%高难度题型
  • 2026珠海本地正规实体婚恋行业权威深度测评白皮书(珠海靠谱相亲机构TOP5榜单 - 星际AI
  • 2026年7月国内口碑好的考勤系统服务商选型参考名录 - 起跑123
  • 2026年7月最新南宁爱彼官方售后服务网点地址及客服电话一览 - 爱彼中国官方服务中心
  • HoRain云--LangChain 对话记忆
  • 2026年美国物流专线哪家好 帝航供应链时效专项评测 - 起跑123
  • HarmonyOS APP实战-画图APP - 第14篇:可变帧率与性能优化
  • 2026宁波高复优质高三复读学校盘点 - 起跑123