DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

MCP的SSE连接成功,POST却报406:检查endpoint路由

GET事件流成功后,顺着endpoint核对实际POST路径,区分旧SSE路由与Streamable HTTP内容协商。

Java MCP客户端用 GET /sse 建立连接,已经收到HTTP 200和事件流,发送初始化消息时却报:

406 Not Acceptable:
Client must accept both application/json and text/event-stream

先确认406对应哪个请求。旧HTTP+SSE传输与Streamable HTTP的路径、请求头要求不同。GET成功之后的POST如果落到了另一类处理器,报错里的Accept提示就可能把排查带偏。

顺着endpoint事件找到实际POST

旧HTTP+SSE连接通过事件告诉客户端后续发送消息的端点。如果收到的是只含查询参数的地址,例如:

event: endpoint
data: ?sessionId=example-session

需要检查所用客户端把它解析成了什么路径。在一条已核对的Java旧SSE路径中,客户端随后发送 POST /?sessionId=...,进入网关的Streamable HTTP处理器,而没有回到SSE消息端点。

因此同时保留脱敏后的GET路径、endpoint事件、最终POST路径和响应状态。仅看到日志类名包含 SseClientTransport,不能证明后续请求还走SSE路由。也不要公开完整会话ID、认证头或业务消息。

应让服务器公布客户端能够正确解析的消息路径,并核对网关的实际路由。例如服务本身使用 /sse 时,包含路径的 /sse?sessionId=... 比只有查询串更明确。但 /sse 不是所有部署的固定答案:反向代理有公网前缀时,公布地址和客户端解析结果必须对应可访问的外部路径。

Accept要求跟着传输类型检查

旧SSE的GET使用 Accept: text/event-stream,不能仅凭没有 application/json 就把这个GET判为错误。

以2025-11-25的Streamable HTTP规则为例,客户端POST则必须同时接受 application/json 和 text/event-stream,因为请求响应可能采用其中一种。若应用确实使用这种传输,就在正确的MCP端点按其协议设置请求头,而不是继续沿用旧SSE客户端去请求另一处理器。

在前面的错误路由场景中,只补请求头可能让请求进入更深的错误流程,却没有修正消息端点。先把实际POST路由核对清楚,再处理真正适用的内容协商要求。也不要把所有HTTP状态都改写成200,或删除网关的Accept检查来绕过协议。

迁移时把版本与端点一起核对

一条网关兼容改动通过保留请求路径并追加 sessionId 修正了旧SSE端点公布方式;没有核定其首个正式发行版,部署前仍需检查实际包或提交。

SSE路由恢复后,还可能遇到单独的 Unsupported protocol version。如果客户端改用Streamable HTTP,需要确认客户端库确实支持该传输,使用服务器配置的对应端点,并检查协商版本,而不是只改一个URL字段。

2026-07-28又调整了Streamable HTTP,移除了协议层会话与独立GET流端点。本文的endpoint事件与 sessionId 是旧HTTP+SSE路径,不能当成现行协议所有请求的必需步骤。

回查应从同一个客户端完成连接、初始化和一次只读工具列举,观察POST已经到达对应处理器,返回符合协议的响应。若失败请求携带的是早先有效、后来终止的会话ID,并返回404,可以转查旧会话重新初始化。若错误发生在启动或退出的JSON解析,可对照stdio日志分流,不用为这些情况盲目修改HTTP请求头。