
最近在折腾 AI 应用开发尤其是 Agent 项目时我发现自己反复卡在同一个环节模型能力再强接不到业务数据、调不动内部工具就等于建好了发动机却没有传动轴。早期我都是给每个数据源单独写一套调用代码后来接触了 MCPModel Context Protocol整个接入方式被彻底统一了。这篇文章会把 MCP 的核心概念讲清楚并基于当前主流的 LangChain 生态从零搭建一个可以运行的实战项目写一个 MCP Server再通过 LangChain Agent 让它自动被大模型调用。文章覆盖环境准备、协议原理、完整代码、常见报错和工程化建议新手可以照着做有经验的开发者可以直接跳到实战部分复用。1. 背景与核心概念1.1 MCP 到底是什么MCP 的全称是 Model Context Protocol翻译过来是“模型上下文协议”。它是由 Anthropic 在 2024 年 11 月开源的一项开放协议目的是解决大模型与外部数据、工具之间“连接方式混乱”的问题。有一个很形象的比喻如果说大模型是一台电脑那么 MCP 就是这台电脑的 USB-C 接口。在没有 USB-C 之前键盘用圆口、鼠标用方口、显示器用 HDMI、网线用 RJ45每个设备要单独配线而 MCP 做的事情就是把所有外设统一成一个标准接口。AI 应用只需要实现一次 MCP 客户端就能连接任意支持 MCP 的服务端。从专业角度定义MCP 是一套基于 JSON-RPC 2.0 的通信协议它定义了 AI 模型获取上下文、调用工具、访问外部资源的标准方式。目前 MCP 已经覆盖了数据库、文件系统、HTTP API、开发工具、设计工具等大量场景。比如 Figma、蓝湖这类设计工具陆续提供了 MCP Server开发者可以通过自然语言直接操作设计稿的数据还有很多社区维护的 MCP Server可以访问搜索接口、读取网页、操作 Git 仓库等。1.2 MCP 解决了什么问题在做 AI Agent 开发之前我们一般用 function calling函数调用来让模型调用工具。这个方案本身没问题但它有一个明显的短板模型每接一个新工具就要重新写一遍参数定义、鉴权、协议转换逻辑。举个具体例子接入天气 API 时要把 OpenAPI 文档转换成模型能识别的工具描述接入内部业务系统时要封装鉴权和数据映射接入数据库时要单独定义 SQL 查询模板。这些工作一旦超过三个系统维护成本会急剧上升。更麻烦的是每个团队、每个框架的工具定义格式都可能不同。你用 LangChain 写了一套 Agent换到别的框架又要重写。MCP 的核心价值就是把这些“连接逻辑”从 AI 应用里剥离出来放到独立的 Server 端。AI 应用只需要通过一套标准协议去发现工具、调用工具、接收结果。这样带来的好处有四个标准化工具的定义、调用、返回格式统一。复用性同一个 MCP Server 可以被 LangChain、Claude Desktop、自研框架等任意客户端复用。解耦工具逻辑更新时改 Server 即可客户端无需变动。生态化社区上有大量现成的 MCP Server开箱即用。1.3 MCP 与 Agent、LangChain 的关系很多初学者分不清这几个概念我这里用一个分层方式说明LLM大模型负责理解和生成语言是大脑。Agent智能体利用大模型的推理能力自主决定“下一步调用哪个工具、执行什么动作”是决策者。MCP提供标准化的工具/数据连接通道是神经系统。LangChain一个 AI 应用开发框架负责组装模型、提示词、工具、记忆、编排等组件。简单说Agent 是目标LangChain 是脚手架MCP 是连接外部世界的通道。三者在实际项目中经常配合使用LangChain 负责构建 Agent 的执行框架Agent 通过 MCP Client 连接各种 MCP Server最终实现“大模型 真实业务能力”的闭环。2. 环境准备与版本说明2.1 开发环境本文的实战示例使用 Python需要准备以下环境操作系统Windows 10/11、macOS 或 Linux 均可本文以 Ubuntu 24.04 为例。Python建议 3.10 及以上版本。IDEVS Code 或其他主流编辑器。大模型 API任意支持 OpenAI 兼容接口的模型服务本文示例使用 OpenAI 接口风格的配置。不同版本的 LangChain 和 MCP SDK 接口可能有差异项目中所用的版本需要根据你的实际环境调整。我在代码中会标注关键 API 的作用遇到接口报错时优先检查版本。2.2 安装依赖建议先创建独立的虚拟环境避免依赖冲突python -m venv venv source venv/bin/activate # Windows 下使用 venv\Scripts\activate然后安装核心依赖pip install mcp[cli] langchain langchain-mcp-adapters langchain-openai这里简单解释每个包的作用mcp[cli]MCP 官方 Python SDK包含 FastMCP、ClientSession 等核心组件[cli]会附带调试命令mcp。langchainLangChain 主框架。langchain-mcp-adaptersLangChain 官方提供的 MCP 适配层用于把 MCP 工具转换成 LangChain 可用的工具格式。langchain-openaiLangChain 中的 OpenAI 兼容模型接入包。2.3 项目结构我们实战项目的目录结构如下mcp-langchain-demo/ ├── server.py # MCP Server提供天气查询工具 ├── client_test.py # 独立 MCP Client用于验证 Server ├── agent.py # LangChain Agent 集成 MCP 的入口 └── requirements.txt # 依赖清单3. MCP 协议核心原理拆解虽然日常开发中我们更多在跟 SDK 打交道但理解协议本身能帮助你更快排查问题尤其是跨语言、跨框架联调的时候。3.1 MCP 的三大核心抽象MCP 协议定义了三种核心能力理解这三者就能把握 MCP 的设计意图。第一是 Tools工具。工具是让模型执行动作的接口比如查询天气、发送邮件、执行 SQL。每个工具都有名称、描述和参数定义。关键点在于工具是由模型根据用户意图动态选择调用的所以名称要见名知意描述要清晰参数类型要明确。第二是 Resources资源。资源是提供给模型阅读的数据比如文件内容、数据库记录、API 响应。与工具不同资源通常不需要“执行”而是直接作为上下文输入。比如你要让模型分析一份 PDF就可以把这个 PDF 注册成一个 Resource模型读取后进行分析。第三是 Prompts提示词模板。它提供了可复用的提示模板类似于把某个领域的专家指令打包。客户端可以通过prompts/get获取模板再填充参数生成完整的提示词。一句话总结工具负责“动手”资源负责“喂数据”提示词负责“教方法”。3.2 两种主流传输方式MCP 支持多种传输方式实际开发中主要接触两种。stdio标准输入输出方式是最简单也最常见的。MCP Server 作为客户端的一个子进程启动双方通过标准输入 stdin 和标准输出 stdout 进行 JSON-RPC 消息交换。优点是无需网络端口部署简单适合本地工具缺点是 Server 生命周期跟随客户端不适合跨机器部署。Streamable HTTP 方式则把 MCP Server 部署成独立的 HTTP 服务客户端通过 HTTP 请求与其通信。它支持远程调用、身份认证和状态管理更适合生产环境的多服务部署。选择建议是本地实验、开发调试用 stdio 最简单正式部署、多个客户端共享同一个 Server 时优先考虑 Streamable HTTP。3.3 JSON-RPC 消息格式MCP 基于 JSON-RPC 2.0 通信所有请求和响应都是 JSON 对象。比如客户端调用get_weather工具时发送的消息大致如下{ jsonrpc: 2.0, id: 1, method: tools/call, params: { name: get_weather, arguments: { city: 北京 } } }其中method是协议方法名params是参数。核心方法包括initialize客户端与服务端握手协商协议版本和能力。tools/list获取服务端提供的工具列表。tools/call调用指定工具。resources/list获取资源列表。prompts/get获取提示词模板。日常使用 SDK 时这些消息会被封装但理解结构有助于排查问题。当你看到“method not found”或“connection closed”这类错误时大概率就是协议握手或传输方式不匹配。4. 实战MCP Server LangChain Agent 完整集成接下来我们完成一个从零到一的可运行项目。业务场景设定为Agent 可以查询多个城市的天气并回答用户关于天气的追问。4.1 创建项目与依赖清单先创建项目目录并准备requirements.txtmcp[cli]1.2.0 langchain0.3.0 langchain-mcp-adapters0.1.0 langchain-openai0.2.0然后在终端安装pip install -r requirements.txt如果安装时提示版本冲突优先把langchain和langchain-mcp-adapters升级到最新稳定版因为 MCP 适配器的 API 变化较快。4.2 编写 MCP Server在server.py中我们使用 FastMCP 快速定义一个带两个工具的天气服务。# 文件路径server.py from mcp.server.fastmcp import FastMCP # 创建 MCP Server 实例名称会作为服务标识 mcp FastMCP(WeatherServer) # 模拟天气数据源实际项目可替换为数据库或外部 API WEATHER_DATA { 北京: 晴最高温 26℃最低温 14℃东南风 2 级, 上海: 多云最高温 28℃最低温 19℃东风 3 级, 广州: 雷阵雨最高温 30℃最低温 24℃南风 2 级, } mcp.tool() def get_weather(city: str) - str: 查询指定城市的实时天气情况。 Args: city: 城市名称例如北京、上海、广州 Returns: 该城市的天气描述字符串 if city in WEATHER_DATA: return WEATHER_DATA[city] return f暂未收录 {city} 的天气数据请确认城市名称后重试。 mcp.tool() def get_supported_cities() - list[str]: 获取所有支持天气查询的城市列表。 return list(WEATHER_DATA.keys()) if __name__ __main__: # 默认以 stdio 方式运行 mcp.run()这里有两个需要注意的细节。第一mcp.tool()装饰器会把被装饰的函数注册成 MCP 工具。函数的文档字符串docstring非常重要因为 LangChain Agent 会把工具描述拼接进系统提示词让模型知道“什么时候该调用这个工具”。描述写得模糊模型就会在错误场景调用或者干脆不调用。第二参数类型标注必须是具体的类型比如str、int、float、list等。MCP 会根据类型标注自动生成 JSON Schema如果用了dict或者Any工具参数校验会变得不可控。4.3 用独立 Client 验证 Server先不急着集成 LangChain我们要用最底层的 ClientSession 验证 Server 是否正常工作。创建client_test.py# 文件路径client_test.py import asyncio from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client async def main(): # 配置子进程启动参数python server.py 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() print( 可用工具列表 ) for tool in tools.tools: print(f- {tool.name}: {tool.description}) # 调用 get_weather 工具 result await session.call_tool(get_weather, {city: 北京}) print(\n 调用 get_weather 结果 ) print(result.content) if __name__ __main__: asyncio.run(main())运行验证python client_test.py预期输出类似 可用工具列表 - get_weather: 查询指定城市的实时天气情况。 - get_supported_cities: 获取所有支持天气查询的城市列表。 调用 get_weather 结果 [TextContent(typetext, text晴最高温 26℃最低温 14℃东南风 2 级)]看到工具列表和返回内容说明 Server 和 Client 之间的通信链路已经打通。4.4 集成到 LangChain Agent接下来是关键环节让 LangChain Agent 自动决定调用 MCP 工具。创建agent.py# 文件路径agent.py import asyncio from langchain.agents import create_agent from langchain_mcp_adapters.client import MultiServerMCPClient from langchain_openai import ChatOpenAI async def main(): # 注册一个 stdio 类型的 MCP Server async with MultiServerMCPClient( { weather-server: { command: python, args: [server.py], transport: stdio, } } ) as client: # 将 MCP 工具转换为 LangChain 工具 tools client.get_tools() # 初始化大模型 model ChatOpenAI(modelgpt-4o, temperature0) # 创建 Agent agent create_agent(model, tools) # 向 Agent 提问 response await agent.ainvoke( { messages: [ { role: user, content: 北京和上海今天天气怎么样哪个城市更热, } ] } ) # 输出 Agent 最终回复 print(response[messages][-1].content) if __name__ __main__: asyncio.run(main())这段代码做了几件事MultiServerMCPClient是适配层的入口可以同时注册多个 MCP Server。键名是自定义标识command、args指定了 Server 的启动方式transport指定传输类型。client.get_tools()会启动 Server 并读取tools/list返回一个 LangChain 工具列表。create_agent是 LangChain 新版推荐的 Agent 创建方式传入模型和工具框架会自动编排“思考-调用工具-观察结果-再思考”的循环。agent.ainvoke执行对话内部会自动处理中间的工具调用过程。如果你的 LangChain 版本较老使用的可能是initialize_agent或create_tool_calling_agent建议升级到 0.3 以上并使用create_agent。4.5 运行与验证运行 Agentpython agent.py模型会经历类似下面的内部过程读取用户问题判断需要查询两个城市的天气。调用get_weather({city: 北京})得到结果。调用get_weather({city: 上海})得到结果。根据两个结果生成回答。最终输出大致为北京今天晴最高温26℃最低温14℃上海多云最高温28℃最低温19℃。上海比北京更热。到这里你已经完成了一个完整的 MCP LangChain Agent 集成链路。如果调试时模型没有自动调用工具可以开启 LangChain 的运行日志观察中间步骤是否触发了 tools 调用。5. 进阶Agent Skill 与 MCP 有什么区别在最近的 AI 开发讨论中除了 MCPAgent Skill 也是一个高频词汇。很多读者问我它们是不是同一个东西这里统一说明。5.1 两者的定位不同MCP 解决的是“能力连接”问题。它把工具、数据资源从 AI 应用中解耦出来通过标准化协议让模型调用外部系统。你可以理解为MCP 是插头和插座的标准把充电器、显示器、硬盘都接到了电脑上。Agent Skill 则更侧重“任务过程知识”。一个 Skill 通常是一组指令、代码模板和使用说明的集合告诉模型“完成某类任务时需要遵循什么步骤、使用什么策略”。它更像是给模型一本操作手册。举一个区分例子查询天气并返回结构化 JSON适合用 MCP Tool 实现因为这是确定性的对外接口调用。撰写一份季度复盘报告包含数据提取、分析框架、文风要求这适合用 Skill 封装因为过程知识比单纯调用一个接口复杂得多。5.2 如何选择在实际项目中两者的边界并不是互斥的。一个 Skill 内部完全可以通过 MCP 调用外部工具。更合理的做法是需要对接外部系统、提供可复用能力时优先做成 MCP Server。需要沉淀特定领域的工作流程、提示策略时优先做成 Agent Skill。两者结合使用MCP 提供工具基础Skill 提供流程引导。对初学者来说建议先掌握 MCP因为它是 AI 应用开发的基础设施。Skill 是更高层的工作流抽象理解 MCP 之后再学习会顺畅很多。6. 常见问题与排查思路在实践 MCP LangChain 的过程中下面几个问题出现频率最高。问题现象常见原因解决思路Server 启动后立刻退出stdio 子进程启动失败command 或 args 配置错误先在终端手动运行python server.py验证提示 tool not found工具注册失败或客户端与服务端版本不兼容用client_test.py的list_tools检查工具列表Agent 调用工具超时工具执行耗时过长或阻塞优化工具逻辑增加超时配置依赖冲突安装失败langchain 与 langchain-mcp-adapters 版本不匹配统一升级到最新稳定版模型不触发工具调用模型不支持 tool calling或工具描述不清晰更换支持 function calling 的模型完善 docstring调用 MCP 工具返回空结果函数返回了复杂的 Python 对象无法序列化确保返回 str、int、list 等 JSON 可序列化类型6.1 子进程启动失败错误表现为连接直接断开或提示无法启动python。排查步骤python server.py手动启动如果报错说明代码有问题如果正常启动说明MultiServerMCPClient中的command或args配置与当前环境不符。在 Windows 上有时需要把command改为python的完整路径或者使用py命令。6.2 工具描述不完整导致调用不准确模型决定是否调用工具主要依据是工具的名称和描述。建议描述中明确说明“这个工具做什么”“什么场景下使用”“参数含义是什么”。例如mcp.tool() def send_email(to: str, subject: str, body: str) - str: 向指定收件人发送邮件。仅用于用户明确要求发送邮件时使用。 Args: to: 收件人邮箱地址 subject: 邮件主题 body: 邮件正文内容 对比一下如果描述写成“发送邮件”三个字模型在邮件相关场景可能不会调用它因为信息不足以建立关联。6.3 生产环境的连接不稳定本地 stdio 方式在服务器上长期运行时可能会因为进程退出或文件描述符泄露导致连接不稳定。解决方案是把 MCP Server 改造成 Streamable HTTP 模式作为独立服务运行客户端通过 URL 连接。改动主要集中在启动代码# server.py 的启动部分按需切换到 HTTP 模式 if __name__ __main__: mcp.run(transporthttp)具体参数取决于你所安装的 MCP SDK 版本修改前先查阅对应版本的文档。7. 最佳实践与工程建议7.1 工具设计规范MCP 工具等同于对外暴露的 API设计质量直接决定 Agent 的成功率。建议遵循几点名称采用小写动词 名词例如get_weather、create_ticket。每个工具必须有清晰的 docstring注明用途、参数含义和返回值。参数尽量使用简单类型避免深层嵌套结构。返回结果优先使用 JSON 字符串便于模型解析。一个工具只做一件事不要写“万能工具”。7.2 安全与权限边界这是工程落地中最不能省略的部分。MCP Server 如果连了数据库或内部系统本质上是把操作权限交给了模型。必须做到输入校验对用户传入的参数做严格校验防止通过工具拼接出恶意命令或 SQL 注入。最小权限Server 运行账号只授予业务必需权限不要用管理员账号跑服务。密钥隔离不要把 API Key、数据库密码硬编码在 Server 代码中使用环境变量或配置中心管理。操作确认涉及删除、修改、支付等高危操作时增加二次确认机制不要让 Agent 直接执行。7.3 可观测性与日志Agent 调用链路长一旦出问题很难定位。建议在工具函数内外增加结构化日志记录入参、出参和耗时import logging import time logger logging.getLogger(mcp.tool) def log_tool_call(func_name: str): def decorator(func): def wrapper(*args, **kwargs): start time.time() logger.info(调用工具 %s, args%s, kwargs%s, func_name, args, kwargs) try: result func(*args, **kwargs) logger.info(工具 %s 返回成功, 耗时 %.2fs, func_name, time.time() - start) return result except Exception as e: logger.error(工具 %s 执行失败: %s, func_name, e, exc_infoTrue) raise return wrapper return decorator接入分布式追踪系统后可以完整看到“用户提问 → 模型决策 → 工具调用 → 返回结果”的链路。7.4 生产环境注意事项优先使用 Streamable HTTP 部署而不是 stdio避免子进程生命周期难以管理的问题。为每个 MCP Server 配置独立的健康检查接口和超时控制。工具调用失败时返回结构化错误信息而不是抛出未捕获异常方便模型判断下一步动作。版本升级前在测试环境跑一遍工具清单遍历和关键调用用例MCP SDK 迭代速度较快。8. 总结与学习路线这篇文章从概念到实战完整走通了 MCP LangChain Agent 的集成路线。你现在应该已经掌握MCP 是什么以及它如何解决 AI 应用连接外部系统的标准化问题。MCP 的三大核心抽象工具、资源、提示词和两种主流传输方式。使用 FastMCP 编写一个可运行的 MCP Server。通过 LangChain Agent 自动调用 MCP 工具。MCP 与 Agent Skill 的区别和选型思路。常见报错的排查方式和工程化建议。下一步的学习路线我建议按顺序推进熟悉 MCP 官方文档中关于 Authorization、Streamable HTTP 服务端部署、Vendoring 等进阶内容。把实战项目升级为 HTTP 模式体验远程连接与多客户端复用。学习 LangGraph理解状态机、记忆和复杂工作流编排它与 LangChain 本体的区别在于LangChain 适合快速组装链式调用LangGraph 更适合需要分支、循环和状态持久化的复杂 Agent 场景。尝试对接社区现成的 MCP Server比如数据库、Git、办公文档类理解不同 Server 的设计差异。在真实业务里选一个小工具例如工单查询、报表生成改造成 MCP Server推动一次实际的“AI 接入业务系统”。动手写一个 MCP Server 并不难难的是把它设计得严谨、安全、可维护。建议你从今天这个天气示例开始先跑通链路再逐步加入鉴权、日志和 HTTP 部署一步步把标准协议转化为工程能力。如果本文对你有帮助可以收藏备用后续我会继续更新关于 MCP 远程部署和 LangGraph Agent 编排的实战内容。