modelcontextprotocol / modelcontextprotocol/typescript-sdk
OAuth token exchange crashes on gzip-compressed token response (JSON.parse on undecompressed bytes)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 13.4k
- Forks
- 2.2k
- Avg merge
- 3d 15h
- Merged PRs (30d)
- 4
Description
Summary
When completing the OAuth flow against a server whose /oauth/token-request endpoint returns a gzip-compressed token response, mcp-remote crashes while parsing that response. The raw compressed bytes appear to be passed to JSON.parse without being decompressed first.
Environment
- mcp-remote: 0.1.37 and 0.1.38 (both fail)
- Node: v26.2.0
- OS: Windows 11 Enterprise 23H2 (build 22631.7219)
- Auth server: Snowflake MCP endpoint; /oauth/token-request returns gzip-encoded responses (not on every call)
Error
Authorization error during finishAuth
SyntaxError: Unexpected token '\u001f', "\u001f \b\u0000\u0000\u0000\u0000\u0000\u0000\u0003"... is not valid JSON
at JSON.parse ()
at parseJSONFromBytes (node:internal/deps/undici/undici:4292:19)
at successSteps (node:internal/deps/undici/undici:6907:27)
at readAllBytes (node:internal/deps/undici/undici:5754:13)
The leading bytes 1F 8B 08 00 00 00 00 00 03 are the gzip magic header, confirming the body being parsed is still gzip-compressed.
Diagnosis
- A plain curl to the endpoint returns uncompressed JSON (7B 0A ...), so the server only gzips when the client advertises gzip support.
- Node's own fetch() decompresses correctly: a direct fetch() with Accept-Encoding: gzip, reading arrayBuffer(), returns decompressed JSON (is gzip: false).
- This points to the token-exchange code path reading the raw response body without gzip decompression, rather than a Node bug.
Expected
The token response should be decompressed (or fetch() allowed to handle Content-Encoding) before JSON.parse, so gzip-encoded token responses parse successfully.
Actual
Raw gzip bytes are passed to JSON.parse, throwing SyntaxError and aborting the OAuth flow, so the connection never completes against this endpoint.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the finishAuth OAuth flow and the /oauth/token-request exchange, then trace where the response body reaches JSON.parse. Compare that path with Node fetch() handling of gzip-encoded responses. Done means gzip-compressed token responses are decompressed or handled by fetch before parsing, and the OAuth connection completes successfully.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, typescript
- Domain
- api, authentication
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100