OAuth discovery fails with "Failed to parse JSON" when authorizing claude_design MCP — auth-server metadata endpoint returns Cloudflare HTML challenge
Summary
Authenticating the claude_design MCP server (https://api.anthropic.com/v1/design/mcp) from Claude Code CLI fails with:
SDK auth failed: Failed to parse JSON
The browser OAuth window never opens because the OAuth authorization-server metadata endpoint indicated by the server returns an HTML Cloudflare challenge page instead of JSON, so the OAuth client crashes during discovery.
This appears to be a server-side infra bug (Cloudflare bot-protection is fronting the well-known JSON metadata path), not a client bug.
Environment
- Claude Code:
2.1.153 - OS: macOS 15 (Darwin 25.5.0), arm64
- MCP server:
claude_design(https://api.anthropic.com/v1/design/mcp, transporthttp) - User was following the Claude Design in-app prompt:
Use the claude_design MCP (https://api.anthropic.com/v1/design/mcp, auth via /design-login) to import this project
(Side note: /design-login is referenced by Claude Design's own prompt but does not exist in Claude Code 2.1.153 — Unknown command: /design-login. Standard /mcp → Authenticate is the only path currently, and that's the path that hits the JSON-parse bug.)
Repro
claude mcp add --transport http claude_design https://api.anthropic.com/v1/design/mcp(or add via Claude Design's suggested config)/mcp→ selectclaude_design→ Authenticate- Observed:
Claude_design MCP Server
Status: △ needs authentication
Auth: ✘ not authenticated
URL: https://api.anthropic.com/v1/design/mcp
Config location: /Users/<user>/.claude.json
SDK auth failed: Failed to parse JSON
No browser window opens.
Root cause (verified with curl)
Step 1 — MCP endpoint returns proper WWW-Authenticate with resource metadata URL:
$ curl -sS -X POST -H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize",...}' \
-D - https://api.anthropic.com/v1/design/mcp
HTTP/2 401
www-authenticate: Bearer resource_metadata="https://api.anthropic.com/v1/design/.well-known/oauth-protected-resource",
scope="user:design:read user:design:write"
Step 2 — Protected-resource metadata is valid JSON and points to claude.ai as the auth server:
$ curl -sS https://api.anthropic.com/v1/design/.well-known/oauth-protected-resource
{"resource":"https://api.anthropic.com/v1/design/mcp",
"authorization_servers":["https://claude.ai/v1/design/mcp"],
"scopes_supported":["user:design:read","user:design:write"]}
Step 3 — The OAuth authorization-server metadata URL is blocked by Cloudflare's bot challenge and returns HTML, not JSON:
$ curl -sS -w "HTTP %{http_code}\n" \
https://claude.ai/v1/design/mcp/.well-known/oauth-authorization-server
<!DOCTYPE html><html lang="en-US"><head><title>Just a moment...</title>...
HTTP 403
Every plausible metadata URL under claude.ai for this resource is either 403 (Cloudflare challenge) or 200-with-the-SPA-shell:
| URL | Status | Content |
| --- | --- | --- |
| https://claude.ai/v1/design/mcp/.well-known/oauth-authorization-server | 403 | Cloudflare challenge HTML |
| https://claude.ai/v1/design/.well-known/oauth-authorization-server | 403 | Cloudflare challenge HTML |
| https://claude.ai/.well-known/oauth-authorization-server/v1/design/mcp | 200 | claude.ai SPA HTML (not JSON) |
| https://claude.ai/.well-known/oauth-authorization-server | 200 | claude.ai SPA HTML (not JSON) |
Step 4 — Claude Code parses that HTML as JSON → Failed to parse JSON → auth flow aborts before the browser can open. No amount of client-side action can get past this because claude.ai will not serve the metadata to any non-browser UA.
Expected
Either (a) the authorization_servers value in oauth-protected-resource should point to a host that actually serves the OAuth 2.0 authorization-server metadata document as JSON to non-browser clients (probably api.anthropic.com, matching the pattern used by the Google Drive MCP whose metadata IS served at https://api.anthropic.com/.well-known/oauth-authorization-server), or (b) the well-known metadata paths on claude.ai should be exempted from the Cloudflare bot-challenge and return the standard OAuth 2.0 Authorization Server Metadata JSON document (RFC 8414).
Client-side improvement (suggestion)
Even after the server side is fixed, the surface error SDK auth failed: Failed to parse JSON is unhelpful. Consider surfacing the URL that failed to parse and the first bytes of the response body when discovery fails — would have saved ~an hour of debugging here.
Workaround
None from the client side. Users have to open the Claude Design project in a browser and manually copy the .dc.html source out.