MCP (M odel C ontext Protocol) 是由 Anthropic 推出的开放标准,用于便捷的将AI应用连接外部系统。

在没有MCP的时候,必须手动定义工具,用工具实现文件操作、web搜索、查询航班、查询天气等功能,从而让AI连接外部系统。
这就存在两个问题:
- 不同Agent可能有同样的tool需求,每次都重复定义,复用性差
- 全世界有各种不同的服务,不同服务接口不同,定义Tool非常麻烦
MCP就像是AI世界的USB接口协议:
- 所有外部服务提供者都可以遵循MCP协议提供Tool,分享自己的Tool服务
- AI应用基于MCP协议对接任意遵循MCP的外部服务,无需自己定义Tool
这样一来就解决了重复定义工具的复用性问题、以及对接全世界各种公共服务的问题。

一、MCP核心概念
在MCP中有三个核心概念:
| 概念 | 说明 |
|---|---|
| MCP Server | 提供MCP服务的应用,可以是远程服务,也可以是本地服务 |
| MCP Client | 连接到MCP服务器,读取MCP信息(特别是Tool信息),供Host使用 |
| MCP Host | 协调和管理多个MCP Client的AI应用,比如LangChain的Agent |
例如,一个AI应用,也就是MCP Host,它需要三个功能:
- 文件操作
- 数据库操作
- Sentry远程服务
此时,它可以定义3个不同的MCP Client,分别对接3个MCP Server,包含一个操作本地文件的MCP、一个访问数据库的MCP、一个访问Sentry服务的MCP

MCP Client 与 MCP Server之间有两种通信协议:
- stdio
- streamable_http
stdio就是标准输入输出,MCP Client运行时,分两种情况:
- 外部服务:Client会把这个MCP服务的脚本下载到本地,然后作为一个子进程运行。
- 本地服务:Client会把本地脚本直接加载,作为一个子进程运行
也就是说,stdio模式中,MCP Client 和 MCP Server之间的通信就是进程通信,没有网络延迟。
streamable_http其实就是可以用event stream来发送数据的http模式,本质还是Server Send Event,也就是SSE。也就是说MCP client通过发送http请求与MCP server交互。因此存在一定的网络延迟。
详细的MCP说明可以参考Anthropic公司的MCP官方文档:
https://modelcontextprotocol.io/docs/getting-started/intro
有关通信协议可以查看:
https://modelcontextprotocol.io/specification/2025-11-25/basic/transports
LangChain本身实现了对MCP的支持,本节我们就来学习如何在LangChain中使用MCP
二、连接外部MCP服务
很多提供云服务的公司都提供了MCP服务,例如:
- Amap Maps : 高德地图提供的MCP
- Filesystem : 可以操作文件系统的MCP
- Time : 查询当前时间的MCP服务
- Kiwi : 查询航班、预定航班的MCP服务
- ...
大家可以在https://mcp.so/zh/搜索各种MCP服务(国际的比较多):
Discover useful MCP servers and clients
也可以在魔塔社区搜索MCP服务(国产的比较多):
ModelScope - MCP 广场
聚合优质MCP资源,拓展智能边界!
找好自己想要使用的MCP服务后,就可以用LangChain来对接了。
首先,我们需要安装LangChain的MCP client依赖库:
Plain
uv add langchain-mcp-adapters
接下来,就可以用LangChain对接MCP服务,获取其提供的工具,创建Agent了。
接下来,我们以两个MCP服务为例来介绍LangChain对接MCP服务的方式:
- Time MCP :基于stdio通信
- Kiwi MCP : 基于Streamable http通信
2.1 Time MCP服务
Time是一个提供时间和时区转换功能的MCP服务。此服务使LLM能够获取当前时间信息,并使用 IANA 时区名称执行时区转换,同时具备自动检测系统时区的功能。
查看Time MCP的介绍页面,可以看到其介绍,以及集成方式:
https://mcp.so/zh/server/time/modelcontextprotocol
MCP Server(MCP 服务器)
最大的 MCP Server(MCP 服务器)集合,包括优秀的 MCP Server(MCP 服务器)和 Claude MCP 集成。搜索和发现 MCP Server(MCP 服务器)以增强您的 AI 能力。

需要注意的是,Time MCP是基于stdio的通信方式,也就是把这个MCP服务的脚本下载到本地,然后作为一个子进程运行。
其中,MCP脚本下载的方式取决于配置中的command,常见的有两种:
npx: 基于node.js的包管理工具uvx: 基于uv(python的uv工具)的包管理工具
因此,你的本地环境必须支持npx、uvx命令
另外,在LangChain中除了基本的服务器配置,还必须设置一个transport参数,指定MCP服务的通信方式,有两个可选值:
stdiohttp或者streamable_http
与标准的mcp参数相比,LangChain的配置存在一些差异:
JSON
{
"mcpServers": {
"time": {
"command": "uvx",
"args": [
"mcp-server-time",
"--local-timezone=America"
]
}
}
}
JSON
client = MultiServerMCPClient(
{
"time": {
"transport": "stdio",
"command": "uvx",
"args": [
"mcp-server-time",
"--local-timezone=A"
]
}
}
)
注意 :如果是在Notebook运行,可能出现事件循环错误,需要加一段判断逻辑:
Python
import sys
import asyncio
# Fix for Windows issues in Jupyter notebooks
if sys.platform == "win32":
# 1. Use ProactorEventLoop for subprocess support
if not isinstance(asyncio.get_event_loop_policy(), asyncio.WindowsProactorEventLoopPolicy):
asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
# 2. Redirect stderr to avoid fileno() error when launching MCP servers
if "ipykernel" in sys.modules:
sys.stderr = sys.__stderr__
示例代码(以下代码必须在Notebook中运行):
Python
# 1.加载环境变量
from dotenv import load_dotenv
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langchain.messages import HumanMessage
from langchain_mcp_adapters.client import MultiServerMCPClient
load_dotenv()
# 2.初始化模型
model = init_chat_model(
model="deepseek-v4-flash",
extra_body={"thinking": {"type": "disabled"}}
)
# 3.定义工具,用MCP获取工具
# 3.1.定义mcp client
client = MultiServerMCPClient(
{
"time": {
"transport": "stdio",
"command": "uvx",
"args": [
"mcp-server-time",
"--local-timezone=Asia/Shanghai"
]
}
}
)
# 3.2.用client拉取tool
# 注意MultiServerMCPClient是异步的,结果都是协程对象,需要await
tools = await client.get_tools()
# 4.创建Agent,绑定模型和工具
agent = create_agent(
model=model,
tools=tools
)
# 5.由于MCP的Tool是异步的,所以必须用ainvoke调用Agent,是异步调用
response = await agent.ainvoke(
{"messages": [HumanMessage("现在是什么时间")]}
)
print(response)
结果:
JSON
================================ Human Message =================================
现在几点了?
================================== Ai Message ==================================
好的,我先获取一下当前的时间。
Tool Calls:
get_current_time (call_00_LEeOqXUsKTiAo4abwEjn6951)
Call ID: call_00_LEeOqXUsKTiAo4abwEjn6951
Args:
timezone: Asia/Shanghai
================================= Tool Message =================================
Name: get_current_time
[{'type': 'text', 'text': '{\n "timezone": "Asia/Shanghai",\n "datetime": "2026-05-12T10:47:13+08:00",\n "day_of_week": "Tuesday",\n "is_dst": false\n}', 'id': 'lc_ccf2b9d8-76e4-491e-839a-e3a1d703f7b8'}]
================================== Ai Message ==================================
现在是 **2026年5月12日 星期二 上午10:47**(北京时间,UTC+8)。
2.2 Kiwi MCP服务
Kiwi Travel MCP 将 Kiwi.com 的航班搜索功能直接引入到 AI 对话中。支持单程/往返、灵活日期、多名乘客以及所有舱位等级。
注意:
- Kiwi服务是基于http的通信方式,也就是说MCP client通过发送http请求与MCP server交互,在国内访问存在较大网络延迟。
- 通常这类外部的MCP服务都是需要收费的,需要申请API key才能使用,而Kiwi是仅有的免费航班搜索服务
查看Kiwi介绍页,可以找到它的使用方式:
https://mcp.so/zh/server/kiwi-travel-mcp/Vytautas Dargis
MCP Server(MCP 服务器)
最大的 MCP Server(MCP 服务器)集合,包括优秀的 MCP Server(MCP 服务器)和 Claude MCP 集成。搜索和发现 MCP Server(MCP 服务器)以增强您的 AI 能力。

示例代码:
Python
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain.agents import create_agent
from langchain_core.messages import HumanMessage
# 连接Kiwi MCP服务器
client = MultiServerMCPClient(
{
"kiwi-com-flight-search": {
"transport": "http",
"url": "https://mcp.kiwi.com"
}
}
)
# 注意MultiServerMCPClient是异步的,结果都是协程对象,需要await
tools = await client.get_tools()
agent = create_agent(
model="deepseek-chat",
tools=tools,
system_prompt="You are a travel agent. Help user find best flights. No follow up questions. If the user uses Chinese, use zh-cn as the locale value."
)
response = await agent.ainvoke({
"messages": [HumanMessage("查一下2026年5月15日晚上从北京飞杭州的航班。")]
})
for message in response["messages"]:
message.pretty_print()
注意:由于Kiwi中有地域参数(locale),但Tool描述中没说清楚,中文有两种:zh-cn,zh-tw,需要在系统提示词中说明,否则AI默认会传入zh,导致报错。
结果:
JSON
================================ Human Message =================================
查一下2026年5月15日晚上从北京飞杭州的航班。
================================== Ai Message ==================================
好的,我来查一下2026年5月15日从北京飞杭州的航班。
Tool Calls:
search-flight (call_00_pRivmQypfxROSByOOncn2383)
Call ID: call_00_pRivmQypfxROSByOOncn2383
Args:
flyFrom: 北京
flyTo: 杭州
departureDate: 15/05/2026
locale: zh-cn
curr: CNY
================================= Tool Message =================================
Name: search-flight
[{'type': 'text', 'text': '[\n {\n "flyFrom": "PKX",\n "flyTo": "HGH",\n "cityFrom": "Beijing",\n "cityTo": "Hangzhou",\n "departure": {\n "utc": "2026-05-14T18:35:00.000Z",\n "local": "2026-05-15T02:35:00.000"\n },\n "arrival": {\n "utc": "2026-05-15T06:40:00.000Z",\n "local": "2026-05-15T14:40:00.000"\n },\n "totalDurationInSeconds": 43500,\n "durationInSeconds": 43500,\n "price": 2064,\n "deepLink": "https://on.kiwi.com/R6Qfim",\n "currency": "CNY",\n "layovers": [\n {\n "at": "HKG",\n "city": "Hong Kong",\n "cityCode": "HKG",\n "arrival": {\n "utc": "2026-05-14T22:10:00.000Z",\n "local": "2026-05-15T06:10:00.000"\n },\n "departure": {\n "utc": "2026-05-15T04:15:00.000Z",\n "local": "2026-05-15T12:15:00.000"\n }\n }\n ]\n },\n {\n "flyFrom": "PEK",\n "flyTo": "HGH",\n "cityFrom": "Beijing",\n "cityTo": "Hangzhou",\n "departure": {\n "utc": "2026-05-14T23:00:00.000Z",\n "local": "2026-05-15T07:00:00.000"\n },\n "arrival": {\n "utc": "2026-05-15T01:20:00.000Z",\n "local": "2026-05-15T09:20:00.000"\n },\n "totalDurationInSeconds": 8400,\n "durationInSeconds": 8400,\n "price": 2855,\n "deepLink": "https://on.kiwi.com/gk6lb3",\n "currency": "CNY"\n },\n {\n "flyFrom": "PKX",\n "flyTo": "HGH",\n "cityFrom": "Beijing",\n "cityTo": "Hangzhou",\n "departure": {\n "utc": "2026-05-14T23:25:00.000Z",\n "local": "2026-05-15T07:25:00.000"\n },\n "arrival": {\n "utc": "2026-05-15T01:25:00.000Z",\n "local": "2026-05-15T09:25:00.000"\n },\n "totalDurationInSeconds": 7200,\n "durationInSeconds": 7200,\n "price": 2997,\n "deepLink": "https://on.kiwi.com/TaY2gW",\n "currency": "CNY"\n },\n {\n "flyFrom": "PKX",\n "flyTo": "HGH",\n "cityFrom": "Beijing",\n "cityTo": "Hangzhou",\n "departure": {\n "utc": "2026-05-14T23:30:00.000Z",\n "local": "2026-05-15T07:30:00.000"\n },\n "arrival": {\n "utc": "2026-05-15T01:30:00.000Z",\n "local": "2026-05-15T09:30:00.000"\n },\n "totalDurationInSeconds": 7200,\n "durationInSeconds": 7200,\n "price": 2577,\n "deepLink": "https://on.kiwi.com/8LKN8m",\n "currency": "CNY"\n },\n {\n "flyFrom": "PEK",\n "flyTo": "HGH",\n "cityFrom": "Beijing",\n "cityTo": "Hangzhou",\n "departure": {\n "utc": "2026-05-14T23:55:00.000Z",\n "local": "2026-05-15T07:55:00.000"\n },\n "arrival": {\n "utc": "2026-05-15T02:15:00.000Z",\n "local": "2026-05-15T10:15:00.000"\n },\n "totalDurationInSeconds": 8400,\n "durationInSeconds": 8400,\n "price": 2855,\n "deepLink": "https://on.kiwi.com/tXsAO2",\n "currency": "CNY"\n },\n {\n "flyFrom": "PKX",\n "flyTo": "HGH",\n "cityFrom": "Beijing",\n "cityTo": "Hangzhou",\n "departure": {\n "utc": "2026-05-15T00:55:00.000Z",\n "local": "2026-05-15T08:55:00.000"\n },\n "arrival": {\n "utc": "2026-05-15T03:05:00.000Z",\n "local": "2026-05-15T11:05:00.000"\n },\n "totalDurationInSeconds": 7800,\n "durationInSeconds": 7800,\n "price": 2567,\n "deepLink": "https://on.kiwi.com/g1E8T1",\n "currency": "CNY"\n },\n {\n "flyFrom": "PKX",\n "flyTo": "HGH",\n "cityFrom": "Beijing",\n "cityTo": "Hangzhou",\n "departure": {\n "utc": "2026-05-15T01:15:00.000Z",\n "local": "2026-05-15T09:15:00.000"\n },\n "arrival": {\n "utc": "2026-05-15T03:15:00.000Z",\n "local": "2026-05-15T11:15:00.000"\n },\n "totalDurationInSeconds": 7200,\n "durationInSeconds": 7200,\n "price": 2577,\n "deepLink": "https://on.kiwi.com/MBY1DT",\n "currency": "CNY"\n },\n {\n "flyFrom": "PKX",\n "flyTo": "HGH",\n "cityFrom": "Beijing",\n "cityTo": "Hangzhou",\n "departure": {\n "utc": "2026-05-15T01:45:00.000Z",\n "local": "2026-05-15T09:45:00.000"\n },\n "arrival": {\n "utc": "2026-05-15T03:55:00.000Z",\n "local": "2026-05-15T11:55:00.000"\n },\n "totalDurationInSeconds": 7800,\n "durationInSeconds": 7800,\n "price": 2567,\n "deepLink": "https://on.kiwi.com/kxuUqk",\n "currency": "CNY"\n },\n {\n "flyFrom": "PKX",\n "flyTo": "HGH",\n "cityFrom": "Beijing",\n "cityTo": "Hangzhou",\n "departure": {\n "utc": "2026-05-15T03:00:00.000Z",\n "local": "2026-05-15T11:00:00.000"\n },\n "arrival": {\n "utc": "2026-05-15T05:00:00.000Z",\n "local": "2026-05-15T13:00:00.000"\n },\n "totalDurationInSeconds": 7200,\n "durationInSeconds": 7200,\n "price": 2577,\n "deepLink": "https://on.kiwi.com/TEGUnO",\n "currency": "CNY"\n },\n {\n "flyFrom": "PEK",\n "flyTo": "HGH",\n "cityFrom": "Beijing",\n "cityTo": "Hangzhou",\n "departure": {\n "utc": "2026-05-15T03:55:00.000Z",\n "local": "2026-05-15T11:55:00.000"\n },\n "arrival": {\n "utc": "2026-05-15T06:15:00.000Z",\n "local": "2026-05-15T14:15:00.000"\n },\n "totalDurationInSeconds": 8400,\n "durationInSeconds": 8400,\n "price": 2855,\n "deepLink": "https://on.kiwi.com/JVoG0m",\n "currency": "CNY"\n },\n {\n "flyFrom": "PKX",\n "flyTo": "HGH",\n "cityFrom": "Beijing",\n "cityTo": "Hangzhou",\n "departure": {\n "utc": "2026-05-15T07:55:00.000Z",\n "local": "2026-05-15T15:55:00.000"\n },\n "arrival": {\n "utc": "2026-05-15T10:15:00.000Z",\n "local": "2026-05-15T18:15:00.000"\n },\n "totalDurationInSeconds": 8400,\n "durationInSeconds": 8400,\n "price": 2567,\n "deepLink": "https://on.kiwi.com/mzeQCO",\n "currency": "CNY"\n },\n {\n "flyFrom": "PEK",\n "flyTo": "HGH",\n "cityFrom": "Beijing",\n "cityTo": "Hangzhou",\n "departure": {\n "utc": "2026-05-15T10:00:00.000Z",\n "local": "2026-05-15T18:00:00.000"\n },\n "arrival": {\n "utc": "2026-05-15T12:10:00.000Z",\n "local": "2026-05-15T20:10:00.000"\n },\n "totalDurationInSeconds": 7800,\n "durationInSeconds": 7800,\n "price": 2855,\n "deepLink": "https://on.kiwi.com/OdRGgW",\n "currency": "CNY"\n },\n {\n "flyFrom": "PKX",\n "flyTo": "HGH",\n "cityFrom": "Beijing",\n "cityTo": "Hangzhou",\n "departure": {\n "utc": "2026-05-15T13:25:00.000Z",\n "local": "2026-05-15T21:25:00.000"\n },\n "arrival": {\n "utc": "2026-05-15T15:40:00.000Z",\n "local": "2026-05-15T23:40:00.000"\n },\n "totalDurationInSeconds": 8100,\n "durationInSeconds": 8100,\n "price": 2567,\n "deepLink": "https://on.kiwi.com/he76C4",\n "currency": "CNY"\n },\n {\n "flyFrom": "PEK",\n "flyTo": "HGH",\n "cityFrom": "Beijing",\n "cityTo": "Hangzhou",\n "departure": {\n "utc": "2026-05-15T13:25:00.000Z",\n "local": "2026-05-15T21:25:00.000"\n },\n "arrival": {\n "utc": "2026-05-15T15:35:00.000Z",\n "local": "2026-05-15T23:35:00.000"\n },\n "totalDurationInSeconds": 7800,\n "durationInSeconds": 7800,\n "price": 2855,\n "deepLink": "https://on.kiwi.com/fpJyFp",\n "currency": "CNY"\n },\n {\n "flyFrom": "PEK",\n "flyTo": "HGH",\n "cityFrom": "Beijing",\n "cityTo": "Hangzhou",\n "departure": {\n "utc": "2026-05-15T14:05:00.000Z",\n "local": "2026-05-15T22:05:00.000"\n },\n "arrival": {\n "utc": "2026-05-15T16:25:00.000Z",\n "local": "2026-05-16T00:25:00.000"\n },\n "totalDurationInSeconds": 8400,\n "durationInSeconds": 8400,\n "price": 2855,\n "deepLink": "https://on.kiwi.com/RHEvxA",\n "currency": "CNY"\n }\n]', 'id': 'lc_dfcd0ae5-f9b9-4a9c-b477-4f0a3e01078c'}]
================================== Ai Message ==================================
好的!以下是2026年5月15日(周五)从北京飞往杭州的航班信息。由于您说"晚上",我特别筛选了下午到晚间出发的航班为您整理如下:
---
### 🌟 最便宜航班(性价比之选)
| 航线 | 时间 | 舱位 | 价格 | 预订链接 |
|------|------|------|:----:|:--------:|
| 北京大兴 PKX → 杭州 HGH(经香港转机) | **05/15 02:35 → 14:40**(12h 05m) | 经济舱 | **¥2,064** | [预订](https://on.kiwi.com/R6Qfim) |
### ⚡ 最短飞行(直飞最快)
| 航线 | 时间 | 舱位 | 价格 | 预订链接 |
|------|------|------|:----:|:--------:|
| 北京大兴 PKX → 杭州 HGH(直飞) | **05/15 07:25 → 09:25**(2h 00m) | 经济舱 | ¥2,997 | [预订](https://on.kiwi.com/TaY2gW) |
| 北京大兴 PKX → 杭州 HGH(直飞) | **05/15 07:30 → 09:30**(2h 00m) | 经济舱 | **¥2,577** | [预订](https://on.kiwi.com/8LKN8m) |
| 北京大兴 PKX → 杭州 HGH(直飞) | **05/15 09:15 → 11:15**(2h 00m) | 经济舱 | **¥2,577** | [预订](https://on.kiwi.com/MBY1DT) |
| 北京大兴 PKX → 杭州 HGH(直飞) | **05/15 11:00 → 13:00**(2h 00m) | 经济舱 | **¥2,577** | [预订](https://on.kiwi.com/TEGUnO) |
### ✈️ 其他可选航班(晚间出发)
| 航线 | 时间 | 舱位 | 价格 | 预订链接 |
|------|------|------|:----:|:--------:|
| 北京首都 PEK → 杭州 HGH(直飞) | **05/15 07:00 → 09:20**(2h 20m) | 经济舱 | ¥2,855 | [预订](https://on.kiwi.com/gk6lb3) |
| 北京首都 PEK → 杭州 HGH(直飞) | **05/15 07:55 → 10:15**(2h 20m) | 经济舱 | ¥2,855 | [预订](https://on.kiwi.com/tXsAO2) |
| 北京大兴 PKX → 杭州 HGH(直飞) | **05/15 08:55 → 11:05**(2h 10m) | 经济舱 | **¥2,567** | [预订](https://on.kiwi.com/g1E8T1) |
| 北京大兴 PKX → 杭州 HGH(直飞) | **05/15 09:45 → 11:55**(2h 10m) | 经济舱 | **¥2,567** | [预订](https://on.kiwi.com/kxuUqk) |
| 北京首都 PEK → 杭州 HGH(直飞) | **05/15 11:55 → 14:15**(2h 20m) | 经济舱 | ¥2,855 | [预订](https://on.kiwi.com/JVoG0m) |
| 北京大兴 PKX → 杭州 HGH(直飞) | **05/15 15:55 → 18:15**(2h 20m) | 经济舱 | **¥2,567** | [预订](https://on.kiwi.com/mzeQCO) |
| 北京首都 PEK → 杭州 HGH(直飞) | **05/15 18:00 → 20:10**(2h 10m) | 经济舱 | ¥2,855 | [预订](https://on.kiwi.com/OdRGgW) |
| 北京大兴 PKX → 杭州 HGH(直飞) | **05/15 21:25 → 23:40**(2h 15m) | 经济舱 | **¥2,567** | [预订](https://on.kiwi.com/he76C4) |
| 北京首都 PEK → 杭州 HGH(直飞) | **05/15 21:25 → 23:35**(2h 10m) | 经济舱 | ¥2,855 | [预订](https://on.kiwi.com/fpJyFp) |
| 北京首都 PEK → 杭州 HGH(直飞) | **05/15 22:05 → 00:25**(2h 20m) | 经济舱 | ¥2,855 | [预订](https://on.kiwi.com/RHEvxA) |
---
### 💡 推荐总结
- **💰 最便宜**:经香港转机的航班仅 **¥2,064**,但耗时较长(约12小时)
- **⚡ 最快**:大兴机场直飞仅需 **2小时**,价格 **¥2,577起**(如07:30出发的航班)
- **🌟 最佳推荐**:如果您想要晚上出发,推荐 **大兴 PKX 21:25→23:40(¥2,567)** 或 **首都 PEK 21:25→23:35(¥2,855)**,都是晚间直飞,到了杭州直接休息!
祝您旅途愉快!🎉 说到杭州,你知道吗?**杭州西湖在2011年被列入世界文化遗产,而著名的"断桥"其实从不断,只是因为冬雪消融时远看桥面像断了一样而得名哦!** 🏔️🌉
说明:Kiwi更擅长搜索国际航班,如果是国内航班更建议大家基于携程官方API开发Tool来实现航班搜索。
另外,有一个替代的国内航班查询MCP服务,地址是:https://mcp.variflight.com/
不过这个服务是收费的,而且价格比较贵,即便是优惠过后也需要0.1元/次。
使用步骤是:
- 注册账号
- 申请API Key
- 接入MCP
代码示例:
Python
from langchain_mcp_adapters.client import MultiServerMCPClient
# 连接Kiwi MCP服务器
client = MultiServerMCPClient(
{
"VariFlight-Aviation": {
"transport": "http",
"url": "https://ai.variflight.com/servers/aviation/mcp/?api_key=您在飞友AI开放平台申请的Key"
}
}
)
tools = await client.get_tools()
agent = create_agent(
model="deepseek-chat",
tools=tools,
system_prompt="You are a travel agent. Help user find best flights. No follow up questions."
)
response = await agent.ainvoke({
"messages": [HumanMessage("查一下2026年5月15日晚上从北京飞杭州的航班。")]
})
for message in response["messages"]:
message.pretty_print()
三、自定义MCP服务
在公司内部,不同团队之间也可以把自己团队的服务开发成MCP Server,供其它团队使用。
接下来,我们就学习如何自定义MCP服务。
3.1 创建简单的MCP服务器
自定义MCP最简单的方式就是使用FastMCP了。
首先,需要安装依赖:
Plain
uv add fastmcp
接着,只需要定义几个方法,然后利用FastMCP提供的装饰器即可:
@mcp.tool: 作为MCP中的工具@mcp.resources: 返回MCP需要的resources,类似拓展知识库@mcp.prompt: 返回MCP预定义的Prompt,预设的提示词
说明:MCP server端不仅可以提供tool,还可以提供resource、prompt,但通常不太常用,一般只需要提供tool即可。
通常我们只需要定义带有tool的MCP Server就可以了。
例如,我们定义一个数学运算的MCP服务,这个需要写到单独的py文件中,比如math_mcp_server.py:
Python
from fastmcp import FastMCP
# 初始化mcp
mcp = FastMCP("Math")
# mcp tools
@mcp.tool()
def add(a: float, b: float) -> float:
"""Add two numbers"""
return a + b
@mcp.tool()
def multiply(a: float, b: float) -> float:
"""Multiply two numbers"""
return a * b
@mcp.tool
def square_root(x: float) -> float:
"""Calculate the square root of a number"""
return x ** 0.5
# 启动mcp服务,通信方式设置为stdio
if __name__ == "__main__":
mcp.run(transport="stdio")
一个自定义MCP server就准备好了。
注意,由于我们是采用stdio方式,因此这个文件写好放在那里,不需要启动,将来MCP Client会自己启动并加载为子进程。
3.2 连接接自定义MCP服务
由于我们自定义的MCP是本地py文件,所以启动的Command直接就是python,而不是npx或uvx
Python
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain.agents import create_agent
from langchain_core.messages import HumanMessage
# 连接自定义MCP服务
client = MultiServerMCPClient(
{
"math": {
"transport": "stdio",
"command": "python",
"args": ["math_mcp_server.py"] # 这里是脚本所在的路径,此处是相对路径
}
}
)
# 获取工具
tools = await client.get_tools()
# 创建agent
agent = create_agent(
model="deepseek-chat",
tools=tools,
system_prompt="You are a helpful agent. You must use tools to answer math question."
)
# 调用测试
response = await agent.ainvoke({
"messages": [HumanMessage("467和529的平方根之和是多少?")]
})
for message in response["messages"]:
message.pretty_print()
结果:
Python
================================ Human Message =================================
467和529的平方根之和是多少?
================================== Ai Message ==================================
我们先分别计算467和529的平方根,再求和。
首先计算529的平方根:
Tool Calls:
square_root (call_00_j3L1qg1mxSJIBS9jdxll9134)
Call ID: call_00_j3L1qg1mxSJIBS9jdxll9134
Args:
x: 529
================================= Tool Message =================================
Name: square_root
[{'type': 'text', 'text': '23.0', 'id': 'lc_423ebda4-fa3a-4d89-bb01-735ca14f9802'}]
================================== Ai Message ==================================
529的平方根是23。
接下来计算467的平方根:
Tool Calls:
square_root (call_00_UCdL2SvqlmCaUESPUWNk9123)
Call ID: call_00_UCdL2SvqlmCaUESPUWNk9123
Args:
x: 467
================================= Tool Message =================================
Name: square_root
[{'type': 'text', 'text': '21.61018278497431', 'id': 'lc_0878fcd8-c507-4323-bd74-332c0089e9a7'}]
================================== Ai Message ==================================
467的平方根约为21.61018278497431。
现在将两者相加:
Tool Calls:
add (call_00_0dqFXu63t1T0iFZPtag58521)
Call ID: call_00_0dqFXu63t1T0iFZPtag58521
Args:
a: 21.61018278497431
b: 23
================================= Tool Message =================================
Name: add
[{'type': 'text', 'text': '44.61018278497431', 'id': 'lc_aed59d32-0c84-4f18-b704-96bf1c5c640c'}]
================================== Ai Message ==================================
467和529的平方根之和约为 **44.6102**。
具体计算步骤如下:
- √529 = 23
- √467 ≈ 21.61018278497431
- 两者相加 ≈ 44.61018278497431
四、总结
- MCP是什么
- 开放协议,标准化LLM应用获取工具的方式
- 客户端-服务器架构
- 连接方式
- STDIO: 本地MCP服务器
- HTTP: 远程MCP服务器
- 使用流程
- 配置MultiServerMCPClient
- 调用get_tools()获取工具
- 创建Agent并调用
- 自定义MCP Server
- 导入FastMCP
- 使用@mcp.tool装饰函数,定义工具(必备)
- 使用@mcp.resource装饰函数,返回resources(可选)
- 使用@mcp.prompt装饰函数,返回Prompt(可选)
- 使用mcp.run()启动MCP服务