Sunnyside Figma Context MCP
Skill by ara.so — Design Skills collection
A Model Context Protocol (MCP) server providing 27 specialized tools to bridge Figma designs with AI development workflows. Supports two data paths: Figma Plugin (highest fidelity, works on any plan including Drafts) and Figma REST API (headless, requires team/project files).
Installation
Prerequisites:
- Node.js 18+
- Figma Personal Access Token (create here)
git clone https://github.com/tercumantanumut/sunnysideFigma-Context-MCP
cd sunnysideFigma-Context-MCP
npm install
npm run build
Environment configuration (.env):
FIGMA_API_KEY=figd_your_token_here
PORT=3333
OUTPUT_FORMAT=json
Start the server:
npm start
# Server runs on http://localhost:3333
# SSE endpoint: /sse
# HTTP endpoint: /mcp
MCP Client Configuration
SSE Transport (Recommended for Plugin Use)
Use when you need the Figma plugin and MCP tools to share extraction state:
{
"mcpServers": {
"sunnyside-figma": {
"type": "sse",
"url": "http://localhost:3333/sse"
}
}
}
stdio Transport
For headless use without plugin integration:
{
"mcpServers": {
"sunnyside-figma": {
"type": "stdio",
"command": "node",
"args": [
"/absolute/path/to/sunnysideFigma-Context-MCP/dist/cli.js",
"--stdio"
],
"env": {
"FIGMA_API_KEY": "figd_your_token_here"
}
}
}
}
HTTP Transport
{
"mcpServers": {
"sunnyside-figma": {
"type": "http",
"url": "http://localhost:3333/mcp"
}
}
}
Figma Plugin Setup
- Open Figma Desktop → Plugins → Development → Import plugin from manifest…
- Navigate to
figma-dev-plugin/manifest.jsonin the cloned repo - Run the plugin on any file
- Select a frame → click Extract Dev Code
The plugin sends extraction data to http://localhost:3333/plugin/* endpoints.
Core Tool Categories
Plugin-Bridge Tools (Highest Fidelity)
These tools read data extracted by the Figma plugin. No API limits, works on Drafts.
get_JSON — Primary extraction tool, returns comprehensive structured data:
// Returns:
{
id: string,
name: string,
type: string,
layoutMode?: string,
primaryAxisAlignItems?: string,
counterAxisAlignItems?: string,
paddingLeft?: number,
// ... full layout properties
fills: Array<{type: string, color: {r, g, b, a}, opacity?: number}>,
strokes: Array<any>,
effects: Array<any>,
variables: {[key: string]: {resolvedType: string, value: any}},
designTokens: {[category: string]: {[token: string]: any}},
allLayersCSS: {[layerId: string]: string} // CSS for every layer
}
get_figma_dev_history — List all past extractions:
// Returns array of:
{
id: string,
name: string,
timestamp: string,
type?: string,
layoutMode?: string
}
get_Basic_CSS — Root-level CSS only:
// Arguments: { extractionId?: string }
// Returns: CSS string from getCSSAsync()
get_All_Layers_CSS — CSS for every layer in selection:
// Arguments: { extractionId?: string }
// Returns: { [layerId: string]: string }
Code Generation Tools
get_react_component — TypeScript React + CSS module:
// Arguments: { extractionId?: string }
// Returns:
{
component: string, // .tsx file
styles: string // .module.css file
}
get_tailwind_component — React with Tailwind classes:
// Arguments: { extractionId?: string }
// Returns: Single-file React component with inline Tailwind classes
get_styled_component — React + styled-components:
// Arguments: { extractionId?: string }
// Returns: React component with styled-components CSS-in-JS
Design Token Lifecycle
extract_design_tokens — Build token catalog from selection:
// Arguments: { extractionId?: string }
// Returns:
{
colors: {[name: string]: {value: string, type: string}},
spacing: {[name: string]: {value: string, type: string}},
typography: {[name: string]: {value: string, type: string}},
// ... other categories
}
simulate_token_change — Dry-run a token modification:
// Arguments:
{
tokenPath: string, // e.g., "colors.primary.500"
newValue: any,
reason?: string
}
// Returns: { simulationId: string, affected: string[] }
analyze_token_change_impact — Blast-radius analysis:
// Arguments: { simulationId: string }
// Returns:
{
affectedNodes: Array<{id, name, currentValue, newValue}>,
breakingChanges: Array<{issue, severity}>,
recommendations: string[]
}
apply_token_change — Commit a simulated change:
// Arguments: { simulationId: string }
// Returns: { success: boolean, appliedChanges: number }
rollback_token_change — Revert an applied change:
// Arguments: { simulationId: string }
// Returns: { success: boolean, rolledBackChanges: number }
generate_migration_code — Produce codemod output:
// Arguments: { simulationId: string, format?: 'js' | 'ts' | 'css' }
// Returns: { code: string, instructions: string }
track_design_system_health — Coverage & conflict report:
// Returns:
{
tokenCoverage: number, // percentage
conflicts: Array<{token, instances, values}>,
orphanedTokens: string[],
recommendations: string[]
}
Figma REST API Tools
Require FIGMA_API_KEY and file access (team/project). Do not work on Drafts.
get_figma_data — Raw file or node JSON:
// Arguments:
{
fileKey: string, // From Figma URL
nodeId?: string // Optional: specific node
}
// Returns: Full Figma API response
get_figma_page_structure — Page-level tree:
// Arguments: { fileKey: string }
// Returns:
{
pages: Array<{
id: string,
name: string,
children: Array<{id, name, type}>
}>
}
download_figma_images — Batch export assets:
// Arguments:
{
fileKey: string,
nodeIds: string[],
format: 'svg' | 'png' | 'jpg',
scale?: number,
outputDir?: string
}
// Returns: { downloads: Array<{nodeId, path}> }
analyze_figma_components — Component detection:
// Arguments: { fileKey: string }
// Returns:
{
components: Array<{
id: string,
name: string,
description?: string,
instances: number
}>
}
Figma Dev Mode Tools (Professional Plan Only)
Bridge to Figma's official Dev Mode MCP Server (localhost:3845).
check_figma_dev_connection — Test Dev Mode server:
// No arguments
// Returns: { connected: boolean, error?: string }
get_figma_dev_mode_code — Official React + Tailwind generator:
// Arguments: { fileKey: string, nodeId: string }
// Returns: { code: string, format: string }
Common Usage Patterns
Pattern 1: Extract and Generate Component
// User selects a frame in Figma and runs the plugin.
// Agent workflow:
// 1. Check extraction history
const history = await use_mcp_tool("sunnyside-figma", "get_figma_dev_history", {});
const latestExtraction = history[0];
// 2. Get full structured data
const data = await use_mcp_tool("sunnyside-figma", "get_JSON", {
extractionId: latestExtraction.id
});
// 3. Generate Tailwind component
const component = await use_mcp_tool("sunnyside-figma", "get_tailwind_component", {
extractionId: latestExtraction.id
});
// Write component to file
await writeFile("./components/HeroSection.tsx", component);
Pattern 2: Design System Audit
// User clicks "Scan Entire Project" in plugin
// 1. Get project overview
const overview = await use_mcp_tool("sunnyside-figma", "get_plugin_project_overview", {});
// 2. Extract design tokens
const tokens = await use_mcp_tool("sunnyside-figma", "extract_design_tokens", {});
// 3. Check health metrics
const health = await use_mcp_tool("sunnyside-figma", "track_design_system_health", {});
// 4. Report conflicts
if (health.conflicts.length > 0) {
console.log("Token conflicts detected:");
health.conflicts.forEach(conflict => {
console.log(`- ${conflict.token}: ${conflict.instances} instances with different values`);
});
}
Pattern 3: Safe Token Migration
// User wants to rename "primary-500" to "brand-primary"
// 1. Simulate the change
const simulation = await use_mcp_tool("sunnyside-figma", "simulate_token_change", {
tokenPath: "colors.primary.500",
newValue: "brand-primary",
reason: "Align with new brand guidelines"
});
// 2. Analyze impact
const impact = await use_mcp_tool("sunnyside-figma", "analyze_token_change_impact", {
simulationId: simulation.simulationId
});
console.log(`Affects ${impact.affectedNodes.length} nodes`);
console.log(`Breaking changes: ${impact.breakingChanges.length}`);
// 3. Generate migration code
const migration = await use_mcp_tool("sunnyside-figma", "generate_migration_code", {
simulationId: simulation.simulationId,
format: "ts"
});
await writeFile("./migrations/rename-primary-token.ts", migration.code);
// 4. If safe, apply
if (impact.breakingChanges.length === 0) {
await use_mcp_tool("sunnyside-figma", "apply_token_change", {
simulationId: simulation.simulationId
});
}
Pattern 4: Headless Asset Export from URL
// User provides Figma URL: https://www.figma.com/file/ABC123/Design?node-id=10%3A52
// 1. Parse URL
const fileKey = "ABC123";
const nodeId = "10:52";
// 2. Get node data
const nodeData = await use_mcp_tool("sunnyside-figma", "get_figma_data", {
fileKey,
nodeId
});
// 3. Export as SVG
const exports = await use_mcp_tool("sunnyside-figma", "download_figma_images", {
fileKey,
nodeIds: [nodeId],
format: "svg",
outputDir: "./assets"
});
console.log(`Exported to: ${exports.downloads[0].path}`);
Pattern 5: Multi-Layer CSS Extraction
// User selects complex component with nested layers
// 1. Get latest extraction
const history = await use_mcp_tool("sunnyside-figma", "get_figma_dev_history", {});
const extractionId = history[0].id;
// 2. Get CSS for all layers
const allCSS = await use_mcp_tool("sunnyside-figma", "get_All_Layers_CSS", {
extractionId
});
// 3. Get structured data for layer names
const data = await use_mcp_tool("sunnyside-figma", "get_JSON", {
extractionId
});
// 4. Build CSS module with named classes
let cssModule = "";
Object.entries(allCSS).forEach(([layerId, css]) => {
const layerName = findLayerName(data, layerId);
cssModule += `.${toClassName(layerName)} {\n${css}\n}\n\n`;
});
await writeFile("./styles/component.module.css", cssModule);
Troubleshooting
"No extracted data available"
Cause: Plugin hasn't sent data or client is using stdio (separate process).
Solution:
- Re-open Figma plugin and click Extract Dev Code
- If using stdio transport, switch to SSE to share state with the HTTP server:
{ "mcpServers": { "sunnyside-figma": { "type": "sse", "url": "http://localhost:3333/sse" } } }
Figma REST API 404 / Timeout
Cause: File is in Drafts or token lacks access.
Solution:
- Move file from Drafts to a team/project
- Verify
FIGMA_API_KEYhas correct permissions - Fallback to plugin-bridge tools (work on Drafts)
check_figma_dev_connection Fails
Cause: Figma Dev Mode MCP Server not enabled or Free plan.
Solution:
- Requires Figma Professional plan
- Enable in Figma Desktop: Preferences → Enable local MCP Server
- Dev Mode server must be running on
localhost:3845 - Free plan users: use plugin-bridge tools instead
Server Won't Start on Port 3333
Cause: Port already in use.
Solution:
# Change in .env
PORT=3334
Update MCP client URL: http://localhost:3334/sse
Token Simulation Not Showing Changes
Cause: Simulation not applied or extraction is stale.
Solution:
- Check simulation list:
await use_mcp_tool("sunnyside-figma", "list_token_simulations", {}); - Apply simulation:
await use_mcp_tool("sunnyside-figma", "apply_token_change", { simulationId: "sim-123" }); - Re-extract from Figma plugin to see changes
Plugin Shows "Failed to Send Data"
Cause: MCP server not running or wrong port.
Solution:
- Verify server is running:
npm start - Check console for
Server running on port 3333 - Plugin sends to hardcoded
localhost:3333— if using different port, update plugin code:// figma-dev-plugin/code.ts const response = await fetch('http://localhost:YOUR_PORT/plugin/extract', { method: 'POST', // ... });
Key Configuration Options
Environment Variables:
# Required
FIGMA_API_KEY=figd_your_token_here
# Optional
PORT=3333 # HTTP server port
OUTPUT_FORMAT=json # Response format (json | text)
FIGMA_DEV_MODE_URL=http://localhost:3845 # Official Dev Mode server
Plugin Configuration:
Edit figma-dev-plugin/manifest.json to adjust plugin metadata:
{
"name": "Sunnyside Dev Extractor",
"id": "your-plugin-id",
"api": "1.0.0",
"main": "code.js",
"ui": "ui.html",
"editorType": ["figma"]
}
Development Commands
npm run dev # Watch mode build (tsup)
npm run dev:cli # stdio development loop
npm run type-check # TypeScript validation
npm run lint # ESLint
npm test # Jest test suite
npm run inspect # Open MCP inspector UI
npm run build # Production build
Tool Selection Guide
| Goal | Use Tool | Why |
|---|---|---|
| Get comprehensive layer data | get_JSON |
Single call returns layout, fills, variables, tokens, and CSS for all layers |
| Generate production component | get_tailwind_component or get_react_component |
Ready-to-use code with styling |
| Audit design system | get_plugin_project_overview + track_design_system_health |
Full project scan with token coverage |
| Plan token refactor | simulate_token_change → analyze_token_change_impact |
Safe what-if analysis |
| Export assets headlessly | download_figma_images |
Batch SVG/PNG export from file key |
| Use official Figma codegen | get_figma_dev_mode_code |
Requires Pro plan, uses Figma's generator |
Plugin vs. REST API decision tree:
- Need Drafts support? → Plugin tools
- Headless automation? → REST API tools
- Highest CSS fidelity? → Plugin (uses native
getCSSAsync()) - Batch export many files? → REST API tools
Advanced: Token Registry Architecture
The token lifecycle tools maintain an in-memory registry:
// Internal structure (reference only)
interface TokenRegistry {
tokens: Map<string, {
value: any,
type: string,
path: string[]
}>,
dependencies: Map<string, Set<string>>, // token -> nodeIds
simulations: Map<string, {
changes: Array<{tokenPath, oldValue, newValue}>,
applied: boolean
}>
}
Query registry state:
const registry = await use_mcp_tool("sunnyside-figma", "debug_token_registry", {});
Build dependency graph:
const graph = await use_mcp_tool("sunnyside-figma", "build_dependency_graph", {
extractionId: "latest"
});
// Returns: { tokens: {...}, edges: [...] }
This enables surgical updates: when a token changes, only affected components need regeneration.