
1. 从一次真实需求说起为什么单靠模型搞不定多工具协同我试过让模型直接回答“北京南站附近有哪些酒店帮我规划路线并保存成文档”结果它给出的酒店名字听起来很合理但一查地图根本不存在。原因很简单大模型擅长语言推理但它没有实时地图数据也不能真的往你硬盘里写文件。它只能“编”不能“做”。这就是远程 MCP 项目实战要解决的问题。MCP 全称 Model Context Protocol是一套让大模型应用用统一协议调用外部工具的标准。你可以把它理解成“AI 世界的 USB-C 接口”以前每接一个工具就要写一套适配代码现在只要工具方按 MCP 协议暴露服务客户端就能统一发现、统一调用。LangChain 作为编排层负责把模型、MCP 工具和 Agent 循环串起来。这篇文章面向的是已经会写基础 LangChain 代码、想进一步做多工具协同智能体的开发者。我会用高德地图 MCP 做地点与路线查询用 Chrome DevTools MCP 做浏览器控制用 FileSystem MCP 做本地文件读写再用 TaoToken 统一模型调用通道把整条链路跑通。适合谁适合正在做 AI Agent 落地、需要接入真实外部能力、又不想为每个工具单独造轮子的同学。整篇文章的检索核心是LangChain 连接远程 MCP 服务并实现多工具协同。下面从环境准备开始一步步给出可复制的配置和代码。2. TaoToken 前置准备统一 Key 与 API 通道在写 MCP 客户端之前先把模型调用通道准备好。多工具 Agent 会频繁调用模型如果每个模型服务商都单独管理 Key、单独配 baseURL后期切换和维护会很麻烦。TaoToken 的作用就是提供统一的 API 通道和 Key 管理让 LangChain 侧只需要配置一个入口。你需要先拿到两样东西一个是 TaoToken 的 API Key一个是确认要使用的模型 ID。API Key 在控制台的 API Keys 页面创建地址是 https://taotoken.net/api-keys 。创建后复制保存后面写进.env文件。模型 ID 可以在模型对话页面确认地址是 https://taotoken.net/model-chat 选一个支持工具调用function calling的模型这点很关键因为 MCP 工具调用依赖模型返回结构化的 tool_calls。TaoToken 的 API 入口是 https://taotoken.net/api 注意这个地址不带任何查询参数直接作为 baseURL 使用。LangChain 的ChatOpenAI兼容 OpenAI 格式所以只要把 baseURL 指向这个入口apiKey 填 TaoToken 的 Key就能调用。如果你后续要做长期编码或 Agent 任务可以了解 Coding Plan地址是 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentlangchain_mcp_agent 它更适合高频、长周期的开发场景。这里要强调一个原则模型 Key、高德 Key 都属于敏感信息全部放环境变量不要硬编码。项目根目录建一个.env文件内容大致如下TAOTOKEN_API_KEY你的TaoTokenKey AMAP_MAPS_API_KEY你的高德地图Key然后在.gitignore里加上.env避免密钥被提交到仓库。高德地图 Key 需要去高德开放平台申请选择 Web 服务类型因为 MCP 走的是 HTTP 接口。这一步做完模型通道和地图通道的凭证就齐了。TaoToken 在这里承担的是“统一模型出口”的角色不管后面 Agent 循环调用多少次模型都走同一个 baseURL 和同一个 Key切换模型时只改 modelName不用动其他代码。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentlangchain_mcp_agent 遇到参数细节可以对照查。3. 可复制配置MCP Server 与 LangChain 客户端这一节给出完整可复制的配置。先装依赖npm init -y npm install langchain/mcp-adapters langchain/openai langchain/core dotenv chalklangchain/mcp-adapters提供MultiServerMCPClient这是连接多个 MCP Server 的核心类。它支持两种连接方式远程 HTTP 用url本地进程用commandargs。下面这份配置同时接入高德地图、Chrome DevTools、文件系统三类服务你可以直接复制到项目里。import dotenv/config; import { MultiServerMCPClient } from langchain/mcp-adapters; const mcpClient new MultiServerMCPClient({ mcpServers: { // 远程 MCP高德地图走 HTTP amap-maps-http: { url: https://mcp.amap.com/mcp?key${process.env.AMAP_MAPS_API_KEY} }, // 本地 MCP文件系统只开放指定工作目录 filesystem: { command: npx, args: [ -y, modelcontextprotocol/server-filesystem, /Users/yourname/workspace/mcp-demo ] }, // 本地 MCPChrome DevTools控制浏览器 chrome-devtools: { command: npx, args: [-y, chrome-devtools-mcplatest] } } });这段配置里amap-maps-http是远程服务不需要本地启动进程直接通过 URL 连接。filesystem和chrome-devtools是本地 stdio 方式npx会自动拉取对应的 MCP Server 包。文件系统那个路径参数非常重要它限定了 AI 只能在这个目录下读写千万不要写成/或用户主目录。如果你用的是支持 MCP 的编辑器比如 Trae、Cline可以把同样的结构写成 JSON 放进 MCP 配置区{ mcpServers: { amap-maps-http: { url: https://mcp.amap.com/mcp?key你的高德Key }, filesystem: { command: npx, args: [-y, modelcontextprotocol/server-filesystem, /Users/yourname/workspace/mcp-demo] }, chrome-devtools: { command: npx, args: [-y, chrome-devtools-mcplatest] } } }注意 JSON 里不能写${process.env...}要填真实值所以这种配置方式更适合本地临时调试正式项目还是用代码读环境变量。接下来创建模型并绑定工具。这里用 TaoToken 作为统一通道import { ChatOpenAI } from langchain/openai; const model new ChatOpenAI({ modelName: 你的模型ID, apiKey: process.env.TAOTOKEN_API_KEY, temperature: 0, configuration: { baseURL: https://taotoken.net/api } }); const tools await mcpClient.getTools(); const modelWithTools model.bindTools(tools);temperature: 0是为了让工具调用更稳定减少模型随机发挥。getTools()会连接所有配置的 MCP Server把工具列表拉回来并转换成 LangChain Tool。bindTools()把工具绑定到模型绑定后模型才能生成tool_calls。这里有个关键点工具能不能被正确调用取决于工具描述是否清晰。高德地图 MCP 会暴露地点搜索、路线规划等工具文件系统 MCP 会暴露读写文件工具Chrome DevTools MCP 会暴露浏览器控制工具。模型根据这些描述判断“什么时候用哪个”。4. 端到端验证Agent 循环与成功结果配置完成后写 Agent 循环把模型和工具串起来。核心逻辑是模型判断是否需要工具需要就执行把结果放回上下文再让模型继续判断直到不再请求工具。import { HumanMessage, ToolMessage } from langchain/core/messages; function stringifyToolResult(result) { if (typeof result string) return result; if (result?.content) return JSON.stringify(result.content); return JSON.stringify(result); } async function runAgent(query, maxIterations 30) { const messages [new HumanMessage(query)]; 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(最终回答, response.content); return response.content; } for (const toolCall of response.tool_calls) { const foundTool tools.find(t t.name toolCall.name); if (!foundTool) continue; const toolResult await foundTool.invoke(toolCall.args); messages.push(new ToolMessage({ content: stringifyToolResult(toolResult), tool_call_id: toolCall.id })); } } return messages[messages.length - 1].content; } await runAgent(北京南站附近的2个酒店以及去的路线路线规划生成文档保存到当前目录的一个 md 文件); await mcpClient.close();运行这段代码你会看到终端里一轮轮打印工具调用。第一轮模型通常会调用高德地图的地点搜索工具拿到北京南站附近的酒店列表第二轮可能调用路线规划工具分别算到两个酒店的路线第三轮模型整理好 Markdown 内容后调用文件系统工具写入文件。最后模型不再请求工具输出最终回答。验证成功的标志有三个终端能看到工具调用日志工作目录下真的生成了.md文件打开里面有酒店名称和路线模型最终回答里总结了做了什么。如果文件生成了但内容是空的多半是模型整理内容时参数没传对检查文件写入工具的 args 结构。tool_call_id这个字段不能省。当模型一次请求多个工具时它靠这个 ID 把结果和请求对应起来。少了它模型可能把 A 工具的结果当成 B 工具的导致后续推理错乱。5. 常见报错排查401、local proxy failed 与 reading choices实际跑的时候最容易在这几个地方卡住。下面按真实报错对照排查。401 Unauthorized。这个通常出现在模型调用或高德接口。先确认.env里的TAOTOKEN_API_KEY和AMAP_MAPS_API_KEY都加载成功可以在代码里临时打印process.env.TAOTOKEN_API_KEY是否存在。如果 Key 没问题检查 baseURL 是不是写成了https://taotoken.net/api多一个斜杠或少一个路径都可能 401。高德那边则要确认 Key 是 Web 服务类型且没有开启 IP 白名单限制。local proxy failed / connection refused。这类错误多出现在本地 MCP Server 启动失败。npx拉包需要网络如果本地 npm 源不通filesystem和chrome-devtools就起不来。可以先在终端手动跑一遍npx -y modelcontextprotocol/server-filesystem /你的目录看能不能正常启动。另外 Chrome DevTools MCP 需要本地有可用的 Chrome 实例没装浏览器也会失败。reading choices of undefined。这个报错说明模型返回结构不符合预期通常是 baseURL 或模型 ID 配错请求打到了非兼容接口。确认modelName是 TaoToken 支持的、且具备工具调用能力的模型 ID。如果模型不支持 function calling返回里就没有tool_callsAgent 循环会直接结束表现成“模型不调用工具”。OAuth / 鉴权相关报错。远程 MCP 服务如果要求额外鉴权URL 里要带上对应 token。高德 MCP 目前通过key查询参数鉴权格式是https://mcp.amap.com/mcp?keyxxx。如果换成其他远程 MCP要按它的文档补鉴权参数。工具找不到foundTool 为 undefined。说明模型请求了一个工具列表里不存在的名字。打印tools.map(t t.name)看看实际有哪些工具再对照模型返回的toolCall.name。有时候是 MCP Server 没连上工具列表为空导致的。排查时建议把console.log(tools)打开先确认工具列表非空再确认模型返回了tool_calls最后确认工具执行有结果。这三步定位下来大部分问题都能找到。6. 把链路用起来模型对话、接入文档与 Coding Plan整条链路跑通后你会发现 MCP LangChain 的价值在于开发者不用把每个步骤写死在业务代码里而是提供工具能力和执行循环让模型动态决定下一步。高德地图负责真实地理信息Chrome DevTools 负责浏览器操作文件系统负责落地结果TaoToken 负责统一模型出口。想快速验证模型是否支持工具调用可以直接在模型对话页面试地址是 https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentlangchain_mcp_agent 输入一个需要多步推理的问题看它会不会主动请求工具。接入参数和鉴权细节对照接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentlangchain_mcp_agent 。Key 管理在 API Keys 页面 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentlangchain_mcp_agent 。如果你要做长期编码或 Agent 项目Coding Plan 地址是 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentlangchain_mcp_agent 。最后留一个实用技巧给文件系统 MCP 单独建一个工作目录每次任务前清空任务后检查产物。这样既能保证 AI 有明确的读写范围又方便你验证它到底做了什么。多工具协同的智能体稳定性和可观测性比功能数量更重要。