Spring AI 集成 MCP 服务踩坑实录:SSE 与 Streamable HTTP 协议的兼容性深度剖析

摘要: 在使用 Spring AI 集成 Model Context Protocol (MCP) 服务时,开发者常遇到 404 Not Found 错误。本文通过分析 MCP 协议从 2024 版本(SSE)到 2025 版本(Streamable HTTP)的演进,结合 LangChain4j 的源码差异,详细解释了为何直接升级传输层会导致报错,并给出了适用于 Spring AI 框架的最佳实践方案。


1. 引言:背景与问题

随着 AI 应用的复杂化,MCP(Model Context Protocol)成为了连接 LLM 和外部工具的标准。在 Java 生态中,我们通常使用 LangChain4jSpring AI 来构建客户端。

最近在尝试对接一个 MCP 服务端时,我遇到了一个典型的报错:

java 复制代码
java.lang.RuntimeException: Unexpected status code: 404
    at dev.langchain4j.mcp.client.transport.http.StreamableHttpMcpTransport.lambda$execute$0(StreamableHttpMcpTransport.java:209)

明明旧的代码能跑通,为什么换成新的 StreamableHttpMcpTransport 就报 404?这背后其实是 MCP 协议版本迭代带来的"代沟"。

2. 协议演进:从 SSE 到 Streamable HTTP

为了理解这个问题,我查阅了 MCP 官方文档的历史版本,对比了 2024-11-05 (旧版)和 2025-03-26(新版)的核心差异。

2.1 传输机制的根本变革
特性 2024-11-05 (旧版) 2025-03-26 (新版)
核心协议 HTTP + SSE (Server-Sent Events) Streamable HTTP
通信模式 双工模式:GET 建立 SSE 长连接 + POST 发送指令 单一端点:统一通过 POST 交互,可选 GET 流式响应
端点数量 通常需要两个端点(如 /sse/post 仅需一个 MCP Endpoint (如 /mcp
Spring AI 支持 ✅ 原生支持 ❌ 暂不支持(截至 2026 年初)

深度解析:

  • 旧版 (SSE) :客户端发送 GET /sse 建立一个"听筒",服务端通过这个连接推送消息;客户端发送 POST 到另一个地址(如 /message)来发送指令。
  • 新版 (Streamable) :废弃了 SSE。客户端直接向 POST /mcp 发送所有请求。如果需要流式响应,服务端会返回 Content-Type: text/event-stream
2.2 为什么会出现 404?

当你在代码中使用:

java 复制代码
McpTransport transport = StreamableHttpMcpTransport.builder()
        .url("http://127.0.0.1:3000/sse") // 错误!
        .build();

你的意图是使用 新版客户端 去连接 旧版服务端

  • 新版客户端 会向 http://127.0.0.1:3000/sse 发送一个 POST 请求。
  • 旧版服务端/sse 路径只接受 GET 请求(用来建立长连接),根本不认识 POST
  • 结果:服务端懵了,返回 404 Not Found

3. Spring AI 与 LangChain4j 的现状分析

3.1 Spring AI 的兼容性

截至目前,Spring AI 框架主要基于旧版的 LangChain4j 实现 ,其底层逻辑完全遵循 2024-11-05 (SSE) 规范。

这意味着,如果你在 Spring Boot 项目中配置 MCP:

yaml 复制代码
spring:
  ai:
    mcp:
      clients:
        my-client:
          transport: http
          http:
            sse-url: http://127.0.0.1:3000/sse # 必须指向 SSE 端点

你必须确保后端服务支持旧版的 SSE 协议。强行在配置中填入 Streamable 的参数是无效的,因为框架底层并没有实现新版的握手逻辑。

3.2 LangChain4j 的过渡期

LangChain4j 1.0 版本为了兼容未来,引入了 StreamableHttpMcpTransport。但这并不意味着它能自动适配所有服务端。这是一个"非此即彼"的选择:

  • 服务端是旧版 →\rightarrow→ 客户端必须用 HttpMcpTransport (SSE模式)。
  • 服务端是新版 →\rightarrow→ 客户端必须用 StreamableHttpMcpTransport

4. 解决方案与最佳实践

针对目前的开发环境,我建议采取以下策略:

4.1 方案一:拥抱现状(推荐)

既然 Spring AI 和大部分现有工具链都还在使用旧版协议,我们就不要强行"升级"传输层。

保持旧代码:

java 复制代码
McpTransport transport = new HttpMcpTransport.Builder()
        .sseUrl("http://127.0.0.1:3000/sse") // 指向服务端的 SSE 入口
        .build();

服务端要求: 确保你的 MCP 服务端(如 Python 的 FastMCP)开启了 transport="sse" 或兼容模式。

4.2 方案二:纯 Java 项目升级指南

如果你不使用 Spring AI,而是纯 LangChain4j 项目,并且你确定服务端已经升级到了 2025-03-26 协议:

  1. 服务端 :必须监听单一的 POST 端点(通常是 /mcp),不再区分 SSE。

  2. 客户端 :修改 URL 为 /mcp

    java 复制代码
    McpTransport transport = StreamableHttpMcpTransport.builder()
            .url("http://127.0.0.1:3000/mcp") // 注意路径变了
            .build();

5. 总结

MCP 协议的演进是为了简化流式传输,但在过渡期给开发者带来了不小的困扰。

核心结论:

  1. 不要混用:新版客户端不能连旧版服务端,反之亦然。
  2. Spring AI 用户 :请继续使用 .sseUrl() 配置,目前的 Spring AI 版本尚未适配 Streamable HTTP。
  3. 404 报错的本质:是 HTTP Method 不匹配(客户端发 POST,服务端只听 GET)。

希望这篇文章能帮你少走弯路!如果你也在研究 MCP,欢迎在评论区交流。

相关推荐
weixin_156241575761 天前
基于YOLO深度学习的动物检测与识别系统
人工智能·深度学习·yolo
水如烟1 天前
孤能子视角:“人+AI“孤能子,跨物种自指闭环?以及医学人机接口BMI
人工智能
IT_陈寒1 天前
Python的asyncio把我整不会了,原来问题出在这儿
前端·人工智能·后端
Database_Cool_1 天前
Tair 短期记忆架构实践:淘宝闪购 AI Agent 的秒级响应记忆系统
人工智能·架构
叶舟1 天前
LYT-NET:一个超级轻量的低光照图像增强Transformer网络
人工智能·深度学习·transformer·llie·低光照图像增强
乾元1 天前
《硅基之盾》番外篇二:算力底座的暗战——智算中心 VXLAN/EVPN 架构下的多租户隔离与防御
网络·人工智能·网络安全·架构
ALL_IN_AI1 天前
本地部署 Ollama 大模型:零成本开启 AI 开发之旅
人工智能
木心术11 天前
设备管理网管系统:详细下一步行动指南
前端·人工智能·opencv
小白狮ww1 天前
Qwen3.5-27B-Claude-4.6-Opus-Reasoning-Distilled 蒸馏模型,27B 参数也能做强推理
人工智能·自然语言处理·claude·通义千问·opus·推理·qwen3.5