Streamable HTTP server: Accept and Content-Type are matched case-sensitively and by substring/prefix

已关闭
#1,381 1 条评论 0 个 reaction 已指派 1 人 在 GitHub 查看

维护者通常 3 天内回复

@DaleSeo 已经在做这个了。

开始于 2026年10月20日。

  • #1382 来自 @passionworkeer —— 未关闭

评估

这个 Issue 还没有评估数据。

描述

bug P1 ready for work T-transport

Version: rmcp 3.6.0 (also 3.5.1), transport-streamable-http-server, StreamableHttpService.

What happens

The POST and GET handlers in crates/rmcp/src/transport/streamable_http_server/tower.rs check Accept and Content-Type with raw string matching:

// POST, Accept
header.contains(JSON_MIME_TYPE) && header.contains(EVENT_STREAM_MIME_TYPE)
// POST, Content-Type
header.starts_with(JSON_MIME_TYPE)
// GET, Accept
header.contains(EVENT_STREAM_MIME_TYPE)

That gives these results:

Request Result Expected
Content-Type: Application/JSON 415 accepted
Accept: APPLICATION/JSON, TEXT/EVENT-STREAM 406 accepted
Content-Type: application/jsonx accepted 415
Accept: application/json-seq, text/event-stream accepted 406
Accept: application/json;q=0, text/event-stream accepted 406 (q=0 means "not acceptable")
Accept split across two header lines (application/json and text/event-stream) 406 (only the first value is read) accepted

Expected

RFC 9110 §8.3.1 says the type, subtype and parameter names are case-insensitive. §5.3 allows a list-valued field like Accept to be sent as several field lines, which are equivalent to one comma-joined line. §12.5.1 says q=0 marks a type as not acceptable. Comparing parsed media types would cover all of these. For example: split on , across every Accept value, take the part before ;, trim it, compare with eq_ignore_ascii_case, and skip entries whose q is 0.

Impact

Low. Mainstream clients send lowercase values on a single line, so they work. A proxy or client that normalises header case, or splits Accept into separate lines, gets refused. The prefix and substring matches also let a non-JSON Content-Type through to the JSON deserialiser. That then fails later, with a less useful error.

Repro

curl -i -X POST http://127.0.0.1:8000/mcp \
  -H 'Content-Type: Application/JSON' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
# HTTP/1.1 415 Unsupported Media Type

The check runs before the body is read, so the body and protocol headers don't matter.

AI disclosure: written with Claude Code. I reviewed it.

主要语言
Rust
星标
4.1k
派生
694
平均合并
4 天 9 小时
30 天内合并 PR
41

环境准备

在 Codespaces 中打开

在浏览器里用你自己的 GitHub 账号启动这个项目的开发容器。

  • 没有 Dockerfile 或 Docker Compose 文件
  • 没有 Pull Request 模板
  • 阅读贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

modelcontextprotocol/rust-sdk 的其他 Issue

查看 modelcontextprotocol/rust-sdk 的全部 Issue

相似的 Issue

更多 Rust Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。