OAuth discovery fails with "Failed to parse JSON" when authorizing claude_design MCP — auth-server metadata endpoint returns Cloudflare HTML challenge

Open 💬 0 comments Opened Jul 1, 2026 by gw225

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, transport http)
  • 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

  1. claude mcp add --transport http claude_design https://api.anthropic.com/v1/design/mcp (or add via Claude Design's suggested config)
  2. /mcp → select claude_designAuthenticate
  3. 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.

View original on GitHub ↗