LangChain与MCP实战:Agent工具接入标准化的完整指南
2026/8/30 14:17:17 网站建设 项目流程

如果你最近在 CSDN、GitHub 或者 B 站刷到“MCP”这个词,大概率会和我一样有个困惑:MCP 是不是又一个要替代 LangChain 的框架?为什么 LangChain 的教程里满屏都是 MCP,LangGraph 的示例里也在讲 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 应用时反复出现的通用逻辑封装成组件。

典型场景包括:

  • 模型接入:ChatOpenAIChatOllama等。
  • RAG 流水线:加载文档、切分、向量化、检索、生成。
  • Agent 编排:让模型决定调用哪些工具。

1.2 LangGraph 解决什么问题

LangGraph 是 LangChain 官方团队推出的编排库,核心是“图状态机”。它允许你把 Agent 内部流程建模成节点和边的有向图,节点可以执行工具调用、模型调用、条件分支,边负责状态流转。

一个常见的误解是 LangGraph 是 LangChain 的升级版。更准确的说法是:LangChain 提供组件,LangGraph 提供流程控制。在复杂 Agent 场景里,LangGraph 比旧的AgentExecutor更适合生产环境,因为它对状态流转、循环、记忆和分支的控制更精确。

1.3 MCP 解决什么问题

MCP(Model 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 Server,LLM 可以通过它控制浏览器做端到端测试。
  • 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\activate

3.2 安装依赖

需要安装以下包:

  • mcp:MCP 官方 Python SDK,包含 Server 和 Client。
  • langchain:LangChain 核心框架。
  • langchain-openai:统一接入 OpenAI 兼容接口。
  • langgraph:用于创建 Agent。
  • langchain-mcp-adapters:MCP 工具转 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( model=os.getenv("MODEL_NAME", "gpt-4o-mini"), temperature=0, base_url=os.getenv("OPENAI_BASE_URL", "https://api.openai.com/v1"), ) agent = create_agent( model=model, 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_timemultiply,最后返回组合结果。这一步验证了“模型工具调用”链路是通的。

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.db

python -c "import sqlite3; conn=sqlite3.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( command="python", 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( model=os.getenv("MODEL_NAME", "gpt-4o-mini"), temperature=0, base_url=os.getenv("OPENAI_BASE_URL", "https://api.openai.com/v1"), ) async def run(): server_params = StdioServerParameters( command="python", 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( model=model, tools=tools, 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 运行完整示例

启动前确认三件事:

  1. mcp_server.pylangchain_mcp_agent.py在同一个目录下。
  2. demo.db已经创建好。
  3. 模型服务配置正确,已设置OPENAI_API_KEY或对应的环境变量。

执行:

python langchain_mcp_agent.py

预期你会看到:

  • 程序先启动本地 MCP Server 进程;
  • Client 与 Server 建立连接;
  • Agent 打印已加载的工具列表;
  • 模型根据用户问题,先后调用get_current_timequery_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 组合起来之前,建议分步验证:

  1. 先单独运行mcp_client_demo.py,确认 MCP Server 能被客户端发现和调用。
  2. 再运行agent_demo.py,确认普通 LangChain Agent 能正常使用工具。
  3. 最后运行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_userssend_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,你会对这个技术栈有完全不同的理解。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询