MCP(Model Context Protocol)[ 1 ]

1. MCP 概述
1.1 MCP 的由来
MCP 的全称是 Model Context Protocol。
那这个 MCP 到底是什么?想要弄懂它,我们先从工具调用相关的业务场景和大家讲起。
在如今高速发展的 AI 应用生态里,存在大量同类场景:
-
第一个场景,某智能助手需要调用高德地图接口获取位置信息;
-
第二个场景,用户向 AI 提问时,系统需要联网检索外部资料;
-
第三个场景,很多企业内部有多套 AI 应用,全部依赖同一套公共服务,比如用户权限校验服务,这套统一服务专门负责鉴权,多个业务应用都会复用它。
这个时候问题就来了,Tool Calling(工具调用) 可以使大模型能够突破语言生成的局限,主动调用外部系统完成实际任务。然而,随着工具数量增长和应用场景复杂化,传统的 Tool Calling 实现方式逐渐暴露出一系列工程挑战:
-
工具接口格式不统一,需为每个服务定制解析逻辑;
-
模型侧需硬编码工具定义 (如函数名、参数
schema),缺乏动态发现能力; -
多平台兼容性差
-
……
讲到这里大家可以思考一个问题:我们之前已经学习过 Agent 开发、自定义工具,用这套现有方案能不能实现上面三类需求?
答案是可以的。我们来拆解一下传统的实现方式: 我们可以直接在代码里自定义 Agent,针对不同业务单独开发对应工具。
第一种场景,想要调用高德地图拿位置,我们单独写一个工具,在工具内部对接高德开放 API,就能完成定位查询能力;
第二种场景,联网搜索同理,单独对接搜索服务商 API,封装成专属工具即可实现;
第三种场景的痛点就暴露出来了。举个例子:假设我们第一个项目里写了一个天气查询工具,对接天气 API;如果现在新开第二个独立项目,新项目同样需要查询天气,按照传统方案,你必须在新项目里重复编写一套一模一样的天气工具,重新对接天气接口,这就产生了大量冗余重复开发。
那我们就会产生一个需求:能不能只开发一套独立服务,这个服务向外提供标准化的天气工具能力?只要这套天气服务能和我们各个业务项目建立连接,不管是新项目还是旧项目,都不用再重复编写天气工具。业务项目只需要通过远程调用,先读取服务提供的工具列表,再发起工具调用请求,最后接收服务返回的结果,就能复用天气查询能力。 这个需求对应的解决方案,就是 MCP,MCP 就是为了解决重复开发工具、多项目复用外部能力这个痛点诞生的。
我们再重申一遍,MCP 全称 Model Context Protocol,翻译为模型上下文协议。它是一套标准化规范,作用是让大模型能够安全地连接任意外部工具、外部数据源。
所以为了解决这个问题,一个名为 模型上下文协议 (Model Context Protocol,MCP) 的标准应运而生。 MCP 并不替代 Tool Calling,而是为其提供一个统一、可扩展、跨平台的连接基础设施。
MCP 是
Tool Calling的 "标准化运行时" 可以把两者的关系理解为
Tool Calling是决策行为:模型决定 "要不要调用工具"、"调哪个工具"、"传什么参数"MCP 是通信协议:规定 "如何描述工具"、"如何发起调用"、"如何传递结果"、"如何管理会话状态"
这就像 Web 应用中的浏览器与 HTTP 协议的关系:
-
浏览器决定要访问哪个页面 (相当于模型发起
Tool Calling) -
而真正完成数据传输的是底层的
HTTP协议 (相当于 MCP 承载调用过程)
再比如假设你要做一个旅游推荐机器人,它可以:
查天气 + 查景点信息 + 预定酒店
这些功能分别由三个不同的团队提供服务。 如果每个服务都自己定义一套交互方式 -- 有的用 REST API,有的用 gRPC,有的返回 XML,有的要求特定 Header 认证…… 如果没有 MCP,你的 AI 应用程序就要写三套调用逻辑,维护三种错误处理机制,非常麻烦。
更糟糕的是,AI 本身并不直接理解 HTTP 请求怎么发、JSON 怎么构造。它只能告诉你:"我想查某个用户的地址。" 至于怎么调用接口、传什么参数、如何解析结果,必须有人帮它完成。 于是,我们需要一个 "翻译官"+"中介平台"—— 这就是 MCP 诞生的意义。
接下来我们梳理它的完整工作逻辑,方便大家理解:
我们业务项目里的 Agent,底层依托大语言模型运行。
大模型在整个链路里负责决策,第一步要做的决策就是:当前问题是否需要调用工具、调用哪一个工具。 想要完成这个决策,外部工具服务必须提前告知我们的业务项目(大模型)它具备哪些可用工具,这是整个流程的第一步;
第二步,业务项目拿到完整工具列表后,就可以发起工具调用请求;
第三步,外部工具服务执行对应工具逻辑后,把执行结果回传给业务项目内的大语言模型,由模型结合返回结果做后续推理处理。 以上就是 MCP 最基础的工作逻辑。
接下来我们就来聊聊什么是 MCP,它为什么重要,以及它是如何工作的
1.2 MCP 是什么
MCP (
Model Context Protocol) is an open-source standard for connecting AI applications to external systems.Using MCP, AI applications like Claude or ChatGPT can connect to data sources (e.g. local files, databases), tools (e.g. search engines, calculators) and workflows (e.g. specialized prompts)—enabling them to access key information and perform tasks.
Think of MCP like a
USB-Cport for AI applications. Just asUSB-Cprovides a standardized way to connect electronic devices, MCP provides a standardized way to connect AI applications to external systems.摘自:
MCP (Model Context Protocol) 是一个开放标准协议,它的目标是让大模型驱动的 AI 应用 (比如 Claude、ChatGPT 等) 能够像 " 插上 USB-C 接口 " 一样,轻松连接到外部系统 —— 包括数据库、文件、工具、软件甚至物理设备
你可以把它想象成: AI 的 "万能插座" 或 "通用接口"。 以前每个 AI 工具要接入某个服务 (如日历、邮箱),都得单独开发一套对接逻辑;现在有了 MCP,就像所有设备都统一用 USB-C 充电一样,只要遵循这个标准,就能即插即用。

1.3 MCP 能做什么
- Agents can access your Google Calendar and Notion, acting as a more personalized AI assistant.
- Claude Code can generate an entire web app using a Figma design.
- Enterprise chatbots can connect to multiple databases across an organization, empowering users to analyze data using chat.
- AI models can create 3D designs on Blender and print them out using a 3D printer.
以上引用自:
总结一下,就是 MCP 让 AI 模型不再只是 "聊天机器人",而是可以:
-
获取你的私人数据 (在授权前提下)
-
使用专业工具执行任务
-
自动完成复杂工作流
也就是说 MCP 本质是大模型的万能标准化插头,专门用来给大模型补充上下文。这里的 “上下文” 是一个抽象概念,不只是我们之前学的聊天对话记录、context,还包含三类核心资源:
-
各类外部工具;
-
文件、数据库等结构化数据资源;
-
可复用的提示词模板。
案例 1: 企业级数据分析助手
销售经理问: "为什么上个月华南区销量下降了?"
AI 通过 MCP 同时访问:
- CRM 系统 (客户跟进记录)
- ERP 系统 (库存与发货数据)
- 邮件系统 (内部沟通异常报告)
分析发现:某关键供应商延迟交货导致缺货
自动生成可视化图表 + 改进建议文档
对于开发者而言,可以不再为每个 AI 应用重复开发插件,只需做一个 MCP Server,多个 AI 都能调用。 对于 AI 应用 / Agent 而言,可以快速集成海量工具,增强产品竞争力 (比如让 ChatGPT 能控制微信)。 对于普通用户而言,可以获得更聪明、更懂你、能办事的 AI 助手,而不是只会回答问题的 "百科机器人"。
案例 2:如果外部服务里提前封装好了提示词模板,各个 AI 应用都能通过 MCP 协议直接读取;不同提示词模板还能和对应工具绑定,A 模板适配工具 A、B 模板适配工具 B。这三类资源全部属于大模型的扩展上下文,能大幅扩充大模型的实际业务能力。
我们这里再深入类比 USB-C 协议帮大家加深理解: 生活中的 USB-C 是通用标准,手机、电脑、显示器等设备都可以通过它传输数据、供电; MCP 和它逻辑一致,作为标准化协议,打通 AI 应用与外部资源,实现工具、数据、提示词模板的双向数据传输,这就是 MCP 的核心定位。通过这个类比,大家应该就能明白 MCP 协议的本质作用。
接下来我们讲解 MCP 底层完整组成结构,它一共有三类核心角色:Host、Client、Server,三者互相配合完成通信。
-
Host(宿主) 宿主就是 AI 应用程序本身。比如电脑上的 Claude 桌面客户端、编辑器里的各类 AI 插件,这些能直接和用户交互的程序都属于 Host。Host 有两个关键特性:一是直接面向用户交互;二是不会直接对接外部数据源、外部工具,它不直接和外部资源通信。Host 的核心行为是启动内部的 Client 客户端,一个 Host 可以同时启动多个 Client。
-
Client(客户端) Client 运行在 Host 内部,相当于协议翻译官,每一个 Client 单独对应一个 Server 建立通信通道。Client 与 Server 之间统一采用
JSON-RPC 2.0轻量级远程调用协议交互。 Client 会代替上层 Host 向 Server 询问:你具备哪些可用能力,再把获取到的工具、资源清单转发给内部大模型,供模型做调用决策。 -
Server(服务端) Server 是真正执行业务逻辑的轻量程序,通常单文件即可部署,也是我们开发者主要开发的部分。我们会在 Server 内部封装所有外部能力,也就是前面提到的三类资源:工具、数据资源、提示词模板。 Server 相当于协议桥梁,负责对接真实的外部系统,把外部能力统一封装成
MCP标准格式,再交给 Client 交互。
我们分别拆解三类资源的含义:
-
工具:模型可调用执行的业务函数,例如天气查询、邮件发送、高德地图定位接口等;
-
资源:结构化外部数据,例如本地文件内容、数据库存储记录,AI 应用可通过
MCP读取这类数据; -
提示词模板:提前编写好的标准化对话模板,方便业务快速复用,还能和工具绑定配套使用。
补充通信方式【下面详细解释】:Client 和 Server 支持两种通信模式
-
本地进程通信:依靠标准输入输出(stdin/stdout)完成交互;
-
网络远程通信:例如 SSE 长连接等网络方案;同时协议内部原生内置安全相关能力,后续遇到具体场景再详细讲解。
2. MCP 传输方式
MCP 支持两种主要的客户端 - 服务器通信传输机制。
2.1 HTTP(也称 streamable-http)
-
通过
HTTP请求通信。有关详细信息,请参见 MCP HTTP 运输规范。 -
适合远程服务器、云部署。
-
支持传递自定义请求头(如认证
token)和实现httpx.Auth接口的认证机制。示例自定义身份验证实现
配置示例:
client = MultiServerMCPClient({
"weather": {
"transport": "http",
"url": "http://localhost:8000/mcp",
"headers": { # 可选
"Authorization": "Bearer YOUR_TOKEN"
},
# "auth": custom_auth_object # 可选, 实现 httpx.Auth
}
})
2.2 stdio
-
客户端将服务器作为子进程启动,通过标准输入 / 输出通信。
-
适合本地工具、简单配置。
-
有状态特性:子进程在客户端连接期间持续存在,但
MultiServerMCPClient默认仍为每次工具调用创建新会话。
配置示例:
client = MultiServerMCPClient({
"math": {
"transport": "stdio",
"command": "python",
"args": ["/path/to/your_server.py"],
}
})
讲完三大核心角色和相关通信方式,接下来我们完整走一遍标准交互流程,以查询北京天气为例,直观感受整套链路的执行逻辑:
第 1 步:Server 启动,对外宣告自身能力 Server 程序启动完成后,通过中间 Client 桥梁,告知上层 Host:我提供 get_weather 工具,同时同步该工具所需的全部入参定义。
第 2 步:Client 连接 Server,自动发现全量工具 Client 和 Server 建立连接时,会调用 MCP 协议原生提供的工具列表查询方法,一次性拉取 Server 所有可用工具清单。后续我们写代码时会用到同名接口,用法完全一致。
第 3 步:Host 接收用户问题,打包用户提问 + 工具列表下发大模型 用户在 Host(AI 应用)输入问题 “北京天气怎么样”,Host 把用户问题、刚刚拉取到的完整工具列表打包,发送给内部大语言模型,启动 Agent 推理流程。
第 4 步:大模型执行决策,选定需要调用的工具并填充参数 大模型结合用户问题和工具列表做判断:查询天气需要调用 get_weather 工具,同时把入参 city 字段赋值为 “北京”,生成标准工具调用请求。
第 5 步:Client 转发模型生成的工具调用请求至 Server Host 接收大模型输出的调用指令后,交由对应 Client,通过 JSON-RPC 2.0 协议把工具名称、入参完整转发给天气 Server。
第 6 步:Server 接收请求,执行对应工具业务逻辑 Server 收到调用指令,识别到需要执行 get_weather、参数 city = 北京,内部调用天气 API 完成数据查询。
第 7 步:Server 标准化封装结果,通过 Client 回传给 Host Server 把查询到的天气数据按照 MCP 规范封装成统一格式,经由 Client 反向传输回上层 Host,也就是我们的 Agent 程序。
第 8 步:大模型接收工具返回结果,生成最终自然语言回答 Host 拿到标准化工具返回消息后,交给大模型整合数据,生成通顺的最终回答展示给用户。
整套流程底层分为 8 个标准步骤,用户只能看到最终一句问答结果,底层完整链路对用户完全透明;但我们开发学习 MCP,必须掌握这一套标准流程。【这个我们在快速上手的时候会进行演示】
这里有一个核心优势:只要所有程序遵循 MCP 协议规范,不管上层 Host 换成什么业务项目、底层切换任意大模型,我们开发好的 Server 服务完全不用修改一行代码,工具清单、业务逻辑全部复用,这就是标准化协议带来的开发便利。
补充说明:这套 8 步通信流程是通用的,如果需求改为读取数据库、读取本地文件,底层交互逻辑和天气查询完全一致,全部依靠 Client 这个协议桥梁完成双向通信,这也体现了 MCP 协议的通用性。
最后厘清一个关键概念:MCP 并不会替代我们之前学习的 Tool Calling(工具调用),而是对工具调用的接口层做统一标准化。
大模型自身的推理能力、工具调用决策能力,是模型本身自带的,由上层 Host 里绑定的大模型提供;
但如何对外暴露工具、如何标准化描述工具、调用请求怎么传输、工具结果怎么回传,全部统一遵循 MCP 协议的规范约束。
我们用网络协议做类比,方便大家理解:我们之前前学过网络 HTTP 协议,HTTP 标准化规定了浏览器和服务器之间如何传输文本、交互数据;但网页长什么样子、页面业务逻辑,是由上层 HTML 决定的。分层逻辑非常清晰:HTTP 是底层传输标准,HTML 是上层业务表现。
对应到 AI 体系里:MCP 就相当于 AI 工具调用领域的 HTTP 传输协议。上层 Host 是我们的 AI 应用,应用内部绑定的大模型负责推理、工具决策(等同于 HTML 上层业务能力);下层是各类外部 Server 服务;中间依靠 MCP 这套统一协议,完成工具、数据、提示词的标准化传输。
到这里,关于 MCP 的定义、类比理解、底层三大核心角色、完整交互流程、和 Tool Calling 的区分关系,所有底层原理就全部给大家讲解完毕了。
3. MCP 快速上手
3.1 自定义 MCP 服务器
接下来我们不讲过多概念,直接带大家快速上手实操 MCP。 在正式编码之前,我们先梳理清楚整体架构,明确本次案例需要搭建的核心模块。
按照我们前面讲解的 MCP 架构思路,一整套完整的 MCP 调用体系主要包含三部分:
第一,宿主 Host,也就是我们的 AI 应用,下面我们也会手动搭建对应的 Agent 智能体;
第二,客户端 Client,专门用于连接、通信、发现服务端工具;
第三,服务端 Server,我们会在 Server 中自定义多个业务工具,最终让上层 AI 应用通过标准的 MCP 协议远程调用服务端的所有工具。
梳理完架构后,我们开始分步编码实现。首先我们先完成MCP 服务端 Server 的搭建。 根据我们之前讲解的 MCP 八大执行步骤,第一步就是启动 Server,并且对外宣告自身的工具能力。所以我们优先开发服务端程序。
我们新建一个 Python 文件,用来编写 MCP 服务端代码。 本次快速上手案例中,我们先实现最简单的计算器工具服务,包含加法、乘法两个基础计算能力。
想要快速搭建标准的 MCP 服务端,我们需要依赖 fastmcp 第三方库【使用 库创建自己的 MCP 服务器】FastMCP
这里大家注意:fastmcp 并不是 LangChain 官方提供的库,而是一个专门封装了原生 MCP 协议的开源框架,能够帮助我们极简、快速搭建标准的 MCP 服务端与客户端。上面链接也附带了官方文档,大家后面可以自行查阅学习详细用法。
首先我们需要在项目环境中安装依赖:
pip install fastmcp
安装完成后,我们就可以正式编写 MCP 服务端代码。大家一定要注意包的导入路径和命名空间,不要导入错误。
from fastmcp import FastMCP
我们先实例化一个 FastMCP 对象,给当前服务命名为计算服务,以此生成一个标准的 MCP 服务实例。 服务实例创建完成后,调用 run() 方法即可启动服务。启动时必须指定 transport 参数,用来声明当前 MCP 服务使用的通信传输协议。
我们之前讲过,MCP 的 Client 和 Server 支持两种通信方式: 第一种是本地进程通信(标准输入输出 stdio),适用于本地开发调试; 第二种是网络 HTTP 通信(streamable-http),适用于远程服务部署调用。
两种方式我们都会带大家实操演示。首先我们搭建基于 stdio 本地进程通信的 MCP 服务。 将 transport 参数设置为 stdio,此时服务会以本地子进程方式启动,后续客户端只能通过本地进程通信的方式连接并调用工具。
# ==================== 1. 创建 MCP 服务器实例 ====================
# FastMCP 是一个用于构建 Model Context Protocol (MCP) 服务器的框架
# MCP 是一种协议,允许 AI 模型通过标准化的方式调用外部工具和获取上下文
# "Math" 是服务器的名称,用于标识这个 MCP 服务
mcp = FastMCP("Math")
# ==================== 3. 主程序入口 ====================
if __name__ == "__main__":
"""
启动 MCP 服务器
MCP 服务器支持多种传输方式:
- stdio: 标准输入/输出(最常用,适合与本地 AI 客户端通信)
- sse: Server-Sent Events(适合 Web 环境)
- http: HTTP 协议(适合 REST API 风格)
使用 stdio 传输时:
1. 服务器通过标准输入接收 JSON-RPC 请求
2. 通过标准输出返回 JSON-RPC 响应
3. AI 客户端(如 Claude Desktop)可以启动子进程并与之通信
工作流程:
1. AI 客户端启动 MCP 服务器子进程
2. 服务器通过 stdio 发送工具列表(初始化阶段)
3. AI 模型决定调用哪个工具
4. 客户端通过 stdio 发送工具调用请求
5. 服务器执行工具并返回结果
6. 客户端将结果传递给 AI 模型
"""
mcp.run(
transport="stdio", # 使用标准输入输出进行通信
)
服务实例创建完成后,我们需要定义工具。 fastmcp 提供了专用装饰器 @mcp.tool(),被该装饰器修饰的函数,都会被自动注册为 MCP 可调用的标准工具。
我们依次定义两个工具函数: 第一个是加法工具,接收两个整型参数 a、b,返回两数之和; 第二个是乘法工具,接收两个整型参数 a、b,返回两数之积。
# ==================== 2. 定义工具函数(使用 @mcp.tool() 装饰器) ====================
@mcp.tool()
def add(a: int, b: int) -> int:
"""
两数相加
这是一个 MCP 工具函数,AI 模型可以通过 MCP 协议调用它
装饰器 @mcp.tool() 会自动:
1. 将函数注册为 MCP 工具
2. 提取函数的文档字符串作为工具描述
3. 解析函数参数类型,生成 JSON Schema
4. 使工具可以被 AI 模型发现和调用
Args:
a (int): 第一个加数
b (int): 第二个加数
Returns:
int: 两数之和
"""
return a + b
@mcp.tool()
def multiply(a: int, b: int) -> int:
"""
两数相乘
这个工具同样使用 @mcp.tool() 装饰器注册
AI 模型在需要乘法运算时会调用此工具
Args:
a (int): 第一个乘数
b (int): 第二个乘数
Returns:
int: 两数之积
"""
return a * b
示例 1:数学服务器(stdio 传输)【完整代码】
from fastmcp import FastMCP
# ==================== 1. 创建 MCP 服务器实例 ====================
# FastMCP 是一个用于构建 Model Context Protocol (MCP) 服务器的框架
# MCP 是一种协议,允许 AI 模型通过标准化的方式调用外部工具和获取上下文
# "Math" 是服务器的名称,用于标识这个 MCP 服务
mcp = FastMCP("Math")
# ==================== 2. 定义工具函数(使用 @mcp.tool() 装饰器) ====================
@mcp.tool()
def add(a: int, b: int) -> int:
"""
两数相加
这是一个 MCP 工具函数,AI 模型可以通过 MCP 协议调用它
装饰器 @mcp.tool() 会自动:
1. 将函数注册为 MCP 工具
2. 提取函数的文档字符串作为工具描述
3. 解析函数参数类型,生成 JSON Schema
4. 使工具可以被 AI 模型发现和调用
Args:
a (int): 第一个加数
b (int): 第二个加数
Returns:
int: 两数之和
"""
return a + b
@mcp.tool()
def multiply(a: int, b: int) -> int:
"""
两数相乘
这个工具同样使用 @mcp.tool() 装饰器注册
AI 模型在需要乘法运算时会调用此工具
Args:
a (int): 第一个乘数
b (int): 第二个乘数
Returns:
int: 两数之积
"""
return a * b
# ==================== 3. 主程序入口 ====================
if __name__ == "__main__":
"""
启动 MCP 服务器
MCP 服务器支持多种传输方式:
- stdio: 标准输入/输出(最常用,适合与本地 AI 客户端通信)
- sse: Server-Sent Events(适合 Web 环境)
- http: HTTP 协议(适合 REST API 风格)
使用 stdio 传输时:
1. 服务器通过标准输入接收 JSON-RPC 请求
2. 通过标准输出返回 JSON-RPC 响应
3. AI 客户端(如 Claude Desktop)可以启动子进程并与之通信
工作流程:
1. AI 客户端启动 MCP 服务器子进程
2. 服务器通过 stdio 发送工具列表(初始化阶段)
3. AI 模型决定调用哪个工具
4. 客户端通过 stdio 发送工具调用请求
5. 服务器执行工具并返回结果
6. 客户端将结果传递给 AI 模型
"""
mcp.run(
transport="stdio", # 使用标准输入输出进行通信
)
至此,我们在一个 MCP 服务中成功注册了加法、乘法两个工具。 直接运行代码,即可启动本地 MCP 服务。 启动成功后,控制台会输出标准启动日志,标明当前服务名称、传输协议为 stdio,代表本地进程通信的 MCP 服务搭建成功。

完成本地进程通信的计算器服务后,我们再搭建基于网络 HTTP 通信的 MCP 服务,本次我们实现天气查询工具。
新建一个服务文件,同样实例化 FastMCP 对象,命名为天气服务。 定义一个天气查询工具函数,通过 @mcp.tool() 完成工具注册,传入城市参数,返回对应天气结果。
启动服务时,transport 参数设置为 streamable-http 网络传输协议。 使用 HTTP 协议的服务需要手动指定启动端口,我们设置为 8000,只要是本机未被占用的端口均可。
示例 2:天气服务器(streamable-http 传输)【完整代码】
from fastmcp import FastMCP
mcp = FastMCP("Weather")
@mcp.tool()
async def get_weather(city: str):
"""获取天气"""
return f"{city}天气晴朗!"
if __name__ == "__main__":
mcp.run(
transport="streamable-http",
port=8000,
)
运行代码启动服务,控制台会打印 HTTP 服务启动日志,同时生成可访问的服务地址:http://127.0.0.1:8000/mcp。 这就代表基于网络通信的 MCP 天气服务搭建完成,外部可以通过 HTTP 接口远程连接调用。

到这里,我们完成了 MCP 实操的第一步:服务端启动、对外宣告工具能力。 后续客户端连接后,就可以通过工具发现接口,自动获取服务端的所有工具列表。
3.2 定义 MCP 客户端
接下来我们进行第二步:创建 MCP 客户端 Client。
这里给大家重点区分一下: 服务端我们使用 fastmcp 框架搭建,因为 LangChain 目前没有提供服务端搭建方案; 但客户端我们使用 langchain-mcp-adapters 官方适配库。 这个库专门适配 LangChain 生态,可以让我们自己的 Agent 智能体无缝对接 MCP 服务端工具,完美适配 Host 宿主架构,极大简化了客户端开发成本。
首先安装客户端依赖:使用 langchain-mcp-adapters 库让 LangChain Agent 调用 MCP 服务器上定义的工具
pip install langchain-mcp-adapters
核心用法:
-
创建
MultiServerMCPClient,配置一个或多个 MCP 服务器(支持stdio和http传输)。 -
调用
client.get_tools()获取所有工具。 -
将工具传入
create_agent,构建 Agent。
依赖安装完成后,我们导入 MultiServerMCPClient 客户端类。 这个客户端支持同时连接多个 MCP 服务端,无论是本地 stdio 服务还是远程 http 服务都可以统一管理。
客户端的配置核心是一个字典,字典的键为服务自定义标识名,值为对应服务的详细配置。
我们同时配置两个服务:
第一个是计算器服务,采用 stdio 本地进程通信。 配置传输协议为 stdio,指定启动命令为 python,并填入我们计算器服务文件的绝对路径,让客户端可以拉起本地子进程完成通信。
第二个是天气服务,采用 streamable-http 网络通信。 配置传输协议为 streamable-http,无需配置命令,直接填入我们刚刚启动的本地服务地址 http://127.0.0.1:8000/mcp,实现远程连接。
客户端配置完成后,核心操作就是工具发现。 原生 MCP 协议提供工具列表查询方法,而 LangChain 封装后的客户端直接使用 client.get_tools() 即可一次性获取所有连接服务端的全部工具。
这里大家重点注意:LangChain 的 MCP 客户端是异步客户端。 get_tools() 属于异步方法,不能直接同步调用,必须封装在 async 异步函数中,并且通过 asyncio.run() 启动执行。
工具获取成功后,下一步就是将 MCP 工具绑定到 Agent 智能体。
我们调用 LangChain 的 create_agent 方法,传入大模型名称和我们刚刚获取的 MCP 工具列表。 之所以可以直接绑定,是因为 LangChain 已经完成了适配,MCP 工具可以直接被 Agent 识别、调度、调用。
工具绑定完成后,我们就可以通过 Agent 实现完整的 MCP 工具调用流程。 同样因为客户端和 Agent 调用均为异步逻辑,我们使用 ainvoke() 异步调用方法,传入用户提问内容。
我们测试两个场景:
- 计算场景:提问混合运算,让 Agent 自主决策调用加法、乘法工具;
- 天气场景:提问城市天气,让 Agent 调用远程 HTTP 天气工具。
这里补充一个实操小技巧:如果 Agent 不主动调用工具,可以在提示词中约束模型,告知模型回答问题必须优先调用工具,强制触发工具调用逻辑。
运行代码后可以清晰看到完整执行链路: 用户输入问题 → 大模型决策需要调用的工具 → 客户端转发调用请求 → 服务端执行对应工具逻辑 → 结果通过 MCP 协议回传客户端 → 大模型整合结果生成最终回答。
整个底层的 8 步 MCP 协议交互对用户完全透明,用户仅需输入问题即可得到结果,这就是 MCP 标准化协议的便捷性。
示例:同时连接数学(本地)和天气(远程)服务器
import asyncio
from langchain_core.messages import HumanMessage
from langchain_deepseek import ChatDeepSeek
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain.agents import create_agent
# ==================== 1. 初始化模型 ====================
model = ChatDeepSeek(
model="deepseek-chat",
temperature=0.0,
)
# ==================== 2. 主异步函数 ====================
# FastMCP 客户端是异步的,因此我们需要使用 asyncio.run 来运行客户端
async def main():
# ==================== 3. 创建多服务器 MCP 客户端 ====================
client = MultiServerMCPClient({
"Math": { # 数学服务器
"transport": "stdio", # 使用标准输入输出通信
"command": "python", # 启动命令
"args": [r"E:/pythonPlace/WorkSpace/LangChain V1/MCP/快速上手【server + stdio】.py"], # 服务器脚本路径
},
"Weather": { # 天气服务器
"transport": "streamable-http", # 使用 HTTP 流式传输
"url": "http://localhost:8000/mcp", # 服务器地址
},
})
# ==================== 4. 获取所有工具 ====================
tools = await client.get_tools() # 自动从两个服务器获取工具
# ==================== 5. 创建 Agent ====================
agent = create_agent(
model=model,
tools=tools, # 包含 Math 和 Weather 的所有工具
system_prompt="务必调用工具!", # 强制 Agent 使用工具
)
# ==================== 6. 执行查询 ====================
# 数学查询
math_response = await agent.ainvoke(
{
"messages": [HumanMessage(content="(3 + 5) * 12 等于多少?")]
},
)
# 天气查询
weather_response = await agent.ainvoke(
{
"messages": [HumanMessage(content="上海的天气怎么样?")]
}
)
# ==================== 7. 输出结果 ====================
print(math_response)
print(weather_response)
if __name__ == "__main__":
async.run(main())
我们编写异步主函数,在函数中初始化客户端、连接服务、获取全部工具,并且打印工具信息,验证连接是否成功。
┌─────────────────────────────────────────────────────────────────────────────┐
│ │
│ │
│ ▄▀▀ ▄▀█ █▀▀ ▀█▀ █▀▄▀█ █▀▀ █▀█ │
│ █▀ █▀█ ▄▄█ █ █ ▀ █ █▄▄ █▀▀ │
│ │
│ │
│ │
│ FastMCP 3.4.2 │
│ https://gofastmcp.com │
│ │
│ 🖥 Server: Math, 3.4.2 │
│ 🚀 Deploy free: https://horizon.prefect.io │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
[06/29/26 19:46:48] INFO Starting MCP server 'Math' with transport.py:210
transport 'stdio'
┌─────────────────────────────────────────────────────────────────────────────┐
│ │
│ │
│ ▄▀▀ ▄▀█ █▀▀ ▀█▀ █▀▄▀█ █▀▀ █▀█ │
│ █▀ █▀█ ▄▄█ █ █ ▀ █ █▄▄ █▀▀ │
│ │
│ │
│ │
│ FastMCP 3.4.2 │
│ https://gofastmcp.com │
│ │
│ 🖥 Server: Math, 3.4.2 │
│ 🚀 Deploy free: https://horizon.prefect.io │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
[06/29/26 19:46:52] INFO Starting MCP server 'Math' with transport.py:210
transport 'stdio'
┌─────────────────────────────────────────────────────────────────────────────┐
│ │
│ │
│ ▄▀▀ ▄▀█ █▀▀ ▀█▀ █▀▄▀█ █▀▀ █▀█ │
│ █▀ █▀█ ▄▄█ █ █ ▀ █ █▄▄ █▀▀ │
│ │
│ │
│ │
│ FastMCP 3.4.2 │
│ https://gofastmcp.com │
│ │
│ 🖥 Server: Math, 3.4.2 │
│ 🚀 Deploy free: https://horizon.prefect.io │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
[06/29/26 19:46:55] INFO Starting MCP server 'Math' with transport.py:210
transport 'stdio'
{'messages': [HumanMessage(content='(3 + 5) * 12 等于多少?', ...'), AIMessage(content='让我一步步计算:\n\n1. 先计算括号内的加法:3 + 5', ..., tool_calls=[{'name': 'add', 'args': {'a': 3, 'b': 5}, ...}], ...), ToolMessage(content=[{'type': 'text', 'text': '8', 'id': 'lc_bb42f128-8e7f-4a23-8237-d087a061abf9'}], name='add', id='a42faa7e-2d15-469f-8e62-3363bd27c206', tool_call_id='call_00_rV1tXX5VOZb8J9hVhj1r0309', artifact={'structured_content': {'result': 8}}), AIMessage(content='2. 再将结果乘以 12:8 * 12', ..., tool_calls=[{'name': 'multiply', 'args': {'a': 8, 'b': 12}, 'id': 'call_00_54V9TEFz4h7qfmWvw5sG8277', 'type': 'tool_call'}], ...), ToolMessage(content=[{'type': 'text', 'text': '96', 'id': 'lc_ffb042f7-537f-46eb-9e15-83bdf77496e7'}], name='multiply', id='cdf4cb3c-a5c4-42e3-a562-6dc90edb7766', tool_call_id='call_00_54V9TEFz4h7qfmWvw5sG8277', ...), AIMessage(content='**(3 + 5) × 12 = 96** ✅',...}
{'messages': [HumanMessage(content='上海的天气怎么样?', ...), AIMessage(content='好的,我来查询上海的天气情况。', ..., tool_calls=[{'name': 'get_weather', 'args': {'city': '上海'}, 'id': 'call_00_x6LoQgKaJpwYJMo9jpYl0159', 'type': 'tool_call'}], ...), ToolMessage(content=[{'type': 'text', 'text': '上海天气晴朗!', 'id': 'lc_da1d5205-c07c-4cc8-8894-80b99d5837b0'}], name='get_weather', id='652fd09b-f512-4fb1-a374-96fa109df2e3', ...), AIMessage(content='上海的天气目前是**晴朗**的!☀️ 天气不错,适合外出活动。不过具体温度和风力等详细信息暂时没有提供,建议您出门前查看更详细的天气预报哦。', ...]}
配置完成后重启运行代码,即可成功获取所有工具。 打印结果中可以清晰看到:计算器服务的加法、乘法工具,天气服务的天气查询工具,包含工具名称、功能描述、参数类型、必填字段等完整结构化信息,代表客户端工具发现成功。
注意事项:
FastMCP 客户端是异步的,因此我们需要使用 asyncio.run(main()) 来运行客户端。
默认情况下,MultiServerMCPClient 是无状态的:每次工具调用都会创建一个全新的 MCPClientSession,执行工具后立即清理。
这里给大家讲解一个高频报错问题:如果你的电脑开启了网络代理,运行代码时会出现本地服务连接失败、超时的问题。 原因是代理会拦截 127.0.0.1 本地请求,导致无法访问本地 MCP 服务。
解决方案:配置系统环境变量
-
配置
no_proxy=127.0.0.1,让本地回环地址跳过代理; -
配置
http_proxy、https_proxy,填入自己的代理地址和端口,保证大模型联网请求正常使用代理。
到这里,我们就完整完成了 MCP 快速上手的全部实操代码,实现了多服务、多协议、多工具的统一调用,完整跑通了 MCP 底层交互流程。
3.3 有状态会话
接下来还要给大家补充一个关键特性:LangChain 封装提供的 MCPClient 默认是无状态的。
这里说的无状态是什么意思呢?每次我们发起远程工具调用时,客户端都会单独创建一个全新的 MCP 会话(session)。工具执行完毕之后,这个临时会话会立刻被销毁、清理。
举个我们之前写的算术题例子:提问一道需要同时调用加法、乘法两个工具的混合运算。如果这个服务是基于 streamable-http 网络传输的,默认情况下程序会创建两次独立的会话,分别执行加法工具、乘法工具,两次执行结束后分别清理两个会话。频繁新建、销毁会话会造成大量资源损耗,性能开销很大。
如果我们需要控制 MCP 会话的生命周期,客户端也给我们提供了对应的实现方案,可以手动管理会话,实现会话复用。如当处理维护工具调用上下文的有状态服务器时,可以使用 client.session() 上下文管理器,配合 load_mcp_tools 加载工具。
拿我们的天气服务器举例,默认每调用一次天气工具就会新建一个 session,我们现在改成手动持久化管理会话: 客户端实例创建完成后,调用 client.session() 方法,传入我们要持久连接的服务标识,也就是这里的天气服务(它是 HTTP 远程服务),以此单独维护这条服务的长会话。
因为整套客户端代码都是异步逻辑,这里需要搭配 async with 异步上下文管理器来创建、持有会话,实现会话持久复用。
开启手动会话管理后,获取工具的写法就和默认无状态模式完全不一样了。 无状态模式下我们直接调用 client.get_tools() 一次性拉取所有服务工具;但现在我们基于手动维护的 session 获取工具,需要引入 load_mcp_tools 这个专用方法,把我们创建好的持久会话传入这个函数,通过当前会话加载该服务对应的全部工具,这个加载操作同样是异步的,需要加上 await 关键字等待执行完成。
示例:上下文管理器,配合 load_mcp_tools 加载工具
import asyncio
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain.agents import create_agent
from langchain_deepseek import ChatDeepSeek # 使用 DeepSeek 或其他可用模型
# from langchain.chat_models import init_chat_model # 或使用统一初始化
# ==================== 1. 主异步函数 ====================
async def main():
print("🚀 启动 MCP 客户端...")
# 创建多服务器客户端
client = MultiServerMCPClient({
"Math": {
"transport": "stdio",
"command": "python",
"args": [r"C:/Users/26892/Desktop/new-langchain/test19.py"],
},
"weather": {
"transport": "streamable-http",
"url": "http://localhost:8000/mcp",
}
})
try:
# ==================== 方式1:使用 session 上下文(推荐) ====================
print("📡 连接到天气服务器...")
async with client.session("weather") as session:
# 🔥 关键修复:使用 await session.get_tools()
tools = await session.get_tools()
print(f"✅ 从 weather 服务器加载了 {len(tools)} 个工具: {[tool.name for tool in tools]}")
# 初始化模型
model = ChatDeepSeek(
model="deepseek-chat", # 或使用 "gpt-4o-mini"
temperature=0.0,
)
# 创建 Agent
agent = create_agent(
model=model,
tools=tools,
system_prompt="务必调用工具获取准确信息!",
)
# 执行查询
print("\n🌤️ 查询上海天气...")
weather_response_1 = await agent.ainvoke({
"messages": [{"role": "user", "content": "上海的天气怎么样?"}]
})
print("\n🌤️ 查询北京天气...")
weather_response_2 = await agent.ainvoke({
"messages": [{"role": "user", "content": "北京的天气怎么样?"}]
})
# 输出结果
print("\n" + "="*50)
print("📊 查询结果")
print("="*50)
print(f"\n上海: {weather_response_1['messages'][-1].content}")
print(f"\n北京: {weather_response_2['messages'][-1].content}")
print("="*50)
except Exception as e:
print(f"❌ 发生错误: {e}")
import traceback
traceback.print_exc()
finally:
# 关闭客户端
await client.close()
print("✅ 客户端已关闭")
# ==================== 2. 程序入口 ====================
if __name__ == "__main__":
asyncio.run(main())
只增加这一段会话管理代码后,上下文内所有针对这个天气服务的 Agent 工具调用,都会全程复用这同一个持久会话,不会再重复创建、销毁临时 session,大幅减少资源浪费。
此时会话的生命周期由 async with 块管理,块结束后会话自动关闭。
我们运行这段改造后的代码,功能和之前完全一致,依旧可以正常调用天气工具。这里主要是给大家区分清楚两种会话模式:MultiServerMCPClient 默认无状态,按需新建临时会话;如果有性能需求、需要复用连接,就用 client.session() 搭配 load_mcp_tools 手动管控会话生命周期,实现长会话持久复用。
到这里,MCP 快速上手实操的全部内容就讲解完毕了。 从下一部分开始,我们学习 MCP 的完整核心能力。目前我们实操只演示了 MCP 服务提供工具(tool) 的能力,但上面我们提到过,一台 MCP Server 不只是能对外暴露可调用函数工具,还可以对外提供结构化数据资源、可复用提示词模板,这两类内容统一归类为资源。 AI 应用都可以依靠 MCP 标准化协议,统一读取、使用这些资源。也就是说 MCP 能从工具、数据、提示词多个维度,给我们的 AI 应用提供非常全面、强大的扩展能力。
更多推荐

所有评论(0)