Using the use_figma Tool for Programmatic Figma File Editing: Complete MCP Guide
The use_figma tool executes JavaScript in a headless Figma Plugin API runtime, requiring the figma-use skill to enforce 17 critical safety rules that ensure atomic execution and return-based communication.
The Figma MCP Server Guide repository enables AI agents to manipulate Figma files programmatically through the use_figma tool. Unlike traditional Figma plugins, this tool operates within a constrained, headless environment where every script execution is atomic and validated against strict runtime constraints defined in skills/figma-use/SKILL.md.
Core Architecture and Safety Model
The use_figma tool operates on a skill-driven architecture that prioritizes file safety and deterministic execution.
Skill-Driven Workflow
Every use_figma invocation must be preceded by loading the figma-use skill, which encodes mandatory operational rules. The skill definition resides at skills/figma-use/SKILL.md and establishes the contract between the AI agent and the headless runtime.
Atomic Execution Guarantees
The runtime executes scripts atomically—if any of the 17 critical constraints in SKILL.md are violated, the entire operation fails immediately and makes no changes to the design file. This atomicity enables safe retry patterns: you can fix errors and re-run without risk of partial mutations corrupting the document.
Return-Based Communication Pattern
Unlike standard Figma plugins, use_figma prohibits console.log and figma.closePlugin. The only communication channel is the JSON-serializable return value. All created or modified node IDs must be explicitly returned to enable reference in subsequent calls.
Critical Rules and Constraints
The figma-use skill mandates 17 non-negotiable constraints covering color ranges, async handling, page resets, and node manipulation. Key rules include:
- Color values must use 0-1 floating point ranges, not 0-255 (Rule 6)
- Page navigation requires
await figma.setCurrentPageAsync(page); the synchronous setter throws an error (Rule 9) - Node appending must occur before any
layoutSizingmodifications (Rule 12) - ID tracking requires returning all created or mutated node IDs (Rule 15)
- Incremental work recommends splitting large operations into separate atomic calls (Rule 5)
Working with Pages and Context
Each use_figma invocation automatically resets to the first page of the target file. To operate on other pages, you must explicitly switch context:
const targetPage = figma.root.children.find(p => p.name === "Landing");
await figma.setCurrentPageAsync(targetPage);
This asynchronous requirement differs from standard plugin development, where figma.currentPage might be synchronous. The deprecated synchronous setter throws an error in the headless environment.
Practical Implementation Examples
The following patterns demonstrate compliant use_figma workflows from the skill documentation.
Inspecting File Structure (Read-Only)
Start with inspection to understand the document structure before mutation:
const pages = figma.root.children.map(p => ({
name: p.name,
id: p.id,
childCount: p.children.length,
}));
return { pages };
Creating Shapes with Validation
Create a rectangle on a specific page while respecting color range and appending rules:
// Switch to the target page
const targetPage = figma.root.children.find(p => p.name === "Landing");
await figma.setCurrentPageAsync(targetPage);
// Create a rectangle
const rect = figma.createRectangle();
rect.resize(200, 100);
rect.x = 300; // position away from (0,0) to avoid overlap
rect.fills = [{ type: "SOLID", color: { r: 1, g: 0, b: 0 } }]; // 0-1 range
// Append to page (must happen before layoutSizing changes)
targetPage.appendChild(rect);
return { createdNodeIds: [rect.id] };
Managing Design Tokens and Variables
Complex operations should follow the incremental approach, splitting creation and binding into separate atomic calls:
Step A: Create the variable collection and color token.
const coll = await figma.variables.createLocalVariableCollectionAsync("Design Tokens");
const colorVar = await coll.createVariableAsync("primaryRed", "COLOR");
await colorVar.setValueAsync({ r: 1, g: 0, b: 0 });
await colorVar.setScopesAsync(["FRAME_FILL", "SHAPE_FILL"]);
return { collectionId: coll.id, variableId: colorVar.id };
Step B: Bind the variable to an existing rectangle using IDs returned from previous operations.
const rect = figma.getNodeById('YOUR_RECT_ID_HERE'); // replace with ID from previous return
const paint = { type: "SOLID", color: { r: 1, g: 0, b: 0 } };
const boundPaint = await figma.createPaintStyleAsync();
boundPaint.paints = [paint];
const bound = await figma.setBoundVariableForPaintAsync(boundPaint.id, colorVar.id);
rect.fills = [bound];
return { mutatedNodeIds: [rect.id] };
Supported API Surface
The headless runtime implements the full Figma Plugin API surface defined in skills/figma-use/references/plugin-api-standalone.d.ts, with exceptions for UI-only methods such as figma.notify and getPluginData. For method availability and type safety, reference the typings file rather than standard Figma plugin documentation.
Error Recovery and Debugging
When scripts fail, the atomic execution model ensures the file remains unmodified. The Error Recovery & Self-Correction table in skills/figma-use/SKILL.md maps common error messages to specific fixes. Since partial states cannot occur, you can safely iterate on your code until it passes all 17 validation constraints.
Essential Reference Files
skills/figma-use/SKILL.md– Mandatory skill definition containing the 17 critical rules and workflow guidanceskills/figma-use/references/plugin-api-standalone.d.ts– Complete TypeScript typings for the supported Plugin API surfaceskills/figma-use/references/api-reference.md– Quick lookup for supported vs. unsupported methodsskills/figma-use/references/gotchas.md– Real-world pitfalls with before-and-after code correctionsskills/figma-use/references/variable-patterns.md– Best practices for design token creation and scopingskills/figma-use/references/component-patterns.md– Component set and variant construction guides
Summary
- Atomic execution ensures failed
use_figmascripts make zero changes to your Figma files - Mandatory skill loading of
figma-useenforces 17 safety constraints that differ from standard plugin development - Return-value communication replaces
console.logandfigma.closePluginfor data extraction - Asynchronous page navigation requires
await figma.setCurrentPageAsync()instead of synchronous assignment - Incremental workflows split complex operations into multiple atomic calls, returning node IDs for chaining
Frequently Asked Questions
What happens if a use_figma script encounters an error?
The script fails entirely and makes no changes to the file due to atomic execution. Unlike traditional Figma plugins where partial mutations might persist, the headless runtime rolls back all operations when any of the 17 critical rules are violated, allowing safe retries after fixes.
How do I debug code when console.log is not supported?
You must use the return statement to output debugging information. Return objects containing inspection data, variable states, or node properties, then examine the JSON response. The use_figma environment ignores console.log calls entirely, and figma.closePlugin is prohibited.
Can I use the full standard Figma Plugin API with use_figma?
Nearly all standard methods are available except UI-specific functions like figma.notify and getPluginData. The authoritative source is skills/figma-use/references/plugin-api-standalone.d.ts in the figma/mcp-server-guide repository, which defines the exact surface area available in the headless environment.
Why must I return node IDs from every creation operation?
The use_figma runtime resets between calls and starts on the first page each time. Without returning IDs like rect.id or collectionId, subsequent invocations cannot reference created nodes. This return-based reference system enables multi-step workflows while maintaining stateless, atomic execution.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →