← Back to dashboard

Figma Integration Guide

Text
███████╗██╗ ██████╗ ███╗   ███╗ █████╗
██╔════╝██║██╔════╝ ████╗ ████║██╔══██╗
█████╗  ██║██║  ███╗██╔████╔██║███████║
██╔══╝  ██║██║   ██║██║╚██╔╝██║██╔══██║
██║     ██║╚██████╔╝██║ ╚═╝ ██║██║  ██║
╚═╝     ╚═╝ ╚═════╝ ╚═╝     ╚═╝╚═╝  ╚═╝

Figma Integration Guide

Focus: Design-to-code workflows, component inspection, and Figma canvas automation from Claude Code using the official Figma MCP server.

Overview

Figma is the standard design tool for UI/UX. Its official MCP server gives Claude Code direct access to design files — reading component specs, extracting tokens, generating code from components, writing content back to the canvas, and running Code Connect mappings. This enables a true design-to-code pipeline: Claude reads Figma, writes the component, and links it back.

Here is the big picture — the MCP bridges design and code both ways, and you get to use both directions:

Official Documentation


MCP Server Setup

Figma recommends the hosted remote MCP server — it requires no desktop app, provides the broadest feature set, and is now available on all seats and plans. The endpoint is https://mcp.figma.com/mcp and auth is OAuth (an interactive "Allow access" browser flow) — there is no longer a static X-Figma-Token header on the MCP server itself. (The old mcp.figma.com/v1/mcp path is gone.)

Recommended path — install the official Figma plugin (bundles the MCP server config plus Agent Skills):

Bash
claude plugin install figma@claude-plugins-official
# then restart Claude Code, run /plugin, open the Installed tab,
# select the `figma` server, press Enter, and click "Allow access" to authorize (OAuth)

Manual alternative — add the remote server directly:

Bash
# Triggers the OAuth "Allow access" flow on first use — no token header needed
claude mcp add --transport http figma https://mcp.figma.com/mcp

.mcp.json Configuration (Remote)

JSON
{
  "mcpServers": {
    "figma": {
      "type": "http",
      "url": "https://mcp.figma.com/mcp"
    }
  }
}

On first connection Claude Code opens the OAuth flow; approve access to your Figma account. No personal access token is stored for the MCP server.

Desktop (local) MCP Server

For enterprise/org needs Figma also ships a local server inside the Figma desktop app (enable it under Preferences → "Enable local MCP server"). It is available on a Dev or Full seat on paid plans and listens on http://127.0.0.1:3845/mcp:

Bash
claude mcp add --transport http figma-desktop http://127.0.0.1:3845/mcp

Third-party Community Server (figma-developer-mcp)

figma-developer-mcp (the community "Framelink" server, currently 0.13.2) is a third-party stdio server — not Figma's official MCP. It authenticates with a personal access token and can be handy for read-only REST-backed workflows:

Bash
claude mcp add figma-framelink -- npx -y figma-developer-mcp \
  --figma-api-key=${FIGMA_ACCESS_TOKEN} \
  --stdio

Prefer the official remote server above for design-context and write-to-canvas work. A personal access token (for the REST API or this community server) is generated at: https://www.figma.com/settings → Personal access tokens

Available MCP Tools

ToolDescription
get_design_contextGet full design specs, code hints, and screenshot for a node
get_screenshotCapture a screenshot of a Figma node
get_metadataGet file metadata (name, pages, last modified)
get_figjamGet FigJam board content
get_librariesGet shared component libraries
search_design_systemSearch for components by name
get_variable_defsGet design tokens (colors, spacing, typography)
get_code_connect_mapMap Figma components to codebase components
add_code_connect_mapLink a Figma component to a code component
generate_diagramCreate a diagram in FigJam
download_assetsExport nodes as PNG / SVG / PDF via the MCP

The server's tool set keeps growing — recent additions include motion, shader, and Weave (weave_*) tools. Run /plugin (or your client's tool list) to see the current inventory; the standalone get_design_pages tool was folded into get_metadata.


Figma REST API Integration

Bash
npm install axios  # or use fetch

Extract Component Info

TypeScript
const FIGMA_TOKEN = process.env.FIGMA_ACCESS_TOKEN!;
const FILE_KEY = "your-file-key"; // from figma.com/design/{fileKey}/...

// Get file structure
const file = await fetch(`https://api.figma.com/v1/files/${FILE_KEY}`, {
  headers: { "X-Figma-Token": FIGMA_TOKEN },
}).then((r) => r.json());

// Get specific node
const nodeId = "1:23"; // from URL param node-id=1-23
const nodes = await fetch(
  `https://api.figma.com/v1/files/${FILE_KEY}/nodes?ids=${nodeId}`,
  { headers: { "X-Figma-Token": FIGMA_TOKEN } }
).then((r) => r.json());

// Export node as PNG
const images = await fetch(
  `https://api.figma.com/v1/images/${FILE_KEY}?ids=${nodeId}&format=png&scale=2`,
  { headers: { "X-Figma-Token": FIGMA_TOKEN } }
).then((r) => r.json());

console.log(images.images[nodeId]); // URL to the exported PNG

REST file/nodes/images endpoints are still under /v1 and still authenticate with the X-Figma-Token header (OAuth2 is also supported). No /v1 deprecation is in effect as of this review.

Webhooks (REST API v2)

Figma webhooks live at https://api.figma.com/v2/webhooks (note: v2, not v1) — subscribe to file events (FILE_UPDATE, FILE_COMMENT, FILE_VERSION_UPDATE, LIBRARY_PUBLISH, etc.). There is no HMAC signature header: you set a passcode when creating the webhook, Figma echoes it in every event payload, and your handler must compare the incoming passcode against the stored one and reject mismatches with 400 before acting — this is the codeAmani webhook-verification requirement applied to Figma.

TypeScript
// app/api/webhooks/figma/route.ts (Next.js App Router)
import { NextRequest, NextResponse } from "next/server";

export async function POST(req: NextRequest) {
  const body = await req.json();
  // Verify the request really came from Figma before doing any work
  if (body.passcode !== process.env.FIGMA_WEBHOOK_PASSCODE) {
    return new NextResponse("Invalid passcode", { status: 400 });
  }
  // handle body.event_type (FILE_UPDATE, FILE_COMMENT, ...)
  return NextResponse.json({ ok: true });
}

Environment Variables

Bash
# Required
FIGMA_ACCESS_TOKEN=figd_...         # Personal access token from Figma settings

# Optional for automation scripts
FIGMA_FILE_KEY=...                  # Default file key for automation
FIGMA_TEAM_ID=...                   # Team ID for shared library access
FIGMA_WEBHOOK_PASSCODE=...          # Passcode to verify inbound v2 webhook events

Automation Workflows

Design-to-Code Workflow

The core Claude Code + Figma workflow follows four clean steps — here is how the calls flow:

  1. Share a Figma URL or node ID
  2. Claude calls get_design_context → gets specs, colors, spacing, component screenshot
  3. Claude generates a React/Vue component matching the design
  4. Claude calls add_code_connect_map → links the Figma component to the generated component

Example prompt inside Claude Code:

"Implement the Button/Primary component from figma.com/design/AbCdEf/Design-System?node-id=1:23"

Slash Command: Figma to Component

.claude/commands/figma.md:

Markdown
Implement the Figma design at URL or node: $ARGUMENTS

1. Use the Figma MCP tool `get_design_context` with the file key and node ID extracted from $ARGUMENTS
2. Use `get_screenshot` to see the visual
3. Generate a TypeScript React component that matches the design exactly:
   - Use Tailwind CSS for styling
   - Extract all colors as CSS variables or Tailwind tokens
   - Make it responsive
   - Add proper TypeScript props interface
4. Write the component to the appropriate file in `src/components/`
5. Create a Storybook story for it
6. Report the component code and any design tokens used

Usage: /project:figma figma.com/design/AbCdEf/Design-System?node-id=1-23


Code → design (write to canvas)

The MCP is not read-only. Claude Code can write native Figma structure back into a file — real frames, components, variants, variables, and auto layout — not just flat screenshots. This is the inverse of the design-to-code flow above and is what keeps the motionstack design system in sync when code moves ahead of the canvas.

Three official write tools cover this direction:

ToolDirectionWhat it produces
create_new_filescaffoldA fresh, blank Figma / FigJam / Slides file to write into
use_figmacode/intent → canvasNative Figma objects via the Plugin API — components, variables, frames, auto layout, with awareness of the existing design system
generate_figma_designrunning app → canvas"Code to canvas" — captures live rendered UI from the browser as standard, flat Figma layers for human review

MANDATORY skill note: You MUST load the /figma-use skill before every use_figma call, and the /figma-create-new-file skill before every create_new_file call. Calling these tools without first loading the matching skill causes common, hard-to-debug failures. For pushing a whole page or layout, also load /figma-generate-design.

Workflow: generate a component into Figma from a description or code

  1. (If no target file) load /figma-create-new-file, then call create_new_file to scaffold a blank file
  2. Load /figma-use — this is required before the next step
  3. Discover what already exists: search_design_system plus get_variable_defs so the new work reuses real tokens and components instead of hardcoded values
  4. Call use_figma, which executes Plugin API JavaScript inside the file to assemble the component section-by-section, binding design-system variables
  5. For a full app screen instead of one component, capture the running UI with generate_figma_design ("code to canvas") for the team to review before implementation

Example prompt inside Claude Code:

"Create a Button/Primary component in our design-system file from src/components/Button.tsx, reusing our existing color and spacing variables."

Gotcha: use_figma is beta and intentionally limited — there is a ~20 KB response cap per call, no image / asset import, no custom fonts, and a Full seat with edit access is required (Dev seats are read-only). Make large changes incrementally across several calls rather than one giant payload, and expect to manually review and clean up the result.

Code Connect creates a permanent mapping between Figma components and real code so Dev Mode shows actual component usage instead of raw CSS.

Heads-up — Code Connect v2 (Aug 2026). @figma/code-connect is now 2.0.0. As of v2.0.0 (18 Aug 2026) the framework-specific parsers (the React .figma.tsx form below with an example: () => <JSX/> function) are no longer maintained — under v2 they only work with figma connect migrate/unpublish, and all other commands tell you to migrate. Parserless template files (.figma.ts / .figma.js) are now the only actively-maintained format. Author them with the shipped /figma-code-connect skill and follow the templates migration guide. npx figma connect publish is unchanged. To keep the legacy React parser, pin v1: npm install --save-dev @figma/code-connect@1.

Current (v2) — parserless template file (Button.figma.ts):

TypeScript
// Button.figma.ts — v2 template file (no framework parser)
/**
 * @figmaNode https://www.figma.com/design/[FILE_KEY]?node-id=[NODE_ID]
 */
import figma from "figma";
import { Button } from "./Button";

export default figma.connect(Button, {
  props: {
    variant: figma.enum("Variant", { Primary: "primary", Secondary: "secondary" }),
    disabled: figma.boolean("Disabled"),
    label: figma.string("Label"),
  },
  example: ({ variant, disabled, label }) => (
    <Button variant={variant} disabled={disabled}>{label}</Button>
  ),
});

Legacy (v1 React parser) — requires @figma/code-connect@1:

TypeScript
// Button.figma.tsx — legacy React parser (pin @figma/code-connect@1)
import { figma } from "@figma/code-connect/react";
import { Button } from "./Button";

figma.connect(Button, "https://www.figma.com/design/[FILE_KEY]?node-id=[NODE_ID]", {
  props: {
    variant: figma.enum("Variant", { Primary: "primary", Secondary: "secondary" }),
    disabled: figma.boolean("Disabled"),
    label: figma.string("Label"),
  },
  example: ({ variant, disabled, label }) => (
    <Button variant={variant} disabled={disabled}>{label}</Button>
  ),
});
Bash
# Publish Code Connect mappings to Figma (unchanged in v2)
npx figma connect publish

GitHub Actions: Auto-generate Types from Design Tokens

YAML
# .github/workflows/design-tokens.yml
name: Sync Figma Tokens
on:
  schedule:
    - cron: "0 9 * * 1"   # Every Monday morning
  workflow_dispatch:

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '22' }
      - name: Fetch design tokens
        env:
          FIGMA_ACCESS_TOKEN: ${{ secrets.FIGMA_ACCESS_TOKEN }}
          FIGMA_FILE_KEY: ${{ secrets.FIGMA_FILE_KEY }}
        run: node scripts/sync-tokens.js
      - name: Commit updated tokens
        run: |
          git config user.name "Design Sync Bot"
          git config user.email "noreply@figma.com"
          git add src/tokens/
          git diff --staged --quiet || git commit -m "chore: sync Figma design tokens"
          git push

Common Use Cases

Use CaseApproach
Design to React componentMCP get_design_context → generate code
Component library syncget_libraries + search_design_system
Design token extractionMCP get_variable_defs → CSS/TypeScript
Visual regression checkget_screenshot → compare to rendered component
Code Connect linkingadd_code_connect_map + figma connect publish
FigJam diagramsMCP generate_diagram

Troubleshooting

IssueFix
403 ForbiddenToken lacks access to that file — check sharing settings
Node not foundExtract node-id from URL; convert - to : (e.g., 1-23 → 1:23)
Design context emptyComponent may be in a library — use get_libraries first
Screenshot failsNode must be visible (not hidden) in the file
Code Connect not publishingRun npx figma connect publish from project root
figma connect errors telling you to migrateYou're on v2 with legacy .figma.tsx parser files — migrate to template files (/figma-code-connect skill) or pin @figma/code-connect@1
MCP server won't connectRemote endpoint is https://mcp.figma.com/mcp (not /v1/mcp); re-run the OAuth "Allow access" flow via /plugin
Figma webhook events ignoredVerify passcode matches before acting; reject mismatches with 400