mcp: allow Content-Type parameters in streamable transport (#878)

Use `mime.ParseMediaType` to parse the `Content-Type` header instead of
exact string matching. Previously, the server required an exact match on
`application/json`.

This allows the server to accept `application/json` with parameters
(e.g. `charset=utf-8`), even though [they are not
required](https://datatracker.ietf.org/doc/html/rfc4627.html#section-6),
following the robustness principle.

Per [RFC 8259 (section
8.1)](https://datatracker.ietf.org/doc/html/rfc8259.html#section-8.1),
`application/json` is always UTF-8, so such parameters are technically
redundant. However, parsing the media type makes the server more
tolerant of client behaviour, improving compatibility without
compromising security.
This commit is contained in:
Rafael Dantas Justo 2026-04-03 12:42:20 -03:00 • committed by GitHub
commit 27f29c1cef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -20,6 +20,7 @@ import (
"maps"
"math"
"math/rand/v2"
"mime"
"net"
"net/http"
"slices"
@ -264,8 +265,8 @@ func (h *StreamableHTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Reque
}
// Validate 'Content-Type' header.
if req.Method == http.MethodPost {
contentType := req.Header.Get("Content-Type")
if contentType != "application/json" {
mediaType, _, err := mime.ParseMediaType(req.Header.Get("Content-Type"))
if err != nil || mediaType != "application/json" {
http.Error(w, "Content-Type must be 'application/json'", http.StatusUnsupportedMediaType)
return
}