Desktop app DCR uses client_name "Claude Desktop (…)" which Figma's MCP register endpoint rejects with 403 — CLI works because it sends "Claude Code"
Summary
The Figma remote MCP server (https://mcp.figma.com/mcp) allowlists OAuth Dynamic Client Registration by exact client_name. Figma's POST /v1/oauth/mcp/register returns 200 only for a known set of client names (Claude Code, Codex, …) and 403 Forbidden for everything else.
The Claude Desktop app (Managed MCP UI / Cowork connectors) registers with:
client_name: `Claude Desktop (${app.getVersion()})` // e.g. "Claude Desktop (1.18286.0)"
which Figma rejects → the connection dies at initialize with the user-facing error:
HTTP 403 … Invalid OAuth error response: Unexpected token 'F', "Forbidden" is not valid JSON. Raw body: Forbidden
FAILED REQUEST HTTP https://mcp.figma.com/mcp → initialize
The Claude Code CLI connects fine to the same endpoint — because it registers as client_name: "Claude Code", which is on Figma's allowlist.
Reproduction (deterministic, no auth needed)
REG=https://api.figma.com/v1/oauth/mcp/register
body(){ echo "{\"client_name\":\"$1\",\"redirect_uris\":[\"http://127.0.0.1:33418/callback\"],\"grant_types\":[\"authorization_code\",\"refresh_token\"],\"response_types\":[\"code\"],\"token_endpoint_auth_method\":\"none\",\"scope\":\"mcp:connect\"}"; }
for n in "Claude Desktop (1.18286.0)" "Claude Desktop" "Claude Code" "Codex" "Cursor"; do
printf '%-30s -> %s\n' "$n" "$(curl -s -o /dev/null -w '%{http_code}' -X POST $REG -H 'content-type: application/json' --data "$(body "$n")")"
done
Output:
Claude Desktop (1.18286.0) -> 403
Claude Desktop -> 403
Claude Code -> 200
Codex -> 200
Cursor -> 403
The client_name is the only variable — same redirect_uri, grant_types, scope, and token_endpoint_auth_method throughout. (client_id/client_secret returned by the 200 responses omitted here.)
Root cause
The clientMetadata getter in the desktop app's MCP OAuth provider hardcodes client_name: "Claude Desktop (<version>)". Figma's register endpoint is not a generic RFC 7591 DCR endpoint — it is name-allowlisted, and the desktop app's name isn't on the list.
This is distinct from the parser hypothesis in #59463: the WWW-Authenticate 401 is parsed fine (the OAuth flow starts and produces a valid authorization URL); the failure is one step later, at POST /register. The "Forbidden" is not valid JSON message is the desktop client choking on Figma's plaintext 403 body from the register call.
Impact
Figma MCP is completely unusable from the Claude Desktop app (Managed MCP + Cowork connector), while working from the Claude Code CLI against the identical endpoint. This blocks managed/enterprise rollout of the Figma connector to desktop users, who have no /mcp manual-auth fallback (cf. #59854).
Suggested fixes
- Send
client_name: "Claude Code"(or another Figma-allowlisted name) from the desktop DCR path, for parity with the CLI that already works today. Simplest fix. - Coordinate with Figma to allowlist the desktop
client_name. - Broader: honor a pre-configured
clientId/clientSecretand skip DCR (dup of #26675) — the desktop "Bring your own client" UI already exposes both fields; wiring it to bypass DCR would sidestep this whole class of allowlist/DCR-less-server bugs.
Related
- #59463 — same symptom (Figma "Failed to connect"), but root-caused to the
WWW-Authenticateparser; this report shows the actual failure is theclient_nameallowlist at/register. - #59854 — Cowork DCR failure (GitHub connector), no manual-auth fallback in Cowork.
- #26675 — support pre-configured OAuth client credentials without DCR.
Environment
- Claude Desktop 1.18286.0, macOS 15 (Darwin 25.5.0)
- Figma remote MCP
https://mcp.figma.com/mcp, scopemcp:connect