From 521bbc81d8c783f6fdb77fa94b1408e534d76218 Mon Sep 17 00:00:00 2001 From: Christopher Tso Date: Sun, 28 Dec 2025 12:48:57 +1100 Subject: [PATCH 1/3] fix: handle OAuth error responses returned with HTTP 200 status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some OAuth servers (e.g., GitHub) return error responses with HTTP 200 status instead of 4xx. The SDK now checks for an `error` field in the JSON response before attempting to parse it as tokens. This provides users with meaningful error messages like: "The client_id and/or client_secret passed are incorrect." Instead of confusing Zod validation errors about missing access_token. Fixes #1342 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- packages/client/src/client/auth.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/client/src/client/auth.ts b/packages/client/src/client/auth.ts index 93048e4b3..52cda173e 100644 --- a/packages/client/src/client/auth.ts +++ b/packages/client/src/client/auth.ts @@ -1086,7 +1086,15 @@ async function executeTokenRequest( throw await parseErrorResponse(response); } - return OAuthTokensSchema.parse(await response.json()); + const json = await response.json(); + + // Some OAuth servers (e.g., GitHub) return error responses with HTTP 200 status. + // Check for error field before attempting to parse as tokens. + if (json.error) { + throw await parseErrorResponse(JSON.stringify(json)); + } + + return OAuthTokensSchema.parse(json); } /** From b8fdf1010b9e3092b299dfea7a5113539170ade2 Mon Sep 17 00:00:00 2001 From: Christopher Tso Date: Sun, 28 Dec 2025 12:56:34 +1100 Subject: [PATCH 2/3] fix: add type safety and changeset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix TypeScript error by properly typing json as unknown - Add changeset for the patch release Fixes #1342 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .changeset/oauth-error-http200.md | 7 +++++++ packages/client/src/client/auth.ts | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 .changeset/oauth-error-http200.md diff --git a/.changeset/oauth-error-http200.md b/.changeset/oauth-error-http200.md new file mode 100644 index 000000000..1ce4fdd9e --- /dev/null +++ b/.changeset/oauth-error-http200.md @@ -0,0 +1,7 @@ +--- +'@modelcontextprotocol/client': patch +--- + +Fix OAuth error handling for servers returning errors with HTTP 200 status + +Some OAuth servers (e.g., GitHub) return error responses with HTTP 200 status instead of 4xx. The SDK now checks for an `error` field in the JSON response before attempting to parse it as tokens, providing users with meaningful error messages. diff --git a/packages/client/src/client/auth.ts b/packages/client/src/client/auth.ts index 52cda173e..4f0e6a727 100644 --- a/packages/client/src/client/auth.ts +++ b/packages/client/src/client/auth.ts @@ -1086,11 +1086,11 @@ async function executeTokenRequest( throw await parseErrorResponse(response); } - const json = await response.json(); + const json: unknown = await response.json(); // Some OAuth servers (e.g., GitHub) return error responses with HTTP 200 status. // Check for error field before attempting to parse as tokens. - if (json.error) { + if (typeof json === 'object' && json !== null && 'error' in json) { throw await parseErrorResponse(JSON.stringify(json)); } From f98b92e9a64f7b60d31a3bdb0e5c242c0fd2ea02 Mon Sep 17 00:00:00 2001 From: Christopher Tso Date: Fri, 9 Jan 2026 07:47:04 +1100 Subject: [PATCH 3/3] check OAuth error field only on parse failure Co-authored-by: Paul Carleton --- packages/client/src/client/auth.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/client/src/client/auth.ts b/packages/client/src/client/auth.ts index 4f0e6a727..c8f09d822 100644 --- a/packages/client/src/client/auth.ts +++ b/packages/client/src/client/auth.ts @@ -1088,13 +1088,16 @@ async function executeTokenRequest( const json: unknown = await response.json(); - // Some OAuth servers (e.g., GitHub) return error responses with HTTP 200 status. - // Check for error field before attempting to parse as tokens. - if (typeof json === 'object' && json !== null && 'error' in json) { - throw await parseErrorResponse(JSON.stringify(json)); + try { + return OAuthTokensSchema.parse(json); + } catch (parseError) { + // Some OAuth servers (e.g., GitHub) return error responses with HTTP 200 status. + // Check for error field only if token parsing failed. + if (typeof json === 'object' && json !== null && 'error' in json) { + throw await parseErrorResponse(JSON.stringify(json)); + } + throw parseError; } - - return OAuthTokensSchema.parse(json); } /**