LLM—— 基于 MCP 协议(Streamable HTTP 模式)的工具调用实践
在上一篇博客中,我们介绍了 LLM—— 基于 MCP 协议(SSE 模式)的工具调用实践 。本文我们将聚焦于MCP协议(Streamable HTTP 模式)的工具调用实践,了解Streamable HTTP 模式下,客户端与服务端的交互方式,并通过实际的案例加深对该模式下交互的体验,那就让我们开始吧!
一、什么是 MCP Streamable HTTP 模式?
MCP 的 Streamable HTTP 模式是对早期 HTTP+SSE 模式的标准化升级,具备以下关键特性:
能力 | 描述 |
---|---|
单一 /mcp 接口 | 所有消息统一通过一个 HTTP 路由处理 |
支持 POST | 客户端可发送 JSON-RPC 请求/通知 |
支持 GET | 客户端可监听 SSE 流接收服务器消息 |
支持流式响应 | 响应可拆分为 token 流或异步事件推送 |
支持 Session 管理 | 可状态化地追踪上下文并做权限控制 |
支持连接恢复 | SSE 流支持基于 Last-Event-ID 的断点续传 |
二、 示例程序
服务端:注册工具并启动 HTTP 服务
from mcp.server.fastmcp import FastMCP# 创建 MCP 服务端(无状态 HTTP 模式)
mcp = FastMCP("MyServer", host="127.0.0.1", port=8050, stateless_http=True)# 注册工具 say_hello
@mcp.tool()
def say_hello(name: str) -> str:return f"Hello, {name}! Nice to meet you!"# 注册工具 add
@mcp.tool()
def add(a: int, b: int) -> int:return a + b# 启动服务,使用 Streamable HTTP 模式
if __name__ == "__main__":mcp.run(transport="streamable-http")
🔎 说明:
- MCP 服务器将监听
/mcp
路径,处理所有 POST/GET 请求 - 所有函数通过
@mcp.tool()
注册,自动暴露为 JSON-RPC 工具接口 - 使用
stateless_http=True
代表服务器为无状态模型,适合横向扩展
客户端:调用远程工具并输出结果
import asyncio
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_clientasync def main():# 与 MCP 服务建立连接(使用流式 HTTP)async with streamablehttp_client("http://localhost:8050/mcp") as (read_stream, write_stream, get_session_id):async with ClientSession(read_stream, write_stream) as session:await session.initialize() # 初始化连接tools_result = await session.list_tools() # 列出所有工具print("Available tools:")for tool in tools_result.tools:print(f"- {tool.name}: {tool.description}")result = await session.call_tool("add", arguments={"a": 1, "b": 2}) # 远程调用 add 函数print(f"1 + 2 = {result.content[0].text}")if __name__ == "__main__":asyncio.run(main())
🧩 说明:
- MCP 客户端远程调用Server端的工具 add(a=1, b=2)
- MCP 客户端(通过 ClientSession.call_tool)将此请求封装为 JSON-RPC 格式,并发送给服务端
- 服务端运行了 add() 函数,并把结果返回给客户端
- 返回的内容不是一个简单的数字,而是被封装在一个 JSON-RPC 响应对象中
- 程序最终从返回结果中提取了 content[0].text 字段进行打印
程序运行结果:
如果我们把server端的程序中,stateless_http=True
去掉,让它走默认值False,会发生什么呢?
mcp = FastMCP("MyServer", host="127.0.0.1", port=8050)
我们再来运行下程序
我们发现,stateless_http=False
的情况下,在输出的日志中明显多了下面两条
Created new transport with session ID: 82a3519c341d4088a9c4c0856b991480
...
Terminating session: 82a3519c341d4088a9c4c0856b991480
说明:
- 默认 stateless_http=False(有状态)时,MCP Server 会为每个客户端维护会话(Session)。每个会话对应一个 Session ID,用于所有后续请求识别。
- 当stateless_http=True(无状态)时,MCP Server 不会创建或追踪会话,每次请求作为完全独立的一次性操作处理,不返回 Mcp-Session-Id,也不要求客户端持有。
三、总结
MCP 的 Streamable HTTP 模式 结合 HTTP 标准化、SSE 流能力、Session 状态管理与 JSON-RPC 结构表达,为开发者提供了:
- 高效的工具注册与调用方式
- 可扩展的服务架构
- 可靠的多端通信保障
- 平滑的旧版本兼容策略
对于希望打造智能体工具平台的开发者而言,这种方式既现代、又实用。