Skip to content

fix: prevent dual Content-Type header in OAuth token requests#1122

Open
peschee wants to merge 1 commit intomodelcontextprotocol:mainfrom
peschee:fix/oauth-direct-dual-content-type
Open

fix: prevent dual Content-Type header in OAuth token requests#1122
peschee wants to merge 1 commit intomodelcontextprotocol:mainfrom
peschee:fix/oauth-direct-dual-content-type

Conversation

@peschee
Copy link

@peschee peschee commented Feb 27, 2026

Summary

  • Bug: OAuth token exchange requests sent to authorization servers (e.g. Keycloak) were rejected with Failed to parse media type application/json, application/x-www-form-urlencoded when using direct SSE or Streamable HTTP transports.
  • Root cause: The custom fetch wrappers for direct transports were setting default Content-Type: application/json and Accept: application/json, text/event-stream headers. When the SDK's OAuth layer issued token requests with Content-Type: application/x-www-form-urlencoded, the headers were merged, producing a malformed dual Content-Type value.
  • Fix: Move default accept/content-type headers out of the fetch wrapper and into requestInit.headers with lowercase keys. Simplify the custom fetch to a pass-through. The SDK's createFetchWithInit merges defaults with per-request headers (per-request wins), so OAuth token requests now correctly use application/x-www-form-urlencoded.

Test plan

  • npm run build-client passes
  • cd client && npm run lint passes
  • Manual test: connect to a Keycloak-protected MCP server using direct SSE or Streamable HTTP — OAuth token exchange should succeed without Content-Type errors

…ect connections

The custom fetch wrappers for direct SSE and Streamable HTTP transports
were overwriting or conflicting with headers set by the SDK's OAuth
token requests. This caused authorization servers (e.g. Keycloak) to
reject token exchanges with "Failed to parse media type application/json,
application/x-www-form-urlencoded".

Move default accept/content-type headers out of the fetch wrapper and
into requestInit.headers with lowercase keys, and simplify the custom
fetch to a pass-through. The SDK's createFetchWithInit merges defaults
with per-request headers (per-request wins), so OAuth token requests
now correctly use application/x-www-form-urlencoded.
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.

1 participant