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

Chiusa
#1,381 1 commento 0 reazioni 1 assegnatario Vedi su GitHub

I maintainer di solito rispondono entro 3 giorni

@DaleSeo ci sta già lavorando.

Dal 20/10/2026.

  • #1382 di @passionworkeer — aperta

Valutazione

Questa issue non è ancora stata valutata.

Descrizione

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.

Lingua principale
Rust
Stelle
4.1k
Fork
694
Merge medio
4g 9h
PR unite (30g)
41

Preparare l'ambiente

Apri in Codespaces

Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di modelcontextprotocol/rust-sdk

Tutte le issue di modelcontextprotocol/rust-sdk

Issue simili

Altre issue su Rust

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.