Announcing CIMD support for MCP Client registration
Learn more

Figma MCP vs Figma API for AI Agents (2026)

TL;DR

  • Figma's MCP server and REST API solve different problems. The MCP server (open beta, free during beta) turns a selected node into framework code and can write to the canvas through Skills. The REST API reads file JSON, manages comments, variables, dev resources, webhooks, and analytics, but it cannot create or modify nodes.
  • The MCP server is locked to an approved client list. Custom OAuth apps cannot obtain the mcp:connect scope, dynamic client registration is rejected, and personal access tokens are not accepted. If your agent is not an allowlisted IDE client, the official MCP server is closed to it.
  • The REST API supports three credential types: OAuth 2.0 for per-user delegated access, plan access tokens for organization-level headless automation, and personal access tokens for local scripts. This is the only path a custom production agent can actually build on.
  • Neither path solves per-user credential isolation. Every user has their own Figma credential, which means N tokens to store, refresh, and revoke at scale. That is infrastructure you own regardless of which path you pick.
  • Scalekit's Figma connector exposes the REST surface as per-user scoped tools backed by a token vault, with a full audit trail; so the MCP vs API decision does not change your auth infrastructure.

Your agent needs to read and act on Figma. Figma ships two things that both say "AI" on the tin: an official MCP server at mcp.figma.com/mcp and a REST API at api.figma.com. They are not two routes to the same place. The MCP server is a beta, design-to-code tool that only approved IDE clients can connect to. The REST API is a decade-old data surface that cannot modify the canvas. Which one your agent should build against depends entirely on what it does. Here is how to pick.

What Figma MCP and Figma API actually are

The Figma MCP server

Figma's MCP server is a design-to-code tool, not a general data API. It exists in two forms. The desktop server runs locally through the Figma desktop app at http://127.0.0.1:3845/mcp and requires a Dev or Full seat. The remote server runs at https://mcp.figma.com/mcp and adds write-to-canvas capability.

MCP status and tools

The server is in open beta; it is free during the beta and Figma states it will become a usage-based paid feature. It exposes around a dozen tools, still expanding: get_design_context, get_metadata, get_screenshot, get_variable_defs, get_code_connect_map, plus remote-only tools like search_design_system, get_libraries, and the use_figma canvas write Skill. Official docs: Figma MCP server.

The Figma REST API

The Figma REST API is a versioned HTTP interface that returns a JSON representation of any file you can access. It reads files, nodes, components, styles, and version history; renders images; reads and posts comments; reads and writes variables and dev resources; and manages Webhooks V2 for real-time events. It does not modify nodes on the canvas. Authentication accepts OAuth 2.0 tokens, plan access tokens, and personal access tokens. Official docs: Figma REST API.

Comparing them where it matters for agents

What your agent can actually do

The MCP server owns the design-to-code path and canvas writes. The REST API owns programmatic data, events, and headless access. The overlap is narrow.

Capability
Figma MCP server
Figma REST API
Turn a node into framework code
Yes, get_design_context
No, returns raw node JSON only
Code Connect component-to-code mapping
Yes
No
Screenshot or render a node
Yes, get_screenshot
Yes, images render endpoint
Read variables and styles in a selection
Yes, get_variable_defs
Yes, variables endpoints
Write to canvas: create or modify frames, components
Yes, remote only via Skills
No, REST cannot modify nodes
Capture a live web page into Figma
Yes, remote
No
Read full file document tree programmatically
Limited, selection or link based
Yes, files and nodes endpoints
Comments: read, post, react
No
Yes
Webhooks and real-time events
No
Yes, Webhooks V2
Version history
No
Yes
Dev resources: attach external links
No
Yes
Library analytics: usage and actions
No
Yes, Enterprise
Activity logs for the organization
No
Yes, Enterprise, OAuth only
Connect from a custom or arbitrary agent client
No, client allowlist
Yes
Headless, non-interactive auth
No, interactive OAuth only
Yes, plan access tokens

Where the gap bites

The split is architectural, not a roadmap gap. The MCP server was built to feed design context into a coding agent inside an IDE; that is why it produces code and screenshots and can write back to the canvas. The REST API was built to read and observe files programmatically; that is why it has webhooks, comments, version history, and analytics. An agent that needs to react to a design change, post a comment, or run on a schedule lives in the REST API. An agent that translates a selected frame into a React component lives in the MCP server, inside a supported editor.

The auth path each one puts you on

MCP: OAuth only, and only for approved clients

The remote MCP server authenticates through Figma's OAuth flow, and that is the only method. There is a hard constraint underneath it: access is restricted to clients in the Figma MCP Catalog, such as VS Code, Cursor, Claude Code, and Codex. Figma support has confirmed that custom OAuth apps cannot request the mcp:connect scope, that dynamic client registration against the MCP register endpoint returns a 403, and that personal access tokens are rejected at the MCP endpoint. The desktop server sidesteps OAuth by riding the signed-in desktop app session, but it requires the desktop app running with a Dev or Full seat.

Why this defines the decision for custom agents

If you are building your own production agent, not shipping a feature inside an approved IDE, the official MCP server is effectively closed. Developers in Figma's own forum have reported pivoting to building against the REST API because their gateway or backend could not obtain an approved MCP client. This is the single most disqualifying constraint for production agent builders, and it mirrors the GitHub App token gap: the limitation is the auth architecture, not the capability.

REST API: three credential types

The REST API gives you three options. OAuth 2.0 is the recommended path for acting on behalf of individual users; each user consents through a browser flow and the token is scoped to what that user can see. Plan access tokens are organization-scoped, support expiration up to one year, can be restricted to an allowlist of resources, and are meant for CI/CD and headless automation that should not be tied to a person. Personal access tokens are for local scripts; they now expire within 90 days and grant access to every file the user can reach, with no per-file restriction.

The identity problem that follows you either way

For a multi-tenant B2B design agent, the per-user model is correct: every user authorizes their own Figma account and the agent acts with their permissions. The REST API's OAuth path gives you one token per user. The plan access token gives you one static token per organization for background jobs. In neither case does the path store, rotate, or revoke those credentials for you. The token type differs; the credential management infrastructure required is identical.

What you own in production

On the MCP path

Figma manages the server, the tool schemas, and code generation. You do not maintain a schema library, and your agent picks up new tools when Figma ships them. What you give up is control: schemas are unversioned and change when Figma updates the hosted server, and you are bound to the approved-client model and to beta-stage rate limits. Rate limits cap Starter plan and View or Collab seats at 6 tool calls per month; Dev or Full seats follow the Tier 1 REST API limits.

On the REST API path

You own the full operational surface: endpoint selection, request construction, pagination, error handling, rate-limit retries, and the token lifecycle. The REST API uses cost-based rate limits, where heavier operations like image rendering cost more than reads, and OAuth limits apply per application while PAT limits apply per user. The tradeoff is stability: REST endpoints are versioned, so a deterministic pipeline is not exposed to an unexpected schema change shipped to the MCP server.

When to use MCP, when to use the API

Use the Figma MCP server when

  • Your agent runs inside an approved IDE client such as VS Code, Cursor, Claude Code, or Codex, and the user is present for the OAuth flow.
  • The core job is design-to-code: turning a selected frame into framework code that respects your variables and Code Connect mappings.
  • You need to write to the canvas from an agent, for example generating or editing frames using your design system through the use_figma Skill.
  • You are working interactively and want Figma to maintain the tool schemas for you.

Use the Figma REST API when

  • You are building a custom or multi-tenant agent that is not an approved MCP client; this is the only path that will accept your application.
  • Your agent runs headless: scheduled design-system audits, asset exports, or pipeline jobs with no user present, using plan access tokens.
  • You need capabilities the MCP server does not expose: comments, webhooks and real-time events, version history, dev resources, or library analytics.
  • You need a deterministic, versioned contract for a production pipeline rather than an evolving beta tool surface.

What each path cannot do (sourced from official docs)

This is the part most comparisons skip. Listing what is genuinely impossible on each side, from Figma's own documentation, is what makes the choice safe.

What the Figma MCP server cannot do

The MCP server has no comments surface, no webhooks or event subscriptions, no version history, no dev resources management, and no library analytics; all of those are REST-only. It cannot be reached by an arbitrary client, because access is restricted to the Figma MCP Catalog and the mcp:connect scope is not available to custom OAuth apps. It cannot run headless, because it requires an interactive OAuth flow or the desktop app session and rejects personal access tokens. Selection-based prompting works only on the desktop server; the remote server requires a link to a frame or layer.

What the Figma REST API cannot do

The REST API cannot create or modify nodes on the canvas. Figma support states plainly that the REST API does not allow modification of nodes; the file and node endpoints are GET-only for content. It cannot generate framework code from a design the way get_design_context does, and it has no Code Connect mapping. Canvas mutation is possible only through the Plugin API, which runs inside Figma, or through the MCP server's write Skills, which in turn wrap the Plugin API. Variables endpoints require the file_variables:read or file_variables:write scope and are gated to Enterprise; activity logs and the Discovery API require OAuth and Enterprise.

The capability neither path gives a custom agent

Write-to-canvas is the clearest example of a capability that exists in Figma but is out of reach for a custom backend agent. It is not in the REST API at all, and on the MCP side it is available only to approved IDE clients through Skills. If your agent needs to author Figma content programmatically from your own backend today, neither official path delivers it.

The credential problem that exists on both paths

One token per user, on every path

Whether you use OAuth on the REST API or the MCP flow inside an IDE, you end up with one Figma credential per user. Fifty customers means fifty OAuth tokens, fifty credential lifecycles, fifty things to encrypt, refresh, and revoke. Plan access tokens shift the unit to one per organization for headless jobs, but they are static, long-lived secrets that someone has to store and rotate. None of these paths gives you a vault, a rotation policy, or a revocation flow.

The shared-token failure mode

A single shared Figma token looks fine in a demo. In production it breaks attribution: every comment the agent posts and every export it runs appears as one service identity, the audit trail shows a generic account, and one user's token can reach files another user authorized. The fix is per-user credential isolation enforced at the infrastructure layer, the same requirement on both the MCP and REST paths.

Where Scalekit fits

Scalekit's Figma connector resolves the per-user token on every tool call from an AES-256 token vault, so each action stays tied to the user who authorized it, with a full audit trail rather than a shared account. The credential never touches your agent runtime or the LLM context. The same vault works whether you call Figma through Scalekit's scoped tools or through a Scalekit-hosted MCP endpoint, so the path decision does not change what you build for auth. Connector page: scalekit.com/connectors/figma. Connector docs: docs.scalekit.com/agentkit/connectors/figma.

Connect your agent to Figma with Scalekit

Scalekit's Figma connector wraps the REST API as more than 40 per-user scoped tools, backed by OAuth 2.0 and the token vault. It is the practical way to give a custom or multi-tenant agent authenticated Figma access without building the OAuth lifecycle yourself.

Set up the connector

Create a Figma connection in the Scalekit dashboard under AgentKit, register your Figma app's Client ID and Client Secret, and select the scopes your agent needs, such as files:read, file_variables:read, file_variables:write, and webhooks:write. The connection_name you use in code must match the connection name configured in the dashboard exactly; a mismatch here is the most common integration error. Add your Scalekit credentials to your environment:

SCALEKIT_ENVIRONMENT_URL= SCALEKIT_CLIENT_ID= SCALEKIT_CLIENT_SECRET=

Authorize a user (Node.js)

The agent never sees a token. You generate an authorization link for a user identifier, the user consents once, and Scalekit vaults the credential under that identifier.

import { ScalekitClient } from '@scalekit-sdk/node' import 'dotenv/config' const scalekit = new ScalekitClient( process.env.SCALEKIT_ENVIRONMENT_URL, process.env.SCALEKIT_CLIENT_ID, process.env.SCALEKIT_CLIENT_SECRET, ) // connection_name must match the connection configured in the Scalekit dashboard const connection = 'figma' const identifier = 'user_123' const { link } = await scalekit.actions.getAuthorizationLink({ connectionName: connection, identifier, }) console.log('Authorize Figma:', link)

Authorize a user (Python)

import os from scalekit.client import ScalekitClient from dotenv import load_dotenv load_dotenv() scalekit_client = ScalekitClient( env_url=os.getenv("SCALEKIT_ENVIRONMENT_URL"), client_id=os.getenv("SCALEKIT_CLIENT_ID"), client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"), ) actions = scalekit_client.actions # connection_name must match the connection configured in the Scalekit dashboard connection_name = "figma" identifier = "user_123" link_response = actions.get_authorization_link( connection_name=connection_name, identifier=identifier, ) print("Authorize Figma:", link_response.link)

Retrieve the authorized tool surface, then execute

Before the agent runs, retrieve the tools the current user's connected account is authorized to call. This is a scoped surface, not a full catalog: the agent sees only what this user permitted, which keeps tool selection accurate and tokens low. Then run the standard tool-use loop and call execute_tool for each request.

Claude (Anthropic) agent loop

Scalekit returns tool schemas in Anthropic's native input_schema format, so no conversion is needed.

import os, scalekit.client, anthropic from google.protobuf.json_format import MessageToDict scalekit_client = scalekit.client.ScalekitClient( client_id=os.getenv("SCALEKIT_CLIENT_ID"), client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"), env_url=os.getenv("SCALEKIT_ENVIRONMENT_URL"), ) actions = scalekit_client.actions client = anthropic.Anthropic() # Retrieve the tools authorized for this user's connected account scoped_response, _ = actions.tools.list_scoped_tools( identifier="user_123", filter={"connection_names": ["figma"]}, page_size=100, ) llm_tools = [ { "name": MessageToDict(t.tool).get("definition", {}).get("name"), "description": MessageToDict(t.tool).get("definition", {}).get("description", ""), "input_schema": MessageToDict(t.tool).get("definition", {}).get("input_schema", {}), } for t in scoped_response.tools ] messages = [{"role": "user", "content": "List the components in file ABC123 and flag any without descriptions"}] while True: response = client.messages.create( model="claude-sonnet-4-6", max_tokens=1024, tools=llm_tools, messages=messages, ) if response.stop_reason == "end_turn": print(response.content[0].text) break tool_results = [] for block in response.content: if block.type == "tool_use": result = actions.execute_tool( tool_name=block.name, identifier="user_123", tool_input=block.input, ) tool_results.append({ "type": "tool_result", "tool_use_id": block.id, "content": str(result.data), }) messages.append({"role": "assistant", "content": response.content}) messages.append({"role": "user", "content": tool_results})

LangChain agent loop

actions.langchain.get_tools() returns native StructuredTool objects scoped to the user; bind them and run the loop.

from langchain_openai import ChatOpenAI from langchain_core.messages import HumanMessage, ToolMessage tools = actions.langchain.get_tools( identifier="user_123", connection_names=["figma"], page_size=100, ) tool_map = {t.name: t for t in tools} llm = ChatOpenAI(model="gpt-4o").bind_tools(tools) messages = [HumanMessage("Export every icon node in file ABC123 as SVG")] while True: response = llm.invoke(messages) messages.append(response) if not response.tool_calls: print(response.content) break for tc in response.tool_calls: result = tool_map[tc["name"]].invoke(tc["args"]) messages.append(ToolMessage(content=str(result), tool_call_id=tc["id"]))

Use it as a Virtual MCP endpoint

If your client speaks MCP, Scalekit also exposes the same per-user Figma surface as a hosted Virtual MCP endpoint, with no MCP server to deploy or maintain. The endpoint is static; the identity is resolved per user from a short-lived session token.

{ "mcpServers": { "figma": { "url": "https://mcp.scalekit.com/figma", "headers": { "Authorization": "Bearer $SCALEKIT_TOKEN" } } } }

Other frameworks

Scalekit ships native adapters for LangChain, Anthropic, OpenAI, Google ADK, Vercel AI, and Mastra. The listScopedTools and executeTool pattern is framework-agnostic, so it drops into any runtime, including ones without a packaged adapter. If you need an adapter Scalekit does not ship yet, request it in the Scalekit community Slack.

Observability: agent auth logs

For multi-tool and multi-tenant agents, the value is downstream of the call. Every tool execution is logged with the user who authorized it, which tool ran, and what it returned, so attribution survives across agents and tenants. That audit trail answers the questions a security review asks: under whose credentials did the agent read this file, and can access for one user be revoked without touching another. This is what a shared bot token cannot give you, and it is the same trail whether you call Figma through scoped tools or the Virtual MCP endpoint.

Need the design-to-code surface or canvas writes?

Scalekit's connector covers the REST surface: file reads, components, styles, comments, variables, dev resources, webhooks, and library analytics. It does not provide Figma's IDE-only design-to-code tools or use_figma canvas writes, because those are restricted to approved MCP clients and are not reachable from a custom backend. If your agent needs that surface, tell us your use case so we can prioritize it: join the community Slack, talk to us, or talk to Scalekit's engineers.

Which one to build against

If you are shipping a design-to-code feature inside an approved IDE and the user is present, the Figma MCP server is the right tool; it is purpose-built for that workflow and Figma maintains the schemas. If you are building a custom or multi-tenant agent, running headless, reacting to file events, or working with comments, variables, dev resources, or analytics, the REST API is the only viable path; the MCP server's client allowlist closes the door to everything else. Most teams will not face a real choice: the official MCP server is not open to their agent, so they build on the REST API. Either way, the credential management problem is identical, and that is what needs production-grade infrastructure.

Browse the Scalekit Figma connector: scalekit.com/connectors/figma

No items found.
Agent Auth Quickstart
On this page
Share this article
Agent Auth Quickstart

Acquire enterprise customers with zero upfront cost

Every feature unlocked. No hidden fees.
Start Free
$0
/ month
1 million Monthly Active Users
100 Monthly Active Organizations
1 SSO connection
1 SCIM connection
10K Connected Accounts
Unlimited Dev & Prod environments