All skills
figma avatar

/figma-use

@1729207 official
by figmafigma/mcp-server-guide2k stars
194

**MANDATORY prerequisite** — you MUST invoke this skill BEFORE every `use_figma` tool call. NEVER call `use_figma` directly without loading this skill first. Skipping it causes common, hard-to-debug failures. Trigger whenever the user wants to perform a write action or a unique read action that requires JavaScript execution in the Figma file context — e.g. create/edit/delete nodes, set up variables or tokens, build components and variants, modify auto-layout or fills, bind variables to properties, or inspect file structure programmatically.

Use this Skill: https://skilld.dev/gh/figma/mcp-server-guide/figma-use

This session only. Nothing lands on disk.

referencesapi-reference.md

≈3.2k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Figma Plugin API Reference

Part of the use_figma skill. What works and what doesn't in the use_figma environment.

Contents

  • Node Creation
  • Grouping and Boolean Operations
  • Library Imports
  • Variables API
  • Core Properties
  • Node Manipulation
  • Descriptions and Documentation Links
  • SVG and Images
  • Utilities and Plugin Lifecycle
  • Node Traversal
  • Unsupported APIs

Node Creation (Design Mode)

figma.createRectangle()
figma.createFrame()
figma.createAutoLayout()        // Frame with auto layout enabled, both axes hug — prefer over createFrame() for layout containers
figma.createAutoLayout("VERTICAL") // Same but vertical direction
figma.createComponent()         // Creates a ComponentNode
figma.createText()
figma.createEllipse()
figma.createStar()
figma.createLine()
figma.createVector()
figma.createPolygon()
figma.createBooleanOperation()
figma.createSlice()
figma.createPage()              // Page node can be created, but child persistence is limited in use_figma
figma.createSection()
figma.createTextPath()

Grouping & Boolean Operations

figma.group(nodes, parent, index?)              // Group nodes
figma.flatten(nodes, parent?, index?)           // Flatten to vector
figma.union(nodes, parent?, index?)             // Boolean union
figma.subtract(nodes, parent?, index?)          // Boolean subtract
figma.intersect(nodes, parent?, index?)         // Boolean intersect
figma.exclude(nodes, parent?, index?)           // Boolean exclude
figma.combineAsVariants(components, parent?)    // Combine ComponentNodes into ComponentSet (Design/Sites only)

Library Component / Style / Variable Lookup by Key

search_design_system returns componentKey for components / component sets and key for styles and variables. Pass any of these straight into the unified $fig lookup — the plan queues the library import automatically. Same call sites also accept node IDs and real style / variable IDs for assets already in the current file.

// Components / component sets
const comp     = $fig.get(COMPONENT_KEY)                       // wrap a component / set
const instance = $fig.instance(COMPONENT_SET_KEY, {            // instance + variant props
  props: { Size: 'md', Variant: 'primary' },
})

// Styles (paint / text / effect / grid)
const fill   = $fig.getStyle(PAINT_STYLE_KEY)
$fig.rectangle({ fills: fill })
$fig.text({ characters: 'Title', textStyle: $fig.getStyle(TEXT_STYLE_KEY) })
$fig.frame({ effects: $fig.getStyle(EFFECT_STYLE_KEY) })

// Variables
const brand = $fig.getVar(BRAND_COLOR_VAR_KEY)
$fig.rectangle({ fills: [{ type: 'SOLID', color: brand }] })
$fig.autoLayout({ itemSpacing: $fig.getVar(SPACING_400_KEY) })

For component sets, pass the variant property values in props — $fig.instance resolves them via the underlying setProperties after creating the instance from defaultVariant. You do not need to import the set, drill into compSet.children, or pick a variant child by hand.

Raw-API fallback for styles + variables (mid-script metadata)

When you need an imported style's or variable's metadata before deciding what to build next, the raw plugin APIs are still legal. Use sparingly — most flows are simpler via $fig.getStyle(key) / $fig.getVar(key).

// Styles
const style = await figma.importStyleByKeyAsync("STYLE_KEY")
await node.setFillStyleIdAsync(style.id)
await node.setTextStyleIdAsync(style.id)
await node.setEffectStyleIdAsync(style.id)
await node.setGridStyleIdAsync(style.id)

// Variables
const variable = await figma.variables.importVariableByKeyAsync("VARIABLE_KEY")
node.setBoundVariable("width", variable)
const newPaint = figma.variables.setBoundVariableForPaint(paintCopy, "color", variable)
node.fills = [newPaint]

Variables API

// Collections
const collection = figma.variables.createVariableCollection("Name")
collection.name                           // Get/set name
collection.modes                          // Array of {modeId, name} — starts with 1 mode
collection.addMode("Dark")               // Returns new modeId string
collection.renameMode(modeId, "Light")

// Variables
const variable = figma.variables.createVariable("name", collection, "COLOR")
//                                                       ^ must be a collection object (passing an ID string is deprecated)
// resolvedType: "COLOR" | "FLOAT" | "STRING" | "BOOLEAN"
variable.setValueForMode(modeId, value)

// Scopes — controls where variable appears in property pickers
variable.scopes = ["FRAME_FILL", "SHAPE_FILL"]   // only fill pickers
variable.scopes = ["TEXT_FILL"]                    // only text color picker
variable.scopes = ["STROKE_COLOR"]                 // only stroke picker
variable.scopes = []                               // hidden from all pickers (use for primitives)
// All valid scope values:
//   ALL_SCOPES, TEXT_CONTENT, CORNER_RADIUS, WIDTH_HEIGHT, GAP,
//   ALL_FILLS, FRAME_FILL, SHAPE_FILL, TEXT_FILL,
//   STROKE_COLOR, STROKE_FLOAT, EFFECT_FLOAT, EFFECT_COLOR,
//   OPACITY, FONT_FAMILY, FONT_STYLE, FONT_WEIGHT, FONT_SIZE,
//   LINE_HEIGHT, LETTER_SPACING, PARAGRAPH_SPACING, PARAGRAPH_INDENT

// Querying (always use the Async variants — sync versions are deprecated)
await figma.variables.getVariableByIdAsync(id)
await figma.variables.getLocalVariablesAsync(resolvedType?)
await figma.variables.getVariableCollectionByIdAsync(id)
await figma.variables.getLocalVariableCollectionsAsync()

// Binding variables to paints (COLOR variables)
const newPaint = figma.variables.setBoundVariableForPaint(paintCopy, "color", variable)
// ⚠️ Returns a NEW paint — must capture return value!
node.fills = [newPaint]

// Binding variables to effects (COLOR/FLOAT variables)
const newEffect = figma.variables.setBoundVariableForEffect(effectCopy, field, variable)
// field for shadows: "color" (COLOR), "radius" | "spread" | "offsetX" | "offsetY" (FLOAT)
// field for blurs: "radius" (FLOAT)
// ⚠️ Returns a NEW effect — must capture return value!
node.effects = [newEffect]

// Binding variables to layout grids (FLOAT variables)
const newGrid = figma.variables.setBoundVariableForLayoutGrid(gridCopy, field, variable)
// field: "sectionSize" | "offset" | "count" | "gutterSize"
// ⚠️ Returns a NEW layout grid — must capture return value!
node.layoutGrids = [newGrid]

// Binding variables to node properties (FLOAT/STRING/BOOLEAN)
// Layout & sizing (FLOAT):
node.setBoundVariable("width", variable)
node.setBoundVariable("height", variable)
node.setBoundVariable("minWidth", variable)
node.setBoundVariable("maxWidth", variable)
node.setBoundVariable("minHeight", variable)
node.setBoundVariable("maxHeight", variable)
node.setBoundVariable("paddingLeft", variable)
node.setBoundVariable("paddingRight", variable)
node.setBoundVariable("paddingTop", variable)
node.setBoundVariable("paddingBottom", variable)
node.setBoundVariable("itemSpacing", variable)
node.setBoundVariable("counterAxisSpacing", variable)
// Corner radii (FLOAT) — use individual corners, NOT cornerRadius:
node.setBoundVariable("topLeftRadius", variable)
node.setBoundVariable("topRightRadius", variable)
node.setBoundVariable("bottomLeftRadius", variable)
node.setBoundVariable("bottomRightRadius", variable)
// Other (FLOAT):
node.setBoundVariable("opacity", variable)
node.setBoundVariable("strokeWeight", variable)
// ⚠️ fontSize, fontWeight, lineHeight are NOT bindable via setBoundVariable
// — set these directly as values on text nodes

// Aliases
figma.variables.createVariableAlias(variable)

// Explicit modes — CRITICAL for variant components
node.setExplicitVariableModeForCollection(collection, modeId)  // pass collection object, NOT an ID string
// Without this, all nodes use the default (first) mode of the collection

Core Properties

figma.root                      // DocumentNode
figma.currentPage               // Current page — READ ONLY; the sync setter (figma.currentPage = page) does NOT work and throws
figma.setCurrentPageAsync(page) // Switch page and load its content (MUST await) — this is the ONLY way to change pages
figma.fileKey                   // File key string
figma.mixed                     // Mixed sentinel value

Node Manipulation

// Fills & Strokes (read-only arrays — must clone)
node.fills = [{ type: 'SOLID', color: { r: 1, g: 0, b: 0 } }]
node.strokes = [{ type: 'SOLID', color: { r: 0, g: 0, b: 0 } }]
node.strokeWeight = 1
node.strokeAlign = 'INSIDE'             // 'INSIDE' | 'CENTER' | 'OUTSIDE'

// Effects
node.effects = [{ type: 'DROP_SHADOW', color: {r:0,g:0,b:0,a:0.25}, offset:{x:0,y:4}, radius:4, visible:true }]

// Layout
node.layoutMode = 'HORIZONTAL'          // 'NONE' | 'HORIZONTAL' | 'VERTICAL'
node.primaryAxisAlignItems = 'CENTER'    // 'MIN' | 'CENTER' | 'MAX' | 'SPACE_BETWEEN'
node.counterAxisAlignItems = 'CENTER'    // 'MIN' | 'CENTER' | 'MAX' | 'BASELINE'
node.paddingLeft = 8
node.paddingRight = 8
node.paddingTop = 4
node.paddingBottom = 4
node.itemSpacing = 4
node.layoutSizingHorizontal = 'HUG'     // 'FIXED' | 'HUG' | 'FILL'
node.layoutSizingVertical = 'HUG'       // 'FIXED' | 'HUG' | 'FILL'

// Sizing
node.resize(width, height)                     // ⚠️ Resets sizing modes to FIXED
node.resizeWithoutConstraints(width, height)   // Doesn't affect constraints

// Corner radius
node.cornerRadius = 8

// Visibility & Opacity
node.visible = true
node.opacity = 0.5

// Naming & Hierarchy
node.name = "My Node"
parent.appendChild(child)
parent.insertChild(index, child)
node.remove()

Descriptions & Documentation Links

Only access description on components and component sets. Accessing it on a frame, instance, or other scene node throws instead of returning undefined.

// Description — plain text, shown in Figma's component panel
if (node.type === "COMPONENT" || node.type === "COMPONENT_SET") {
  node.description = "A short summary of this component's purpose and usage."
}

// Documentation links — array of {uri, label} shown as clickable links
componentSet.documentationLinks = [
  { uri: "https://example.com/docs", label: "Component Docs" }
]
// ⚠️ uri MUST be a valid URL (https://...) — relative paths will throw

SVG Import

const svgNode = figma.createNodeFromSvg('<svg>...</svg>')

Images

const image = figma.createImage(uint8Array)
node.fills = [{ type: 'IMAGE', scaleMode: 'FILL', imageHash: image.hash }]

Fonts

// Discover all available fonts and their exact style strings
const allFonts = await figma.listAvailableFontsAsync()  // Font[] — each has { fontName: { family, style } }
const interStyles = allFonts.filter(f => f.fontName.family === "Inter")

// MUST load a font before any text property edit
await figma.loadFontAsync({ family: "Inter", style: "Regular" })

// Check if the file has missing fonts
figma.hasMissingFont  // boolean

Utilities

figma.base64Encode(uint8Array)     // Uint8Array → base64 string
figma.base64Decode(base64String)   // base64 string → Uint8Array
figma.createComponentFromNode(node) // Convert existing node to component (Design/Sites only)

Plugin Lifecycle

Scripts are automatically wrapped in an async IIFE with error handling. Use return to send data back:

return { nodeId: frame.id }     // Return object — auto-serialized to JSON
return "success message"        // Return string
// Errors are auto-captured — no try/catch or closePlugin needed

Node Traversal

node.findAll(pred?)            // Find all descendants matching predicate
node.findOne(pred?)            // Find first descendant matching predicate
node.findChildren(pred?)       // Find direct children matching predicate
node.findChild(pred?)          // Find first direct child matching predicate
node.children                  // Direct children array
node.parent                    // Parent node

What Does NOT Work

API Status
figma.notify() Throws "not implemented" — most common mistake
figma.showUI() No-op (silently ignored)
figma.openExternal() No-op (silently ignored)
figma.loadAllPagesAsync() Not implemented
figma.variables.extendLibraryCollectionByKeyAsync() Not implemented
figma.teamLibrary.* Not implemented (requires LiveGraph)
figma.getLocalComponents*() Does not exist — unlike styles, there is no getLocalComponents() or getLocalComponentSetsAsync() (or any getLocalComponent* variant). Use findAll(n => n.type === 'COMPONENT') / findAll(n => n.type === 'COMPONENT_SET') to locate components in the current file.

Source: SKILL.md on GitHub

No alerts8d4 checks · Risk SAFE
  • Gen Agent Trust Hub8d

    The skill provides comprehensive instructions and reference material for interacting with the Figma Plugin API. No security issues were detected.

  • Socket8d

    No alerts

  • Snyk8d

    Risk: LOW · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 1729207. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated 2 weeks ago
disable-model-invocation
false
  • figma
  • plugin-api
  • design-systems
  • javascript
  • components
  • variables
  • auto-layout
  • tokens

README badge

README badge for figma/mcp-server-guide/figma-use

Loads prerequisites for the `use_figma` tool, which executes JavaScript in Figma files via the Plugin API. This skill teaches critical rules for font loading, text editing, auto-layout, pagination, async operations, and incremental work patterns that prevent hard-to-debug failures. Install this before any Figma programmatic task—creating or editing nodes, binding variables, building components, or inspecting file structure.

Generated from the current SKILL.md.

Do I need to load this skill before calling use_figma?
Yes. This skill is a mandatory prerequisite. You must load figma-use before every use_figma tool call and include it in the skillNames parameter, or the call will fail with hard-to-debug errors.
What kind of operations does this skill cover?
Write actions and unique read actions that require JavaScript execution in Figma files: creating/editing/deleting nodes, setting up variables and tokens, building components and variants, modifying auto-layout or fills, binding variables to properties, and inspecting file structure programmatically.
Can I use console.log() to debug my code?
No. console.log() output is not returned. Use return statements to send data back instead — return values are automatically JSON-serialized.
How do I switch to a different page in Figma?
Use await figma.setCurrentPageAsync(page) to switch pages and load their content. The synchronous setter figma.currentPage = page does not work and will throw an error.
What should I do if a use_figma call fails?
Stop and do not retry immediately. Failed scripts are atomic — no changes are made to the file. Read the error message carefully, fix the script, and retry.

Generated from the current SKILL.md. These answers refresh after source changes.