Figma
Adding Figma MCP to ivar.json, authenticating across providers, and handling allowlist requirements.
The Figma MCP integration connects your hall to Figma's official remote MCP endpoint (https://mcp.figma.com/mcp). Figma uses OAuth 2.0 authentication with server-side allowlists.
1. Add Figma to ivar.json
Add the canonical figma entry under mcp in your hall manifest:
{
"mcp": [
{
"name": "figma",
"type": "http",
"url": "https://mcp.figma.com/mcp"
}
]
}Figma MCP is OAuth-only and does not support Personal Access Token (PAT) authentication. The endpoint enforces a server-controlled redirect allowlist.
2. Sync provider configs
Run ivar sync to project the canonical figma definition into hall-qualified names (acme-figma) for your configured providers:
ivar sync3. Authenticate
Authenticate Figma for a specific provider or across all configured providers in the hall:
# Authenticate for a single provider
ivar mcp auth figma --provider claude-code
ivar mcp auth figma --provider opencode
ivar mcp auth figma --provider omp
# Or authenticate for all configured providers in one step
ivar mcp auth figma --all-providersExpected provider behavior
| Provider | Mechanism | Behavior |
|---|---|---|
| Claude Code | Provider-native OAuth | Claude Code manages its own OAuth lifecycle via claude mcp login acme-figma. Ivar does not preregister clients or manage tokens for Claude Code; credentials remain in Claude's internal credential store. |
| OpenCode | Ivar PKCE + credential store | OpenCode's dynamic client registration (DCR) is rejected by Figma's server allowlist. Ivar preregisters the client, runs an internal PKCE flow on loopback, and writes the resulting tokens into OpenCode's credential store (mcp-auth.json). |
| OMP | Ivar PKCE + omp auth-broker | Because OMP has no native MCP login CLI, Ivar performs prerequisite registration and internal PKCE, then imports the OAuth tokens into OMP's broker store keyed by profile and endpoint URL. |
Generated OAuth metadata
When ivar mcp auth executes dynamic registration or endpoint discovery, it persists discovered client and endpoint metadata back to ivar.json:
{
"name": "figma",
"type": "http",
"url": "https://mcp.figma.com/mcp",
"oauth": {
"client_id": "<generated_client_id>",
"client_secret_env": "IVAR_MCP_ACME_FIGMA_SECRET",
"token_url": "<discovered_token_endpoint>",
"resource": "<discovered_resource>"
}
}Client secrets are stored in .ivar/secrets/mcp.env and referenced by environment variable name (client_secret_env). Tokens are stored directly in provider credential stores.
Client secret environment variable
Secret origin
The secret is issued by Figma's dynamic client registration endpoint (https://api.figma.com/v1/oauth/mcp/register), called automatically by ivar mcp auth figma when the manifest entry has no oauth block. There is no Figma dashboard page to copy it from and no manual OAuth app to create.
The registration request sends:
- The allowlisted
client_name - The loopback redirect URI
http://127.0.0.1:19876/callback authorization_codeandrefresh_tokengrant types- The
coderesponse type token_endpoint_auth_method: "none"
Figma's response carries client_id (written to ivar.json) and a client_secret issued in practice despite requesting none. Ivar stores that secret in .ivar/secrets/mcp.env and uses client_secret_post, because Figma's token endpoint otherwise rejects the exchange with Client secret is required.
If the response carries no client_secret, the client stays public: no client_secret_env in ivar.json and no environment variable is required.
Registration is idempotent: an entry that already has oauth is never re-registered, so a second run never mints a new secret.
The secret value exists only in .ivar/secrets/mcp.env on the machine that authenticated and is never committed. To recover it on a second machine, copy that line across from .ivar/secrets/mcp.env, or remove the oauth block from ivar.json and re-run ivar mcp auth figma to register a fresh client.
Name derivation
Ivar derives the environment variable name from the hall-qualified server name. It converts ASCII alphanumeric characters to uppercase, folds all other characters to _, and wraps the result as IVAR_MCP_<NAME>_SECRET.
For example, the projected server acme-figma derives:
IVAR_MCP_ACME_FIGMA_SECRETivar.json records only this variable name in oauth.client_secret_env. The secret value itself is never written to the manifest.
Secret storage and file format
Secret values live in <hall>/.ivar/secrets/mcp.env. This file is gitignored by the root .ivar/* rule and written atomically with owner-only permissions (0600 on Unix).
# MCP client secrets managed by ivar
IVAR_MCP_ACME_FIGMA_SECRET="<client_secret>"Format rules:
- One
KEY=VALUEentry per line. - Blank lines and
#comments are ignored. - Keys must be ASCII identifiers (letters, digits, underscores; cannot start with a digit).
- Values may be bare or double-quoted with JSON escaping. Ivar re-renders the file sorted by key with quoted, JSON-escaped values.
- The file is not shell-evaluated: do not use
exportor shell variable expansion.
Resolution order
When resolving the secret, Ivar evaluates sources in order:
- Caller environment: If the variable is present in the executing environment, Ivar uses that value and backfills it into
.ivar/secrets/mcp.env. - Secret file: Otherwise, Ivar reads the value from
.ivar/secrets/mcp.env. - Missing secret: If neither source defines the variable, execution halts with error code
mcp.missing_client_secret_env. To resolve, export the variable (export IVAR_MCP_ACME_FIGMA_SECRET=<client_secret>) and re-runivar mcp auth.
ivar mcp auth figma performs dynamic registration and persists the secret automatically. Manual edits to mcp.env are only needed during recovery—such as cloning a hall onto a new machine, rotating secrets, or supplying a secret that exists solely in your host environment.
Provider consumption
| Provider | Reference format | Injection behavior |
|---|---|---|
| OpenCode | {env:IVAR_MCP_ACME_FIGMA_SECRET} in opencode.json | ivar session start injects the resolved secret value directly into the OpenCode child process environment. |
| OMP | ${IVAR_MCP_ACME_FIGMA_SECRET} in mcp.json | OMP resolves the variable from its runtime environment when starting the server. |
| Claude Code | None | Claude Code manages authentication in its own credential store and does not use this variable. |
Troubleshooting
Missing secret metadata
If ivar sync or provider startup fails with mcp.missing_client_secret_env or missing secret errors, verify that .ivar/secrets/mcp.env or your host environment defines the required variable. See Client secret environment variable above to configure the variable or re-run ivar mcp auth figma.
Upstream allowlist or registration changes
Figma restricts OAuth redirects to approved callback URLs. If authentication fails during the browser handshake:
- Confirm that your loopback redirect URI matches Figma's permitted client ports (
http://127.0.0.1:19876/callback). - If Figma updates its upstream client registration policy, re-run
ivar mcp auth figma --provider <provider>to refresh dynamic registration and token bindings. Check provider and CLI output for actionable diagnostics if upstream policy rejects the handshake.
Next steps
- Linear MCP integration — Configure Linear issue tracking MCP.
- MCP OAuth guide — Learn how Ivar manages secrets and credential lifecycles.
- Provider guides — Detailed per-provider setup for Claude Code, OpenCode, and OMP.
- MCP Reference — Complete specification of
ivar.jsonMCP schemas.