Skip to content

Fix Content-Type rejection for application/json; charset=utf-8#2362

Merged
SamMorrowDrums merged 7 commits intomainfrom
fix/content-type-charset-2333
Apr 21, 2026
Merged

Fix Content-Type rejection for application/json; charset=utf-8#2362
SamMorrowDrums merged 7 commits intomainfrom
fix/content-type-charset-2333

Conversation

@IrynaKulakova
Copy link
Copy Markdown
Contributor

Summary

Fixes #2333

The Go SDK's StreamableHTTPHandler performs strict string matching (contentType != "application/json") and rejects requests with Content-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 — New NormalizeContentType middleware that uses mime.ParseMediaType() to parse the Content-Type and strips optional parameters when the media type is application/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 — Wired NormalizeContentType as the first middleware in the chain.
  • pkg/http/handler_test.go — Integration test TestContentTypeHandling verifying 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-8 redundant but valid per HTTP semantics. This middleware is a workaround until the upstream Go SDK is fixed to use proper media type parsing.

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>
Copilot AI review requested due to automatic review settings April 21, 2026 12:00
@IrynaKulakova IrynaKulakova requested a review from a team as a code owner April 21, 2026 12:00
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 NormalizeContentType middleware using mime.ParseMediaType() to strip parameters for application/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

Comment thread pkg/http/middleware/content_type.go Outdated
Comment on lines +21 to +25
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")
}
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +57 to +65
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)
}
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment thread pkg/http/handler_test.go Outdated
IrynaKulakova and others added 2 commits April 21, 2026 14:13
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>
@github-actions
Copy link
Copy Markdown
Contributor

⚠️ License files need updating

The license files are out of date. I tried to fix them automatically but don't have permission to push to this branch.

Please run:

script/licenses
git add third-party-licenses.*.md third-party/
git commit -m "chore: regenerate license files"
git push

Alternatively, enable "Allow edits by maintainers" in the PR settings so I can fix it automatically.

github-actions Bot and others added 2 commits April 21, 2026 12:16
Auto-generated by license-check workflow
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
omgitsads
omgitsads previously approved these changes Apr 21, 2026
SamMorrowDrums
SamMorrowDrums previously approved these changes Apr 21, 2026
@omgitsads
Copy link
Copy Markdown
Member

@copilot can you run a go mod tidy on this to fix the build?

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>
Copilot AI dismissed stale reviews from SamMorrowDrums and omgitsads via 709b07d April 21, 2026 12:41
Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 21, 2026

@copilot can you run a go mod tidy on this to fix the build?

Done — I ran go mod tidy and pushed the update in commit 709b07d (with follow-up cleanup to keep the PR scope minimal).

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:

  • golangci-lint.run
    • Triggering command: /usr/bin/curl curl -sSfL REDACTED (dns block)
    • Triggering command: /usr/bin/curl curl -sSfL REDACTED -tests /tmp/go-build2623875808/b401/vet.cfg 0.1-go1.25.0.lin-p --global ux-amd64/pkg/tool/linux_amd64/vet gpg.program (dns block)
  • raw.ghe.example.com
    • Triggering command: /tmp/go-build2623875808/b366/oauth.test /tmp/go-build2623875808/b366/oauth.test -test.testlogfile=/tmp/go-build2623875808/b366/testlog.txt -test.paniconexit0 -test.timeout=10m0s /tmp/go-build2623875808/b120/vet.cfg ux-amd64/src/runtime/race --global ux-amd64/pkg/tool/linux_amd64/vet commit.gpgsign (dns block)
  • raw.mycompanygithub.com
    • Triggering command: /tmp/go-build2623875808/b404/utils.test /tmp/go-build2623875808/b404/utils.test -test.testlogfile=/tmp/go-build2623875808/b404/testlog.txt -test.paniconexit0 -test.timeout=10m0s EixNmrG1m-grZTIJ3uOU/EixNmrG1m-grZTIJ3uOU -goversion go1.25.0 -c=4 -race -nolocalimports -importcfg /tmp/go-build2623875808/b358/importcfg conf�� 0.1-go1.25.0.lin-p eXsHsJ9DP ux-amd64/pkg/tool/linux_amd64/vet commit.gpgsign (dns block)
  • raw.myghe.com
    • Triggering command: /tmp/go-build2623875808/b404/utils.test /tmp/go-build2623875808/b404/utils.test -test.testlogfile=/tmp/go-build2623875808/b404/testlog.txt -test.paniconexit0 -test.timeout=10m0s EixNmrG1m-grZTIJ3uOU/EixNmrG1m-grZTIJ3uOU -goversion go1.25.0 -c=4 -race -nolocalimports -importcfg /tmp/go-build2623875808/b358/importcfg conf�� 0.1-go1.25.0.lin-p eXsHsJ9DP ux-amd64/pkg/tool/linux_amd64/vet commit.gpgsign (dns block)
  • raw.notgithub.com
    • Triggering command: /tmp/go-build2623875808/b404/utils.test /tmp/go-build2623875808/b404/utils.test -test.testlogfile=/tmp/go-build2623875808/b404/testlog.txt -test.paniconexit0 -test.timeout=10m0s EixNmrG1m-grZTIJ3uOU/EixNmrG1m-grZTIJ3uOU -goversion go1.25.0 -c=4 -race -nolocalimports -importcfg /tmp/go-build2623875808/b358/importcfg conf�� 0.1-go1.25.0.lin-p eXsHsJ9DP ux-amd64/pkg/tool/linux_amd64/vet commit.gpgsign (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI requested a review from omgitsads April 21, 2026 12:44
@SamMorrowDrums SamMorrowDrums merged commit 7fd6a92 into main Apr 21, 2026
18 checks passed
@SamMorrowDrums SamMorrowDrums deleted the fix/content-type-charset-2333 branch April 21, 2026 12:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

'Content-Type must be 'application/json' - when setting charset

5 participants