ARTICLE DETAIL

资讯详情

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

LangChain Agent集成MCP全流程:从工具调用到记忆系统实战

LangChain Agent集成MCP全流程:从工具调用到记忆系统实战 LangChain Agent 集成 MCP 全流程解析从工具调用到企业级 Agent 记忆系统实战最近经常收到一类问题同样在写 Agent为什么别人接了一堆工具还能保持对话上下文不乱自己的 Agent 一接入三五个工具就开始“失忆”换一个工具还得重写一遍接入逻辑如果只把几个 function schema 塞给大模型你很快就会碰上三个硬问题。第一工具一多系统提示词被撑爆模型反而开始频繁“幻觉式调用”。第二每个工具都要单独写一遍适配层换个 Agent 框架等于全部重来。第三多轮对话没有真正的记忆用户换个说法Agent 就不知道刚才发生了什么。MCPModel Context Protocol就是为了解决这摊子事出现的。这篇文章不打算只做概念科普而是从零写一个 MCP Server再把 LangChain Agent 通过官方标准适配器接入这套工具最后落到企业级开发最关心的 Agent 记忆系统上。看完之后你至少能获得三样东西一条清晰的 MCP Server 开发与调试路径一套 LangChain Agent 调用 MCP 工具的可运行示例一个从内存记忆到持久化记忆的演进方案以及生产环境要避开的坑。1. 为什么要关注 MCPAgent 工具调用的真实痛点先理解一个背景问题Agent 的价值不在于“能调用工具”而在于“能稳定地决定何时调用什么工具并把工具结果融回上下文”。现在的 Agent 框架基本都有工具调用能力问题出在标准和工程化上。在没有 MCP 之前接入一个内部 API 通常要写这样一套逻辑# 伪代码传统工具注册方式示意 tools [ { type: function, function: { name: search_flight, description: 查询航班信息, parameters: { type: object, properties: { departure: {type: string}, arrival: {type: string} }, required: [departure, arrival] } } } ]单一两个工具还好说。当工具数量上升到几十个每个工具都有独立鉴权、独立输入输出规范、独立维护状态时问题就变成模型侧的 schema 越来越大token 开销和调用出错率同时上升每个 Agent 框架都要重新实现一遍“工具发现、参数校验、结果回传”工具结果里夹带的敏感字段难以统一过滤团队内部不同服务之间的工具接口风格千差万别。MCP 的思路是做一个标准化协议层把“Agent 要连接什么资源”和“具体怎么连”解耦。它把工具、数据、提示词统一抽象成 Server 端能力Agent 应用通过 MCP Client 标准协议访问不再关心工具背后是内部 HTTP API、数据库还是本地命令行脚本。从技术演进的角度看MCP 更像 USB 接口设备内部怎么实现无所谓只要插入标准接口主机就能识别。过去我们是在为每个“设备”定制接线方案现在只需要按协议标准暴露能力即可。判断MCP 不是某一家框架的专属插件它是一层协议。对 LangChain 用户来说最大的收益不是“少写几行代码”而是“工具接入方式和模型、框架解耦”。这对团队协作和跨项目复用价值很大。2. MCP 核心概念与 LangChain、LangGraph 的边界2.1 MCP 协议里的三个核心对象MCP 在协议层面定义了三种可被 Agent 使用的能力类型能力类型作用类比Tools可执行的函数Agent 决定是否调用远程 APIResources可读取的数据源通常由用户或 Agent 按需读取文件、数据库表Prompts可复用的提示词模板降低重复构造 Prompt 成本命令模板日常开发中Tools 是最常用的。MCP Server 把工具通过stdio或sseHTTP暴露给 ClientClient 通过tools/list拿到工具列表把工具声明交给模型模型返回tool_callClient 再通过tools/call唤起实际执行。2.2 Skill 和 MCP 到底有什么区别最近社区里讨论“Agent Skill 和 MCP 有什么区别”非常多。这个问题的本质是Skill 是 Agent 框架层面的“技能包”它经常包含提示词、调用策略、工具逻辑的组合解决的是“这个 Agent 会什么”MCP 是协议层面的“标准接口”解决的是“工具如何被任意 Agent 发现和调用”。维度SkillMCP定位某个 Agent 框架里的技能模板跨框架的开放协议核心作用复用提示词、逻辑、工具组合统一工具接入与调用依赖关系依赖具体框架框架需要实现 MCP Client迁移成本换框架后 Skill 往往要重写Server 可被任意支持 MCP 的客户端复用类比一份岗位说明书一个统一招聘接口这里有个容易误解的点MCP 并不替代 Agent 框架也不替代提示词工程。它只解决“工具怎么接进去”的问题。Agent 的决策能力仍然由模型和框架负责。2.3 LangChain 与 LangGraphAgent 开发的“组件库”和“调度器”写 Agent 时经常绕不开 LangChain 和 LangGraph 的对比。LangChain 本质是一套 LLM 应用组件库提供了模型封装、提示词、解析器等基础模块适合快速拼装链式流程。LangGraph 则是一个基于图状态机的编排框架它更擅长处理循环、分支、人工确认、持久化这类复杂的 Agent 状态流转。很多现代 Agent 实现包括 LangChain 官方推荐的 prebuilt Agent其实已经运行在 LangGraph 之上。用一句话概括LangChain 负责“组件”LangGraph 负责“编排”两者不是替代关系。文章后面使用create_react_agent就是 LangGraph 提供的高层 Agent 封装配合 MCP 工具适配后非常简洁。3. 环境准备与前置条件开始编码之前先明确环境。本文不绑定某一套固定版本因为 LangChain、MCP 相关 SDK 迭代较快以官方最新稳定版为准会更稳妥。我的建议运行环境如下Python 3.10 及以上一个可用的 OpenAI 兼容 API并配置OPENAI_API_KEY不限定具体模型文中以gpt-4o-mini为例能够在本地执行pip install。建议新建独立虚拟环境python -m venv .venv source .venv/bin/activate安装核心依赖pip install mcp langchain langchain-openai langchain-mcp-adapters langgraph说明一下这几个库的分工mcp是 MCP 官方 Python SDK用来写 MCP Server也提供 Client 基础能力langchain和langchain-openai提供模型封装与链式组装能力langchain-mcp-adapters是 LangChain 接入 MCP 工具的关键适配层没有它会麻烦很多langgraph提供 Agent 编排和状态持久化能力。项目目录可以这样组织agent-mcp-demo/ ├── math_server.py # MCP Server 端 ├── agent_client.py # LangChain Agent 客户端 └── memory_demo.py # 记忆系统示例4. 第一步实现一个最简 MCP Server先写一个最小可运行的 MCP Server。功能不要太复杂能够演示工具注册、参数校验、结果返回即可。这里用 FastMCP 来简化开发。文件路径math_server.pyfrom mcp.server.fastmcp import FastMCP # 创建 MCP Server 实例 mcp FastMCP(math-server) mcp.tool() def add(a: int, b: int) - int: 计算两个整数的和 return a b mcp.tool() def multiply(a: int, b: int) - int: 计算两个整数的积 return a * b if __name__ __main__: # 使用 stdio 传输方式方便本地调试 mcp.run(transportstdio)这段代码里有几个关键点FastMCP(math-server)创建了一个名为math-server的 MCP Servermcp.tool()装饰器负责把普通函数变成 MCP 工具函数签名中的类型注解会被自动解析成工具参数 schema因此类型注解要尽量完整transportstdio适合本地测试和 LangChain Agent 直接拉起子进程调用。在不依赖 Agent 的情况下可以用 MCP Inspector 或直接写一个小客户端来验证 Server 是否正常。更推荐的方式是先往下走让 LangChain Agent 直接加载这个 Server如果工具列表正常说明 Server 本身没有问题。5. 第二步LangChain Agent 连接 MCP Server接下来写 LangChain Agent 客户端。这里的关键类是langchain_mcp_adapters.client.MultiServerMCPClient它可以同时连接多个 MCP Server并把工具统一转换成 LangChain 可识别的 Tool 对象。文件路径agent_client.pyimport asyncio from langchain_mcp_adapters.client import MultiServerMCPClient from langchain_openai import ChatOpenAI from langgraph.prebuilt import create_react_agent async def main(): # 同时可以配置多个 MCP Server async with MultiServerMCPClient( { math: { command: python, args: [math_server.py], transport: stdio, }, } ) as client: # 获取所有 MCP 暴露出来的工具 tools await client.get_tools() print(MCP Tools:, [tool.name for tool in tools]) model ChatOpenAI(modelgpt-4o-mini, temperature0) # 创建基于 LangGraph 的 React Agent agent create_react_agent(model, tools) result await agent.ainvoke( {messages: [{role: user, content: 计算 12 乘以 34 等于多少}]} ) print(最终回答:, result[messages][-1].content) if __name__ __main__: asyncio.run(main())运行方式export OPENAI_API_KEY你的API Key python agent_client.py预期输出会分为两段先打印 MCP Tools 列表例如[add, multiply]然后 Agent 会输出计算结果。如果模型成功调用了multiply工具输出内容类似“12 乘以 34 等于 408”。从这段代码可以看到接入 MCP 的 Agent 开发流程被压缩成了三件事用MultiServerMCPClient声明要连接哪些 Server调用await client.get_tools()获取工具把 tools 传给create_react_agent创建 Agent。这套流程最大的好处是以后新增工具只需要在 Client 配置里加一个新的 Server或者给 Server 增加新的mcp.tool()方法Agent 侧不需要改逻辑。6. 第三步企业级 Agent 记忆系统实战6.1 Agent 记忆为什么难不少初学者以为记忆就是把过去几轮对话拼接到 prompt 里。真实场景下这个方案很快会暴露问题上下文长度有限塞不进所有历史历史里的中间推理和工具结果会污染最终输出多用户访问同一个 Agent 时会话数据会互相串系统重启后内存里的聊天记录全部丢失。所以要区分两个层面会话状态Session State和长期记忆Long-term Memory。会话状态解决“当前这次对话上下文如何保存”长期记忆解决“用户下一次回来是否还记得我”。6.2 用 LangGraph Checkpointer 实现会话记忆现代 LangChain / LangGraph Agent 原生支持 checkpointer 机制。Checkpointer 相当于整个 Agent 状态机的“快照存储”每次运行后都会把中间状态保存下来下次用同一个thread_id恢复。内存版 Checkpointer 非常简单文件路径memory_demo.pyimport asyncio from langchain_mcp_adapters.client import MultiServerMCPClient from langchain_openai import ChatOpenAI from langgraph.checkpoint.memory import MemorySaver from langgraph.prebuilt import create_react_agent async def main(): async with MultiServerMCPClient( { math: { command: python, args: [math_server.py], transport: stdio, }, } ) as client: tools await client.get_tools() model ChatOpenAI(modelgpt-4o-mini, temperature0) # MemorySaver 是进程内内存级持久化适合 demo checkpointer MemorySaver() agent create_react_agent(model, tools, checkpointercheckpointer) # 同一个 thread_id 表示同一个会话 config {configurable: {thread_id: user-001}} # 第一轮记住用户信息 await agent.ainvoke( {messages: [{role: user, content: 我叫张三是一名后端工程师}]}, config, ) # 第二轮提问看 Agent 是否还记得 result await agent.ainvoke( { messages: [ {role: user, content: 我刚才说了我的职业它是什么} ] }, config, ) print(Agent 回答:, result[messages][-1].content) if __name__ __main__: asyncio.run(main())关键点在于configurable.thread_id。这个 ID 是会话的唯一标识可以理解为“聊天房间号”。同一房间内的消息会复用同一份状态不同房间之间的状态互相隔离。这解决了多用户会话串线的问题。MemorySaver 的实现是把状态存在进程内存中一旦程序重启记忆就没了。它只适合本地演示和单元测试不适合生产环境。生产环境建议用持久化 Checkpointer。6.3 生产环境用什么存记忆LangGraph 生态提供了多种 Checkpointer 后端常见的有Checkpointer存储位置适用场景MemorySaver进程内存本地调试、测试SqliteSaverSQLite 文件单机小规模服务PostgresSaverPostgreSQL生产环境多实例共享状态Redis-basedRedis对低延迟有要求的状态读写生产环境的核心诉求是“多实例共享状态”。如果服务部署了多个副本每个实例各自维护一份内存记忆用户请求落在不同实例时就会“失忆”。所以至少要选择一个外部共享存储比如 PostgreSQL 或 Redis让所有 Agent 实例通过同一个 checkpoint 存储读写。这部分配置会依赖具体后端库建议到 LangGraph 官方文档确认当前推荐写法不要在旧版本代码上硬套新 API。6.4 记忆之外还要考虑摘要与清理即使有了 Checkpointer长期对话仍然会累积越来越多的消息。两个常见策略一是消息摘要。定期把历史消息压缩成一段摘要只保留摘要和最近 N 轮消息控制 token 消耗。二是滑动窗口。只保留最近 K 轮消息更早的内容直接丢弃或归档。这两种策略可以叠加。对于企业级 Agent建议至少做到“摘要 窗口 持久化”三件套。记忆不是一个单点功能它和成本、延迟、隐私强相关。7. 常见问题与排查思路问题现象可能原因排查方式解决方案tools为空Agent 不调用任何工具MCP Server 启动失败或未注册任何mcp.tool()查看运行日志手动运行 Server 看是否有报错先用 MCP Inspector 独立验证 ServerAgent 执行超时提示类似“执行提供方未及时响应”模型响应慢或 MCP 工具内部阻塞或 stdio 管道未正常关闭检查模型 API 日志和 Server 日志确认工具是否被调用调大 Agent 超时时间给 Server 工具增加内部超时控制工具结果已经返回但 Agent 不参考结果模型上下文过长或工具描述不明确打印最终 messages查看工具调用结果是否进入上下文精简工具描述压缩历史消息多个thread_id之间共享了记忆配置了同一个 Checkpointer 且未正确使用 thread_id检查 config 传入链路每个会话显式注入独立 thread_id连接远程 MCP Server 失败网络或鉴权问题检查 Server 端访问日志确认密钥、白名单、超时配置单独说一下“Agent 执行超时”这个问题。它出现时不一定代表 MCP 有问题很可能是模型侧响应慢也可能是工具本身在等待一个外部接口。排查顺序建议是先看是“还没调用工具就超时”还是“调用工具后超时”。前者是模型的决策阶段过慢后者是工具执行阶段过慢。定位到阶段后再去查对应日志不要一上来就盲目调整全局 timeout。8. 最佳实践与工程建议8.1 安全边界工具权限最小化MCP 可以非常方便地暴露工具也非常容易暴露过度。开发时要注意不要在 MCP Server 里暴露任意 shell 执行能力文件读写类工具要限制访问目录数据库类工具要使用只读账号必要时单独建一个受限角色所有工具入口都要做参数校验不能把模型输出直接当成可信输入。如果确实需要 Agent 操作生产数据一定先在测试环境验证工具输出再逐步开放权限并做好操作审计。8.2 日志与脱敏工具调用过程中模型可能会把 API Key、用户手机号、内部地址等敏感信息传给工具或者工具返回值里包含这些信息。生产环境建议在 Agent 调用链路上增加一层输出过滤器工具返回结果进入模型前先过滤常见敏感字段日志里不要打印完整工具入参和出参对每个工具的调用时间和调用来源做审计记录。8.3 超时、重试与回滚Agent 应用本质上是一个分布式系统模型 API、MCP Server、外部服务都可能是故障点。建议为每个 MCP Server 设置独立的连接超时和调用超时工具调用失败时预留重试次数但重试要避免产生重复副作用对鉴权、配置变更保持版本管理MCP Server 更新后要能快速回滚到上一版。8.4 测试策略MCP Server 可以用单测直接调用工具函数验证业务逻辑Agent 整体行为则需要集成测试覆盖“工具被正确选择”“工具结果被正确消费”“多轮记忆不串话”三类场景。测试用例里不要依赖真实外部 API用 mock 或者本地测试 Server 更稳定。9. 总结与后续学习方向这篇文章真正讲清楚了几件事MCP 出现之前 Agent 工具接入的痛点MCP 协议中 Server、Client、工具的关系Skill 和 MCP 的边界LangChain Agent 如何通过langchain-mcp-adapters连接 MCP Server以及企业级 Agent 记忆系统为什么必须依赖 LangGraph Checkpointer 和持久化后端。如果你现在手里已经有 RAG 应用下一步最值得做的就是把其中检索、重排、文档解析等能力通过 MCP Server 暴露给 Agent。这样做一方面可以脱离具体框架运行另一方面也为后续多工具协作打基础。学习的路线建议是这样的先把单个 MCP Server 跑通再尝试在一个 Agent 里接入多个 Server然后加入 Checkpointer 做多轮记忆接着处理摘要和上下文压缩最后补上安全、审计和监控。每一步都尽量在真实业务场景里验证而不是只跑通 hello world。记忆系统是 Agent 从“能用”走向“好用”的关键分水岭。把工具接入和状态管理分开设计线上排查问题会轻松很多。建议先把文中的最小示例完整跑一遍再逐步替换成你自己的业务工具和存储方案。收藏这篇作为操作底稿开发遇到卡点随时回来对照排查思路。
返回列表