storybook-figma-mcp
v0.7.0
Published
MCP server that merges Storybook component metadata and Figma design context into a single rich context for any AI
Maintainers
Readme
storybook-figma-mcp
Connect your Figma designs and Storybook component library to any AI assistant (Claude, Cursor, etc.) — so the AI knows exactly what components exist, which ones are missing, and what to build.
Framework-agnostic — works with React, Vue, Svelte, Angular, and more.
What does this actually do?
When you ask an AI to implement a Figma design, it usually guesses at component names, props, and structure. This package fixes that.
It acts as a bridge between three things:
┌─────────────────┐ ┌──────────────────────┐ ┌──────────────────┐
│ Your Figma │────▶│ storybook-figma-mcp │────▶│ Your AI (Claude │
│ Design File │ │ (this package) │ │ Cursor, etc.) │
│ │◀────│ │◀────│ │
└─────────────────┘ └──────────────────────┘ └──────────────────┘
│
┌─────────▼─────────┐
│ Your Storybook │
│ Component Library │
└───────────────────┘What it does for you:
- Looks at a Figma design and figures out every component needed to build it
- Checks your Storybook to see which components already exist
- Tells the AI which components are ready to use, which need minor updates, and which need to be built from scratch
- Gives the AI a ready-to-paste context block so it can start coding immediately
Before You Start — What You Need
| Requirement | Why | How to get it |
|-------------|-----|---------------|
| Node.js 22+ | To run this package | nodejs.org — run node --version to check |
| Figma Desktop app | To read your Figma designs live | figma.com/downloads |
| Storybook 8+ with @storybook/addon-mcp | Component inventory source | See Storybook docs — or use the built-in fallback |
| A Figma design file | The design you want to build | Any Figma file |
Don't have Storybook running? No problem. This package automatically falls back to reading your local
.stories.ts/.tsx/.vue/.sveltefiles. You'll see a warning message — that's normal.
Storybook 8 + addon-mcp setup:
npm install -D @storybook/addon-mcpAdd
"@storybook/addon-mcp"to theaddonsarray in.storybook/main.ts, then restart Storybook.
Setup (5 minutes)
Step 1 — Install the package
npm install -g storybook-figma-mcpStep 2 — Enable MCP in Figma Desktop
- Open Figma Desktop (not the browser — the desktop app)
- Click Figma in the menu bar → Preferences
- Scroll down to Dev Mode → turn on Enable MCP Server
- Done. No API key needed.
Using Figma in the browser only? See Using Figma Remote at the bottom.
Step 3 — Get your Figma URL
- Open your Figma file
- Click on the frame or component you want to build
- Copy the URL from your browser address bar
It looks like this:
https://www.figma.com/design/SivCOGImwo5DdUOZ9aV7cB/My-Design?node-id=1-2Save this URL — you'll use it in the next step.
Step 4 — Add to your AI tool
Cursor (Recommended Setup)
Open Cursor Settings → Cursor Settings → MCP tab and add a new global MCP server,
or edit ~/.cursor/mcp.json directly:
{
"mcpServers": {
"figma-desktop": {
"url": "http://127.0.0.1:3845/mcp"
},
"storybook": {
"transport": "http",
"url": "http://localhost:6006/mcp"
},
"storybook-figma": {
"command": "storybook-figma-mcp",
"env": {
"FIGMA_MCP_URL": "http://127.0.0.1:3845/mcp",
"STORYBOOK_MCP_URL": "http://localhost:6006/mcp"
}
}
}
}What each server does:
figma-desktop— direct Figma Desktop access for Cursor's own Figma queriesstorybook— direct Storybook access (component docs, stories)storybook-figma— the bridge that combines both forscope_design_components
Reload Cursor after saving (Cmd+Shift+P → Developer: Reload Window).
Claude Code (terminal)
claude mcp add storybook-figma -- storybook-figma-mcpOr with environment variables for custom URLs:
FIGMA_MCP_URL=http://127.0.0.1:3845/mcp \
STORYBOOK_MCP_URL=http://localhost:6006/mcp \
claude mcp add storybook-figma -- storybook-figma-mcpClaude Desktop
Open ~/Library/Application Support/Claude/claude_desktop_config.json and add:
{
"mcpServers": {
"storybook-figma": {
"command": "storybook-figma-mcp",
"env": {
"FIGMA_MCP_URL": "http://127.0.0.1:3845/mcp",
"STORYBOOK_MCP_URL": "http://localhost:6006/mcp"
}
}
}
}Restart Claude Desktop after saving.
How Cursor Uses This to Write Your Code
This is the key question — what actually happens when Cursor calls these tools?
Here's the full picture:
You type a prompt in Cursor
│
▼
Cursor sees the MCP tools are available
│
▼
Cursor calls scope_design_components({ figmaUrl: "...", framework: "react" })
│
▼
storybook-figma-mcp runs the scoping pipeline:
1. Fetches your Figma design tree (every component, frame, and node)
2. Fetches your Storybook component list
3. Matches each Figma component against Storybook
4. Classifies each one: Available / Partial / Missing
│
▼
Cursor receives a structured JSON with:
- A component inventory table (what exists vs. what's missing)
- Estimates for each component (S / M / L / XL)
- Full prop list for available components
- Design tokens (colors, spacing, fonts) from Figma
│
▼
Cursor asks you how to handle missing components
│
▼
You reply (e.g. "use stubs")
│
▼
Cursor calls scope_design_components again with resolution: "stubs"
│
▼
storybook-figma-mcp returns a copyBelowBlock —
a complete markdown context that tells Cursor:
- Which components to import directly
- Which components to stub out
- In what order to build everything
- What design tokens to use
│
▼
Cursor writes the actual code using this exact contextWhy this matters: Without this tool, Cursor guesses at component names, invents props that don't exist, and uses hardcoded colors instead of your tokens. With this tool, it knows your actual codebase.
Full Example — Cursor Building a Dashboard Screen
Here's a complete walkthrough. Imagine you have a Dashboard screen in Figma with a sidebar, stats cards, and a data table. Your Storybook has Button, Card, and Input but nothing else.
Step 1 — Paste this prompt into Cursor
Use scope_design_components to analyse the dashboard screen.
figmaUrl: "https://www.figma.com/design/ABC123/MyApp?node-id=12-5"
framework: "react"
Tell me what components are needed, which exist in Storybook,
and which need to be built.Step 2 — Cursor calls the tool and shows you this
I analysed the dashboard design. Here's what's needed:
| # | Component | Status | Estimate | Notes |
|---|----------------|-----------|----------|-------------------------------|
| 1 | Button | Available | 0-1h | Storybook: Components/Button |
| 2 | Card | Available | 0-1h | Storybook: Components/Card |
| 3 | Input | Available | 0-1h | Storybook: Forms/Input |
| 4 | Sidebar | Missing | 4-12h | Build required |
| 5 | StatsCard | Missing | 1-4h | Build required |
| 6 | DataTable | Missing | 12-32h | Build required |
Total estimate: 18-50h
3 components are missing from your Storybook library.
How do you want to handle the missing components?
(a) build_in_library — build them as proper Storybook stories first
(b) stubs — create minimal placeholders now, replace them later
(c) reduce_scope — only use the 3 existing components
To continue, call again with resolution: "stubs" (or your choice).Step 3 — Reply to Cursor
Use stubs for the missing components and implement the full dashboard.
Call scope_design_components again with:
figmaUrl: "https://www.figma.com/design/ABC123/MyApp?node-id=12-5"
framework: "react"
resolution: "stubs"
Then write all the code.Step 4 — Cursor builds everything
Cursor calls the tool a second time, gets the full context block, and writes code like this:
// Dashboard.tsx
// Generated using storybook-figma-mcp context
import { Button } from '@/components/Button'; // ✅ from Storybook
import { Card } from '@/components/Card'; // ✅ from Storybook
import { Input } from '@/components/Input'; // ✅ from Storybook
import { Sidebar } from './stubs/Sidebar'; // 🔨 stub — replace later
import { StatsCard } from './stubs/StatsCard'; // 🔨 stub — replace later
import { DataTable } from './stubs/DataTable'; // 🔨 stub — replace later
export function Dashboard() {
return (
<div className="dashboard">
<Sidebar />
<main>
<div className="stats-row">
<StatsCard title="Revenue" value="$12,400" />
<StatsCard title="Users" value="1,240" />
</div>
<DataTable />
</main>
</div>
);
}And the stubs themselves:
// stubs/StatsCard.tsx
// ⚠️ Stub — replace with real implementation from Storybook
interface StatsCardProps {
title: string;
value: string;
}
export function StatsCard({ title, value }: StatsCardProps) {
return (
<div style={{ padding: 16, background: 'rgb(99, 102, 241)' }}>
{/* TODO: Implement from Figma node: StatsCard */}
<p>{title}: {value}</p>
</div>
);
}The colors, spacing, and structure come directly from your Figma tokens — not invented by the AI.
How to Use It — Both Tools Explained
Tool 1: scope_design_components — Full design scoping
The main tool. Analyses an entire Figma screen or flow, checks your library, and guides you through building it.
First call (no resolution):
Use scope_design_components:
figmaUrl: "https://www.figma.com/design/ABC/App?node-id=5-10"
framework: "react"Second call (after you decide):
Call scope_design_components again:
figmaUrl: "https://www.figma.com/design/ABC/App?node-id=5-10"
framework: "react"
resolution: "build_in_library"Resolution options:
| Option | What it means | When to use it |
|--------|--------------|----------------|
| build_in_library | Build missing components as proper Storybook stories first | Best practice |
| stubs | Create placeholder components now, replace them later | Shipping fast |
| reduce_scope | Only use components that already exist | MVP / limited sprint |
Custom stub paths (optional):
resolution: "stubs"
customStubPaths: { "DataTable": "./src/components/stubs/DataTable.tsx" }Tool 2: get_component_context — Single component deep dive
Use this when you want everything about one specific component.
Use get_component_context:
figmaUrl: "https://www.figma.com/design/ABC/App?node-id=3-15"Returns Storybook props, variants, Figma design tree, and design tokens — all in one JSON.
More Example Prompts
Build a component from scratch
Use get_component_context for the ProductCard component.
figmaUrl: "https://www.figma.com/design/ABC/App?node-id=8-3"
Then implement it in React using:
- The exact props from the Storybook argTypes
- The colors from the design tokens
- The variants shown in FigmaScope a feature before a sprint
Our team is starting a new sprint on the checkout flow.
Use scope_design_components to give me a full inventory:
figmaUrl: "https://www.figma.com/design/ABC/App?node-id=22-1"
framework: "react"
I want to know the total build estimate and which components
we already have vs. need to build.Build only what exists (no new components)
Use scope_design_components to build the header component
using only what's already in our Storybook.
figmaUrl: "https://www.figma.com/design/ABC/App?node-id=4-7"
framework: "react"
resolution: "reduce_scope"
Don't build anything new — just compose from what we have.Add a missing component to Storybook
Use scope_design_components and then help me build
the missing components properly as Storybook stories.
figmaUrl: "https://www.figma.com/design/ABC/App?node-id=12-5"
framework: "react"
resolution: "build_in_library"
Start with the smallest missing component first.Configuration Options
All options
| What it does | CLI flag | Environment variable | Default |
|-------------|----------|---------------------|---------|
| Default Figma URL (so AI needs zero arguments) | (positional arg) | FIGMA_DEFAULT_URL | — |
| Figma Desktop MCP URL | --figma-mcp-url | FIGMA_MCP_URL | http://127.0.0.1:3845/mcp |
| Figma Remote API key | --figma-api-key | FIGMA_API_KEY | — (not needed for Desktop) |
| Storybook MCP URL | --storybook-mcp-url | STORYBOOK_MCP_URL | http://localhost:6006/mcp |
Examples
# Minimal — just the Figma URL
storybook-figma-mcp "https://www.figma.com/design/ABC/App?node-id=1-2"
# With custom Storybook URL
storybook-figma-mcp "https://..." --storybook-mcp-url http://localhost:9009/mcp
# Using environment variables
export FIGMA_DEFAULT_URL="https://www.figma.com/design/ABC/App?node-id=1-2"
export STORYBOOK_MCP_URL="http://localhost:6006/mcp"
storybook-figma-mcpUsing Figma Remote (No Desktop App)
If you can't use Figma Desktop, connect to Figma's cloud API instead.
Step 1: Get a Figma API token
- Go to figma.com → click your avatar → Settings
- Scroll to Personal access tokens → Generate a new token
- Copy it — you won't see it again
Step 2: Add to your MCP config
{
"mcpServers": {
"storybook-figma": {
"command": "storybook-figma-mcp",
"args": [
"https://www.figma.com/design/ABC/App?node-id=1-2",
"--figma-mcp-url", "https://mcp.figma.com/mcp",
"--figma-api-key", "fig-pat-YOUR_TOKEN_HERE"
]
}
}
}Troubleshooting
"No Storybook MCP found" — is this bad?
No. This is the most common message and it's completely fine.
⚠ No Storybook MCP at http://localhost:6006/mcp
Starting built-in fallback (reads local .stories.* files)It means the package switched to reading your .stories.ts/tsx/js/jsx/vue/svelte files directly from disk. Everything still works.
To use your full Storybook MCP instead, start Storybook first: npm run storybook.
Figma returns empty / no design data
- Make sure you're using Figma Desktop (not just the browser)
- Figma Desktop → Preferences → Dev Mode → check that Enable MCP Server is on
- Right-click any frame in Figma → Copy link to get the correct URL with the right node ID
"FIGMA_API_KEY not set" warning
Only relevant if your --figma-mcp-url starts with https:// (remote Figma). For Figma Desktop, ignore this.
scope_design_components returns state: "STUCK"
The agent couldn't reach Figma or Storybook. The response includes a question field — read it, it tells you exactly what to check.
Tool doesn't appear in Cursor / Claude
Restart your editor after adding the MCP config.
Requirements
- Node.js 22 or newer — check with
node --version - Storybook 8+ with
@storybook/addon-mcpinstalled — optional, but required for accurate component matching - Figma Desktop with MCP enabled, OR a Figma API token for remote access
Programmatic Usage (Advanced)
import { createServer, loadConfig } from "storybook-figma-mcp";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const config = loadConfig({
defaultFigmaUrl: "https://www.figma.com/design/ABC/App?node-id=1-2",
});
const server = createServer(config);
await server.connect(new StdioServerTransport());Available exports:
import {
createServer, // Create the MCP server
loadConfig, // Load config from env / overrides
parseFigmaUrl, // Parse a Figma URL → { fileKey, nodeId }
scanStories, // Find all .stories.* files in a directory
parseStoryFile, // Parse one .stories.* file → StoryMetadata
callFigmaTool, // Call any Figma MCP tool directly
callStorybookTool, // Call any Storybook MCP tool directly
parseTokens, // Parse raw Figma variable data → { colors, spacing, typography }
extractComponentsFromTree, // Extract component names from a Figma design tree
normalizeComponentName, // Convert "button / primary" → "ButtonPrimary"
} from "storybook-figma-mcp";
import type {
Config,
ComponentContext, // get_component_context response
ScopedBuildSpec, // scope_design_components OUTPUT_CONTEXT response
InteractResult, // scope_design_components INTERACT response
StuckResult, // scope_design_components STUCK response
MatchedComponent,
} from "storybook-figma-mcp";License
MIT
