深入解析MCP的三种传输方式实现

引言

在Model Context Protocol (MCP) 定义了多种传输方式以适应不同场景需求。本文将详细解析MCP的三种主要传输方式:标准输入输出(stdio)、服务器发送事件(SSE)和可流式HTTP(Streamable HTTP),帮助开发者根据实际需求选择最佳实现方案

1. 标准输入输出(stdio)模式

标准输入输出模式是最基础的传输方式,特别适合命令行工具和简单的交互场景。

实现逻辑

python 复制代码
# 初始化服务器
app = Server("mcpServer")

async def run_stdio():
    """运行标准输入输出模式的服务器
    
    使用标准输入输出流(stdio)运行服务器,主要用于命令行交互模式
    
    Raises:
        Exception: 当服务器运行出错时抛出异常
    """
    from mcp.server.stdio import stdio_server

    async with stdio_server() as (read_stream, write_stream):
        try:
            await app.run(
                read_stream,
                write_stream,
                app.create_initialization_options()
            )
        except Exception as e:
            print(f"服务器错误: {str(e)}")
            raise

if __name__ == "__main__":
    asyncio.run(run_stdio())

核心特点:

  • 使用标准输入(stdin)和标准输出(stdout)进行通信
  • 实现简单,无需额外网络配置
  • 适合本地调试和CLI工具开发
  • 通过stdio_server()上下文管理器管理流资源

适用场景:

  • 本地开发调试
  • 命令行工具集成
  • 简单的进程间通信

2. 服务器发送事件(SSE)模式

SSE模式利用HTTP长连接实现服务器向客户端的单向实时通信。

该传输方式在 2024-11-05 协议版本开始替换为了 HTTP+SSE 传输,及第三中streamableHttp方式

实现逻辑

python 复制代码
# 初始化服务器
app = Server("mcpServer")

def run_sse():
    """运行SSE(Server-Sent Events)模式的服务器
    
    启动一个支持SSE的Web服务器,允许客户端通过HTTP长连接接收服务器推送的消息
    服务器默认监听0.0.0.0:9000
    """
    sse = SseServerTransport("/messages/")

    async def handle_sse(request):
        """处理SSE连接请求
        
        Args:
            request: HTTP请求对象
        """
        async with sse.connect_sse(
                request.scope, request.receive, request._send
        ) as streams:
            await app.run(streams[0], streams[1], app.create_initialization_options())

    starlette_app = Starlette(
        debug=True,
        routes=[
            Route("/sse", endpoint=handle_sse),
            Mount("/messages/", app=sse.handle_post_message)
        ],
    )
    uvicorn.run(starlette_app, host="0.0.0.0", port=9000)
    
if __name__ == "__main__":
	run_sse()

核心特点:

  • 基于HTTP/1.1的长连接技术
  • 服务器可主动向客户端推送消息
  • 使用SseServerTransport处理SSE连接
  • 提供/sse端点建立连接,/messages/端点接收消息

适用场景:

  • 需要服务器主动推送但不需要双向通信的场景

3. 可流式HTTP(Streamable HTTP)模式

可流式HTTP模式提供了更灵活的HTTP双向通信能力。

实现逻辑

有状态的实现方式

python 复制代码
# 初始化服务器
app = Server("mcpServer")

def run_streamable_http(json_response: bool):
    event_store = InMemoryEventStore()

		# 使用我们的应用和事件存储创建会话管理器
    session_manager = StreamableHTTPSessionManager(
        app=app,
        event_store=event_store,
        json_response=json_response,
    )

		# 用于可流式HTTP连接的ASGI处理器
    async def handle_streamable_http(
            scope: Scope, receive: Receive, send: Send
    ) -> None:
        await session_manager.handle_request(scope, receive, send)

    @contextlib.asynccontextmanager
    async def lifespan(app: Starlette) -> AsyncIterator[None]:
     """用于管理会话管理器生命周期的上下文管理器。"""
        async with session_manager.run():
            yield

		# 使用传输创建ASGI应用程序
    starlette = Starlette(
        debug=True,
        routes=[
            Mount("/mcp", app=handle_streamable_http)
        ],
        lifespan=lifespan,
    )
    uvicorn.run(starlette, host="0.0.0.0", port=3000)

if __name__ == "__main__":
	run_streamable_http(False)

无状态的实现方式

python 复制代码
# 初始化服务器
app = Server("mcpServer")

def run_streamable_http(json_response: bool):
		# 使用我们的应用和事件存储创建会话管理器
    session_manager = StreamableHTTPSessionManager(
        app=app,
        event_store=None,
        json_response=json_response,
        stateless=True,
    )

		# 用于可流式HTTP连接的ASGI处理器
    async def handle_streamable_http(
            scope: Scope, receive: Receive, send: Send
    ) -> None:
        await session_manager.handle_request(scope, receive, send)

    @contextlib.asynccontextmanager
    async def lifespan(app: Starlette) -> AsyncIterator[None]:
     """用于管理会话管理器生命周期的上下文管理器。"""
        async with session_manager.run():
            yield

		# 使用传输创建ASGI应用程序
    starlette = Starlette(
        debug=True,
        routes=[
            Mount("/mcp", app=handle_streamable_http)
        ],
        lifespan=lifespan,
    )
    uvicorn.run(starlette, host="0.0.0.0", port=3000)

if __name__ == "__main__":
	run_streamable_http(False)

核心特点:

  • 有状态的方式使用InMemoryEventStore存储事件,另外实现的持久化方式
  • 通过StreamableHTTPSessionManager管理会话
  • 支持JSON或原始格式响应(json_response参数控制)
  • 提供生命周期管理(lifespan)确保资源正确释放
  • 所有请求通过/mcp端点处理

适用场景:

  • 需要双向通信的Web应用
  • 需要持久化会话管理的应用--使用有状态的实现方式

三种传输方式对比

特性 stdio模式 SSE模式 可流式HTTP模式
通信方向 双向 服务器→客户端 双向
协议支持 标准输入输出 HTTP/1.1 HTTP/1.1+
实时性
复杂度
适用场景 CLI工具/调试 服务器推送通知 复杂双向通信

最佳实践建议

  1. 开发阶段:建议从stdio模式开始,便于调试和快速验证逻辑

  2. 简单推送场景:选择SSE模式,实现简单且资源消耗低

  3. 复杂交互应用:采用可流式HTTP模式,提供完整的双向通信能力

  4. 性能考量

    • stdio模式性能最高但适用场景有限
    • SSE适合大量客户端连接但只需服务器推送的场景
    • 可流式HTTP提供最灵活的功能但资源消耗相对较高

结语

MCP提供的三种传输方式各具特色,能够满足不同场景下的通信需求。目前小编已经编写好三种方式的demo,大家可以开箱即用啦!觉得不错的话,也帮小编点个star支持一下~

  • 纯净的简易框架

使开发者快速的搭建一个支持mcp协议所有传输方式(STDIO、SSE、StreamableHttp)的mcp server服务框架Enable developers to quickly build an MCP server service framework that supports stdio and sse。使开发者快速的搭建一个支持stdio与sse的mcp server服务框架 - wenb1n-dev/easyMcphttps://github.com/wenb1n-dev/easyMcp

  • 具体实现的案例

mysql的增删改查功能; 还包含了数据库异常分析能力;且便于开发者们进行个性化的工具扩展https://github.com/wenb1n-dev/mysql_mcp_server_pro.git

相关推荐
谷哥的小弟3 分钟前
SQLite MCP服务器安装以及客户端连接配置
服务器·数据库·人工智能·sqlite·大模型·源码·mcp
tyw151 小时前
解决 Trae MySQL MCP 连接失败(Fail to start)
mcp·trae·fail to start·mysql mcp·mcp兼容
谷哥的小弟2 小时前
File System MCP服务器安装以及客户端连接配置
服务器·人工智能·大模型·file system·mcp·ai项目
啊湘21 小时前
vscode 使用 github (适用CURSOR等使用)
ide·vscode·github·cursor·mcp
小小呱呱蛙1 天前
Claude Code 自下而上分析(Slash/Sub Agents/Skills/MCP)带来的启发
agent·claude·mcp
callJJ1 天前
MCP配置与实战:深入理解现代开发工具链
javascript·node.js·vue·mcp·windsurf
谷哥的小弟1 天前
Brave Search MCP服务器安装以及客户端连接配置
搜索引擎·大模型·spring ai·mcp·brave search
太空眼睛1 天前
【MCP】使用SpringBoot基于Streamable-HTTP构建MCP-Client
spring boot·ai·llm·sse·mcp·mcp-client·streamable
kaizq2 天前
AI-MCP-SQLite-SSE本地服务及CherryStudio便捷应用
python·sqlite·llm·sse·mcp·cherry studio·fastmcp
太空眼睛2 天前
【MCP】使用SpringBoot基于Streamable-HTTP构建MCP-Server
spring boot·sse·curl·mcp·mcp-server·spring-ai·streamable