ARTICLE DETAIL

资讯详情

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

LangChain与MCP实战:Agent工具接入标准化的完整指南

LangChain与MCP实战:Agent工具接入标准化的完整指南 如果你最近在 CSDN、GitHub 或者 B 站刷到“MCP”这个词大概率会和我一样有个困惑MCP 是不是又一个要替代 LangChain 的框架为什么 LangChain 的教程里满屏都是 MCPLangGraph 的示例里也在讲 MCP先给一个结论MCP 不是 LangChain 的替代品它解决的是“工具接入标准化”这个更底层的问题。LangChain 仍然是那个帮你编排 Prompt、模型、工具和 Agent 的高层框架而 MCP 让“接入外部工具”这件事不再每个框架写一套适配器。把这两者放在一起学才是 2026 年做 Agent 开发比较合理的技术栈。这篇文章不是概念罗列而是一条从 LangChain 基础到 MCP 代码实战的完整路线。我会先讲清楚 LangChain、LangGraph、MCP 之间的关系再用可以直接复制的代码带你跑通一个 Agent 调用 MCP Server 的示例。读完你能回答下面几个问题LangChain 和 MCP 到底哪一层负责什么事为什么说 MCP 让工具接入从“私有格式”变成“公开协议”如何用 LangChain 的 Agent 动态调用 MCP Server 暴露的工具实际项目中接入 MCP 有哪些坑怎么做才不容易翻车如果你已经学过一点 LangChain但一直没想清楚怎么把 MCP 用起来这篇文章建议收藏起来照着做。1. LangChain、LangGraph、MCP先分清这三个概念很多教程把 LangChain、LangGraph、MCP 混在一起讲导致初学者以为它们是同类框架。实际上三者处于不同抽象层级。1.1 LangChain 解决什么问题LangChain 是一套面向 LLM 应用的高层开发框架提供了模型调用、Prompt 管理、输出解析、文档加载、向量存储、Retrieval、Agent 等模块。你可以把 LangChain 理解成一个“零件库 组装手册”它把开发 LLM 应用时反复出现的通用逻辑封装成组件。典型场景包括模型接入ChatOpenAI、ChatOllama等。RAG 流水线加载文档、切分、向量化、检索、生成。Agent 编排让模型决定调用哪些工具。1.2 LangGraph 解决什么问题LangGraph 是 LangChain 官方团队推出的编排库核心是“图状态机”。它允许你把 Agent 内部流程建模成节点和边的有向图节点可以执行工具调用、模型调用、条件分支边负责状态流转。一个常见的误解是 LangGraph 是 LangChain 的升级版。更准确的说法是LangChain 提供组件LangGraph 提供流程控制。在复杂 Agent 场景里LangGraph 比旧的AgentExecutor更适合生产环境因为它对状态流转、循环、记忆和分支的控制更精确。1.3 MCP 解决什么问题MCPModel Context Protocol是一个开放协议由 Anthropic 提出后来逐步成为 AI 工具接入领域的事实标准之一。它定义了一套标准化的通信方式让 LLM 应用通过客户端连接外部“工具服务器”。MCP 本身不是一个 LLM 框架也不关心你的应用是 LangChain、LangGraph、Dify 还是自定义代码。它只管一件事用统一的协议描述工具、发现工具、调用工具、返回结果。1.4 三者对比技术抽象层级核心作用典型问题LangChainLLM 应用框架模型、Prompt、RAG、Agent 组件“零件从哪来”LangGraphAgent 编排框架状态图、节点、分支、循环“流程怎么控制”MCP工具接入协议发现与调用外部工具“工具怎么连”所以当你看到“langchain 过时了吗”这类讨论时其实问错了方向。LangChain 作为一个重量级框架当然有争议但 MCP 只是在工具层做标准化两者并不冲突。更好的做法是用 LangGraph 控制流程用 MCP 接工具用 LangChain 的组件做 RAG 和模型调用。2. 为什么要用 MCP从“写死工具”到“协议接入”在没有 MCP 之前我们接入一个工具通常这样做在 LangChain 里用tool装饰器定义一个函数写上参数类型和 description然后绑定给 Agent。这种方法在单应用内很好用但问题也很明显工具逻辑和应用代码耦合在一起。如果另一个应用也想用这个工具要么复制代码要么重新实现。每个框架都有自己的工具格式脚本工具、浏览器工具、数据库工具接入方式各不相同。MCP 改变了这个模式。它把工具放到独立的 Server 进程中通过标准协议暴露。客户端只需要知道 Server 的启动方式就能动态获取工具列表并直接调用。我举几个现实例子你就能理解为什么 MCP 会火Playwright MCP把浏览器自动化能力封装成 MCP ServerLLM 可以通过它控制浏览器做端到端测试。Figma MCP让 Agent 读取设计稿结构辅助生成前端代码。Chat2DB MCP把数据库查询能力开放给 AI 助手。IDE 类工具例如通过 MCP 把 IDE 的编辑、搜索能力暴露给 Agent。甚至安全分析、科学计算领域的工具也陆续有人编写 MCP Server。这说明 MCP 正在成为工具接入的“通用语言”。从 LangChain 开发者的角度看MCP 带来的最大变化是你不再需要为每个工具单独写胶水代码只需要用官方 Adapter 把 MCP Server 暴露的工具转换成 LangChain 工具剩下的工作交给 Agent。这个思路下面会通过代码完整演示。3. 环境准备与前置条件开始写代码之前先把环境准备好。本文示例以 Python 为主建议使用 Python 3.10 及以上版本并创建独立虚拟环境避免依赖冲突。3.1 创建虚拟环境python -m venv .venv source .venv/bin/activate # Windows 环境执行 # .venv\Scripts\activate3.2 安装依赖需要安装以下包mcpMCP 官方 Python SDK包含 Server 和 Client。langchainLangChain 核心框架。langchain-openai统一接入 OpenAI 兼容接口。langgraph用于创建 Agent。langchain-mcp-adaptersMCP 工具转 LangChain 工具的适配层。安装命令pip install --upgrade pip pip install mcp langchain langchain-openai langgraph langchain-mcp-adapters如果你的网络环境访问 PyPI 较慢可以使用镜像安装pip install -i https://pypi.tuna.tsinghua.edu.cn/simple mcp langchain langchain-openai langgraph langchain-mcp-adapters安装完成后先确认关键包版本pip show mcp langchain langgraph langchain-mcp-adapters版本无需完全一致但建议都使用较新的版本。如果安装过程中出现依赖冲突优先在干净虚拟环境中重试。4. LangChain 工具调用基础先跑通 Agent在接入 MCP 之前先花几分钟跑通一个最基础的 LangChain Agent确保模型调用和工具绑定环节没有问题。4.1 编写一个普通工具新建文件tools_demo.py# 文件路径tools_demo.py from datetime import datetime from langchain_core.tools import tool tool def get_current_time() - str: 获取当前时间。 return datetime.now().strftime(%Y-%m-%d %H:%M:%S) tool def multiply(a: int, b: int) - int: 计算两个整数的乘积。 return a * b这里定义了两个工具一个返回当前时间一个做乘法。工具函数本身不依赖 MCP但我们会用同样的模式把 MCP Server 里的工具包装成 LangChain 工具。4.2 创建 Agent新建文件agent_demo.py# 文件路径agent_demo.py import os from langchain_openai import ChatOpenAI from langgraph.prebuilt import create_agent from tools_demo import get_current_time, multiply # 使用 OpenAI 兼容接口可以替换为你自己的模型服务 model ChatOpenAI( modelos.getenv(MODEL_NAME, gpt-4o-mini), temperature0, base_urlos.getenv(OPENAI_BASE_URL, https://api.openai.com/v1), ) agent create_agent( modelmodel, tools[get_current_time, multiply], system_prompt你是一个帮助用户处理问题的助手请优先使用工具获取信息。, ) def main(): result agent.invoke( {messages: [{role: user, content: 现在是几点计算 8 乘以 12。}]} ) for message in result[messages]: print(message.type, , message.content) if __name__ __main__: main()运行前需要配置模型访问凭证。如果你使用的是 OpenAI 官方服务需要设置环境变量OPENAI_API_KEY如果你使用国产模型或企业内部模型只要它兼容 OpenAI 接口都可以通过base_url指向对应地址。运行export OPENAI_API_KEY你的合法API Key # Windows 系统 # set OPENAI_API_KEY你的合法API Key python agent_demo.py如果一切正常你会看到模型决定先调用get_current_time和multiply最后返回组合结果。这一步验证了“模型工具调用”链路是通的。5. MCP 核心原理与最小 Server现在进入 MCP 部分。先抛开 LangChain亲手写一个 MCP Server再用 MCP 客户端调用它。5.1 MCP 的三层结构MCP 通常包含三层Host宿主运行 LLM 应用的程序比如 LangChain Agent、Dify、Claude Desktop。Client客户端在 Host 内部负责与 MCP Server 建立连接、发现工具、调用工具。Server服务端独立进程或服务真正执行工具逻辑。传输方式有两种很常见stdio本地子进程通信LangChain 通过python mcp_server.py启动一个 Server 进程。HTTP / SSE远程服务通信适合部署在服务器上的共享工具。需要强调的是MCP Server 只是工具背后的执行进程它不负责“思考”。选择工具、决定调用顺序仍然是模型的职责。5.2 编写一个最简单的 MCP Server新建文件mcp_server.py# 文件路径mcp_server.py import sqlite3 from datetime import datetime from mcp.server.fastmcp import FastMCP # 创建一个 MCP Server名称为 demo mcp FastMCP(demo-server) mcp.tool() def get_current_time() - str: 获取当前时间。 return datetime.now().strftime(%Y-%m-%d %H:%M:%S) mcp.tool() def query_users() - str: 查询本地 demo.db 中 users 表的所有用户。 使用前请确保已创建 demo.db 并导入数据。 conn sqlite3.connect(demo.db) try: rows conn.execute(SELECT id, name FROM users).fetchall() finally: conn.close() return \n.join(f{id}:{name} for id, name in rows) if __name__ __main__: # 默认以 stdio 模式运行 mcp.run()这里包含了两个工具一个返回当前时间一个查询 SQLite 数据库。代码很直观关键是mcp.tool()装饰器它把普通函数变成了 MCP 工具。5.3 准备本地 SQLite 测试数据执行下面的命令生成demo.dbpython -c import sqlite3; connsqlite3.connect(demo.db); conn.execute(CREATE TABLE IF NOT EXISTS users(id INTEGER PRIMARY KEY, name TEXT)); conn.executemany(INSERT OR IGNORE INTO users(id,name) VALUES (?,?), [(1, Alice), (2, Bob)]); conn.commit(); conn.close()5.4 用 MCP Client 直接调用新建文件mcp_client_demo.py# 文件路径mcp_client_demo.py import asyncio from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client async def main(): # 指定启动 MCP Server 的命令 server_params StdioServerParameters( commandpython, args[mcp_server.py], ) async with stdio_client(server_params) as (read, write): async with ClientSession(read, write) as session: # 建立连接并初始化 await session.initialize() # 列出 Server 暴露了哪些工具 tools await session.list_tools() print(MCP Server 工具列表) for tool in tools.tools: print(f - {tool.name}: {tool.description}) # 调用 get_current_time result await session.call_tool(get_current_time, {}) print(当前时间结果, result.content[0].text) # 调用 query_users result await session.call_tool(query_users, {}) print(用户列表结果) print(result.content[0].text) if __name__ __main__: asyncio.run(main())运行python mcp_client_demo.py预期会输出类似下面的内容MCP Server 工具列表 - get_current_time: 获取当前时间。 - query_users: 查询本地 demo.db 中 users 表的所有用户。 当前时间结果 2026-01-01 10:00:00 用户列表结果 1:Alice 2:Bob到这里你已经完成了 MCP 的“最小闭环”Server 暴露工具Client 发现并调用工具。接下来要做的是把这段逻辑接入 LangChain Agent。6. LangChain MCP 完整实战让 Agent 动态调用 MCP 工具这一节的最终目标是LangChain Agent 不直接定义工具函数而是通过 MCP 获取工具并根据用户问题自动选择调用。6.1 用 Adapter 快速接入langchain-mcp-adapters提供了load_mcp_tools可以直接把 MCP Server 里的工具转换成 LangChain 工具列表。新建文件langchain_mcp_agent.py# 文件路径langchain_mcp_agent.py import asyncio import os from langchain_mcp_adapters.tools import load_mcp_tools from langchain_openai import ChatOpenAI from langgraph.prebuilt import create_agent from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client model ChatOpenAI( modelos.getenv(MODEL_NAME, gpt-4o-mini), temperature0, base_urlos.getenv(OPENAI_BASE_URL, https://api.openai.com/v1), ) async def run(): server_params StdioServerParameters( commandpython, args[mcp_server.py], ) async with stdio_client(server_params) as (read, write): async with ClientSession(read, write) as session: await session.initialize() # 关键把 MCP Server 暴露的工具加载成 LangChain 工具 tools await load_mcp_tools(session) print(已加载工具数量, len(tools)) for tool in tools: print(工具名称, tool.name) agent create_agent( modelmodel, toolstools, system_prompt你是一个本地助手需要调用工具时请直接调用。, ) result await agent.ainvoke( {messages: [{role: user, content: 现在几点了顺便帮我查一下 users 表里有哪些用户。}]} ) for message in result[messages]: print(message.type, , message.content) if __name__ __main__: asyncio.run(run())这段代码最核心的一行是tools await load_mcp_tools(session)它把 MCP 协议里的工具定义统一转换成了 LangChain Agent 能够理解的BaseTool对象。转换完成之后创建 Agent 的方式和普通 LangChain 工具没有任何区别。6.2 理解 Adapter 背后的原理如果你不想依赖 Adapter也可以手动包装。MCP Client 返回的工具调用结果本质上就是一段文本或结构化内容。我们可以用 LangChain 的tool包装一个调用函数# 伪代码手动包装 MCP 工具 from langchain_core.tools import tool async def build_tools(session): tool async def get_current_time() - str: 从 MCP Server 获取当前时间。 result await session.call_tool(get_current_time, {}) return result.content[0].text tool async def query_users() - str: 从 MCP Server 查询用户列表。 result await session.call_tool(query_users, {}) return result.content[0].text return [get_current_time, query_users]这种写法更适合理解 MCP 的本质工具就是一个“函数”MCP 负责传输。但在实际项目中一个 Server 可能暴露很多工具手动写包装函数维护成本很高所以官方 Adapter 更方便。6.3 运行完整示例启动前确认三件事mcp_server.py和langchain_mcp_agent.py在同一个目录下。demo.db已经创建好。模型服务配置正确已设置OPENAI_API_KEY或对应的环境变量。执行python langchain_mcp_agent.py预期你会看到程序先启动本地 MCP Server 进程Client 与 Server 建立连接Agent 打印已加载的工具列表模型根据用户问题先后调用get_current_time和query_users最终返回包含时间和用户列表的回答。如果模型没有调用工具而是直接硬答请检查模型是否支持 Function Calling。很多轻量模型不支持工具调用这时候 Agent 不会产生tool_calls而是直接生成文本回答。7. 运行结果与效果验证演示示例没有固定的 JSON 输出但我们可以从日志和消息流判断 Agent 是否正常。7.1 判断成功的标准一次成功的 LangChain MCP 调用会在result[messages]中出现以下消息类型human用户输入。ai模型第一次输出可能包含tool_calls。tool工具执行结果。ai模型拿到工具结果后生成的最终回答。只要日志中出现tool类型的消息说明 Agent 确实走了 MCP 工具调用链路。7.2 验证 MCP Server 是否工作如果运行mcp_client_demo.py能正常列出工具并输出结果说明问题不在 MCP 层而在模型配置或 Adapter 层。7.3 如果失败先看哪里在将 Agent 和 MCP 组合起来之前建议分步验证先单独运行mcp_client_demo.py确认 MCP Server 能被客户端发现和调用。再运行agent_demo.py确认普通 LangChain Agent 能正常使用工具。最后运行langchain_mcp_agent.py把两层串起来。这种“先分后合”的方式可以快速定位问题在 MCP 层还是 LangChain 层。8. 常见问题与排查思路下面是实际开发中比较容易踩的坑。问题现象可能原因排查方式解决方案MCP Server 启动后立即退出Server 中混用了print把额外信息输出到 stdout破坏了 stdio 协议在客户端打印错误日志或者在服务端用logging替代print将工具中的调试输出改为logging确保 stdout 只传输协议数据加载工具数量为 0MCP Server 路径错误或 Server 没有正常注册工具先运行mcp_client_demo.py查看工具列表确保 Server 文件可执行且工具使用了mcp.tool()装饰器Agent 不调用任何工具模型不支持 Function Calling或工具 description 不清晰直接请求模型观察是否有tool_calls更换支持工具调用的模型改进工具描述连接远程 MCP Server 超时服务端未启动、认证 token 错误、网络不通先使用curl或浏览器访问服务端点确认服务端进程正常检查地址和认证配置Windows 下无法启动 MCP Client路径中的反斜杠或中文目录导致解析失败打印启动命令观察报错使用绝对路径并统一为正斜杠load_mcp_tools报错导入失败langchain-mcp-adapters版本不兼容检查 pip freeze 中的包版本升级langchain-mcp-adapters或参考官方文档调整 import 路径Agent 返回内容格式异常工具返回了非字符串结构模型解析时出现问题打印原始工具结果在 MCP Server 中统一返回规范化字符串或 JSON 结构排查时记住一个原则MCP 负责工具通信LangChain 负责 Agent 编排模型负责决策。出问题时先判断是哪一层再对症下药。9. 最佳实践与工程建议如果要把 LangChain MCP 用到实际项目里下面这些建议值得认真对待。9.1 一个 MCP Server 只做一类事情不要把文件操作、数据库查询、HTTP 请求全部塞进一个 Server。MCP Server 应该遵循单一职责原则这样工具列表清晰、权限边界容易控制也方便后续复用。9.2 工具命名和描述要规范MCP 工具的描述会直接进入模型上下文影响模型是否选择调用。建议遵循工具名用动词开头例如query_users、send_email。描述写明用途、适用场景、参数含义。需要参数时尽量给参数添加说明。9.3 本地开发用 stdio生产环境用远程传输本地调试时stdio 模式最简单不需要额外端口和认证。但生产环境一般会把 MCP Server 部署到独立服务通过 HTTP 或 SSE 暴露。远程传输必须增加鉴权比如 Token 或 API Key避免任何未授权请求调用敏感工具。9.4 敏感操作必须有授权和审计MCP 工具本质上是一个有本地权限的进程可以读文件、连数据库、执行命令。如果 Server 被恶意调用后果会很严重。在工程上建议工具按权限分级敏感操作增加二次确认。Server 日志记录每一次工具调用。对第三方 MCP Server 保持警惕不要轻易安装来历不明的 Server。9.5 正确看待 Skill 与 MCP 的区别社区里常有人问“Agent Skill 和 MCP 有什么区别”。这两个概念解决的问题不完全一样。Skill 偏向“能力包”包含提示词、代码逻辑、甚至业务流程。MCP 偏向“工具通信协议”解决多个应用如何统一接入同一个工具。实际项目中你可能会同时用 Skill 来封装复杂业务能力用 MCP 来接入通用工具。两者不是替代关系而是互补关系。9.6 不要为了用 MCP 而用 MCP如果你的工具只在本地 LangChain 项目中使用不打算给其他应用复用直接用tool定义反而更简单。MCP 的价值在于标准化、复用和跨应用共享当你有多个应用需要调用同一组工具再引入 MCP 才更划算。10. 后续学习方向别停在能跑通跑通上面的示例意味着你已经理解了 LangChain 和 MCP 协作的最小闭环。但这只是起点想要深入建议按这个顺序继续学透 MCP 协议本身资源、Prompt、Sampling 等概念以及 HTTP 传输和认证方式。掌握 LangGraph把 Agent 流程改造成显式状态图以便处理复杂分支、人工确认和循环。尝试在 Dify 或低代码平台中接 MCP很多平台已经支持通过配置连接本地或远程 MCP Server这会进一步加深你对协议的理解。研究多 Agent 与 MCP 的组合不同 Agent 共享同一组 MCP 工具是未来团队协作式 Agent 系统的一个重要方向。如果时间允许可以写一个自己的 MCP Server比如封装公司内部接口或常用的测试环境操作。自己完整实现一遍 Server比看几十篇教程都更有效。打开终端先跑通mcp_client_demo.py再把它接到 Agent 上。真正让你的 Agent 产生一次tool_calls你会对这个技术栈有完全不同的理解。
返回列表