Fix Content-Type rejection for application/json; charset=utf-8#2362
Fix Content-Type rejection for application/json; charset=utf-8#2362SamMorrowDrums merged 7 commits intomainfrom
Conversation
Add NormalizeContentType middleware that strips optional parameters (e.g. charset=utf-8) from application/json Content-Type headers before the request reaches the Go SDK's StreamableHTTP handler, which performs strict string matching. Per RFC 8259, the charset parameter is redundant for JSON but must be accepted per HTTP semantics. Fixes #2333 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR fixes interoperability issues in HTTP mode by normalizing Content-Type: application/json; charset=utf-8 to application/json before requests reach the Go MCP SDK’s strict StreamableHTTPHandler Content-Type check (fixes #2333).
Changes:
- Added
NormalizeContentTypemiddleware usingmime.ParseMediaType()to strip parameters forapplication/json. - Wired the new middleware as the first middleware in the HTTP handler chain.
- Added unit + integration tests covering parameterized JSON Content-Types and rejection of unsupported/missing Content-Type.
Show a summary per file
| File | Description |
|---|---|
| pkg/http/middleware/content_type.go | Adds Content-Type normalization middleware for JSON requests. |
| pkg/http/middleware/content_type_test.go | Unit tests validating normalization behavior across several Content-Type variants. |
| pkg/http/handler.go | Registers NormalizeContentType first in the middleware chain so the SDK sees normalized headers. |
| pkg/http/handler_test.go | Integration test to ensure parameterized JSON Content-Types don’t trigger 415 from the StreamableHTTP handler. |
Copilot's findings
- Files reviewed: 4/4 changed files
- Comments generated: 3
| if ct := r.Header.Get("Content-Type"); ct != "" { | ||
| mediaType, _, err := mime.ParseMediaType(ct) | ||
| if err == nil && mediaType == "application/json" { | ||
| r.Header.Set("Content-Type", "application/json") | ||
| } |
There was a problem hiding this comment.
NormalizeContentType hard-codes both the header name and the JSON media type string. Since pkg/http/headers already defines ContentTypeHeader and ContentTypeJSON constants, using them here would avoid duplication/typos and keep header handling consistent across the HTTP stack.
| inner := http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { | ||
| capturedCT = r.Header.Get("Content-Type") | ||
| }) | ||
|
|
||
| handler := NormalizeContentType(inner) | ||
| req := httptest.NewRequest(http.MethodPost, "/", nil) | ||
| if tt.inputCT != "" { | ||
| req.Header.Set("Content-Type", tt.inputCT) | ||
| } |
There was a problem hiding this comment.
This test uses raw string literals for the Content-Type header name and expected JSON content type. Consider switching to pkg/http/headers.ContentTypeHeader and headers.ContentTypeJSON to keep tests aligned with the shared header constants and reduce the chance of typos if values ever change.
Upgrades github.com/modelcontextprotocol/go-sdk from v1.5.0 to v1.5.1-0.20260403154220-27f29c1cef3b which includes proper media type parsing for Content-Type headers, fixing the strict string matching that rejected application/json; charset=utf-8. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The go-sdk bump (27f29c1) includes the proper fix upstream, making the middleware unnecessary. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Auto-generated by license-check workflow
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
@copilot can you run a |
Agent-Logs-Url: https://github.com/github/github-mcp-server/sessions/49811f97-33b0-476c-8811-419dee2a5318 Co-authored-by: omgitsads <4619+omgitsads@users.noreply.github.com>
709b07d
Agent-Logs-Url: https://github.com/github/github-mcp-server/sessions/49811f97-33b0-476c-8811-419dee2a5318 Co-authored-by: omgitsads <4619+omgitsads@users.noreply.github.com>
Done — I ran Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
Summary
Fixes #2333
The Go SDK's
StreamableHTTPHandlerperforms strict string matching (contentType != "application/json") and rejects requests withContent-Type: application/json; charset=utf-8. This breaks clients like the C# MCP SDK which include charset by default.Changes
pkg/http/middleware/content_type.go— NewNormalizeContentTypemiddleware that usesmime.ParseMediaType()to parse the Content-Type and strips optional parameters when the media type isapplication/json, before the request reaches the Go SDK handler.pkg/http/middleware/content_type_test.go— Unit tests for the middleware (7 cases).pkg/http/handler.go— WiredNormalizeContentTypeas the first middleware in the chain.pkg/http/handler_test.go— Integration testTestContentTypeHandlingverifying various Content-Type values through the full handler (5 cases).Notes
Per RFC 8259, JSON text MUST be encoded as UTF-8, making
charset=utf-8redundant but valid per HTTP semantics. This middleware is a workaround until the upstream Go SDK is fixed to use proper media type parsing.