深入理解 MCP(Model Context Protocol):从原理到实战
本文将从 MCP 的核心定义出发,逐步拆解其架构设计、通信机制,并通过完整的代码示例演示如何搭建 MCP 服务器和客户端,帮助你全面掌握这一 AI 工程化领域的关键协议。
目录
1.3 核心架构:Client-Host-Server 模型
1.5 服务端三大原语:Tools、Resources、Prompts
二、Function Call 与 MCP 的区别(面试重点)
一、什么是 MCP
1.1 定义
MCP(Model Context Protocol,模型上下文协议) 是由 Anthropic 于 2024 年 11 月底 推出的一种开放标准协议,旨在为大语言模型(LLM)提供统一的、标准化的方式与外部数据源和工具之间进行通信。
官方将 MCP 类比为 "AI 应用的 USB-C 接口"——正如 USB-C 为电子设备提供了统一的连接方式,MCP 为 AI 应用与外部系统之间提供了标准化的连接协议。
MCP 的核心目标是让 LLM 跳出静态知识库的限制,能够 主动、实时地获取外部数据、调用外部工具,从而将 AI 的能力从"对话"延伸到"行动"。
┌─────────────────────────────────────────────────┐
│ MCP 架构全景 │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────────┐│
│ │ 数据源 │◄──►│ MCP 服务 │◄──►│ AI 应用 ││
│ │(数据库/ │ │ Server │ │ (Host端) ││
│ │ 文件/API) │ └──────────┘ └──────────────┘│
│ └──────────┘ ▲ ▲ │
│ │ │ │
│ MCP 协议层 MCP 客户端 │
│ (JSON-RPC 2.0) (嵌入Host中) │
└─────────────────────────────────────────────────┘
1.2 为什么需要 MCP
传统 AI 集成面临的问题:
| 问题 | 描述 |
|---|---|
| 架构碎片化 | 每接入一个外部服务,就需要一套独立的集成代码,N 个服务对应 N 套代码 |
| 难以扩展 | 新增工具或数据源需要重新开发适配层,维护成本高 |
| 上下文受限 | 模型只能依赖训练数据和有限的 prompt 内容,无法访问实时外部信息 |
| 缺乏标准 | 各厂商各做各的集成方案,互不兼容 |
MCP 的解决方案:
- 提供 统一的协议规范,一次接入,处处可用
- 支持 动态发现和调用工具,无需提前硬编码
- 实现 标准化的双向通信,模型既能读取数据也能执行操作
- 开放生态,任何人可以开发 MCP Server 并被任意 MCP Client 调用
1.3 核心架构:Client-Host-Server 模型
MCP 采用三层架构设计,各角色职责清晰:
┌──────────────────────────────────────────────────────────┐
│ Host(宿主应用) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ MCP Client │ │ MCP Client │ │ MCP Client │ │
│ │ #1 │ │ #2 │ │ #3 │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
└─────────┼────────────────┼────────────────┼───────────────┘
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ MCP Server │ │ MCP Server │ │ MCP Server │
│ (本地) │ │ (远程) │ │ (远程) │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 本地文件/ │ │ 远程API/ │ │ 数据库/ │
│ CLI 工具 │ │ 云服务 │ │ 第三方服务 │
└─────────────┘ └─────────────┘ └─────────────┘
- Host(宿主):AI 应用本身(如 Claude Desktop、Cherry Studio、自定义 Agent 程序),负责管理整体交互流程和安全策略
- MCP Client(客户端):嵌入在 Host 内部,每个 Client 与一个 MCP Server 建立一对一连接,负责协议层面的消息收发
- MCP Server(服务端):轻量级程序,对外暴露 Tools、Resources、Prompts 三类能力,通过标准化协议被 Client 调用
1.4 MCP 协议层详解
MCP 底层通信基于 JSON-RPC 2.0 协议,所有消息都遵循请求-响应模式:
// 请求示例
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "add",
"arguments": { "a": 5, "b": 3 }
}
}
// 响应示例
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{ "type": "text", "text": "8" }
]
}
}
MCP 支持三种消息类型:
| 消息类型 | 方向 | 说明 |
|---|---|---|
| Request(请求) | 双向 | 期望对方返回响应,包含 id、method、params |
| Response(响应) | 双向 | 对请求的应答,包含 id 和 result 或 error |
| Notification(通知) | 双向 | 单向消息,不需要响应,无 id 字段 |
1.5 服务端三大原语:Tools、Resources、Prompts
MCP Server 对外暴露三种标准化能力原语:
| 原语 | 控制方 | 描述 | 类比 |
|---|---|---|---|
| Tools | 模型控制 | 可执行的函数/操作,由 LLM 自主决定何时调用 | 函数调用(Function Call) |
| Resources | 应用控制 | 可读取的数据源,由应用程序决定如何使用 | GET 请求获取数据 |
| Prompts | 用户控制 | 预定义的提示词模板,由用户主动选择触发 | 快捷指令/模板 |
- Tools 是最常用的能力,例如"查询天气"、"发送邮件"、"操作数据库"
- Resources 类似于只读数据接口,例如"读取配置文件"、"获取数据库 schema"
- Prompts 是可复用的提示词模板,例如"代码审查模板"、"数据分析模板"
二、Function Call 与 MCP 的区别(面试重点)
这是高频面试题,需要从多个维度理解两者的差异。
2.1 两者定义
Function Call 是大模型自带的一种能力,允许模型在对话过程中决定是否需要调用外部函数,并自动生成结构化的调用参数(函数名 + JSON 参数)。通常在本地代码中直接执行。
MCP 是一种标准化的通信协议,定义了 AI 应用与外部工具/服务之间如何发现、调用和交互。可以跨进程、跨系统、跨网络。
2.2 多维度对比
| 维度 | Function Call | MCP |
|---|---|---|
| 本质 | 模型的一种能力 | 一套通信协议标准 |
| 定位 | "模型如何发起调用" | "系统之间如何规范调用" |
| 偏重 | 模型能力层 | 工程架构层 |
| 调用方式 | 通常本地执行 | 支持本地和远程调用 |
| 标准化程度 | 各厂商实现不同(OpenAI、Anthropic、Google 各有差异) | 统一的协议规范 |
| 工具发现 | 需要在 prompt 中预定义函数 schema | Server 自动注册,Client 动态发现 |
| 跨系统 | 难以跨进程/跨网络 | 原生支持分布式调用 |
| 生态复用 | 函数定义与具体应用绑定 | 一个 Server 可被任意 Client 复用 |
| 协议基础 | 无统一协议 | 基于 JSON-RPC 2.0 |
2.3 两者关系
MCP 并非要替代 Function Call,而是在其之上构建了更完整的工程化方案:
┌──────────────────────────────────────────────┐
│ AI 应用 (Host) │
│ ┌────────────────────────────────────────┐ │
│ │ 大语言模型 (LLM) │ │
│ │ ┌──────────────────────────┐ │ │
│ │ │ Function Call 能力 │ │ │
│ │ │ (模型决定调用哪个工具) │ │ │
│ │ └────────────┬─────────────┘ │ │
│ └────────────────┼──────────────────────┘ │
│ ▼ │
│ ┌────────────────────────────────────────┐ │
│ │ MCP Client / MCP Protocol │ │
│ │ (标准化的调用通道与工具发现) │ │
│ └────────────────┬──────────────────────┘ │
└───────────────────┼──────────────────────────┘
▼
┌─────────────────┐
│ MCP Server │
│ (标准化工具服务) │
└─────────────────┘
简单来说:Function Call 负责"决定调用",MCP 负责"规范执行"。在实际应用中,模型通过 Function Call 机制识别到需要调用工具,然后通过 MCP 协议去标准化地调用对应的 MCP Server。
三、MCP 生态:主流平台与市场
截至目前,MCP 生态已初具规模,以下是主要的 MCP 资源平台:
| 平台 | 地址 | 说明 |
|---|---|---|
| Model Context Protocol 官网 | https://modelcontextprotocol.io | 官方文档与规范定义 |
| MCP.so | https://mcp.so/ | 社区驱动的 MCP Server 聚合平台 |
| Smithery | https://smithery.ai/ | MCP 工具市场,支持自动化 OAuth 认证,提供 CLI 工具链 |
| 魔搭社区(ModelScope) | https://www.modelscope.cn/mcp | 阿里达摩院的 MCP 市场,中文生态友好 |
| MCP Marketplace | https://mcp.higress.ai/ | 阿里云 Higress 提供的 MCP 市场 |
| Glama | https://glama.ai/mcp/servers | MCP Server 目录与搜索平台 |
| PulseMCP | https://www.pulsemcp.com/ | MCP 生态新闻与 Server 目录 |
| Cline Marketplace | https://cline.bot/mcp-marketplace | Cline 编程助手内置的 MCP 市场 |
Smithery 使用示例(CLI 工具链):
# 登录认证
npx smithery auth login
# 添加 MCP 服务(以 Notion 为例,会触发 OAuth 授权流程)
npx smithery mcp add notion
# → auth_required
# → https://auth.smithery.ai/...
# 访问授权 URL 完成认证
# 列出可用工具
npx smithery tool list
# 调用工具
npx smithery tool call \
notion notion-create-pages \
'{"pages": [{"properties": {"title": "Q4 Investor Update"}}]}'
Smithery 的核心优势是 "Zero auth plumbing"——当请求需要认证时,它自动处理 OAuth 流程、凭证注入和重试,开发者无需编写任何认证代码。
四、Cherry Studio 中使用 MCP
Cherry Studio 是一款支持 MCP 协议的 AI 桌面客户端,可以零代码地配置和使用 MCP Server。
4.1 基本流程
第一步:下载并注册
前往 https://www.cherry-ai.com/download 下载最新版本(当前 v1.9.5),完成注册和登录。
第二步:配置大模型
在设置中配置你的 LLM API Key 和模型信息(支持 OpenAI、Anthropic 等多种模型提供商)。
第三步:配置 MCP 环境
在 Cherry Studio 的 MCP 设置面板中,可以通过以下两种方式添加 MCP Server:
- 手动配置:直接填写 MCP Server 的启动命令或连接地址
- JSON 导入:粘贴 MCP Server 的 JSON 配置文件,一键导入
第四步:高德地图实战示例
- 1.前往 https://lbs.amap.com/ 注册并申请 API Key
- 2.在 Cherry Studio 中配置高德地图的 MCP Server 地址
- 3.在对话中直接使用自然语言查询地址、搜索附近美食等
4.2 高德地图 MCP 配置示例
在 Cherry Studio 的 MCP 配置中,添加如下 JSON 配置:
{
"mcpServers": {
"amap": {
"command": "npx",
"args": [
"-y",
"@amap/amap-maps-mcp-server"
],
"env": {
"AMAP_MAPS_API_KEY": "你的高德API密钥"
}
}
}
}
配置完成后,在对话中即可直接提问,例如:
- "帮我查一下北京市朝阳区望京SOHO的具体地址"
- "搜索我附近的火锅店"
- "从北京南站到首都机场怎么走"
五、MCP 的通信传输方式
MCP 的传输层与协议层是解耦的。协议层统一使用 JSON-RPC 2.0,传输层则可根据场景选择不同方式。目前官方支持三种传输机制:
5.1 stdio(标准输入/输出)
类型:经典的进程间通信(IPC)方式
工作原理:
┌────────────────┐ stdin/stdout ┌────────────────┐
│ MCP Client │ ◄───── (管道) ─────► │ MCP Server │
│ (父进程) │ │ (子进程) │
└────────────────┘ └────────────────┘
不经过网络,本地直连
- 客户端将 MCP Server 启动为一个 子进程
- 通过 stdin(标准输入) 向服务端发送请求
- 通过 stdout(标准输出) 接收服务端响应
- 整个过程 不经过网络,完全在本地完成
- stderr 用于传输日志等诊断信息
适用场景:
- 本地开发和调试
- 将 CLI 工具快速封装为 MCP Server
- 对安全性要求高、不希望暴露网络端口的场景
一句话理解:本地进程之间的"直接对话",简单高效。
5.2 SSE(Server-Sent Events)
类型:基于 HTTP 的单向流式推送协议
工作原理:
┌────────────┐ ┌────────────┐
│ MCP Client │ ──── HTTP GET /sse ────► │ MCP Server │
│ │ ◄── text/event-stream ── │ │
│ │ │ │
│ │ ──── HTTP POST /msg ───► │ │
└────────────┘ └────────────┘
- 1.客户端通过 HTTP GET 请求连接到服务端的 SSE 端点(通常为
/sse) - 2.服务端保持连接不断开,以
text/event-stream格式持续推送数据 - 3.客户端需要发送消息时,通过单独的 HTTP POST 请求发送到
/message端点
特点:
- 服务端到客户端的推送是 持续的、单向的流
- 客户端到服务端需要通过 额外的 HTTP POST 请求
- 基于标准 HTTP,天然支持跨网络和跨域
适用场景:
- 分布式系统
- 远程 MCP Server 调用
- 需要流式输出的场景(如 AI 逐字生成)
一句话理解:服务器不断"推消息"给客户端。
注意:SSE 传输方式已被 MCP 官方标记为 deprecated(弃用),推荐使用 Streamable HTTP 替代。但对于已有的 Server 实现,SSE 仍然被广泛支持。
5.3 Streamable HTTP(可流式 HTTP)
类型:基于 HTTP 的双向流式通信方式
工作原理:
┌────────────┐ ┌────────────┐
│ MCP Client │ ──── HTTP POST /mcp ───────► │ MCP Server │
│ │ ◄── JSON 或 SSE 响应 ──────── │ │
│ │ │ │
│ │ ──── GET /mcp (可选) ───────► │ │
│ │ ◄── SSE 流式推送 ──────────── │ │
└────────────┘ └────────────┘
- 客户端通过 HTTP POST 到
/mcp端点发送请求 - 服务端可返回 普通 JSON 响应 或 SSE 流式响应
- 支持通过 GET 请求建立可选的 SSE 连接,用于服务端主动推送(如通知)
- 一个端点处理所有通信,简化了部署
特点:
- 支持 双向通信
- 不限于 SSE 格式,支持灵活的数据格式
- 无状态友好,便于水平扩展和负载均衡
- 是 MCP 传输层的 未来推荐方案
适用场景:
- 分布式应用
- AI 服务的远程调用
- Agent / MCP 远程工具链
一句话理解:可以"边问边答"的 HTTP 通信,最灵活、最通用。
5.4 三种方式对比总结
| 特性 | stdio | SSE | Streamable HTTP |
|---|---|---|---|
| 通信方向 | 双向(管道) | 服务端单向推 + 客户端 POST | 双向 |
| 网络支持 | 仅本地 | 支持远程 | 支持远程 |
| 协议基础 | stdin/stdout | HTTP | HTTP |
| 流式支持 | 无 | 是 | 是 |
| 状态管理 | 有状态 | 有状态 | 无状态友好 |
| 部署复杂度 | 低 | 中 | 中 |
| 扩展性 | 差(单机) | 一般 | 好 |
| 推荐程度 | 本地开发首选 | 已 deprecated | 官方推荐 |
六、MCP 初始化与生命周期
MCP 客户端与服务端之间有一个规范化的 连接生命周期,分为三个阶段:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 初始化阶段 | ────►│ 运行阶段 │────►│ 关闭阶段 │
│(Initialize) │ │ (Operation) │ │ (Shutdown) │
└─────────────┘ └─────────────┘ └─────────────┘
阶段一:初始化(Initialize)
Client Server
│ │
│ ──── initialize 请求 ────────► │ (发送协议版本和客户端能力)
│ │
│ ◄─── initialize 响应 ──────── │ (返回服务端能力)
│ │
│ ──── initialized 通知 ───────► │ (确认初始化完成)
│ │
双方在此阶段进行 能力协商(Capability Negotiation):
// 客户端发送的 initialize 请求
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {
"tools": {},
"sampling": {}
},
"clientInfo": {
"name": "MyAgent",
"version": "1.0.0"
}
}
}
// 服务端返回的 initialize 响应
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-03-26",
"capabilities": {
"tools": { "listChanged": true },
"resources": { "subscribe": true },
"prompts": { "listChanged": true }
},
"serverInfo": {
"name": "Demo",
"version": "1.0.0"
}
}
}
阶段二:运行(Operation)
初始化完成后,客户端与服务端进入正常交互阶段:
- 客户端可以调用
tools/list、resources/list、prompts/list来发现服务端提供的能力 - 客户端可以通过
tools/call调用工具 - 服务端可以通过通知(Notification)告知客户端能力变化
阶段三:关闭(Shutdown)
任何一方都可以发起关闭,通常是客户端发起:
Client Server
│ │
│ ──── close 通知 ─────────────► │
│ │
│ 连接关闭,释放资源 │
七、实战:编写 MCP 服务器
7.1 准备工作
# 安装 MCP Python SDK
pip install mcp
7.1 stdio 模式
这是最简单的入门方式,MCP Server 作为本地子进程运行。
文件:mcp_server_stdio.py
from mcp.server.fastmcp import FastMCP
# 创建一个 FastMCP 实例,参数为服务名称
mcp = FastMCP("Demo")
# ── 注册工具(Tools) ──────────────────────────────────
@mcp.tool()
def add(a: int, b: int) -> int:
"""计算两个数的和"""
return a + b
@mcp.tool()
def mul(a: int, b: int) -> int:
"""计算两个数的积"""
return a * b
@mcp.tool()
def subtract(a: int, b: int) -> int:
"""计算两个数的差"""
return a - b
@mcp.tool()
def divide(a: float, b: float) -> float:
"""计算两个数的商,除数不能为零"""
if b == 0:
raise ValueError("除数不能为零")
return a / b
if __name__ == "__main__":
# 以 stdio 模式运行
mcp.run("stdio")
启动方式:
python mcp_server_stdio.py
7.2 SSE 模式
将 MCP Server 暴露为 HTTP 服务,支持远程调用。
文件:mcp_server_sse.py
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Demo-SSE")
@mcp.tool()
def add(a: int, b: int) -> int:
"""计算两个数的和"""
return a + b
@mcp.tool()
def mul(a: int, b: int) -> int:
"""计算两个数的积"""
return a * b
@mcp.tool()
def greet(name: str) -> str:
"""向指定的人打招呼"""
return f"你好,{name}!欢迎使用 MCP 服务。"
if __name__ == "__main__":
# 以 SSE 模式运行,默认监听 0.0.0.0:8000
mcp.run("sse")
启动方式:
python mcp_server_sse.py
# 服务将在 http://0.0.0.0:8000/sse 上监听
7.3 Streamable HTTP 模式
官方推荐的新一代传输方式。
文件:mcp_server_http.py
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Demo-HTTP")
@mcp.tool()
def add(a: int, b: int) -> int:
"""计算两个数的和"""
return a + b
@mcp.tool()
def mul(a: int, b: int) -> int:
"""计算两个数的积"""
return a * b
@mcp.tool()
def calculate_total(items: list[float]) -> float:
"""计算一组金额的总和"""
return sum(items)
if __name__ == "__main__":
# 以 Streamable HTTP 模式运行,默认端口 8000,路径 /mcp
mcp.run("streamable-http")
启动方式:
python mcp_server_http.py
# 服务将在 http://0.0.0.0:8000/mcp 上监听
7.4 注册 Resource 与 Prompt
除了 Tools,MCP Server 还可以注册 Resources 和 Prompts:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("FullDemo")
# ── Tools(工具) ──────────────────────────────────
@mcp.tool()
def add(a: int, b: int) -> int:
"""计算两个数的和"""
return a + b
# ── Resources(资源) ──────────────────────────────
@mcp.resource("config://app")
def get_config() -> str:
"""返回应用配置信息"""
return '{"version": "1.0.0", "author": "MCP Demo", "debug": false}'
@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
"""根据用户名返回个性化问候"""
return f"Hello, {name}! Welcome to the MCP world."
# ── Prompts(提示词模板) ──────────────────────────
@mcp.prompt()
def review_code(code: str) -> str:
"""代码审查提示词模板"""
return f"""请对以下代码进行审查,关注以下方面:
1. 代码质量与可读性
2. 潜在的 Bug 或边界情况
3. 性能优化建议
4. 安全性问题
待审查代码:
```{code}```
"""
@mcp.prompt()
def analyze_data(data_description: str) -> str:
"""数据分析提示词模板"""
return f"""请对以下数据进行分析:
数据描述:{data_description}
请提供:
1. 数据概览与关键指标
2. 趋势分析
3. 异常检测
4. 可操作的建议
"""
if __name__ == "__main__":
mcp.run("stdio")
八、实战:编写 MCP 客户端
客户端使用 langchain-mcp-adapters 库将 MCP Server 的工具无缝集成到 LangChain Agent 中。
8.1 安装依赖
pip install langchain-openai langchain-mcp-adapters langchain langgraph
8.1 stdio 方式连接
客户端启动 MCP Server 作为子进程,通过 stdin/stdout 通信。
import asyncio
import os
from langchain_core.messages import HumanMessage
from langchain_openai import ChatOpenAI
from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.prebuilt import create_react_agent
# 加载环境变量(根据你的项目结构调整)
# from config import load_project_env
# load_project_env()
# 初始化 LLM
my_llm = ChatOpenAI(
api_key=os.getenv("MODEL_API_KEY"),
base_url=os.getenv("MODEL_BASE_URL"),
model=os.getenv("MODEL_NAME"),
)
async def get_agent():
"""创建 Agent,通过 stdio 连接 MCP Server"""
client = MultiServerMCPClient(
{
"demo": {
"command": "python", # Python 解释器路径
"args": ["mcp_server_stdio.py"], # MCP Server 脚本路径
"transport": "stdio",
}
}
)
tools = await client.get_tools()
print("可用工具:", [tool.name for tool in tools])
agent = create_react_agent(
my_llm,
tools,
)
return agent, client
async def chat(user_input: str) -> str:
"""与 Agent 对话"""
agent, client = await get_agent()
try:
state = await agent.ainvoke(
{"messages": [HumanMessage(content=user_input)]}
)
messages = state.get("messages", [])
if messages:
return messages[-1].content
return "未获得结果"
finally:
# 关闭客户端连接
await client.close()
def main():
print("MCP Client (stdio) 已就绪,输入 exit 退出。")
while True:
user_input = input("\n用户: ").strip()
if user_input.lower() == "exit":
break
if not user_input:
continue
result = asyncio.run(chat(user_input))
print(f"助手: {result}")
if __name__ == "__main__":
main()
8.2 SSE 方式连接
import asyncio
import os
from langchain_core.messages import HumanMessage
from langchain_openai import ChatOpenAI
from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.prebuilt import create_react_agent
my_llm = ChatOpenAI(
api_key=os.getenv("MODEL_API_KEY"),
base_url=os.getenv("MODEL_BASE_URL"),
model=os.getenv("MODEL_NAME"),
)
async def get_agent():
"""创建 Agent,通过 SSE 连接远程 MCP Server"""
client = MultiServerMCPClient(
{
"demo": {
"url": "http://127.0.0.1:8000/sse",
"transport": "sse",
}
}
)
tools = await client.get_tools()
print("可用工具:", [tool.name for tool in tools])
agent = create_react_agent(my_llm, tools)
return agent, client
async def chat(user_input: str) -> str:
agent, client = await get_agent()
try:
state = await agent.ainvoke(
{"messages": [HumanMessage(content=user_input)]}
)
messages = state.get("messages", [])
return messages[-1].content if messages else "未获得结果"
finally:
await client.close()
def main():
print("MCP Client (SSE) 已就绪,输入 exit 退出。")
while True:
user_input = input("\n用户: ").strip()
if user_input.lower() == "exit":
break
if not user_input:
continue
print(f"助手: {asyncio.run(chat(user_input))}")
if __name__ == "__main__":
main()
8.3 Streamable HTTP 方式连接
import asyncio
import os
from langchain_core.messages import HumanMessage
from langchain_openai import ChatOpenAI
from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.prebuilt import create_react_agent
my_llm = ChatOpenAI(
api_key=os.getenv("MODEL_API_KEY"),
base_url=os.getenv("MODEL_BASE_URL"),
model=os.getenv("MODEL_NAME"),
)
async def get_agent():
"""创建 Agent,通过 Streamable HTTP 连接远程 MCP Server"""
client = MultiServerMCPClient(
{
"demo": {
"url": "http://127.0.0.1:8000/mcp",
"transport": "streamable_http",
}
}
)
tools = await client.get_tools()
print("可用工具:", [tool.name for tool in tools])
agent = create_react_agent(my_llm, tools)
return agent, client
async def chat(user_input: str) -> str:
agent, client = await get_agent()
try:
state = await agent.ainvoke(
{"messages": [HumanMessage(content=user_input)]}
)
messages = state.get("messages", [])
return messages[-1].content if messages else "未获得结果"
finally:
await client.close()
def main():
print("MCP Client (Streamable HTTP) 已就绪,输入 exit 退出。")
while True:
user_input = input("\n用户: ").strip()
if user_input.lower() == "exit":
break
if not user_input:
continue
print(f"助手: {asyncio.run(chat(user_input))}")
if __name__ == "__main__":
main()
8.4 同时连接多个 MCP Server
MultiServerMCPClient 的强大之处在于可以同时连接多个不同类型的 MCP Server:
async def get_agent():
"""同时连接多个 MCP Server"""
client = MultiServerMCPClient(
{
# 本地计算器服务(stdio)
"calculator": {
"command": "python",
"args": ["mcp_server_stdio.py"],
"transport": "stdio",
},
# 远程天气服务(SSE)
"weather": {
"url": "http://weather-server.example.com/sse",
"transport": "sse",
},
# 远程数据库服务(Streamable HTTP)
"database": {
"url": "http://db-server.example.com/mcp",
"transport": "streamable_http",
},
}
)
tools = await client.get_tools()
print("可用工具:", [tool.name for tool in tools])
agent = create_react_agent(my_llm, tools)
return agent, client
九、总结与展望
核心要点回顾
| 要点 | 内容 |
|---|---|
| MCP 是什么 | AI 应用与外部系统之间的标准化通信协议("AI 的 USB-C") |
| 三层架构 | Host(宿主)→ Client(客户端)→ Server(服务端) |
| 三大原语 | Tools(工具)、Resources(资源)、Prompts(提示词模板) |
| 协议基础 | JSON-RPC 2.0 |
| 传输方式 | stdio(本地)、SSE(远程,已 deprecated)、Streamable HTTP(远程,推荐) |
| 与 Function Call 关系 | Function Call 负责"决定调用",MCP 负责"规范执行",二者互补 |
适用场景
- 个人开发:快速为本地 AI 助手接入文件操作、数据库查询、API 调用等能力
- 企业应用:将内部系统(CRM、ERP、数据仓库)封装为 MCP Server,统一被 AI 应用调用
- Agent 开发:构建具备复杂工具调用能力的 AI Agent,通过 MCP 协议实现工具的动态发现和编排
未来展望
MCP 生态仍在快速演进中。随着更多厂商和社区的参与,MCP 有望成为 AI 工具调用领域的 事实标准,就像 HTTP 之于 Web、gRPC 之于微服务一样,成为 AI 基础设施的关键一环。
更多推荐

所有评论(0)