news 2026/9/7 12:21:37

LangChain+MCP+LangGraph实战:构建工具调用型AI Agent

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LangChain+MCP+LangGraph实战:构建工具调用型AI Agent

2026年的AI应用开发,已经不再是“调一个模型接口”那么简单。你翻开源项目社区,或者打开AI大模型相关岗位的要求,几乎都会遇到几个固定关键词:LangChain、MCP、LangGraph、Agent。

问题在于,这四个词经常被割裂地讲。有人只讲LangChain基础用法,有人只介绍MCP协议概念,有人直接扔一段LangGraph代码。真正把它们串成一条能跑通的应用链路,并且讲清楚每一步为什么这么做的资料,其实并不多。

这篇文章打算做一件事:从一个最小可运行的Agent项目出发,把LangChain、MCP、LangGraph各自承担的角色拆清楚,再手把手带你把它们组合成一个具备“工具调用能力”的AI助手。

适合读者包括:刚接触AI大模型开发、想搞懂Agent内部机制的同学;已经在用LangChain但还不清楚它和LangGraph区别的开发者;需要在项目中接入MCP工具服务的后端工程师。读完你至少能独立搭建一个“让大模型自主决定调用什么工具”的Agent,并且知道常见报错该从哪里排查。

1. 背景与核心概念:四个关键词到底分别解决什么问题

1.1 为什么2026年的Agent开发绕不开这四个词

先说一个常见误区:很多人把LangChain、MCP、LangGraph当成同类型框架去比较,其实它们解决的完全是不同层面的问题。

  • LangChain解决的是“大模型应用的基础零件问题”。它把模型调用、Prompt模板、文本切分、向量存储、工具定义这些高频操作封装成统一接口,你不需要每次从零写调用代码。
  • MCP(Model Context Protocol,模型上下文协议)解决的是“大模型如何安全、标准化地连接外部工具和数据源”的问题。过去每个Agent接一个工具就要写一套私有协议,MCP提供了一套统一标准。
  • LangGraph解决的是“复杂Agent流程如何编排、如何控制状态”的问题。它允许你定义带循环、分支、人工确认的图结构工作流。
  • Agent则是一种应用形态:让大模型在循环中自主决定调用哪些工具、什么时候给出最终答案。

把这四个词放在一起,可以理解为:LangChain提供零件,MCP提供插槽,LangGraph负责组装生产线,Agent就是这条生产线上完成闭环任务的执行单元。

1.2 常见应用场景

  • 智能客服:用户提问后,Agent自动查询订单库、物流接口,再组织语言回答。
  • 代码助手:Agent调用代码搜索工具、读取文件、执行测试命令。
  • 数据分析助手:Agent连接数据库MCP服务,自主写SQL、查数据、生成结论。
  • 自动化运维:Agent根据告警信息调用监控接口、执行剧本、输出处理报告。

这些场景的共同特征是:模型不能只靠“记忆”回答,必须实时获取外部信息,并且整个决策链路可追踪、可控制。这正是LangChain + MCP + LangGraph组合擅长的地方。

2. 环境准备与版本说明

在开始写代码之前,先把环境整理好。Agent开发中90%的“跑不起来”问题,都出在Python版本、依赖包版本、密钥配置这三件事上。

2.1 基础运行环境

  • 操作系统:Windows / macOS / Linux 均可,本文命令以通用命令行示例为准。
  • Python:建议使用 3.9 及以上版本。
  • 包管理工具:pip 或 poetry。
  • 模型服务:需要准备一个兼容OpenAI接口的大模型服务,可以是云端API,也可以是本地通过兼容网关暴露的服务。

注意:LangChain、LangGraph、MCP相关包的版本迭代非常快。本文不锁定具体小版本号,建议安装时统一拉取最新稳定版,同时保证Python环境干净(最好使用虚拟环境)。

2.2 创建虚拟环境并安装依赖

python -m venv agent-demo-env source agent-demo-env/bin/activate # Windows下使用 agent-demo-env\Scripts\activate pip install --upgrade pip pip install langchain langchain-openai langgraph langchain-mcp-adapters mcp python-dotenv

如果安装过程中出现依赖冲突,优先检查Python版本是否过老,或尝试分步安装mcplangchain-mcp-adapters

pip install mcp pip install langchain-mcp-adapters

2.3 密钥配置

新建.env文件,用来存放模型服务的密钥与基础配置:

OPENAI_API_KEY=你的密钥 OPENAI_API_BASE=https://你的模型服务地址 OPENAI_MODEL_NAME=你的模型名称

如果你的模型服务商兼容OpenAI接口,LangChain的ChatOpenAI可以直接通过base_url指定网关地址。不要把密钥硬编码在Python文件里,更不要提交到Git仓库。

3. 核心概念拆解:先理解原理,再动手写代码

3.1 LangChain:模型调用与工具定义的基础层

LangChain的定位可以理解为一个“胶水层”。它不替代大模型,而是让接入模型、拼接Prompt、定义工具这些操作变得更统一。

看一个最基础的模型调用示例:

# 文件路径:demo_langchain_basic.py import os from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain_core.messages import HumanMessage load_dotenv() llm = ChatOpenAI( model=os.getenv("OPENAI_MODEL_NAME", "gpt-4o-mini"), temperature=0, ) resp = llm.invoke([HumanMessage(content="用一句话介绍LangChain")]) print(resp.content)

这里需要注意的点是,ChatOpenAI并不强制要求使用OpenAI官方服务,很多国内模型服务都提供OpenAI兼容接口,你只需要设置base_url,就可以让LangChain与不同厂商的模型对话。

LangChain更重要的能力是工具定义。在Agent场景中,大模型需要通过函数调用能力去触发外部操作。LangChain把工具的输入输出描述标准化,让模型能够“看懂”工具参数。

from langchain_core.tools import tool @tool def add(a: int, b: int) -> int: """计算两个整数相加的结果""" return a + b print(add.name) # add print(add.description) # 计算两个整数相加的结果

这段代码背后的价值是:大模型看到add函数的名称、描述、参数类型后,才能自动生成正确的调用参数。如果你不给工具写好命名和描述,模型就无法知道什么时候该调用它、参数应该填什么。

3.2 MCP:统一工具与数据源接入协议

MCP(Model Context Protocol)由Anthropic提出,目标是解决“每个Agent都要为不同工具编写私有接口”的重复劳动。

MCP架构中有三个角色:

  • MCP Host:运行大模型应用的宿主程序,你的Agent应用就是Host。
  • MCP Client:Host内部的通信客户端,负责建立会话、发送工具调用请求。
  • MCP Server:独立进程或服务,负责暴露工具(Tools)、资源(Resources)、提示模板(Prompts)。

一个MCP Server可以同时给Claude Desktop、自定义LangChain应用、其他Host使用。也就是说,工具只开发一次,处处可复用。

使用Python SDK可以快速创建一个MCP Server。当前主流写法是基于FastMCP高层封装:

# 文件路径:mcp_server.py import datetime from mcp.server.fastmcp import FastMCP # 创建一个名为 weather-demo 的MCP服务 mcp = FastMCP("weather-demo") @mcp.tool() def get_weather(city: str) -> str: """查询指定城市的天气情况,城市名使用中文,例如:北京、上海""" # 演示环境使用本地模拟数据,实际项目中可以在这里调用天气服务API weather_map = { "北京": "晴,24℃,微风", "上海": "多云,28℃,东南风3级", "广州": "阵雨,30℃,南风2级", } return weather_map.get(city, f"抱歉,暂时没有 {city} 的天气数据") @mcp.tool() def get_current_time() -> str: """获取服务器当前时间,返回格式为 YYYY-MM-DD HH:MM:SS""" return datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") if __name__ == "__main__": mcp.run()

@mcp.tool()装饰器会把函数自动注册成工具。工具描述写得好不好,直接影响大模型调用它的准确率。

注意:FastMCP的具体导入路径在不同版本的mcp包中可能略有差异,如果遇到导入错误,可以查看当前SDK的官方文档确认最新推荐写法。这个示例的重点是让大家理解MCP Server的组织形式。

默认情况下,mcp.run()以stdio模式启动,适合由父进程启动并通信。如果希望做成网络服务,可以使用Streamable HTTP等传输模式,原理类似,但地址和端口配置需要按项目环境调整。

3.3 LangGraph:用图来编排Agent的执行流程

LangChain比较擅长处理“线性链路”:先调用模型,再取结果,再调用另一个模型。但真实Agent是“带循环的”:模型决定调用工具,工具返回结果,结果再喂回模型,模型可能再次调用工具,直到最后才给出答案。

这种循环用传统Chain表达很别扭,LangGraph正是为此设计的。

LangGraph把流程建模成“状态图”。你需要定义:

  • 状态(State):在节点之间传递的数据结构。
  • 节点(Node):一个处理函数,可以是调用模型,也可以是执行工具。
  • 边(Edge):决定下一个执行哪个节点的连接关系。
  • 条件边(Conditional Edge):根据当前状态动态决定下一步走向。

看一个最简单的手动状态图示例:

# 文件路径:demo_langgraph_basic.py from typing import TypedDict from langgraph.graph import StateGraph, END from langgraph.graph.message import add_messages from typing import Annotated class AgentState(TypedDict): messages: Annotated[list, add_messages] def first_node(state: AgentState): return {"messages": [("ai", "我是第一个节点")]} def second_node(state: AgentState): return {"messages": [("ai", "流程执行结束")]} # 1. 构建状态图 graph = StateGraph(AgentState) # 2. 添加节点 graph.add_node("first", first_node) graph.add_node("second", second_node) # 3. 设置入口 graph.set_entry_point("first") # 4. 连接边 graph.add_edge("first", "second") graph.add_edge("second", END) # 5. 编译并运行 app = graph.compile() result = app.invoke({"messages": []}) print(result["messages"])

运行后可以看到,消息列表里依次出现了两个节点写入的内容。这说明LangGraph的执行顺序完全由你定义的边决定,不是靠代码从上到下硬执行。

3.4 Agent的核心循环:思考、行动、观察

理解了工具定义、MCP服务、图编排之后,还需要理解Agent本身的运行逻辑。主流Agent采用ReAct思路:Reason(推理)+ Act(行动)。

循环过程如下:

  1. 思考(Thought):模型理解用户问题,判断当前需要什么信息。
  2. 行动(Action):模型选择并调用一个工具,传入结构化参数。
  3. 观察(Observation):系统返回工具执行结果。
  4. 重复上述步骤,直到模型认为信息充分。
  5. 最终回答(Final Answer):模型基于全部上下文组织最终回复。

LangGraph的create_react_agent就是把这个循环封装好的高层接口。你只需要提供模型和工具列表,框架会自动构建“模型节点 -> 工具节点 -> 模型节点”的循环。

这个过程最容易被忽略的是:模型是否具备“工具调用”能力。如果你的模型本身不支持function calling,或者服务商没有开启相关参数,那么Agent只会输出一串“我想调用某某工具”的话,而不是真正触发调用。所以实战中模型选择是关键前提。

4. 完整实战案例:用LangChain + MCP + LangGraph构建一个工具型Agent

接下来进入核心实战部分。我们要构建一个Agent,它能够根据用户问题自主选择调用“查询天气”和“获取当前时间”两个MCP工具,最终给出自然语言回答。

4.1 项目结构

agent-demo/ ├── .env ├── requirements.txt ├── mcp_server.py └── agent_app.py
  • .env:存放模型密钥、地址等配置。
  • requirements.txt:记录项目依赖。
  • mcp_server.py:基于FastMCP实现远端工具服务。
  • agent_app.py:LangGraph Agent主程序,加载MCP工具并完成对话。

4.2 编写依赖清单

langchain langchain-openai langchain-core langgraph langchain-mcp-adapters mcp python-dotenv

保存后,执行:

pip install -r requirements.txt

如果你的环境同时存在多个Python项目,强烈建议始终使用虚拟环境,避免包版本冲突。

4.3 编写MCP服务端

天气和时间工具已经在上文写好了。这里再补充一个细节:MCP Server也是普通的Python程序,可以在本机以子进程方式启动,也可以部署到远程服务器。本文演示的是以子进程方式启动,所以LangChain客户端需要通过StdioServerParameters指定启动命令。

为避免与其他模块冲突,MCP服务端文件保持独立,不要在里面导入LangChain相关包。

4.4 编写Agent主程序

# 文件路径:agent_app.py import os import asyncio from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langgraph.prebuilt import create_react_agent from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client from langchain_mcp_adapters.tools import load_mcp_tools load_dotenv() # 初始化大模型 llm = ChatOpenAI( model=os.getenv("OPENAI_MODEL_NAME", "gpt-4o-mini"), temperature=0, ) # 配置MCP Server启动参数,使用python运行mcp_server.py server_params = StdioServerParameters( command="python", args=["mcp_server.py"], ) async def build_agent(): """创建Agent实例:连接MCP服务并加载工具""" # 建立stdio客户端连接 async with stdio_client(server_params) as (read, write): async with ClientSession(read, write) as session: # 初始化MCP会话 await session.initialize() # 将MCP Server暴露的工具转换为LangChain工具 tools = await load_mcp_tools(session) # 使用LangGraph预置的ReAct Agent结构 agent = create_react_agent(llm, tools) # 调用Agent,传入用户消息 result = await agent.ainvoke( {"messages": [("user", "现在几点了?顺便告诉我北京的天气。")]} ) return result if __name__ == "__main__": response = asyncio.run(build_agent()) for message in response["messages"]: # 打印每一轮消息,便于观察Agent的思考与调用轨迹 print(f"角色: {message.type}") print(f"内容: {message.content}") print("---")

这段代码的逻辑分为四步:

第一步,初始化大模型。temperature设为0,让模型尽量稳定、少做自由发挥。

第二步,配置MCP连接参数。command="python"表示用当前虚拟环境的Python启动服务端,args=["mcp_server.py"]表示被启动的脚本。

第三步,在异步上下文中建立MCP会话。session.initialize()是握手过程,必须等初始化完成之后才能加载工具。

第四步,调用load_mcp_tools把MCP Server暴露的工具转换成LangChain工具列表,然后传给create_react_agent

4.5 运行与验证

在项目目录下执行:

python agent_app.py

如果一切正常,你会看到类似以下结构的输出:

角色: human 内容: 现在几点了?顺便告诉我北京的天气。 --- 角色: ai 内容: [{'name': 'get_current_time', 'arguments': {}}, ...] --- 角色: tool 内容: 2026-01-18 14:30:22 --- 角色: ai 内容: [{'name': 'get_weather', 'arguments': {'city': '北京'}}, ...] --- 角色: tool 内容: 北京,晴,24℃,微风 --- 角色: ai 内容: 当前时间是2026-01-18 14:30:22。北京的天气是晴天,24℃,微风。

这个输出展示了一次完整的Agent运行过程:

  • 模型先调用了get_current_time,拿到一个工具结果。
  • 模型发现还需要天气信息,于是继续调用get_weather
  • 拿到两个工具的返回结果后,模型最终整合信息,输出面向用户的完整回答。

这就是ReAct循环在真实项目中的样子。你不需要手写循环判断逻辑,LangGraph已经帮你处理了状态维护和流程控制。

4.6 如果只想快速体验LangGraph自带工具

有些人可能暂时不想接入MCP,想先看Agent能不能跑通。可以临时把工具列表替换成普通LangChain工具:

from langchain_core.tools import tool @tool def add(a: int, b: int) -> int: """计算两个整数相加的结果""" return a + b agent = create_react_agent(llm, [add]) result = agent.invoke({"messages": [("user", "计算123加456的结果")]})

这种方式适合验证环境配置是否正确。等基础流程跑通,再切换到MCP加载远程工具,排错范围会更小。

5. 常见问题与排查思路

在Agent开发过程中,报错是常态。下面这张表整理了我认为出现频率最高的几类问题,每条都对应一套排查路径。

问题现象常见原因解决思路
pip安装依赖时出现冲突Python版本过低,或包之间依赖不兼容使用Python 3.10+虚拟环境重新安装;分步安装mcp和langchain-mcp-adapters
启动agent_app.py后MCP连接失败mcp_server.py路径不正确,或当前虚拟环境未激活检查命令中args=["mcp_server.py"]的路径;确认在虚拟环境中运行脚本
Agent没有真正调用工具,只输出文本模型服务不支持function calling,或base_url配置错误确认模型服务商是否兼容OpenAI工具调用协议;更换支持function calling的模型
工具描述不生效,模型反复调错参数函数签名和docstring写得不够具体在docstring中说明每个参数的含义、单位、取值范围;给工具起无歧义的名字
Agent进入死循环或调用次数过多图结构中没有设置最大迭代步数,或工具频繁返回错误create_react_agent配置recursion_limit;检查工具内部是否有异常
运行时报TypeError: 'coroutine' object...异步代码没有使用awaitasyncio.run检查load_mcp_toolsagent.ainvoke是否在异步上下文内正确等待
加载MCP工具为空MCP Server启动失败,或@mcp.tool()没有被注册成功单独运行python mcp_server.py检查启动输出;确认没有导入错误

5.1 模型总是不调用工具怎么办

这是Agent开发中最容易出现的问题。

排查顺序建议如下:

  1. 先单独测试模型接口是否支持工具调用。可以直接用llm.bind_tools([add])方式,看看返回结果里是否有tool_calls字段。
  2. 检查Prompt是否给了模型足够的工具使用提示。create_react_agent会内置System Prompt,但工具本身的描述仍然很重要。
  3. 尝试把temperature调低,模型在低温下更倾向遵循结构化调用指令。
  4. 换成专门针对工具调用优化的模型,不要用纯对话模型。

5.2 MCP连接成功但工具执行超时

MCP工具一般会在独立进程中执行,如果工具函数内部有网络请求,可能因为外部服务慢导致超时。实际项目中建议:

  • 在工具内部做好超时控制。
  • 给工具函数添加异常捕获,返回友好错误信息,而不是让整个MCP进程崩溃。
  • 在Agent外层设置合理的递归限制和步数限制,防止工具调用链无限拉长。

6. 最佳实践与工程建议

能跑通Demo只是第一步。把Agent部署到生产环境,还需要考虑很多工程细节。

6.1 工具即接口文档,描述质量决定上限

大模型无法“看到”工具内部实现,它只能依靠函数名、参数类型、docstring做决策。因此:

  • 函数名必须直观,比如get_weather_by_city好于w_func_v2
  • 说明每一个参数的格式和取值范围,例如“城市名使用中文,如北京、上海”。
  • 对于可能返回空结果的工具,要主动说明边界情况。
  • 工具数量不宜过多。一个Agent节点挂几十个工具时,模型出现选择困难的情况会明显上升。如果工具很多,考虑先做工具分类路由。

6.2 状态设计和超时控制

LangGraph的状态是节点间传递的核心。状态字段定义得越清晰,调试越容易。建议在TypedDict中把最终结果、中间步骤、错误信息分开存放,不要把所有内容塞进一个大字典。

同时设置recursion_limit

result = agent.invoke( {"messages": [("user", "查询北京天气")]}, config={"recursion_limit": 15}, )

这样即使模型反复调用工具,也不会无限制地消耗你的模型API额度。

6.3 安全边界与人工确认

如果Agent涉及写数据库、发邮件、删除文件、执行Shell命令等敏感操作,务必在关键节点前加入人工确认机制。

LangGraph提供了Human-in-the-loop能力。你可以在工具节点之前增加一个中断节点,由操作者确认后再继续执行。原则是:默认禁止高风险操作,白名单放行,日志留痕。

MCP Server本身也是一种攻击面。不要把带有危险权限的工具直接暴露给互联网,MCP服务之间要做好鉴权与网络隔离,遵循最小权限原则。

6.4 配置、密钥与可观测性

  • 密钥一律从环境变量或密钥管理服务读取,不要写死在代码里。
  • 不同环境(开发、测试、生产)使用不同的MCP Server地址和模型配置。
  • 对Agent的完整运行链路保存日志,包括模型决策、工具入参、工具返回结果。
  • 有条件时接入LangSmith或自建Trace体系,便于追踪每一步耗时和错误来源。

7. 总结与后续学习建议

现在你已经拥有了一个最小的“LangChain + MCP + LangGraph”技术骨架:LangChain负责模型接入和工具抽象,MCP让工具服务和主应用解耦,LangGraph提供Agent循环控制能力,Agent在循环中自主决定调用哪些工具来解决问题。

这篇文章建立的是一个起点。真实项目中,你还需要继续掌握几个方向。

第一,把MCP Server升级到网络传输模式,让工具服务独立部署,供多个Agent应用共用。这样工具团队和应用团队可以平行推进。

第二,研究LangGraph的高级节点特性,比如条件分支、子图、持久化存储。当Agent流程变复杂后,这些能力能帮你管理更细粒度的状态。

第三,完善工具服务的错误处理与监控。生产环境中,工具不可用比模型不可用更常见。

如果你对这块内容感兴趣,建议直接打开官方文档,从create_react_agent对应的接口定义开始阅读,再动手改造本文示例:给MCP Server增加一个新工具,观察Agent会不会在复杂任务中自动组合多个工具。自己动手扩展一遍,比反复看教程有效得多。希望这篇文章能在你入门AI Agent开发时,帮你少走一些弯路。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 12:18:40

Cocos Creator安卓图片选择裁剪上传下载完整指南

简介:面向Cocos Creator开发者的Android相机相册调用与头像裁剪上传下载完整工程包,覆盖从权限申请、拉起相机/相册、系统裁剪到上传下载的完整流程,适合需要快速实现用户头像选择、裁剪及云端同步功能的中高级Android开发者。资源共321个文件…

作者头像 李华
网站建设 2026/9/7 12:18:19

访问控制理论与策略实战:从RBAC到ABAC的权限体系设计

简介:面向网络安全初学者与系统开发者的访问控制学习资料,围绕RBAC0基于角色的访问控制模型展开,涵盖理论讲解与可运行源码实现。压缩包包含671个文件,大小59.74MB,以Java源码、class字节码、JSP页面、XML配置、Jar依赖…

作者头像 李华
网站建设 2026/9/7 12:16:35

散热器单片机控制系统:从DS18B20测温到PWM风扇调速的完整设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 12:16:11

固定资产管理软件公司哪家技术强 核心技术维度对比

固定资产管理软件核心技术维度梳理评估固定资产管理软件技术实力需重点关注架构能力、数据处理能力、安全能力、集成能力四类核心维度。当前企业固定资产管理数字化转型进程加快,不同规模、不同行业的企业对资产管理系统的技术要求存在差异,明确核心技术…

作者头像 李华
网站建设 2026/9/7 12:14:49

开源AI代理实战:用CrewAI构建多智能体自动化工作流

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华