起因上个月我写了第一个 MCP Server,跑通了 stdio 传输,觉得自己已经入门了。然后我踩了个坑:把 stdio 模式的 server 部署到服务器上,对着终端发愣——stdio 要求 client 和 server 在同一个进程里,我的编辑器在本地,server 在远程,完全不配套。查了一圈才知道,MCP 不是只有 stdio 一种传输方式。2026 年的生态里,传输层已经分出了两条路:一条是本地开发用的 stdio,一条是生产部署用的 Streamable HTTP。这篇文章是我从 stdio 迁移到 HTTP 的全部记录,该踩的坑一个没少。## stdio:入门友好,生产痛苦MCP 最早只有 stdio 传输。它的设计很简单:client 启动一个 server 子进程,通过 stdin/stdout 交换 JSON-RPC 消息。// 从 client 发给 server 的典型请求

{“jsonrpc”: “2.0”, “id”: 1, “method”: “tools/call”, “params”: {“name”: “get_weather”, “arguments”: {“city”: “北京”}}}跑第一个 server 时觉得这设计挺优雅——不用管端口、认证、跨域,两个进程间管道通信,延迟极低(微秒级)。我原来写 Server 的工具查询方法,伪代码大概是这样:async def handle_request(request):
if request.method == “tools/list”:
return {“tools”: […]}
elif request.method == “tools/call”:
return await execute_tool(request.params)
# 读取 stdin 解析请求
line = await stdin.readline()
request = json.loads(line)
response = await handle_request(request)
# 写到 stdout
stdout.write(json.dumps(response) + “\n”)这里踩了个坑:stdout 默认有缓冲,不 flush 的话 server 和 client 会死锁——你等我我先等你。加了一行 sys.stdout.flush() 才正常。### stdio 的天花板跑通之后很快发现了 stdio 的限制:- 不能远程。client 和 server 必须在同一台机器上。想在服务器上部署一个 MCP Server 给团队的编辑器用?stdio 做不到。

  • 进程绑定。一个 server 进程只能服务一个 client。每个编辑器窗口都得单独起一个 server 进程,资源浪费严重。
  • 没有标准日志。server 的 print 输出走 stdout——但 stdout 已经被 MCP 协议占用了。调试时日志和协议数据混在一起。## 转向 Streamable HTTPStreamable HTTP 是 2026 年初 MCP 规范引入的新传输方式。它把 MCP 从本地进程通信提升到了网络协议层面。核心区别其实就一句话:把 stdin/stdout 换成了 HTTP POST + SSE(Server-Sent Events)。# Streamable HTTP 模式下,server 端的核心逻辑
    from fastapi import FastAPI
    from sse_starlette.sse import EventSourceResponseapp = FastAPI()@app.post(“/mcp”)
    async def handle_mcp(request: dict):
    “”"
    接收 MCP 请求,返回响应。
    如果是流式请求(如 tools/call 有进度),走 SSE。
    “”"
    method = request.get(“method”)
    if method == “tools/list”:
    return {“tools”: […]}
    elif method == “tools/call”:
    # 异步执行,通过 SSE 推送进度
    async def event_stream():
    yield {“event”: “progress”, “data”: “50%”}
    result = await execute_tool(request[“params”])
    yield {“event”: “result”, “data”: result}
    return EventSourceResponse(event_stream())
docker build -t my-mcp-server .
docker run -d -p 8080:8080 my-mcp-server# 任意 client 连接
# curl 就能调用 MCP 工具
curl -X POST http://server:8080/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"search_docs","arguments":{"query":"MCP传输"}}}'
```### 迁移过程中踩的坑- **第一个坑:SSE 重连。** MCP Server 走 SSE 推送流式结果时,如果网络闪断,Client 不会自动重连。我的工具调用到一半断了,Client 端永远等不到结果。修复方式是在 Server 端加超时机制(我设了 30 秒),超时后主动断开让 Client 重试。
- **第二个坑:认证。** stdio 模式下不需要认证(管道是安全的),HTTP 模式下必须考虑谁可以调用你的 Server。MCP 规范没规定认证方式,社区做法是在 HTTP 头里带 API Key 或 JWT:
  ```python
  from fastapi import Depends, HTTPException, Header
  
  async def verify_token(authorization: str = Header(None)):
      if not authorization or not authorization.startswith("Bearer "):
          raise HTTPException(status_code=401)
      # 验证 token
  • 第三个坑:长连接超时。 一些反向代理(Nginx、Cloudflare)默认 60 秒就会断开空闲连接。MCP 的 SSE 流可能持续几分钟。需要在代理配置里加长超时或启用 WebSocket 模式。## 本地用 stdio,生产用 HTTP跑完一轮迁移后,我觉得 MCP 社区说的"stdio for development, HTTP for production"是对的,但不是全部。我的推荐:本地开发、单机使用 → stdio

  • 毫秒级延迟,没有网络开销

  • 不需要配端口、认证、HTTPS

  • 适合个人编辑器插件团队协作、远程调用、CI/CD → Streamable HTTP

  • Server 可以集中部署,团队共用

  • 支持鉴权、限流、日志监控

  • Docker/K8s 部署,运维友好极端场景 → 两个都用

  • 开发时走 stdio(热重载方便),部署后走 HTTP

  • 写一个 adapter 层,根据环境切换传输协议class MCPTransport:
    “”“根据配置选择 stdio 或 HTTP 传输”“”
    def init(self, config):
    if config.transport == “stdio”:
    self._impl = StdioTransport(config)
    elif config.transport == “http”:
    self._impl = HTTPTransport(config)

    async def send(self, request):
    return await self._impl.send(request)这个 adapter 码了大概 80 行,但之后切换传输方式只需要改配置文件的一个字段,不用改业务代码。## 效果迁移到 Streamable HTTP 后,我的 MCP Server 从"只能在自己电脑上用"变成了"团队的 DevOps 工具链"。三个同事同时在编辑器里连同一个 Server,每人调不同的工具,互不干扰。部署上最大的变化是能用 Docker Compose 管理了:version: ‘3’
    services:
    mcp-server:
    build: .
    ports:
    - “8080:8080”
    environment:
    - MCP_TRANSPORT=http
    - API_KEYS=key1,key2,key3
    restart: unless-stopped一个 docker-compose up 就上线了,比当初折腾 stdio 缓冲问题愉快太多。话说回来,如果只是自己写个小工具本地用,stdio 完全够用,没必要上 HTTP。选择什么传输方式,取决于你的 Server 要给多少人用、在哪里用。MCP 协议的好处是传输层是可替换的——选错了随时能换。

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐