ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

LangChain与MCP组合实战:构建Agent工具调用与生产级应用

LangChain与MCP组合实战:构建Agent工具调用与生产级应用 最近把 LangChain 和 MCP 的组合完整跑了一遍。先说结论LangChain 负责把大模型应用编排起来MCP 负责让模型通过统一协议调用外部工具和数据源两者配合之后做 Agent 应用会省掉大量自定义工具接入的重复代码。这篇文章适合正在做 Agent、想让模型接实时搜索、数据库、文件或浏览器工具的开发者。最值得关注的不只是怎么跑通一个 Demo而是你能不能形成一套稳定的方式把工具接入、错误处理、批量任务和生产化部署都管起来。我不会按“从入门到精通”的口号式思路来写而是按实际落地顺序拆先理清概念再准备环境然后从零写一个 MCP Server 并用 LangChain 调用接着扩展联网检索、RAG、记忆和多工具编排最后把批量并发和常见排查链路讲清楚。内容偏工程实操每个阶段都给出判断标准。1. 先理清 LangChain、LangGraph 和 MCP 到底在解决什么问题1.1 LangChain把零散大模型能力组织成应用的组件库LangChain 不是模型而是一个应用开发框架。它把大模型应用里常见的环节拆成了组件比如模型调用、提示词管理、记忆、检索、工具、Agent、链式流程。你用 LangChain 写应用本质上是在拼这些组件。很多人会问 LangChain、vLLM、PyTorch 是不是同一类东西。不是。PyTorch 是深度学习训练和推理的底层框架vLLM 是高性能推理服务LangChain 是应用层框架负责调用模型并把流程编排起来。你可以用 LangChain 接入 OpenAI、Anthropic、本地模型也可以接 vLLM 部署的服务它们是不同层级的分工。现在的 LangChain 已经不像早期那样只靠 Chain 串流程。官方更推荐使用 LCEL 表达式语言复杂流程则交给 LangGraph。如果你只是想在模型外面套一层固定的提示词模板LangChain 是够用的如果你的应用里存在条件分支、循环、人工审批、多角色协作那就要把 LangGraph 纳入考虑。1.2 MCP用一套协议让模型工具接入标准化MCP 全称 Model Context Protocol中文常叫模型上下文协议。它的目标是统一“模型应用”和“外部工具/数据源”之间的连接方式。MCP 的架构可以拆成三层MCP Host承载 Agent 或应用的宿主比如桌面客户端、IDE 插件、LangChain Agent。MCP Client在宿主内部负责和 Server 通信的客户端。MCP Server提供具体能力的服务比如文件读取、网页抓取、数据库查询。一个 MCP Server 可以暴露三类能力Tools可被模型调用的函数包含名称、描述、参数 JSON Schema。Resources可读取的数据资源比如文件内容、配置信息。Prompts预置的提示词模板客户端可以直接复用。为什么需要 MCP因为以前每个 Agent 接一个工具就要写一套自定义调用代码工具参数格式可能还不一样。MCP 把工具发现、参数声明、调用、结果返回变成了标准化流程。MCP Server 写一次支持 MCP 的客户端都能用。经常看到的.mcp文件其实是 MCP 客户端的服务配置文件通常记录 command、args、env 等信息。你可以理解成“告诉客户端去哪里启动哪个 Server”的配置片段。1.3 LangChain 与 LangGraph 的分工很多人看到 LangGraph 和 LangChain 的区别就头大。简单理解LangChain 是组件库提供模型、提示词、记忆、工具、RAG 等基础能力。LangGraph 是图式状态编排框架负责管理复杂流程的状态、分支、循环和持久化。用 LangChain 自带的 AgentExecutor 也能做工具调用。流程简单时它足够直接。流程一旦复杂起来比如需要多轮工具调用、有条件分支、需要人工确认、需要从故障点恢复AgentExecutor 就会显得不够灵活。LangGraph 并不是要取代 LangChain而是复用 LangChain 的模型、提示词、工具和检索组件在更上层做状态化编排。如果你看到官方示例里大量使用 LangGraph不必意外这是 LangChain 生态里复杂工作流的主流路线。1.4 Skill、Agent Skill 与 MCP 的区别社区里经常讨论 Agent Skill 和 MCP 的区别。我的理解是MCP 解决的是“工具怎么被模型调用”的协议问题。Skill 更偏“把完成某类任务的知识、指令、提示词甚至脚本打包成一个能力包”。一个 Agent 可以同时拥有 Skill 和 MCP 工具。Skill 告诉模型该怎么干MCP 给模型提供实际去调用某个系统的接口。可以粗略类比成Skill 是操作手册MCP 是标准插头。两者不是竞争关系侧重点不同。2. 环境准备装什么、去哪找 MCP Server、关键概念2.1 基础环境和依赖我建议先确认 Python 版本。MCP 相关依赖通常要求 Python 3.10 以上具体以你安装的包为准。不要一上来就装一堆先看目标 MCP Server 的 README再把依赖装进虚拟环境。基础依赖一般包括langchain主框架。langchain-openai 或 langchain-anthropic模型接入。mcpMCP 协议库。langchain-mcp-adaptersLangChain 和 MCP 之间的适配层。如果你要接本地模型可以考虑 langchain-ollama。注意langchain-mcp-adapters这个包还在迭代安装后先确认版本再去查对应版本的示例代码。版本不同接口名可能有差异。2.2 三类 MCP Server 来源MCP Server 主要有三种来源官方或社区仓库。比如 modelcontextprotocol/servers 里就有文件系统、fetch 网页抓取、Playwright 浏览器自动化等 Server。产品方提供的 MCP Server。很多 SaaS 工具已经提供官方 MCP 接入比如设计协作工具、数据库管理工具、浏览器控制工具。自己写。用 FastMCP 或 TypeScript SDK一个简单 Server 很短时间内就能写出来。看到“免费联网 MCP”这类说法时要留个心眼。它的本质通常是封装了网页抓取或搜索 API。选择时重点看三件事是否有请求频率限制、是否把你的 API Key 交给第三方代理、是否会在返回结果里夹带广告或不可信内容。2.3 必须建立的 MCP 协议概念开始写代码前建议先建立几个协议概念概念作用Transport数据传输方式本地服务常用 stdio远程服务用 Streamable HTTP 或 SSEInitializationClient 和 Server 建立连接后先握手协商协议版本和能力List Tools客户端列出 Server 暴露的工具模型才知道有哪些函数可调用Call Tool模型生成调用参数后客户端调用 Server 工具再返回结果调试时最容易踩的坑是“协议流被污染”。MCP 走 stdio 时Server 和 Client 之间通过标准输入输出传协议数据。如果代码里莫名 print 了一行调试信息这行文本会混进协议流导致解析失败。这个问题我后面在排查链路里会再写。2.4 Windows 环境下的路径和权限Windows 上经常遇到“服务启动不了”的问题。常见原因不是代码错误而是command 没写绝对路径或者没有用 python -m 方式启动。脚本路径里包含空格args 没有正确引号处理。用了错误的 Python 解释器依赖安装在另一个环境里。权限方面本地 Server 不要用管理员权限常驻。如果 MCP Server 暴露的是文件读写或数据库操作尽量把作用范围限制在指定目录不要给整个磁盘权限。3. 第一个实战自建一个 MCP Server 并用 LangChain 调用3.1 用 FastMCP 写一个最小可运行的 Server我用一个天气查询工具来演示。真实环境里这里可以替换成天气 API 调用演示时先返回模拟数据就好。# mcp_weather_server.py from mcp.server.fastmcp import FastMCP mcp FastMCP(weather-demo) mcp.tool() def get_weather(city: str) - str: 获取指定城市的天气情况。 Args: city: 城市名称比如北京、上海。 # 演示用真实环境替换为天气 API 调用 return f{city}晴26℃风力3级 if __name__ __main__: mcp.run()这段代码定义了一个 MCP Server名为 weather-demo暴露了一个 get_weather 工具。注意工具描述要写清楚因为模型会依据描述决定是否调用它。3.2 先不接入 LangChain单独验证 Server我先建议单独验证 Server而不是直接接入 LangChain。因为如果 Server 本身有问题后面 Agent 跑不通时很难定位。验证方式可以是用 MCP Inspector或者直接写一个短客户端脚本。核心目标有三个Server 能启动不会 crash。能列出工具能看到 get_weather 的名称、描述和参数 Schema。直接调用工具返回值符合预期。这一步确认通过后再进入 LangChain 集成。3.3 LangChain 连接 MCP Server 的接入点LangChain 通过langchain-mcp-adapters加载 MCP 工具。示例代码如下import asyncio from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client from langchain_mcp_adapters.tools import load_mcp_tools server_params StdioServerParameters( commandpython, args[mcp_weather_server.py], ) async def main(): async with stdio_client(server_params) as (read, write): async with ClientSession(read, write) as session: await session.initialize() tools await load_mcp_tools(session) print(tools) asyncio.run(main())这段代码做了这几件事用 StdioServerParameters 指定启动命令。command 要写实际解释器Windows 环境下建议写完整 python 路径或使用 python -m。通过 stdio_client 建立连接。建立 ClientSession执行 initialize 握手。调用 load_mcp_tools 把 Server 暴露的工具加载成 LangChain 的 Tool 对象。如果 tools 列表为空先不要怀疑 LangChain优先检查 Server 是否成功列出来工具。3.4 组合 Agent 并完成一次真实问答工具加载成功后把它交给 LangChain 的 Agent 使用。from langchain.agents import create_tool_calling_agent, AgentExecutor from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate model ChatOpenAI(modelgpt-4o-mini, temperature0) prompt ChatPromptTemplate.from_messages([ (system, 你是一个智能助手可以使用工具获取信息。), (placeholder, {chat_history}), (human, {input}), (placeholder, {agent_scratchpad}), ]) agent create_tool_calling_agent(model, tools, prompt) executor AgentExecutor(agentagent, toolstools, verboseTrue) result executor.invoke({input: 北京今天天气怎么样}) print(result[output])这里用的模型必须支持 function calling 或 tool calling。模型会先判断需要调用 get_weather传参 city北京拿到返回结果后再组织成自然语言回答。如果你用的是本地模型要确认它支持 OpenAI 兼容的工具调用接口。不支持的话create_tool_calling_agent 会跑不通需要换 ReAct 范式或其他方案。3.5 判断成功与失败的标准我总结了一个简单的判断表方便对照检查项成功标准常见失败表现Server 启动进程正常常驻无异常退出退出码非 0报 ModuleNotFoundError工具列表能看到 get_weather 及参数 Schema列表为空或只有内置工具工具调用返回结构化数据返回空、超时、协议解析错误Agent 回答模型结合工具结果给出回答模型不调用工具或编造结果注意这里不要急着优化并发。先用一条输入把“Server 启动 - 工具加载 - Agent 调用 - 结果返回”全链路跑通。4. 实战扩展联网检索、RAG、记忆和多工具编排4.1 用 MCP 给 Agent 补上联网检索能力MCP 最常见的应用之一就是让 Agent 获得联网能力。常见方案包括fetch抓取网页内容。Playwright浏览器自动化可以打开页面、点击、滚动、取正文。搜索 API 的官方封装通过搜索接口返回结果列表。接入方式和天气示例完全一样只是把 Server 换成对应的 MCP Server。需要注意两点要遵守目标网站的 robots 协议不要高频抓取不要绕过登录鉴权。生产环境优先使用有正式 API 授权和限流的搜索服务而不是去抓取别人前端页面。如果你要抓取的是公开文档页面fetch 通常够用。如果要做交互式页面操作再考虑 Playwright。4.2 把 MCP 工具接进 RAG 流程LangChain 本来就很适合做 RAG加载文档、切分、向量化、检索、生成。MCP 在这里的价值是“统一取数接口”。你可以写一个 MCP Server暴露 search_documents 工具内部封装向量数据库查询或者封装 SQL 查询。LangChain 侧只负责组织提示词、调用模型、处理检索结果。这样知识库切换时LangChain 的逻辑可以基本不动只要换 MCP Server 的实现。“LangChain Prompt RAG MCP”这个组合核心要点是MCP 负责取数LangChain 负责组织和输出模型负责理解与生成。职责边界清晰之后调试起来会省很多事。4.3 给 Agent 加上记忆MCP 不负责记忆。记忆是编排框架的事。简单场景下LangChain 的 Memory 类组件可以管理聊天历史。复杂场景下LangGraph 支持持久化 checkpointer可以保存和恢复对话状态。如果你做的是多轮对话应用要重点关注两件事历史消息的截断策略不能无限往上下文里塞。Token 上限。工具返回内容过大时先做摘要或截断再进入模型。一般建议直接用 LangGraph 的持久化能力因为 Agent 流程一旦有分支单靠 Memory 组件会很难管理。4.4 多工具混合编排一个 Agent 可以同时挂多个 MCP Server比如文件系统、搜索、数据库。工具多了以后有两个容易出问题的点工具描述冲突。多个 Server 里如果有同名工具模型可能分不清该选哪个。建议在工具描述或命名空间上做区分。工具太多导致调用选择变差。模型需要在几十个工具里选一个难度比从三个工具里选大得多。如果发现模型选择不准优先精简工具数量而不是增加提示词压力。4.5 其他技术栈Dify、Java、C# 如何接入 MCPMCP 是语言无关的协议。除了 Python其他技术栈也可以接入。Dify 这类应用平台可以在界面里配置 MCP 服务本质上是把 MCP Server 挂到节点上然后让 Agent 或工作流调用。Java 和 C# 都有对应 MCP SDK。接入原理一样先建立 session再 list tools再 call tools。只是 API 命名不同。如果你在桌面工具或 IDE 插件里用 MCP通常是客户端负责管理连接Server 无感知。不管用什么语言核心流程都是“握手 - 列出工具 - 调用工具 - 返回结果”。只要理解这一层换语言只是换个 SDK 写法。5. 从 Demo 到可维护异步、并发、日志、失败重试5.1 单任务跑通不等于批量可用很多人把 Demo 跑通之后直接把循环一写就开始跑批量然后发现各种问题。原因很简单批量任务不只是“把单条逻辑重复执行”它还涉及资源竞争、排队、超时、失败恢复、输出整理。我的习惯是分三步单条跑通。小批量跑 10 条观察成功率、耗时、输出格式。再考虑并发和队列。如果 10 条任务里有 2 条失败不建议立刻开并发先把失败原因找出来。5.2 并发参数怎么调并发不能拍脑袋。先看资源瓶颈在哪里瓶颈表现初始建议模型 API 限流请求频繁报 429先单线程跑观察限流阈值MCP Server 本地资源CPU 高、内存涨、响应慢并发从 1 开始递增数据库连接池连接超时、连接数满先检查连接池上限外部搜索 API返回 403、429严格按配额控制 QPS我一般会从并发 1 开始跑少量任务记录耗时然后 2、4、8 逐步递增。如果并发从 4 升到 8 时错误率明显上升就先停在这个档位找原因可能是外部限流也可能是 Server 内部的连接池不够。不要一上来就开最大并发。先看日志再改参数。暴力并发只会把问题从“功能不完善”变成“服务被打挂”。5.3 日志与输出设计Agent 应用里的日志不能只记录最终结果。每个任务至少应该包括输入摘要。模型选中的工具。工具传入的参数。工具返回的原始内容。最终输出。总耗时。错误信息或异常栈。有一点容易被忽略模型没有调用工具这也是一条重要信息。如果任务预期应该调用工具但模型直接回答说明模型或提示词有问题必须记录下来。输出文件也要整理。如果任务有批次建议用任务 ID 做文件名不要用固定文件名覆盖写。固定文件名在并发和重复执行时容易互相干扰。5.4 失败重试与幂等工具调用失败后不是所有错误都适合重试。可以重试的是超时、网络抖动、临时限流。不能重试的是参数错误、鉴权失败、工具不存在。设计重试参数时至少要控制最大重试次数、退避间隔、退避递增方式。写操作要特别考虑幂等。比如每次 Agent 任务生成一个 request_id传入工具接口服务端按这个 ID 去重。这样重复调用不会产生多条脏数据。否则网络超时后重试一次可能触发两次写入。5.5 上线前的功能验收清单我建议在正式投入前按这份清单过一遍MCP Server 能稳定列出工具。每个工具都能被模型正确选中。输入错误时模型不会编造结果而是明确说“工具调用失败”。连续跑 50 条任务没有严重崩溃。有并发限制不会把外部 API 打爆。MCP Server 没有暴露在公网工具权限最小化。生产环境里稳定性比功能多更重要。少挂一个工具效果只会差一点批量任务中途崩溃可能整个流程都要重新来。6. 常见问题排查链路6.1 工具注册不上现象LangChain 加载后 tools 列表为空或者 Agent 说“找不到某个工具”。排查顺序建议先单独启动 MCP Server看能不能正常运行。检查 command 和 args 路径Windows 上先确认解释器绝对路径。检查脚本里有没有写if __name__ __main__: mcp.run()。检查 mcp 和 langchain-mcp-adapters 版本是否兼容。检查你用的是 load_mcp_tools还是 load_mcp_resources。大部分情况不是模型问题而是 Server 没启动成功。先抓日志。6.2 工具能注册但调用返回异常现象工具列表能看到调用时报错、返回空或者返回内容解析失败。排查顺序不经过 LangChain直接用客户端调用工具确认工具本身能返回。检查输出格式常用的是 JSON 或纯文本但必须能正常序列化。检查 Server 端是否在 stdio 模式下 print 了额外内容。协议流被污染时客户端解析会失败。检查工具内部有没有抛出未捕获异常。6.3 stdio 服务启动失败或端口冲突如果用的是 stdio看启动命令是否指向正确的 Python 解释器。看依赖是不是装在当前环境。看脚本路径是否有空格需要引号处理。如果用的是 HTTP Transport先看端口有没有被占用。Windows 用 netstatLinux 用 lsof。看 Server 的 host 和 port 配置是否和客户端一致。看防火墙有没有放开对应端口。6.4 模型与协议版本兼容问题不同模型对 tool calling 的支持差异很大。有的模型不支持函数调用此时 create_tool_calling_agent 会失败需要改用 ReAct 或其他提示词驱动方案。如果是版本更新导致的接口变化建议去查当前安装版本的官方示例而不是直接用旧代码硬跑。这个领域版本迭代很快网上很多旧文章只能当思路参考。6.5 Token、上下文和超时限制工具返回内容过长时会把上下文窗口撑爆。常见对策工具内部先做截断。LangChain 侧引入摘要步骤。设置合理的执行超时。模型偶尔会生成一个不存在的工具名。常见原因是模型能力偏弱或工具描述不够清晰。可以简化工具描述减少候选工具数或换更强模型。6.6 安全与权限边界这一点必须单独说不要把 MCP Server 直接暴露在公网。远程服务必须做鉴权。文件、数据库类工具要限制作用范围不要给整个系统权限。MCP 返回的数据不能直接当作可信内容拼进系统提示词后执行。如果 Agent 内部使用不可信输入要对输入做长度限制和内容校验。MCP 本身是一种标准化能力但标准化不意味着自动安全。工具权限、网络边界、数据校验这些仍然要自己负责。6.7 LangChain 过时了吗经常有人问 LangChain 是不是过时了。我的看法是如果你只是简单调用模型直接用模型厂商 SDK 更轻量如果你要做工具编排、Agent 流程、RAGLangChain 和 LangGraph 依然是常用选择。MCP 的接入适配也在 LangChain 生态里逐步完善。真正的问题不是“用不用 LangChain”而是“你的场景需不需要这么重的一层”。一个固定提示词接口完全没必要上框架一个需要多个工具、多轮决策、状态恢复的 Agent再用裸 SDK 就会很痛苦。最后留一个建议先把单条任务跑稳把输入格式、日志、失败重试和输出命名理清楚再考虑批量和并发。很多问题不是 LangChain 或 MCP 能力不够而是前置环境和输入材料没有处理干净。踩过几次之后你会发现这套组合真正值钱的地方不是某一项花哨功能而是它对工具接入方式的统一和收敛。
返回列表