一、三种 MCP 通讯方式对比
MCP(Model Context Protocol)目前支持三种通讯方式,各有特点:
1. stdio(标准输入输出)
工作原理
- 通过本地进程的 stdin/stdout 进行通信
- 客户端以子进程方式启动 MCP 服务器
- 双方通过管道交换 JSON-RPC 格式消息(换行符分割)
适用场景
- 本地进程间通信(如命令行工具、文件系统操作)
- 简单的批处理任务或工具调用
|----------|--------------------------------------------------------|
| 优点 | 限制 |
| 实现简单,低延迟 | 仅限本地,不支持分布式部署 |
| 无需网络配置 | 服务端不能输出控制台日志(会污染协议流) |
| 适合本地开发 | ------------------------------------------------------ |
2. SSE(Server-Sent Events)⚠️ 已弃用
工作原理
- 基于 HTTP 长连接实现单向消息推送
- 客户端通过
GET /sse建立连接 - 服务器通过 SSE 流发送 JSON-RPC 消息
- 客户端通过
POST /message发送请求
适用场景
- 远程服务调用(如云服务、多客户端监控)
- 需要实时数据推送的场景(如流式对话)
|--------------------------|-----------------------------------|
| 优点 | 限制 |
| 支持实时单向推送 | 2025年3月后已被 Streamable HTTP 取代 |
| 适合流式交互 | 连接中断后无法恢复 |
| ------------------------ | 需维持长连接,资源消耗较高 |
3. Streamable HTTP(流式 HTTP)✅ 官方推荐
工作原理(2025年3月引入)
- 通过统一的
/message端点实现双向通信 - 客户端通过 HTTP POST 发送请求
- 服务器可将响应升级为 SSE 流式传输(按需)
- 支持无状态模式,无需维持长连接
核心优势
- ✅ 支持连接恢复(无需重新开始)
- ✅ 无需维持长连接,降低资源消耗
- ✅ 统一端点设计(
/message),简化接口 - ✅ 兼容现有基础设施(负载均衡、中间件等)
适用场景
- 高并发远程服务调用
- 需要灵活流式响应的场景(如 AI 助手动态输出)
二、stdio 模式实现
架构流程图: 创建 Server → 启动服务 → Client 连接 → 加载 Tools → Agent 调用

Step 1:创建 MCP Server
from mcp.server.fastmcp import FastMCP
mcp = FastMCP('Math Tools')
@mcp.tool()
def add(a: int, b: int) -> int:
return a + b
@mcp.tool()
def multiply(a: int, b: int) -> int:
return a * b
if __name__ == '__main__':
mcp.run(transport='stdio') # ← 关键:stdio 模式
💡 说明: 使用 @mcp.tool() 注册工具方法,run(transport='stdio') 启动服务。
Step 2:启动 MCP Server
python server.py
💡 服务启动后会持续监听 stdin/stdout 的读写事件。
Step 3:开发 MCP Client(含 Agent)
3.1 定义 Server 参数
server_params = StdioServerParameters(
command='python',
args=['path/to/mcp_stdio_server.py']
)
3.2 加载 MCP Tools
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await load_mcp_tools(session)
print(f"成功加载 {len(tools)} 个工具")
3.3 创建 Agent 并调用
agent = initialize_agent(
tools=tools,
llm=llm,
agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
verbose=True,
)
resp = await agent.ainvoke("14+17*5=?")
完整示例代码
import os
import asyncio
from dotenv import load_dotenv
from mcp import StdioServerParameters, ClientSession
from mcp.client.stdio import stdio_client
from langchain_mcp_adapters.tools import load_mcp_tools
from langchain.agents import initialize_agent, AgentType
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
model="qwen-plus",
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://ws-kcaoxz5olbi6r3qa.cn-beijing.maas.aliyuncs.com/compatible-mode/v1",
streaming=True,
temperature=0.7,
)
async def create_mcp_stdio_client():
server_params = StdioServerParameters(
command='python',
args=['D:/sd14/ai-agent/app/mcp_/stdio/mcp_stdio_server.py']
)
try:
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await load_mcp_tools(session)
print(f"成功加载 {len(tools)} 个工具")
agent = initialize_agent(
tools=tools,
llm=llm,
agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
verbose=True,
)
resp = await agent.ainvoke("14+17*5=?")
print(f"\n回答: {resp}")
return resp
except Exception as e:
print(f"连接失败: {e}")
traceback.print_exc()
if __name__ == '__main__':
asyncio.run(create_mcp_stdio_client())
三、SSE 模式实现(已弃用,仅供参考)
⚠️ 官方已废弃,建议直接使用 Streamable HTTP

Server 端差异
if __name__ == '__main__':
mcp.run(transport='sse') # ← 仅 transport 参数不同
Client 端差异
from langchain_mcp_adapters.client import MultiServerMCPClient
client = MultiServerMCPClient({
"math": {
"url": "http://127.0.0.1:8000/sse",
"transport": "sse", # ← 指定传输方式
}
})
tools = await client.get_tools()
SSE 模式完整代码
SSE Server 端 (mcp_sse_server.py)
from mcp.server.fastmcp import FastMCP
# 创建 MCP 服务器实例
mcp = FastMCP('Math Tools - SSE')
# ============ 注册工具方法 ============
@mcp.tool()
def add(a: int, b: int) -> int:
"""
计算两个整数的和
"""
return a + b
@mcp.tool()
def multiply(a: int, b: int) -> int:
"""
计算两个整数的乘积
"""
return a * b
@mcp.tool()
def subtract(a: int, b: int) -> int:
"""
计算两个整数的差 (a - b)
"""
return a - b
@mcp.tool()
def divide(a: int, b: int) -> float:
"""
计算两个整数的商 (a / b)
"""
if b == 0:
raise ValueError("除数不能为0")
return a / b
@mcp.tool()
def power(base: int, exponent: int) -> int:
"""
计算幂运算 (base ^ exponent)
"""
return base ** exponent
# ============ 启动服务 ============
if __name__ == '__main__':
mcp.run(transport='sse')
SSE Client 端 (mcp_sse_client.py)
import os
import asyncio
from dotenv import load_dotenv
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain.agents import initialize_agent, AgentType
from langchain_openai import ChatOpenAI
# ============ 加载环境变量 ============
load_dotenv()
# ============ 初始化 LLM ============
llm = ChatOpenAI(
model="qwen-plus",
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://ws-kcaoxz5olbi6r3qa.cn-beijing.maas.aliyuncs.com/compatible-mode/v1",
streaming=True,
temperature=0.7,
)
# ============ 创建 SSE 客户端 ============
async def create_mcp_sse_client():
try:
# 创建多服务器客户端
client = MultiServerMCPClient(
{
"math": {
"url": "http://127.0.0.1:8000/sse", # SSE 端点
"transport": "sse", # 指定传输方式
}
}
)
# 获取所有工具
tools = await client.get_tools()
print(f"✅ 成功加载 {len(tools)} 个工具:")
for tool in tools:
print(f" - {tool.name}: {tool.description}")
# ============ 创建 Agent ============
agent = initialize_agent(
tools=tools,
llm=llm,
agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
verbose=True,
handle_parsing_errors=True,
)
# ============ 测试调用 ============
print("\n" + "="*50)
print("🧪 测试 1: 基础运算")
print("="*50)
resp1 = await agent.ainvoke("请计算 14 + 17 * 5 = ?")
print(f"\n📝 回答: {resp1['output']}\n")
print("="*50)
print("🧪 测试 2: 复杂表达式")
print("="*50)
resp2 = await agent.ainvoke("计算 (100 - 25) * 4 / 3 = ?")
print(f"\n📝 回答: {resp2['output']}\n")
print("="*50)
print("🧪 测试 3: 幂运算")
print("="*50)
resp3 = await agent.ainvoke("计算 2 的 10 次方等于多少?")
print(f"\n📝 回答: {resp3['output']}\n")
return resp1
except Exception as e:
print(f"❌ 连接失败: {e}")
import traceback
traceback.print_exc()
return None
# ============ 入口 ============
if __name__ == '__main__':
print("🚀 启动 SSE MCP 客户端...")
print("📌 请确保 SSE 服务器已启动: python mcp_sse_server.py")
print()
asyncio.run(create_mcp_sse_client())
SSE 模式启动步骤
# 终端1: 启动 SSE Server
python mcp_sse_server.py
# 终端2: 启动 SSE Client
python mcp_sse_client.py
四、Streamable HTTP 模式实现 ✅ 推荐
Server 端
if __name__ == '__main__':
mcp.run(transport="streamable-http")
Client 端
client = MultiServerMCPClient({
"math": {
"url": "http://127.0.0.1:8000/mcp",
"transport": "streamable_http", # ← 注意:下划线
}
})
tools = await client.get_tools()
Streamable HTTP 完整代码
Streamable HTTP Server 端 (mcp_streamable_server.py)
from mcp.server.fastmcp import FastMCP
# 创建 MCP 服务器实例
mcp = FastMCP('Math Tools - Streamable HTTP')
# ============ 注册工具方法 ============
@mcp.tool()
def add(a: int, b: int) -> int:
"""
计算两个整数的和
"""
return a + b
@mcp.tool()
def multiply(a: int, b: int) -> int:
"""
计算两个整数的乘积
"""
return a * b
@mcp.tool()
def subtract(a: int, b: int) -> int:
"""
计算两个整数的差 (a - b)
"""
return a - b
@mcp.tool()
def divide(a: int, b: int) -> float:
"""
计算两个整数的商 (a / b)
"""
if b == 0:
raise ValueError("除数不能为0")
return a / b
@mcp.tool()
def power(base: int, exponent: int) -> int:
"""
计算幂运算 (base ^ exponent)
"""
return base ** exponent
@mcp.tool()
def factorial(n: int) -> int:
"""
计算阶乘 (n!)
"""
if n < 0:
raise ValueError("阶乘只支持非负整数")
if n == 0 or n == 1:
return 1
result = 1
for i in range(2, n + 1):
result *= i
return result
@mcp.tool()
def fibonacci(n: int) -> list:
"""
生成前 n 个斐波那契数列
"""
if n <= 0:
return []
if n == 1:
return [0]
fib = [0, 1]
for i in range(2, n):
fib.append(fib[i-1] + fib[i-2])
return fib
# ============ 启动服务 ============
if __name__ == '__main__':
mcp.run(transport='streamable-http')
Streamable HTTP Client 端 (mcp_streamable_client.py)
import os
import asyncio
from dotenv import load_dotenv
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain.agents import initialize_agent, AgentType
from langchain_openai import ChatOpenAI
from langchain.callbacks import StreamingStdOutCallbackHandler
# ============ 加载环境变量 ============
load_dotenv()
# ============ 初始化 LLM ============
llm = ChatOpenAI(
model="qwen-plus",
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://ws-kcaoxz5olbi6r3qa.cn-beijing.maas.aliyuncs.com/compatible-mode/v1",
streaming=True,
temperature=0.7,
callbacks=[StreamingStdOutCallbackHandler()],
)
# ============ 创建 Streamable HTTP 客户端 ============
async def create_mcp_streamable_client():
try:
# 创建多服务器客户端
client = MultiServerMCPClient(
{
"math": {
"url": "http://127.0.0.1:8000/mcp", # Streamable HTTP 端点
"transport": "streamable_http", # 注意:下划线
}
}
)
# 获取所有工具
tools = await client.get_tools()
print(f"\n✅ 成功加载 {len(tools)} 个工具:")
for tool in tools:
print(f" - {tool.name}: {tool.description}")
# ============ 创建 Agent ============
agent = initialize_agent(
tools=tools,
llm=llm,
agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
verbose=True,
handle_parsing_errors=True,
max_iterations=5,
)
# ============ 测试调用 ============
test_cases = [
"请计算 14 + 17 * 5 = ?",
"计算 (100 - 25) * 4 / 3 = ?",
"2 的 10 次方等于多少?",
"计算 5!(5的阶乘)等于多少?",
"生成前 10 个斐波那契数列",
]
for i, query in enumerate(test_cases, 1):
print("\n" + "=" * 60)
print(f"🧪 测试 {i}: {query}")
print("=" * 60)
try:
resp = await agent.ainvoke(query)
print(f"\n📝 最终回答:\n{resp['output']}\n")
except Exception as e:
print(f"❌ 调用失败: {e}")
return True
except Exception as e:
print(f"❌ 连接失败: {e}")
import traceback
traceback.print_exc()
return False
# ============ 高级用法:上下文管理 ============
async def advanced_usage():
"""
展示如何优雅地管理客户端生命周期
"""
async with MultiServerMCPClient(
{
"math": {
"url": "http://127.0.0.1:8000/mcp",
"transport": "streamable_http",
}
}
) as client:
tools = await client.get_tools()
print(f"✅ 加载了 {len(tools)} 个工具")
# 创建 Agent
agent = initialize_agent(
tools=tools,
llm=llm,
agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
verbose=True,
)
# 多轮对话
queries = [
"计算 3 + 4 * 5",
"计算 10!",
"生成前 5 个斐波那契数列",
]
for query in queries:
print(f"\n💬 用户: {query}")
resp = await agent.ainvoke(query)
print(f"🤖 AI: {resp['output']}")
# ============ 入口 ============
if __name__ == '__main__':
print("🚀 启动 Streamable HTTP MCP 客户端...")
print("📌 请确保 Streamable HTTP 服务器已启动: python mcp_streamable_server.py")
print("📌 访问地址: http://127.0.0.1:8000/mcp")
print()
# 基础用法
asyncio.run(create_mcp_streamable_client())
# 高级用法(取消注释使用)
# asyncio.run(advanced_usage())
Streamable HTTP 模式启动步骤
# 终端1: 启动 Streamable HTTP Server
python mcp_streamable_server.py
# 终端2: 启动 Streamable HTTP Client
python mcp_streamable_client.py
快速对比总览
|----------|-------|----------|-------------------|
| 特性 | stdio | SSE(已弃用) | Streamable HTTP ✅ |
| 适用场景 | 本地开发 | 远程调用 | 生产环境/云服务 |
| 网络需求 | 无需网络 | 需要 HTTP | 需要 HTTP |
| 连接状态 | 进程级 | 需维持长连接 | 支持无状态 |
| 连接恢复 | N/A | ❌ 不支持 | ✅ 支持 |
| 资源消耗 | 低 | 高 | 低 |
| 官方推荐 | 本地开发 | ❌ 已淘汰 | ✅ 强烈推荐 |
五、补充:如何选择合适的传输方式?
┌─────────────────────────────────────────────────────┐
│ 你的需求是什么? │
├─────────────────────────────────────────────────────┤
│ • 本地开发/测试 → 使用 stdio │
│ • 远程服务/生产部署 → 使用 Streamable HTTP│
│ • 需要流式响应 → 使用 Streamable HTTP│
│ • 高并发场景 → 使用 Streamable HTTP│
│ • 旧项目维护(不推荐新项目)→ SSE(但建议迁移) │
└─────────────────────────────────────────────────────┘
六、踩坑提醒 💡
|------------------------------|---------------------------------------|
| 问题 | 解决方案 |
| stdio 模式 服务端不能 print() | 使用 logging 输出到文件 |
| SSE 连接中断 | 迁移到 Streamable HTTP |
| Streamable HTTP 端口被占用 | 更换端口或检查服务是否已启动 |
| 工具加载失败 | 检查 server 端的 transport 参数是否匹配 |
| 环境变量未生效 | 确保 .env 文件在项目根目录,使用 load_dotenv() |