Authenticate the Figma MCP server for ZCode, despite ZCode not being on Figma's client whitelist.
ZCode connects to remote MCP servers over HTTP and runs the standard MCP OAuth
flow (RFC 9700 / StreamableHTTPClientTransport). Figma's MCP server only
allows a fixed list of client names, and "ZCode" isn't on it — so the
out-of-the-box flow fails at client registration.
This script works around that by performing the OAuth flow under the client
name Codex (which is whitelisted), capturing the resulting tokens, and
injecting them into ZCode's encrypted credential store so ZCode can use them
directly on subsequent connections.
- Registers a new OAuth client named
Codexagainst the Figma MCP server. - Opens a browser for you to authorize the request in Figma.
- Catches the
localhost:3000/callbackredirect and exchanges the authorization code for access + refresh tokens (PKCE). - Encrypts the tokens with the same AES-256-GCM scheme ZCode uses for
~/.zcode/v2/credentials.json, and writes them under the Figma server's id. - Backs up
credentials.jsonfirst and verifies the round-trip after writing.
-
Node.js ≥ 20
-
ZCode installed and run at least once, with the Figma MCP server declared in
~/.zcode/cli/config.json:{ "mcp": { "servers": { "figma": { "url": "https://mcp.figma.com/mcp" } } } }ZCode must have attempted to connect to the server at least once so that a
mcp:oauth:*:discovery_stateentry exists incredentials.json— the script reads the server id from there.
git clone <this repo> ~/projects/darkgenius/zcode-figma-mcp
cd ~/projects/darkgenius/zcode-figma-mcp
npm install# Default flow — opens the browser, waits for you to authorize in Figma.
node figma-mcp-auth.mjs
# Verbose mode — prints decrypted values for debugging.
node figma-mcp-auth.mjs --verbose
# Custom MCP server URL (defaults to https://mcp.figma.com/mcp).
node figma-mcp-auth.mjs https://mcp.figma.com/mcpAfter a successful run:
- Restart ZCode so it re-reads
credentials.json. - Verify in Settings → MCP that the
figmaserver shows as connected and lists its tools (get_screenshot,get_design_context,use_figma, …).
| Path | Purpose |
|---|---|
~/.zcode/v2/credentials.json |
The script adds/overwrites two keys here:mcp:oauth:<server-id>:tokensmcp:oauth:<server-id>:client_information |
~/.zcode/v2/credentials.json.backup |
Copy of credentials.json from just before the write. Overwritten on every run. |
No other files are touched.
The <server-id> in the credential keys is not derived from the URL —
ZCode assigns it during OAuth metadata discovery and stores it inside the
encrypted discovery_state payload. The script:
- Scans all
mcp:oauth:*:discovery_statekeys incredentials.json. - Decrypts each one and matches
resourceMetadata.resourceagainst the target MCP URL. - Falls back to the single available entry if there's only one.
If ZCode has never attempted the flow, there's nothing to match, and the script will tell you to start ZCode once first.
ZCode wraps credential values as enc:v1:<iv>.<authTag>.<ciphertext>, where:
- algorithm:
aes-256-gcm - key:
sha256(ZCODE_CREDENTIAL_SECRET || fallback) - fallback:
zcode-credential-fallback:<platform>:<homedir>:<username> - iv: 12 random bytes, auth tag: 16 bytes, all base64url-encoded
Set the ZCODE_CREDENTIAL_SECRET environment variable to override the fallback
(e.g. on a shared/CI machine).
Access tokens expire (see the expiresAt / expires_in fields — roughly 90
days). When ZCode starts getting 401s from Figma, re-run the script and restart
ZCode. The refresh token may extend the lifetime, but Figma eventually requires
a fresh interactive authorization.
Safari can't connect to the server "localhost" after clicking Authorize.
The local callback server must be reachable from your browser. The script binds
to 0.0.0.0 (all interfaces) so both IPv4 (127.0.0.1) and IPv6 (::1) work —
this is the classic macOS fix, since Safari resolves localhost to ::1. If
you still hit this, make sure nothing else is squatting on port 3000:
lsof -i :3000No mcp:oauth:*:discovery_state entries found.
ZCode hasn't attempted the Figma OAuth flow yet. Open ZCode, ensure the server
is configured, trigger a connection (it will fail at authorization — that's
fine), then re-run this script.
Multiple MCP OAuth servers found … none matches.
There are several remote OAuth MCP servers configured and none of their
discovery payloads reference the Figma URL. Run with --verbose to inspect, or
remove stale entries from credentials.json.
Verification failed / decrypt mismatch.
The machine profile (platform, homedir, username) used for key derivation
must match the one ZCode runs under. If you run ZCode under a different user,
set ZCODE_CREDENTIAL_SECRET consistently for both.