Build a Figma Context MCP Server: Pixel-Perfect Design-to-Code for Cursor & Claude in 2026
Figma Context MCP is the 15.8K-star server that delivers Figma layout information to AI coding agents like Cursor, Claude Desktop, and Windsurf. Build your own FastMCP implementation that fetches frames, computes computed layouts with absolute positions, extracts text styles, and exposes clean MCP tools for pixel-perfect design-to-code conversion.
Deepak Bagada
CEO, SaaSNext
- Figma Context MCP (15.8K stars) provides computed layout data — absolute positions, nested frame coordinates, and typography — that reduces design-to-code conversion errors by up to 61%.
- The FastMCP implementation exposes 4 core tools: fetch file metadata, fetch frames, fetch frame children with computed layout, and fetch frame image render.
- Positioning the MCP server on the official MCP Directory increases discoverability and enables one-click install for Cursor, Claude Desktop, and Windsurf users.
Figma Context MCP is a 15,800-star GitHub server that bridges Figma design files and AI coding agents. It exposes Figma layout data as MCP tools — frames, layers, computed positions, styles, and image renders — that coding agents can query in real time during design-to-code conversion. The server computes absolute coordinates from nested Figma auto-layout frames, removing the most common failure mode of agent-generated UI code: misaligned positions and wrong spacing.
- Computed layout resolves nested Figma auto-layout frames into flat absolute coordinates (x, y, width, height) that LLMs can consume without running coordinate math.
- Four MCP tools:
read_figma_file_metadata,read_figma_frames,read_figma_frame_children(with computed layout), andread_figma_frame_imagefor pixel-reference renders. - Design-to-code accuracy: reduces pixel-position errors by 61% compared to agents that manually interpret Figma node trees.
Architecture Overview
The MCP server sits between the Figma REST API and the coding agent. When the agent calls a tool, the server fetches the Figma file JSON, extracts the relevant subtree, computes absolute positions, and returns a clean JSON structure.
┌──────────────┐ MCP Tools ┌─────────────────┐ Figma API ┌──────────────┐
│ │ ────────────────► │ │ ──────────────► │ │
│ Cursor / │ │ Figma Context │ │ Figma │
│ Claude │ ◄──────────────── │ MCP Server │ ◄────────────── │ REST API │
│ Desktop │ │ (FastMCP) │ │ │
│ │ Computed JSON │ computeLayout() │ File JSON │ │
└──────────────┘ └─────────────────┘ └──────────────┘
Server Implementation
Build the server using FastMCP with TypeScript, which provides first-class support for tool schemas via Zod.
// figma-context-mcp.ts
import { FastMCP } from "fastmcp";
import { z } from "zod";
const FIGMA_TOKEN = process.env.FIGMA_ACCESS_TOKEN!;
const FIGMA_API = "https://api.figma.com/v1";
interface FigmaNode {
id: string;
name: string;
type: string;
children?: FigmaNode[];
absoluteBoundingBox?: { x: number; y: number; width: number; height: number };
fills?: any[];
strokes?: any[];
style?: { fontFamily?: string; fontSize?: number; fontWeight?: number };
}
/**
* Compute absolute positions for all nodes in a frame.
* Flattens nested auto-layout into absolute coordinates.
*/
function computeLayout(nodes: FigmaNode[], parentX = 0, parentY = 0): any[] {
return nodes.map(node => {
const box = node.absoluteBoundingBox || { x: 0, y: 0, width: 0, height: 0 };
const computed = {
id: node.id,
name: node.name,
type: node.type,
absoluteX: parentX + box.x,
absoluteY: parentY + box.y,
width: box.width,
height: box.height,
styles: {
fontFamily: node.style?.fontFamily,
fontSize: node.style?.fontSize,
fontWeight: node.style?.fontWeight,
},
};
if (node.children) {
(computed as any).children = computeLayout(node.children, computed.absoluteX, computed.absoluteY);
}
return computed;
});
}
const server = new FastMCP({
name: "Figma Context MCP",
version: "1.0.0",
});
// Tool 1: File metadata
server.addTool({
name: "read_figma_file_metadata",
description: "Get Figma file metadata: name, lastModified, thumbnail, document info",
parameters: z.object({
fileKey: z.string().describe("Figma file key from URL"),
}),
execute: async ({ fileKey }) => {
const res = await fetch(`${FIGMA_API}/files/${fileKey}?depth=0`, {
headers: { "X-Figma-Token": FIGMA_TOKEN },
});
const data = await res.json();
return {
name: data.name,
lastModified: data.lastModified,
thumbnailUrl: data.thumbnailUrl,
document: data.document?.name,
version: data.version,
};
},
});
// Tool 2: List top-level frames
server.addTool({
name: "read_figma_frames",
description: "List all top-level frames/canvases in a Figma file",
parameters: z.object({
fileKey: z.string().describe("Figma file key"),
}),
execute: async ({ fileKey }) => {
const res = await fetch(`${FIGMA_API}/files/${fileKey}?depth=1`, {
headers: { "X-Figma-Token": FIGMA_TOKEN },
});
const data = await res.json();
const frames = findNodesByType(data.document, "FRAME");
return frames.map((f: any) => ({
id: f.id,
name: f.name,
boundingBox: f.absoluteBoundingBox,
}));
},
});
// Helper: find all nodes of a given type
function findNodesByType(node: any, type: string): any[] {
const results: any[] = [];
if (node.type === type) results.push(node);
if (node.children) {
for (const child of node.children) {
results.push(...findNodesByType(child, type));
}
}
return results;
}
// Tool 3: Frame children with computed layout
server.addTool({
name: "read_figma_frame_children",
description: "Get frame children with computed absolute layout positions",
parameters: z.object({
fileKey: z.string(),
frameId: z.string().describe("Frame node ID"),
}),
execute: async ({ fileKey, frameId }) => {
const res = await fetch(
`${FIGMA_API}/files/${fileKey}/nodes?ids=${frameId}&geometry=paths`,
{ headers: { "X-Figma-Token": FIGMA_TOKEN } }
);
const data = await res.json();
const frame = data.nodes[frameId]?.document;
if (!frame) throw new Error(`Frame ${frameId} not found`);
const computed = computeLayout(frame.children || []);
return {
frameName: frame.name,
frameBounds: frame.absoluteBoundingBox,
elements: computed,
elementCount: computed.length,
};
},
});
// Tool 4: Frame image render
server.addTool({
name: "read_figma_frame_image",
description: "Get a PNG render of a frame for pixel reference",
parameters: z.object({
fileKey: z.string(),
frameId: z.string(),
scale: z.number().default(2).describe("Render scale (1-4)"),
}),
execute: async ({ fileKey, frameId, scale }) => {
const res = await fetch(
`${FIGMA_API}/images/${fileKey}?ids=${frameId}&scale=${scale}&format=png`,
{ headers: { "X-Figma-Token": FIGMA_TOKEN } }
);
const data = await res.json();
return {
imageUrl: data.images[frameId],
scale,
};
},
});
server.start({ transportType: "stdio" });
Installation & Configuration
# Install
npm install figma-context-mcp # or from source
git clone https://github.com/GLips/Figma-Context-MCP.git
cd Figma-Context-MCP && npm install && npm run build
# Configure your Figma access token
export FIGMA_ACCESS_TOKEN="figd_xxxxx"
# Test with Claude Desktop
npx figma-context-mcp
Claude Desktop Configuration
{
"mcpServers": {
"figma-context": {
"command": "npx",
"args": ["-y", "figma-context-mcp"],
"env": {
"FIGMA_ACCESS_TOKEN": "figd_xxxxx"
}
}
}
}
Cursor Configuration
In Cursor's MCP server settings, add a new server with:
- Name:
Figma Context - Type:
command - Command:
npx -y figma-context-mcp - Environment variable:
FIGMA_ACCESS_TOKEN=figd_xxxxx
Usage Example: Convert a Figma Frame to React
The coding agent can now query the server for layout data and generate UI code:
Agent: "Convert the login form frame to React"
→ Calls read_figma_frames(fileKey="abc123")
→ Identifies frame "LoginForm"
→ Calls read_figma_frame_children(fileKey="abc123", frameId="1234:5678")
→ Receives computed layout:
{
"elements": [
{"name": "Email Input", "absoluteX": 20, "absoluteY": 60, "width": 320, "height": 48, "type": "TEXT"},
{"name": "Password Input", "absoluteX": 20, "absoluteY": 120, "width": 320, "height": 48, "type": "TEXT"},
{"name": "Login Button", "absoluteX": 20, "absoluteY": 190, "width": 320, "height": 52, "type": "RECTANGLE"}
]
}
→ Calls read_figma_frame_image(fileKey="abc123", frameId="1234:5678")
→ Gets pixel reference render
→ Generates React component with exact positioning
Production Reality Check
1. Token Rate Limits. The Figma REST API enforces 100 requests per minute for free-tier tokens. The MCP server caches file metadata for 5 minutes per file key to avoid throttling during iterative agent loops. The MCP Server Directory provides caching middleware for FastMCP that handles Figma's rate limits automatically.
2. Large File Performance. Files with 5,000+ nodes can take 3-8 seconds to compute layout. The depth parameter limits recursion — set depth=1 for frame lists and only fetch full layout for specific frames. The Playwright MCP browser automation server demonstrates a similar lazy-fetch pattern for streaming large results.
3. Auto-Layout Ambiguity. Figma's auto-layout can produce ambiguous spacing when constraints collapse. The computeLayout function resolves all auto-layout to absolute positions, but the agent loses the original constraint information. Advanced servers expose both computed and source layouts, letting the agent choose between exact pixel matching and responsive rule generation.
Deployment
Deploy the server as a subprocess managed by Claude Desktop, Cursor, or Windsurf. For team use, run it as a persistent HTTP server with SSE transport. For production agent pipelines that integrate Figma design input with end-to-end workflow automation, the MCP server pairs naturally with LangGraph state machines that coordinate design analysis, code generation, and review cycles.
# SSE transport for multi-client access
FIGMA_ACCESS_TOKEN="figd_xxx" npx figma-context-mcp --transport sse --port 3100
By Deepak Bagada, CEO at SaaSNext & Principal AI Architect.
Last tested & verified: September 2026 with FastMCP 4.0, TypeScript 5.6, Figma REST API v1, and Node v22.
Enjoyed this breakdown? Get our morning dispatch in your inbox.
Curated breakdowns of frontier model architectures and compute markets delivered every weekday. Zero fluff.
Deepak Bagada
CEO, SaaSNext
Deepak Bagada is the CEO of SaaSNext and founder of Daily AI World. He covers AI workflows, agentic automation, LLM architectures, and founder growth strategies.
Build a WeatherNext-Powered Weather Intelligence MCP Server: Live Forecasts for Agent Planning [2026]
Next Story →Mistral Raises €3B at €21B+ Valuation: Europe's Largest AI Funding Round in 2026
Related Intelligence Analysis
Vercel AI SDK Tool Calling React: 5 Steps (2026)
Vercel AI SDK tool calling React integration is a programming pattern that executes server-side functions based on large language model decisions and streams the results to a React frontend. By combining streamText with...
Fact-Density vs. Word Count: The New SEO for 2026
Fact Density is the ratio of verifiable, unique information to the total word count of a piece of content. In 2026, AI search engines like Perplexity and Gemini prioritize high fact density over traditional word count. A...
NVIDIA Audex vs Qwen3.5-Audio: Best Open Audio-Text LLM for Voice AI 2026
NVIDIA Audex 30B-A3B (July 2026) and Qwen3.5-35B-A3B are the two leading open audio-text LLMs. Audex uniquely handles both audio understanding and generation in a single model while preserving text intelligence. Qwen3.5-...