Skip to content

fix(mcpproxy): match application/json ignoring charset parameter - #2636

Open
chiliec wants to merge 3 commits into
theagentrouter:mainfrom
chiliec:fix-mcp-json-content-type-charset
Open

chiliec wants to merge 3 commits into
theagentrouter:mainfrom
chiliec:fix-mcp-json-content-type-charset

Conversation

@chiliec

@chiliec chiliec commented Sep 6, 2026

Copy link
Copy Markdown

Description

The MCP proxy's per-backend response collector (session.go) and the response proxy (handlers.go) decided whether to parse a backend response as JSON via an exact string comparison on the Content-Type header (== "application/json").

A backend responding with Content-Type: application/json;charset=UTF-8 — the servlet-container default emitted by the official MCP Java SDK's servlet transports (HttpServletStatelessServerTransport, which does setContentType("application/json") + setCharacterEncoding("UTF-8")) — failed that check. The body fell through to the SSE parser, which found no data: lines and yielded zero events and zero errors, so the backend's tools/list response was silently discarded (connected-but-toolless, nothing logged).

This parses the media type with mime.ParseMediaType and matches on the application/json media type, ignoring parameters like charset (per RFC 9110 §8.3; charset is meaningless for application/json per RFC 8259 §8.1). A small shared isJSONContentType helper replaces the three exact-match sites in the package (sendRequestPerBackend, copyProxyHeaders, proxyResponseBody).

Related Issues/PRs (if applicable)

Fixes #2568

Special notes for reviewers (if applicable)

Added a regression test TestSendRequestPerBackend_JSONContentTypeWithCharset mirroring the existing TestSendRequestPerBackend_BOMPrefixedJSON, using a backend that returns application/json;charset=UTF-8.

Verification (Go 1.26.6, go test ./internal/mcpproxy/):

  • New test passes with the fix.
  • RED→GREEN confirmed: reverting the session.go dispatch back to the exact string match makes the new test fail with Diff: -message / + (0 events collected); restoring the fix makes it pass.
  • Full internal/mcpproxy package suite green (ok ... 2.980s), go vet and gofmt -l clean on the touched files.

AI-assisted; all results above are from real local runs. Happy to adjust.

The per-backend response collector and the response proxy decided whether
to parse a backend response as JSON via an exact string comparison on the
Content-Type header. A backend responding with application/json;charset=UTF-8
(the servlet-container default emitted by the MCP Java SDK's servlet
transports) failed that check, fell through to the SSE parser, and produced
zero events with no error, so its tools/list response was silently dropped.

Parse the media type with mime.ParseMediaType and match on application/json,
ignoring parameters such as charset.

Signed-off-by: Vladimir Babin <vovababin@gmail.com>
@chiliec
chiliec requested a review from a team as a code owner September 6, 2026 15:42

@nacx nacx left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This fix was already added in #2587, now merged. We can keep the PR for the additional test, but in htat case, mind deleting the now duplicate isJSONContentType method?

…entrouter#2587

The charset-tolerant Content-Type match landed in theagentrouter#2587, which added
isJSONContentType in sse.go. Remove the duplicate implementation (and the
now-unused mime import) from session.go per review; the additive
regression test (JSON response with charset=UTF-8 yields one decoded
event) is kept and now exercises the shared helper.

Signed-off-by: chiliec <vovababin@gmail.com>
@chiliec

chiliec commented Sep 7, 2026

Copy link
Copy Markdown
Author

Thanks — you're right, #2587 already covers the charset-tolerant match. I've deleted the now-duplicate isJSONContentType (and the unused mime import) from session.go in 3347470, so the package uses the single implementation from sse.go.

Kept the additive regression test (TestSendRequestPerBackend_JSONContentTypeWithCharset) — it asserts that a backend response with Content-Type: application/json;charset=UTF-8 is decoded into one event end-to-end through sendRequestPerBackend, which complements the unit-level TestIsJSONContentType. go build/go vet/go test ./internal/mcpproxy/ pass locally.

@Hritik003

Copy link
Copy Markdown
Contributor

lgtm

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.

MCP proxy silently drops backend JSON responses when Content-Type carries a charset parameter (exact string match in session.go)

3 participants