深入理解 MCP 的三种传输方式

引言

MCP (Model Context Protocol) 是一个用于 AI 模型与外部工具通信的协议。很多开发者在接触 MCP 时,常常对其传输方式感到困惑:为什么有的配置是一个命令行,有的是一个 HTTP 地址?今天我们就来深入探讨 MCP 的三种传输方式及其区别。

MCP 的三种传输方式

MCP 目前支持三种传输方式:

  1. stdio (Standard Input/Output) - 标准输入输出
  2. SSE (Server-Sent Events) - 服务器推送事件(已弃用)
  3. Streamable HTTP - 流式 HTTP(推荐)

1. stdio:进程间通信

工作原理

stdio 是最常用的本地集成方式。它的核心特点是:客户端负责启动服务器进程,而不是连接到一个已经运行的进程。

perl 复制代码
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user"],
      "transport": "stdio"
    }
  }
}

通信流程

c 复制代码
┌─────────────┐
│   客户端     │
│  (Claude等)  │
└──────┬──────┘
       │
       │ 1. 执行命令启动子进程
       ▼
┌─────────────┐
│  MCP Server  │
│  (子进程)    │
└──────┬──────┘
       │
       │ 2. 建立 stdin/stdout 管道
       │
    ┌──┴──┐
    │stdin│ ← 客户端写入请求
    │stdout│ → 服务器返回响应
    └─────┘

消息交换示例

css 复制代码
// 客户端侧
cmd := exec.Command("node", "/path/to/server.js")
stdin, _ := cmd.StdinPipe()
stdout, _ := cmd.StdoutPipe()
cmd.Start()

// 发送请求
stdin.Write([]byte(`{"jsonrpc":"2.0","method":"tools/list","id":1}\n`))

// 读取响应
scanner := bufio.NewScanner(stdout)
scanner.Scan()
response := scanner.Text()
css 复制代码
// 服务器侧
func main() {
    server := mcp.NewServer(...)
    
    // 从 stdin 读取
    scanner := bufio.NewScanner(os.Stdin)
    for scanner.Scan() {
        message := scanner.Text()
        response := server.Handle(message)
        // 通过 stdout 返回
        fmt.Println(response)
    }
}

优缺点

优点:

  • ✅ 不需要网络端口,更安全
  • ✅ 自动生命周期管理(客户端退出时服务器也退出)
  • ✅ 配置简单,适合本地工具

缺点:

  • ❌ 只能本地使用,无法远程访问
  • ❌ 每个客户端需要独立的服务器进程

2. SSE:服务器推送事件(已弃用)

SSE 是早期的 HTTP 传输方式,从 2024-11-05 版本开始已被弃用,但为了向后兼容仍被支持。

架构特点

SSE 方式需要两个独立的端点

arduino 复制代码
// 需要两个处理器
router.GET("/sse", handleSSE)       // 服务器推送
router.POST("/message", handleMsg)  // 客户端发送

通信模式

bash 复制代码
客户端 → 服务器:POST /message (发送请求)
服务器 → 客户端:GET /sse (长连接接收推送)

客户端需要同时维护两个连接:

  • 一个用于发送消息
  • 一个用于接收服务器推送

配置示例

json 复制代码
{
  "url": "http://localhost:3000/sse",
  "messageEndpoint": "http://localhost:3000/message",
  "transport": "sse"
}

3. Streamable HTTP:现代化的统一方案(推荐)

Streamable HTTP 是在 2025 年 3 月引入的新传输方法,它简化了 SSE 的复杂性。

核心改进

只需要一个统一的端点,处理所有通信:

go 复制代码
mcpHandler := mcp.NewStreamableHTTPHandler(
    func(r *http.Request) *mcp.Server {
        return appServer.mcpServer
    },
    &mcp.StreamableHTTPOptions{
        JSONResponse: true,  // 支持 JSON 响应
    },
)

// 单一端点处理所有请求
router.Any("/mcp", gin.WrapH(mcpHandler))
router.Any("/mcp/*path", gin.WrapH(mcpHandler))

灵活的响应方式

Streamable HTTP 支持两种响应模式:

  1. 同步 JSON 响应:适合简单的请求-响应
bash 复制代码
POST /mcp
↓
立即返回 JSON 响应
  1. 异步 SSE 流:适合需要持续推送的场景
bash 复制代码
POST /mcp
↓
返回 SSE 流,持续推送消息

配置示例

json 复制代码
{
  "url": "http://localhost:8080/mcp",
  "transport": "http"
}

优势总结

  • ✅ 单一端点,架构简洁
  • ✅ 灵活的响应方式(JSON + SSE)
  • ✅ 内置会话管理和连接恢复
  • ✅ 符合最新规范,推荐使用

三种方式对比

特性 stdio SSE(已弃用) Streamable HTTP
端点数量 N/A 2个独立端点 1个统一端点
通信方式 进程间通信 HTTP 双端点 HTTP 单端点
部署位置 本地 远程 远程
会话管理 自动 复杂 内置支持
响应灵活性 N/A 仅 SSE JSON + SSE
配置复杂度 简单 中等 简单
使用场景 本地工具、插件 遗留系统 现代 Web 服务
状态 ✅ 推荐 ⚠️ 已弃用 ✅ 推荐

实际应用场景

场景 1:本地 AI 助手插件

推荐使用 stdio

perl 复制代码
{
  "mcpServers": {
    "file-system": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"],
      "transport": "stdio"
    },
    "git": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-git"],
      "transport": "stdio"
    }
  }
}

原因:

  • 本地运行,无需网络
  • 自动生命周期管理
  • 安全性高

场景 2:团队共享的远程服务

推荐使用 Streamable HTTP

go 复制代码
func main() {
    mcpServer := mcp.NewServer(...)
    
    mcpHandler := mcp.NewStreamableHTTPHandler(
        func(r *http.Request) *mcp.Server {
            return mcpServer
        },
        &mcp.StreamableHTTPOptions{
            JSONResponse: true,
        },
    )
    
    http.Handle("/mcp", mcpHandler)
    http.ListenAndServe(":8080", nil)
}

客户端配置:

json 复制代码
{
  "url": "https://mcp.example.com/mcp",
  "transport": "http"
}

原因:

  • 多用户共享
  • 可远程访问
  • 统一管理和部署

场景 3:维护遗留系统

可能需要支持 SSE

如果你的系统已经使用了 SSE 方式,可以继续使用以保持兼容性,但建议逐步迁移到 Streamable HTTP。

最佳实践建议

  1. 新项目优先选择

    • 本地工具 → stdio
    • 远程服务 → Streamable HTTP
  2. 安全考虑

    • stdio 天然安全(本地通信)
    • HTTP 方式需要添加认证和加密(HTTPS)
  3. 性能优化

    • stdio 性能最佳(无网络开销)
    • HTTP 方式适合低频调用场景
  4. 错误处理

    c 复制代码
    // stdio 方式
    if err := cmd.Start(); err != nil {
        log.Fatal("Failed to start MCP server:", err)
    }
    
    // HTTP 方式
    if resp.StatusCode != 200 {
        log.Error("MCP request failed:", resp.Status)
    }

结语

MCP 的三种传输方式各有特点,选择合适的传输方式能够让你的应用更加高效和可靠:

  • stdio:本地工具的最佳选择,简单安全
  • SSE:已弃用,仅用于兼容旧系统
  • Streamable HTTP:现代远程服务的标准方案

参考资源:

相关推荐
深空数字孪生6 小时前
从代码实现到概念创新:AIGC如何重塑数据可视化的价值链条?
信息可视化·aigc
猫头虎6 小时前
OpenAI发布构建AI智能体的实践指南:实用框架、设计模式与最佳实践解析
人工智能·设计模式·开源·aigc·交互·pip·ai-native
Mintopia6 小时前
⚡ AI 时代,全栈 Next.js 开发的激情在哪里?
前端·aigc·全栈
货拉拉技术7 小时前
网关 MCP 转换技术:从实现到平台落地
java·架构·mcp
DisonTangor7 小时前
Lumina-DiMOO:用于多模态生成与理解的全扩散大语言模型
人工智能·语言模型·自然语言处理·ai作画·aigc
Mintopia8 小时前
🌌 知识图谱与 AIGC 融合:
前端·javascript·aigc
用户5191495848458 小时前
在VS Code IDE中通过LocalStack集成加速无服务器测试
人工智能·aigc
leafff1239 小时前
Stable Diffusion进行AIGC创作时的算力优化方案
人工智能·stable diffusion·aigc
墨风如雪19 小时前
Karpathy的nanochat:百元就能造ChatGPT?AI圈炸锅了!
aigc