fix: plain 401 for MCP OAuth discovery (#74)

* fix: return plain 401 for MCP OAuth discovery and harden auth flow

- Return plain HTTP 401 with WWW-Authenticate header (no JSON-RPC body)
  so Claude Desktop's MCP client can trigger OAuth discovery correctly
- Remove unused apiKey import from authorize route
- Remove stale codeChallengeMethod parameter from oauth-codes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: add Retry-After header to 429 rate limit response

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-03-21 14:47:47 +01:00
committed by GitHub
co-authored by Claude Opus 4.6
parent 5d66dd6bfc
commit d61670231f
3 changed files with 14 additions and 13 deletions
+14 -10
View File
@@ -1234,21 +1234,25 @@ export async function handleMcpRequest(request: Request): Promise<Response> {
const token = extractBearerToken(request)
if (!token) {
return new Response(
JSON.stringify(jsonRpcError(null, -32000, 'Authorization required')),
{ status: 401, headers: { 'Content-Type': 'application/json', 'WWW-Authenticate': wwwAuth } }
)
return new Response('Unauthorized', {
status: 401,
headers: { 'WWW-Authenticate': wwwAuth },
})
}
const authResult = await validateApiKey(token)
if ('error' in authResult) {
const status = authResult.status
const headers: Record<string, string> = { 'Content-Type': 'application/json' }
if (status === 401) headers['WWW-Authenticate'] = wwwAuth
return new Response(
JSON.stringify(jsonRpcError(null, -32000, authResult.error)),
{ status, headers }
)
if (status === 429) {
return new Response(authResult.error, {
status: 429,
headers: { 'Content-Type': 'text/plain', 'Retry-After': '60' },
})
}
return new Response('Unauthorized', {
status: 401,
headers: { 'WWW-Authenticate': wwwAuth },
})
}
const { userId } = authResult