尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

LangChain+MCP实战:AI Agent工具调用链路

LangChain+MCP实战:AI Agent工具调用链路 LangChain 加 MCP是目前搭建 AI Agent 工具调用链路最值得研究的组合之一。MCP 把外部能力抽象成标准接口LangChain 负责把模型、工具和调用循环串起来DeepSeek 这类大模型负责在每一步决定该调用哪个工具、怎么传参数。如果你正在做 Agent 开发或者刚看完 LangChain 入门教程、还没想清楚它和 LangGraph 有什么区别这篇文章就顺着实际落地顺序拆一遍概念、环境、MCP Server、Agent 代码、批量任务和排查。我想先把目标说清楚不是把代码堆在一起跑通了事而是让你知道每一层在解决什么问题。很多人在网上复制了一段 Agent 代码换一个工具就失灵本质就是没搞清楚协议和编排的关系。后面我会用一个“天气查询”工具做示例这个工具本身不复杂但能完整展示 MCP Server 定义、LangChain 加载、Agent 调用、结果返回的全过程。你把它替换成数据库查询、文件操作或企业内部接口逻辑是一样的。1. 先把 MCP 放进 Agent 的整体结构里1.1 四层关系模型、协议、工具、编排很多人学 LangChain 卡住不是代码难而是概念同时堆在一起。我建议先把 Agent 工具调用拆成四层模型层负责决策和文字生成本身不直接访问数据库或文件系统。协议层MCP。定义工具如何暴露、参数如何传递、结果如何返回。工具层真实能力比如查询数据库、读取文件、调用天气 API。编排层LangChain / LangGraph。控制“先调工具再回答还是先回答再调工具”并维护历史消息。当你说“LangChain 结合 MCP 做 Agent”时实际就是在协议层和工具层之间加了一层标准接口然后让编排层通过这个接口动态发现工具。这样模型不需要预先记住每个工具的实现细节只要按协议发起调用。这个模型想清楚之后再看代码就会舒服很多。后面所有报错排查也都是围绕这四个层来找。1.2 MCP 和自定义 Tool、Agent Skill 有什么区别在 LangChain 早期自定义工具是这样写的定义函数加tool装饰器塞进 tools 列表。它对少量工具完全够用。问题是如果你的工具要同时给多个系统用或者要对接一个已经存在的服务每个系统都要各写一遍接入代码。MCP 的出现就是把这部分标准化。MCP Server 负责暴露工具MCP Client 负责发现和调用工具。你的工具函数只需要在 Server 里实现一次任何支持 MCP 的客户端都能复用。这也是现在能看到各种垂直 MCP Server 的原因比如数据库、设计稿标注、IDE、数据分析等场景都有人在封装。那 Agent Skill 又是什么可以理解为带提示词、示例、脚本和工具的一整套“技能包”MCP 更偏底层协议。两者不是互斥关系你可以用 MCP 暴露工具再用 Skill 把使用方式、提示词模板传给 Agent。很多时候它们会配合使用。1.3 先画出典型链路再决定排查方向文字链路如下MCP Server定义工具 - MCP Client发现并读取工具 - LangChain Tool统一格式化 - Agent 循环模型决策 - 工具调用 - 结果回填给模型 - 输出最终答案为什么先要把链路画出来因为后面每一步报错都能映射到链路的某一环。比如工具列表是空的问题在 Server 暴露模型不调用工具问题常在模型能力和提示词工具调了但用户没看到结果问题可能在 Agent 循环没把结果回填。我一般会先单独测试前两环再进入 Agent。这样能把“Server 问题”和“Agent 问题”隔离开排查会快很多。2. 环境准备先用最小执行链路跑通一次2.1 硬件、系统和 Python 环境要求这套链路主要是 Python 生态加网络调用系统上没有特殊限制。Windows、macOS、Linux 都能跑。关键在于三点Python 版本、虚拟环境、网络访问到模型 API。建议 Python 3.10 以上。为什么MCP SDK 和 LangChain 系列包对 3.10 之后的兼容性比较稳定老版本容易出现某个依赖装不上或者类型报错。虚拟环境一定要建不要直接装到全局环境否则后面安装或升级依赖很容易把系统环境搞乱。硬件方面。如果你用的是 DeepSeek 这类云端模型接口本地不需要独立显卡8GB 内存的普通开发机也能跑因为推理发生在远程。真正吃资源的是本地部署模型那种情况需要看显存、内存和模型体积。低配置机器也能试 Demo但不要把并发开大先把单条任务跑通再说。2.2 模型接口怎么选DeepSeek API、本地模型和 Claude Code 各自的定位这里要分清三类东西很多人混淆DeepSeek API是模型服务。它提供 OpenAI 兼容接口LangChain 可以直接对接。本地模型把模型部署在你自己的机器或内网适合数据敏感场景但工具调用能力不如云端模型稳定。Claude Code是终端里的 Agent 产品适合交互式写代码和文件操作但它不是给 LangChain 用的模型接口。如果你只是想快速复现 Agent 工具调用优先用云端 OpenAI 兼容接口比如 DeepSeek。它不需要本地推理成本也相对可控。如果你要私有化部署就要额外考虑 GPU 资源、推理服务和模型文件名这不是这篇文章的最小路径。Claude Code 和 LangChain 怎么选如果你是写代码场景Claude Code 这类产品更方便如果你要自己控制业务状态、日志、批量任务、用户界面LangChain/LangGraph 更合适。甚至可以两个都保留开发阶段用终端产品做快速实验正式流程用 LangChain 编排。如果你更习惯图形界面在 VSCode 里配置命令行 Agent 工具也可以但那属于产品层面的操作不影响 LangChain 这边的编排逻辑。2.3 依赖安装和目录结构下面是一份最小依赖清单按这个装第一轮就能跑通mkdir langchain-mcp-demo cd langchain-mcp-demo python -m venv .venv source .venv/bin/activate # Windows 用 .venv\Scripts\activate pip install fastmcp pip install langchain langchain-openai langchain-mcp-adapters pip install langgraph python-dotenv说明一句langchain-mcp-adapters是 LangChain 生态里用来把 MCP 工具转成 LangChain Tool 的适配层具体包名以你安装版本为准。如果你的环境里已经装了其他 MCP SDK也可以直接用不一定非用 FastMCP。示例我选 FastMCP因为它写起来最短适合说明原理。目录结构建议这样langchain-mcp-demo/ ├── .env ├── server.py ├── agent.py └── README.md.env里放 API Key不要提交到 Git。server.py放 MCP Serveragent.py放 LangChain Agent。分类清楚之后排查问题会快很多。3. 手写一个 MCP Server工具定义、参数规范和单独验证3.1 用 FastMCP 写一个最简天气工具直接看代码from fastmcp import FastMCP mcp FastMCP(demo-server) mcp.tool() def get_weather(city: str) - str: 根据城市名返回当天天气信息用于演示 MCP 工具调用。 weather_map { 北京: 晴25 摄氏度, 上海: 多云28 摄氏度, 深圳: 阵雨26 摄氏度, } return weather_map.get( city, f暂无 {city} 的天气数据请检查城市名。 ) if __name__ __main__: mcp.run(transportstdio)这个工具很小但已经具备 MCP 的核心要素有一个明确的函数名get_weather有一个参数city有 docstring有返回值。FastMCP 会把函数名、参数 schema 和 docstring 自动转换成 MCP 协议里的工具定义。为什么用stdio因为在同一个机器上MCP Client 直接启动 Server 子进程并通过标准输入输出通信最稳。后面如果工具要跨机器访问再换streamable-http。第一次学习建议先跑stdio少一个网络端口问题。3.2 参数设计和返回值规范直接影响模型调用成功率写工具函数时参数设计直接影响模型能不能正确调用。第一参数要少。一个工具最好 1 到 3 个参数。参数多了模型填错概率会明显上升。第二参数名要直观。city、user_id、start_date这种一眼能看懂的最好不要用arg1、data这种含糊名字。第三docstring 必须讲清楚“这个工具是干什么的”以及“参数取值的边界”。模型靠 docstring 决定什么时候调用工具不能用一句“测试”带过。第四返回值要可解析。建议返回 JSON 字符串或固定结构。如果工具失败不要只抛异常可以把错误信息放进返回值。原因是Agent 循环中工具返回一个“结构化错误信息”模型还能继续处理并向用户说明直接抛异常会让整个 Agent 任务中断用户得到的信息非常有限。给一个错误返回的示例return {success: false, error: 城市参数不能为空}3.3 为什么先单独测试 MCP Server在接入 LangChain 之前先确认 MCP Server 本身没问题。这一步很多人会跳过等到 Agent 里报错才回头查白白浪费时间。最简单的验证方式先写一个小脚本用 MCP 客户端连接 Server列出工具列表。import asyncio from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client async def main(): server_params StdioServerParameters( commandpython, args[server.py], ) async with stdio_client(server_params) as (read, write): async with ClientSession(read, write) as session: await session.initialize() tools await session.list_tools() for tool in tools.tools: print(tool.name, tool.inputSchema) asyncio.run(main())注意这段代码用的是通用 MCP Python SDK具体写法在版本更新后可能有出入核心是“能列出工具”。如果这里能列出get_weather和它的参数 schema后面 LangChain 加载就会顺利很多。列不出来就回头检查 docstring、装饰器和文件路径。验证标准有三个Server 能启动、Client 能连接、工具列表不为空。满足这三条再进下一步。这样后面万一报错你可以更确信问题出在模型或编排层而不是 MCP Server。4. LangChain Agent 接入 MCP 的完整代码4.1 用适配器加载 MCP 工具LangChain 生态里接入 MCP 的常见方式是通过langchain-mcp-adapters。下面是一个基于多服务客户端的加载示例import asyncio from langchain_mcp_adapters.client import MultiServerMCPClient async def load_tools(): client MultiServerMCPClient( { demo: { command: python, args: [server.py], transport: stdio, } } ) tools await client.get_tools() for tool in tools: print(Loaded:, tool.name, tool.description[:60]) return tools if __name__ __main__: asyncio.run(load_tools())这段代码只做一件事启动 server.py 对应的 MCP Server通过 MCP 协议读取工具并把工具转换成 LangChain 的 Tool 对象。打印出来后你会看到get_weather这个工具以及它的描述。需要提醒的是这个适配器在不同版本的类名和包导入路径可能有调整。如果MultiServerMCPClient在你的环境里不存在去检查你安装的langchain-mcp-adapters版本或者看官方文档里的导入路径。这是很常见的版本差异问题不是你的代码逻辑有问题。4.2 配置 LLM以 DeepSeek 的 OpenAI 兼容接口为例模型配置放到独立文件用环境变量管理。以 DeepSeek 为例import os from dotenv import load_dotenv from langchain_openai import ChatOpenAI load_dotenv() llm ChatOpenAI( modelos.getenv(LLM_MODEL, deepseek-chat), api_keyos.getenv(DEEPSEEK_API_KEY), base_urlos.getenv(DEEPSEEK_BASE_URL, https://api.deepseek.com), temperature0.1, )这里有几个点要注意deepseek-chat只是常见模型标识最终以你账号下实际可用的模型为准。模型名写错请求会直接失败。base_url指向 OpenAI 兼容接口
返回列表