Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, email [email protected] and we’ll put it right.

io.github.musepy/genable-mcp

NPM · GENABLE-MCP · SCANNED AUG 3

Write to Figma from any MCP client (Claude Code, Cursor). Complements the read-only official MCP.

Available components

+22 this week 64 Trust /100
Trust breakdown (6 categories)

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score →

Supply Chain Security87
  • No malware found by supply-chain analysis.Pass
  • Only part of the dependency tree could be resolved (95 of 99), so this covers what we could see, not the whole tree.Partial
  • No install/post-install scripts declared.Pass
  • Only part of the dependency tree could be resolved (95 of 99), so this covers what we could see, not the whole tree. View diagnostics → Partial
Provenance & Transparency45
Schema Quality & AI Usability53
  • AI-judged instruction clarity (good).Pass
  • Context-footprint check failed: tool/resource definitions use about 11678 tokens (~284/item across 41 items; 41 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management23
  • Stability observed for 7 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage100
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 100% of tool parameters carry a description.Pass
Capabilities100
  • Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
Install

Add this component to your MCP client. Where a client-specific snippet is available, pick your client below and copy it straight into your config; otherwise use the connection detail shown.

npm · genable-mcp

# add to Claude Code
claude mcp add musepy-genable-mcp -- npx -y genable-mcp
# add to Codex CLI
codex mcp add musepy-genable-mcp -- npx -y genable-mcp
// opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "musepy-genable-mcp": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "genable-mcp"
      ],
      "enabled": true
    }
  }
}
# add to OpenClaw
openclaw mcp add musepy-genable-mcp --command npx --arg -y --arg genable-mcp
# ~/.hermes/config.yaml
mcp_servers:
  musepy-genable-mcp:
    command: "npx"
    args: ["-y", "genable-mcp"]
// mcp.json
{
  "mcpServers": {
    "musepy-genable-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "genable-mcp"
      ]
    }
  }
}
Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 3 Aug 26 +32
    • Provenance: unverified → fail security
    • Install scripts: unverified → pass security
    • Known CVEs: unverified → partial security
    • License: unverified → pass functional
    • Stability: unverified → 0.23 functional
    • MCP protocol: unverified → pass functional
    • Maintenance: unverified → pass functional
    • Dependency health: unverified → partial functional
    • Schema quality: unverified → good functional
    • Licence: MIT functional
  • 2 Aug 26 +10
    • Malware scan: unverified → pass security
    • Stability: Stability not yet verified: we do not have a sandbox capture of the MCP schema this version of the package serves yet. security
    • Capabilities: pass → unverified functional
  • 1 Aug 26 +5
    • Stability: Stability not yet verified: not enough scan history yet (needs a 30-day window). security
    • MCP protocol: unverified → pass functional
  • 31 Jul 26 −7
    • We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
  • 30 Jul 26 −18
    • Tool coverage: 100 → unverified functional
    • First check of Schema quality: unverified functional
  • 27 Jul 26 42

    First indexed and scored.

Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 3 Aug 2026 · Analysed npm/[email protected]

Provenance none

Ecosystem: npm · Outcome: none

Dependencies 95 packages

95 packages in the resolved dependency tree · 95 deprecated · 29 stale.

The dependency tree was only partially resolved, so these counts may be incomplete.

MCP tools — 41 exposed · ~11,678 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability.

Tool Tokens
add_component_prop ~254

Add a component property and bind it to a child node. For TEXT properties: binds to the target text node's characters, so instances can override the text content. For BOOLEAN properties: binds to the target node's visibility. Parameters: node: The component node ID (must be COMPONENT or COMPONENT_SET). name: Property display name. type: TEXT, BOOLEAN, or INSTANCE_SWAP. default: Default value. bind: Child node ID to bind this property to. For TEXT, binds to text content. For BOOLEAN, binds to visibility. Examples: add_component_prop({node: "1:2", name: "Label", type: "TEXT", default: "Click me", bind: "1:5"}) add_component_prop({node: "1:2", name: "Show Icon", type: "BOOLEAN", default: "true", bind: "1:6"})

NameTypeReqDescription
bindstringChild node ID to bind this property to
defaultstringDefault value
namestringyesProperty name
nodestringyesComponent node ID (e.g. "1:2")
typestringyesProperty type

No output schema declared.

No examples provided.

ask_user ~555

Ask the user 1-3 questions in a single form. Each question has its own options and can be single- or multi-select. Bundle related decisions in ONE call instead of multiple turns. Use when: - The prompt is ambiguous on multiple dimensions (audience + aesthetic + length) — bundle them into one form - You need a decision before proceeding (delete existing? which section first?) - Multiple valid approaches exist and user preference matters Returns one of: - { answers: [...] } — array indexed to questions order. string for single-select, string[] for multi-select. The string MAY be one of the option labels OR custom text the user typed via the auto-injected "Other..." option. - { freeText: "..." } — when the user typed a free-form answer in the chat input instead of submitting the form. Treat as authoritative — user is overriding the structured options. Each question: - question: required prompt string. Self-contained — no separate header/label, the question text IS the heading. - options: 2-3 options, each { label, description? }. The form auto-injects an "Other..." row, so the user always sees options.length + 1 rows total — keep options ≤ 3 to stay within the 4-row visual cap. - multiSelect: optional boolean (default false). Use only when the answer is genuinely a list (e.g. "which features?"). For mutually exclusive choices keep false. Conventions: - **First option = recommended.** If you have a strong default for the user, put it FIRST and add "(Recommended)" at the end of the label. The form auto-focuses the first option and the dev/auto-pick fallback selects it — both work better with a deliberate recommendation. - **Do NOT include an "Other" option yourself** — the form auto-injects an "Other..." row per question with an inline text input. Don't add a redundant one. - **Bundle aggressively.** 2 related dimensions in ONE call beats 2 sequential turns. Example: ask_user({ questions: [ { question: "Who is this for?", options: [{label:"B2B SaaS"},{label:"…

NameTypeReqDescription
questionsarrayyes1-3 questions to present in a single form (3 is the soft cap; bundle related decisions but don't pad).

No output schema declared.

No examples provided.

bind_variable ~390

Bind a FLOAT, BOOLEAN, or STRING variable to a node property. prop is a flat Figma bindable field (e.g. fontSize, itemSpacing, paddingTop, cornerRadius, opacity, visible, width, height, characters). Shorthands: gap → itemSpacing, padding → paddingTop, corner → cornerRadius, font-size → fontSize. COLOR variables are NOT bound here — they live inside Paint objects. To apply a color token, specify it at the source instead: • At creation: jsx <frame bg="$TokenName" ...> or fill="$TokenName" • Post-hoc: set_fill({node, bg: "$TokenName"}) or set_stroke When selecting which variable to bind: if the node is a Tablet or Mobile variant (name or variant property contains "Tablet"/"Mobile"), match the node's property value against the Tablet/Mobile mode column from list_variables — not Desktop. Examples: bind_variable({node: "1:2", prop: "fontSize", variable: "VariableID:1:6"}) bind_variable({node: "1:3", prop: "paddingTop", variable: "VariableID:1:7"}) bind_variable({node: "1:4", prop: "visible", variable: "VariableID:1:8"}) bind_variable({node: "1:5", prop: "characters", variable: "VariableID:1:9"})

NameTypeReqDescription
nodestringyesNode ID (e.g. "1:2")
propstringyesFlat Figma bindable field (fontSize, paddingTop, itemSpacing, visible, characters, etc.). COLOR props (fills/strokes) not supported — use set_fill/jsx.
variablestringyesVariableID to bind (FLOAT/BOOLEAN/STRING only)

No output schema declared.

No examples provided.

clone_node ~233

Deep-copy a node with optional property overrides. Examples: clone_node({node: "1:2"}) — clone to page root, same name clone_node({node: "1:2", parent: "/"}) — clone to page root explicitly clone_node({node: "1:2", parent: "/", name: "Hero Copy"}) — clone to root with custom name clone_node({node: "1:2", parent: "1:4"}) — clone into parent node 1:4 clone_node({node: "1:2", parent: "1:4", overrides: {"bg": "#D9D9D9"}})

NameTypeReqDescription
namestringName for the cloned node. Defaults to source node name.
nodestringyesSource node ID (e.g. "1:2")
overridesobjectProperty overrides. Use "Child.prop" for child overrides.
parentstringTarget parent node ID the clone should live inside, or "/" for page root. Defaults to page root.

No output schema declared.

No examples provided.

combine_components ~69

Combine multiple components into a variant set (ComponentSet). Examples: combine_components({nodes: ["1:2", "1:3", "1:4"], name: "Button"})

NameTypeReqDescription
namestringComponent set name
nodesarrayyesComponent node IDs to combine

No output schema declared.

No examples provided.

create_collection ~122

Create a VariableCollection with named modes. The first mode in the array becomes the default mode. Returns {data: {id, modes: [{modeId, name}]}} — use those modeIds with set_variable_value and set_variable_mode. Examples: create_collection({name: "Theme", modes: ["Light", "Dark"]}) create_collection({name: "Device", modes: ["Desktop", "Tablet", "Mobile"]})

NameTypeReqDescription
modesarrayyesMode names (first becomes default)
namestringyesCollection name

No output schema declared.

No examples provided.

create_component ~52

Convert a frame or group to a Figma component. Examples: create_component({node: "1:2"})

NameTypeReqDescription
nodestringyesNode ID (e.g. "1:2") to convert

No output schema declared.

No examples provided.

create_instance ~351

Create an instance of an existing component. Mutates the canvas — appends a new InstanceNode as the last child of `parent` (or the active page root if omitted). The instance is LINKED to the component master, so future component edits propagate. Returns the new instance's nodeId. Use when: - Spawning runtime copies of a Component master (buttons, list items, cards) - Reusing a design-system component in a fresh layout - Programmatic instantiation outside a jsx() tree-build Returns: { data: { id: "5:42", name: "Button", componentId: "1:2" } } Parameters beyond schema: - `node` must be a Component node (not Frame, Text, or another Instance). Discover IDs with find_nodes({ type: "COMPONENT" }). - `parent` optional. If parent is auto-layout, the instance enters the flow and inherits sizing rules. If omitted, the instance is placed at the active page root with detached position — may overlap existing content; set explicit position with edit afterwards. Skip when: - Duplicating a non-component node — instance creation will fail; use clone_node instead. - Building a subtree from scratch — use jsx with <instance ref="ComponentName"/> for atomic single-call construction. Examples: create_instance({node: "1:2"}) // at page root create_instance({node: "1:2", parent: "1:4"}) // inside frame 1:4

NameTypeReqDescription
nodestringyesComponent node ID (e.g. "1:2") to instantiate
parentstringParent node ID for placement

No output schema declared.

No examples provided.

create_variable ~132

Create a variable in an existing collection. No value is set here — use set_variable_value after. Returns {data: {id}}. Examples: create_variable({collection: "VariableCollectionId:1:2", name: "Theme/bg", type: "COLOR"}) create_variable({collection: "VariableCollectionId:1:2", name: "spacing/md", type: "FLOAT"})

NameTypeReqDescription
collectionstringyesVariableCollectionId to create the variable in
namestringyesVariable name (slashes denote hierarchy in the Figma UI)
typestringyesVariable type

No output schema declared.

No examples provided.

create_vector ~675

Create a vector node from SVG path data or a list of points. Use for chart lines, custom icon paths, freeform curves, or any shape that needs path data. Examples: // Polyline (chart trend line) create_vector({ parent: "1:23", name: "TrendLine", x: 40, y: 20, width: 550, height: 240, points: [[0,144],[90,96],[180,120],[270,64],[360,80],[450,40],[540,72]], stroke: "#6366F1", strokeWeight: 2 }) // Raw SVG path (custom shape) create_vector({ parent: "1:23", name: "Wave", width: 200, height: 60, data: "M 0 30 Q 50 0 100 30 T 200 30", stroke: "linear-gradient(90deg, #8B5CF6 0%, #F97316 100%)", strokeWeight: 1.5 }) Path input — provide ONE of: points: [[x,y], ...] compiled to "M x0 y0 L x1 y1 ..." (polyline shortcut) data: "M ... L ..." raw SVG path (LLM-native; supports M, L, C, Q, A, Z) Stroke / fill (same formats as set_stroke / set_fill): hex "#6366F1" gradient "linear-gradient(angle, #color stop%, ...)" variable qualified bare name "$Brand/Primary" Default fill is "transparent" so the vector shows only its stroke. Pass an explicit fill if you want it filled. When NOT to use: - Standard rectangles / ellipses / lines — use jsx <Rect/>, <Ellipse/>, <Line/> elements (simpler, batch-friendly) - Existing vector edits — use edit / set_stroke instead

NameTypeReqDescription
datastringRaw SVG path string. Mutually exclusive with `points`.
fillstringFill — hex / gradient / variable / "transparent" (default: "transparent").
heightnumberyesVector bounds height in px.
namestringNode name (default: "Vector").
parentstringParent node ID. Omit to attach to the current page.
pointsarrayPolyline points as [[x,y], ...]. Compiled internally to "M x0 y0 L x1 y1 ...". Mutually exclusive with `data`.
strokestringStroke color — hex, gradient string, or qualified bare-name token.
strokeAlignstringStroke alignment relative to the path (default: center).
strokeWeightnumberStroke weight in px (default: 1).
widthnumberyesVector bounds width in px.
windingRulestringPath fill winding rule (default: NONZERO).
xnumberX position relative to parent (default: 0).
ynumberY position relative to parent (default: 0).

No output schema declared.

No examples provided.

delete_node ~45

Delete a node and its children. Examples: delete_node({node: "1:2"})

NameTypeReqDescription
nodestringyesNode ID (e.g. "1:2")

No output schema declared.

No examples provided.

describe ~184

Validate a design subtree — semantic description, role detection, and lint rules. Checks for layout conflicts, overflow, missing properties, and structural issues. Parameters: node: Node ID to describe (e.g. "100:5"). Required. depth: How deep to check children (default: 3, max: 8). Returns per-node: role, visual summary, layout summary, and issues (severity: error/warning/info). Examples: describe({node: "100:5"}) → validate subtree, depth 3 describe({node: "100:5", depth: 1}) → shallow check (root + direct children only)

NameTypeReqDescription
depthnumberMax depth to check (default: 3, max: 8)
nodestringyesNode ID to describe (e.g. "100:5").

No output schema declared.

No examples provided.

discover_props ~100

Discover unique property values in a subtree. Examples: discover_props({node: "1:2", props: ["fillColor", "fontSize"]}) Searchable properties: fillColor, textColor, strokeColor, strokeWeight, opacity, cornerRadius, gap, fontSize, fontFamily, fontWeight.

NameTypeReqDescription
nodestringyesTarget node ID (e.g. "1:2")
propsarrayyesProperties to discover

No output schema declared.

No examples provided.

edit ~320

Batch update properties on multiple nodes. For single-property changes, prefer focused setters: set_text — text content set_fill — fill/background color set_stroke — border set_layout — padding, gap, direction Use edit for batch fixes or properties not covered by setters (sizing, radius, opacity, effects, component props): edit({nodes: [ {node: "1:1", props: {w: "fill", corner: 8}}, // Figma native props {node: "1:2", props: {opacity: 0.6}}, {node: "1:3", props: {Label: "Sign In"}}, // instance TEXT prop (by display name) ]}) For instances, use component property DISPLAY NAMES (e.g. "Label") — edit resolves them to Figma's internal keys automatically. Component props can be mixed with Figma props in the same call.

NameTypeReqDescription
contentstringNew text content (single mode)
nodestringNode ID (e.g. "1:2") from jsx/inspect results
nodesarrayBatch: array of {node, props?, content?} objects. No hard item cap — real ceiling is LLM output stream length (~10KB+ of rendered params can stall mid-JSON). If a batch is large and props are rich, s…
propsobjectProperties to update (single mode)

No output schema declared.

No examples provided.

ensure_collection ~229

Idempotent VariableCollection creation — safe to retry. Returns existing collection if one with the same name + identical mode list already exists, otherwise creates a new one. Spec §3.1. Prefer this over create_collection — re-running with the same name + modes returns the existing collection instead of creating a duplicate. Omit idempotency_key — the handler computes it canonically from (name, modes). Pass it only if you need strict concurrency-safety validation (LLMs should not try to compute SHA-256 inline; placeholder strings are rejected). Returns {data: {collection_id, modes: [{modeId, name}], reused?: true}}. Examples: ensure_collection({name: "Theme", modes: ["Light", "Dark"]})

NameTypeReqDescription
idempotency_keystringOptional. Handler auto-computes canonically if omitted. Pass only if you need strict concurrency-safety validation against the SHA-256 formula in spec §3.1.
modesarrayyesMode names (first becomes default)
namestringyesCollection name

No output schema declared.

No examples provided.

ensure_variable ~703

Idempotent variable creation — populates values_by_mode in one shot. Prefer this over create_variable — re-running with the same args returns the existing variable instead of creating a duplicate. Behavior (spec §3.1): - Exactly 1 variable with (collection_id, name, type) in target collection → idempotent reuse. - 0 in target, matches in OTHER collections → create new in target + warning NAME_EXISTS_OUTSIDE_TARGET_COLLECTION. - 0 anywhere → create new. - 2+ in target collection (Figma allows duplicates) → fail SAME_COLLECTION_NAME_DUPLICATE. values_by_mode keys can be either mode NAMES (e.g. "Light") or modeIds (e.g. "1:0"). Each value must match the variable type (hex/RGBA for COLOR, number for FLOAT, string for STRING, boolean for BOOLEAN). Omit idempotency_key — the handler computes it canonically from (collection_id, name, type, values_by_mode). Pass it only if you need strict concurrency-safety validation (LLMs should not try to compute SHA-256 inline; placeholder strings are rejected). Mode coverage policy (spec §6.2): - mode_coverage_required: 'all' (default) — every mode in the collection must have an explicit value. set_fill / bind_variable will REJECT bindings that fall through to a missing mode (MISSING_MODE_VALUES). - mode_coverage_required: 'opt-in-fallback' — fallback to default mode is intended. Bindings emit FALLBACK_BINDING warning instead of failing. Caller MUST provide fallback_reason containing the structured phrase "fallback to <mode_name>" (machine-greppable). Returns {data: {variable_id, name, type, collection_id, mode_coverage[], mode_coverage_required, reused?: true}, warnings?: [...]}. Examples: ensure_variable({collection_id: "VariableCollectionId:1:2", name: "Text/Primary", type: "COLOR", values_by_mode: {Light: "#111", Dark: "#EEE"}}) ensure_variable({collection_id: "VariableCollectionId:1:2", name: "Spacing/desktop", type: "FLOAT", values_by_mode: {Desktop: 24}, mode_coverage_required: "opt-in…

NameTypeReqDescription
collection_idstringyesTarget VariableCollectionId — strict ID, no name lookup.
fallback_reasonstringREQUIRED iff mode_coverage_required="opt-in-fallback". Must contain the structured phrase "fallback to <mode_name>". Persisted on the variable for audit trail.
idempotency_keystringOptional. Handler auto-computes canonically if omitted. Pass only if you need strict concurrency-safety validation against the SHA-256 formula in spec §3.1.
mode_coverage_requiredstringMode coverage policy — "all" (default; every mode must have explicit value) or "opt-in-fallback" (allow fallback, requires fallback_reason).
namestringyesVariable name (slashes denote hierarchy).
typestringyesVariable type
values_by_modeobjectyesMap of mode name OR modeId → value. Hex strings allowed for COLOR.

No output schema declared.

No examples provided.

find_nodes ~103

Search nodes by name or type. Scoped to the current page — call switch_page first if your target lives on a different page. Examples: find_nodes({query: "Button"}) find_nodes({query: "frame", scope: "1:2"})

NameTypeReqDescription
querystringyesSearch query — matches node name or type
scopestringLimit search to subtree. Node ID (e.g. "1:2"). Default: entire page.

No output schema declared.

No examples provided.

find_references ~264

Find every node on the current page that references a given variable. This is the REVERSE of inspect: inspect asks "what does this node bind?", find_references asks "who uses this variable?". Use it when renaming, auditing, or swapping tokens — you need to know all the binding sites before you touch the variable. Scan scope: currentPage only. Invisible nodes are skipped by default. Node-level bindings (e.g. boundVariables.paddingLeft) and per-paint color bindings (fills[i].boundVariables.color, strokes[i].boundVariables.color) are both returned. Parameters: variable — VariableID (e.g. "VariableID:1:5"). Required. Returns: {variable, variableName, variableType, referenceCount, references: [{nodeId, nodeName, nodeType, path}, ...]} path values look like: "boundVariables.paddingLeft" "fills[0].boundVariables.color" "strokes[2].boundVariables.color" Examples: find_references({variable: "VariableID:1:5"})

NameTypeReqDescription
variablestringyesVariableID to look up (e.g. "VariableID:1:5"). Get IDs from list_variables.

No output schema declared.

No examples provided.

get_screenshot ~209

Capture a PNG screenshot of a node. Use after style changes to visually verify the result instead of reading properties back. Returns base64 PNG data embedded in the response. Parameters: node: Node ID from jsx/inspect results (e.g. "100:5"). Page root ("/") is not supported. scale: Export scale 0.5–2 (default 1). Higher = larger file. padding: Reserved for future use — currently ignored. Examples: get_screenshot({node: "100:5"}) → PNG at 1x get_screenshot({node: "100:5", scale: 2}) → PNG at 2x (sharper)

NameTypeReqDescription
nodestringyesNode ID (e.g. "100:5"). Page root "/" is not supported.
paddingnumberReserved for future use.
scalenumberExport scale 0.5–2 (default 1).

No output schema declared.

No examples provided.

get_selection ~112

Get the user's currently selected nodes in Figma. Returns node names, types, and IDs of selected elements. Call this when the user's intent involves modifying existing elements: - "change this button", "update the card", "fix the spacing" - References to "this", "the selected", "it" Skip for fresh design requests ("design a login page", "create a dashboard") — a new canvas has no selection to read, so the call returns nothing and burns an iteration. Examples: get_selection()

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

guideline ~71

Load a page-type design guideline — layout patterns for landing pages, dashboards, login flows, forms, etc. Example: guideline({ name: "form" })

NameTypeReqDescription
namestringyesThe guideline name exactly as it appears in the KNOWLEDGE LIBRARY menu — no "guideline:" prefix, no quotes.

No output schema declared.

No examples provided.

help ~67

Load narrow how-to / process help — tool usage rules, edge cases, naming conventions. Example: help({ name: "interaction-model" })

NameTypeReqDescription
namestringyesThe help name exactly as it appears in the KNOWLEDGE LIBRARY menu — no "help:" prefix, no quotes.

No output schema declared.

No examples provided.

inspect ~424

Read design node(s) — choose what to surface with `facets`. Default (no facets) returns a skeleton: id, name, type, role, children. For anything else, list the facets you need — nothing else is included. Facets: structure name, type, size, layout shorthand — cheap overview layout layoutMode/gap/padding/align/sizing (row/column, fill/hug, etc.) paint|fill fills + Paint.boundVariables.color (see bound tokens) stroke strokes, strokeWeight, strokeAlign, dashPattern effects shadows, blurs typography|text fontFamily, fontSize, fontWeight, lineHeight, letterSpacing appearance opacity, visible, blendMode, cornerRadius, clipsContent variables node-level boundVariables + explicitVariableModes (token bindings) all everything Parameters: node "/" for page root, or node ID from jsx/inspect results (e.g. "100:5"). facets array of facet names listed above. depth Max tree depth (default: 5, max: 10). Examples: inspect({node: "/"}) → page skeleton inspect({node: "100:5"}) → one-node skeleton inspect({node: "100:5", facets: ["variables"]}) → token bindings only inspect({node: "100:5", facets: ["layout", "paint"]}) → layout + fills inspect({node: "100:5", facets: ["all"]}) → full properties Use `get_screenshot` for visual verification. Use `describe` for lint/validation.

NameTypeReqDescription
depthnumberMax depth (default: 5, max: 10)
facetsarrayProperty buckets to surface. Omit for a skeleton-only response.
nodestringyes"/" for page root, or node ID (e.g. "100:5").

No output schema declared.

No examples provided.

jsx ~939

Create design trees with nested JSX markup. One jsx call builds a complete subtree atomically — nesting is the hierarchy. Keep a single logical unit inside one call; the returned root's children are already built, not stubs to be filled in later. Examples: jsx({markup: "<frame name='Card' layout='column' padding={16} fill='#FFFFFF' w='fill' />"}) jsx({markup: "<frame name='Row' layout='row' gap={8} padding={12} w='fill'><icon name='lucide:settings' size={20} /><text name='Label' w='fill'>Account</text><icon name='lucide:chevron-right' size={16} /></frame>"}) Elements: frame, text, rect, ellipse, line, icon, image, instance, component, group, section, vector Attributes (frame): layout, justify, items, wrap, w, h, minW, maxW, p, gap, bg, fill, rounded, stroke, shadow, blur, bgblur, opacity, layoutPositioning Attributes (text): size, weight, lineHeight, font, fill, w (w="fill" for wrap), maxLines, textTruncation Effects: shadow="0,8,32,0,#0006" or shadow={shadow(0,8,32,0,'#0006')}; blur={10} for layer blur; bgblur={20} for frosted-glass/glassmorphism background blur. Multiple effects merge automatically. Decoration in auto-layout: floating orbs/blobs/decorative shapes inside a row/column parent need layoutPositioning="absolute" so they don't get stacked into the main-axis flow. Full-frame backgrounds: set the parent frame's bg directly. Don't add a separate <rect> backdrop. Supported gradient strings (CSS-like subset, not full CSS): - linear-gradient(<angle>deg, <#hex> <pos>%, ...) e.g. "linear-gradient(135deg, #A 0%, #B 100%)" - linear-gradient(to <direction>, <stops>) directions: top/right/bottom/left and corners (e.g. "to bottom right") - radial-gradient(<stops>) centered, ellipse-fill — no position/shape modifiers - radial-gradient(circle, <stops>) centered, circle shape only - conic-gradient(from <angle>deg, <stops>) Unsupported (will be rejected): "circle at X% Y%", "ellip…

NameTypeReqDescription
insertIndexnumberPosition among parent siblings (0 = first). Omit to append at end. Ignored when replaceId is set (inherits old node index).
markupstringyesJSX-like nested markup string
parentstringTarget parent node ID — the frame/container the new subtree will live inside
replaceIdstringReplace this existing node in-place (keeps parent + sibling index). Old node is deleted on success. Markup must be single-root. Mutually exclusive with parent.

No output schema declared.

No examples provided.

list_component_props ~57

List properties and variants of a component, component set, or instance. Examples: list_component_props({node: "1:2"})

NameTypeReqDescription
nodestringyesComponent/instance node ID (e.g. "1:2")

No output schema declared.

No examples provided.

list_variables ~224

List variables as a flat array with referenced collections. Returns {data: {variables[], collections[], nextCursor?}}. Each variable carries its full Figma shape: id, name, variableCollectionId, resolvedType, valuesByMode. collections[] only includes collections referenced by the returned variables (use for mode-name resolution). Parameters: collection — VariableCollectionId to filter by filter — substring match on variable name (case-insensitive) cursor — opaque pagination cursor from a previous call limit — max variables per page (default 100) Examples: list_variables() list_variables({collection: "VariableCollectionId:1:2"}) list_variables({filter: "bg"}) list_variables({cursor: "100"})

NameTypeReqDescription
collectionstringVariableCollectionId to filter by
cursorstringOpaque pagination cursor from a previous call
filterstringSubstring match on variable name (case-insensitive)
limitnumberMax variables per page (default 100)

No output schema declared.

No examples provided.

move_node ~237

Relocate a node without recreating it. Preserves IDs, bound variables, and component instances across the move, so callers tracking the node by ID never need to re-discover it. Use for: (a) changing child order within a container, (b) moving a subtree into a different parent, (c) fixing a placement mistake after jsx. Examples: move_node({node: "1:3", name: "NewTitle"}) — rename in place move_node({node: "1:3", parent: "1:4"}) — move into parent 1:4 move_node({node: "1:5", index: 0}) — reorder within current parent

NameTypeReqDescription
indexnumberReorder position among siblings. 0 = first, -1 = last.
namestringNew name (rename without changing parent)
nodestringyesNode ID (e.g. "1:3") to move/rename
parentstringTarget parent node ID — the frame/container the node should live inside after the call

No output schema declared.

No examples provided.

read_plugin_data ~212

Read plugin data (private or shared) from a Figma node. Use for: i18n metadata, design-system tags, custom plugin annotations, anything stored via setPluginData / setSharedPluginData. If `namespace` is omitted, reads private pluginData (`node.getPluginData(key)`). If `namespace` is provided, reads sharedPluginData (`node.getSharedPluginData(namespace, key)`). Returns `{value: ""}` (empty string) when the key does not exist — Figma's API never throws here. Examples: read_plugin_data({node_id: "1:5", key: "ref"}) read_plugin_data({node_id: "1:5", namespace: "i18n", key: "ref"})

NameTypeReqDescription
keystringyesKey to read.
namespacestringOptional sharedPluginData namespace. Omit for private pluginData.
node_idstringyesFigma node id (resolve via find_nodes / get_selection first).

No output schema declared.

No examples provided.

replace_props ~446

Bulk find-and-replace property values across a subtree (target node + all descendants). Destructive batch mutation — no preview, no undo across many nodes. Returns per-rule match counts. Use when: - Theming pass: change every #FFF fill to #000 across a screen - Token migration: bump every fontSize from 14 to 16 - Normalizing values left inconsistent by earlier passes - The alternative is N targeted single-node calls (set_text / set_fill / edit) Returns: { data: { replacements: [{ rule: 0, matched: 12 }, { rule: 1, matched: 0 }] } } Parameters beyond schema: - `node` is the subtree root; search recurses into all descendants (depth-first). - Each rule's `from` is an EXACT-match string (no substring, no regex). For typed props (fontSize, opacity), pass values as strings — the executor coerces. - Zero matches do NOT error — they return matched: 0. Sanity-check with discover_props first if you're unsure values exist. Skip when: - Updating a single known node — use set_text / set_fill / set_stroke / set_layout for type-aware single-intent edits, or edit for generic. - Values are variable-bound (tokens) — replace_props bypasses bindings; use bind_variable to swap the token instead. - You need partial / fuzzy match — replace_props is exact-only; you'll need find_nodes + a loop. Examples: // single rule, white -> black replace_props({node: "1:2", rules: [{prop: "fillColor", from: "#FFF", to: "#000"}]}) // batch theme update — both rules applied in one pass replace_props({node: "1:2", rules: [ {prop: "fillColor", from: "#FFF", to: "#000"}, {prop: "fontSize", from: "14", to: "16"} ]})

NameTypeReqDescription
nodestringyesTarget node ID (e.g. "1:2")
rulesarrayyesReplacement rules

No output schema declared.

No examples provided.

session_note ~1,095

Read / write your own session scratchpad. Persists across turns within one design session ("New Design" resets it). Notes are how state carries from this turn into the next — the next session loads them as context. Actions: action: "read" → read({key}) returns the current value (empty string if unset) action: "write" → write({key, value}) replaces or deletes (pass value:"" to delete) action: "list" → list({}) returns [{key, chars}] for all existing notes Slots — FORWARD-LOOKING (what we plan / commit to): - plan — this turn's intent + step outline (write at turn start) - decisions — locked choices: style picked + reason, accent token, font scale, hero treatment, etc. (write BEFORE jsx) - brand — durable brand notes pulled from a project design.md (if user supplied one) - todo — TRULY unfinished work for the next turn (omit if everything shipped) Slots — BACKWARD-LOOKING (what happened, write AT TURN END — AUTO-MERGE on write): - failures — tool calls that failed this turn + how you worked around them. Example: "jsx items='stretch' rejected (DSL valid: center|start|end|space-between|baseline); retried with 'center'." If a failure repeats a class you've seen before, name the class. - gotchas — validator warnings you noticed but chose not to fix + why. Example: "4 LOW_CONTRAST on nav links (2.5:1) — deliberate for ambient-grey style; revisit if user complains." Also: magic numbers / hand-tuned positions and what motivated them. Example: "Glow ellipses at (-180, 220) / (1060, 70) — placed half outside frame to bleed in." - learnings — surprises about this codebase / DSL / Figma API. Example: "radial-gradient(circle at X% Y%) rejected — DSL only takes the simple form. Same trap as CSS-prior bleed elsewhere." BACKWARD-LOOKING slots auto-merge: writing to `failures / gotchas / learnings` appends to prior content after a…

NameTypeReqDescription
actionstringyesread | write | list
keystringNote key. Required for read/write. Recommended slots: plan, decisions, brand, todo.
valuestringMarkdown body for write. Pass "" to delete. Ignored for read/list.

No output schema declared.

No examples provided.

set_fill ~406

Set fill or background color on a node. set_fill({node: "1:2", bg: "#F5F5F5"}) set_fill({node: "1:2", fill: "#333333"}) set_fill({node: "1:2", bg: "linear-gradient(135deg, #8B5CF6 0%, #F97316 100%)"}) // Batch — bulk paint update in one call: set_fill({nodes: [{node: "1:2", bg: "#FFF"}, {node: "1:3", bg: "#F5F5F5"}]}) fill = text color or shape fill. bg = frame background. For stroke color, use set_stroke. Accepted color formats (for fill or bg): hex "#FFF", "#F5F5F5" gradient string CSS-like subset, not full CSS: "linear-gradient(<angle>deg, <#hex> <pos>%, ...)" "linear-gradient(to <direction>, ...)" directions: top/right/bottom/left + corners "radial-gradient(<stops>)" centered, no position/shape modifiers "radial-gradient(circle, <stops>)" circle shape only "conic-gradient(from <angle>deg, ...)" Rejected: "circle at X% Y%", "ellipse at ...", named colors, hsl(). variable token qualified bare name "$Surface/Card" transparent "transparent" (bg only)

NameTypeReqDescription
bgstringBackground — hex, gradient string, "transparent", or qualified bare-name token
fillstringText color or shape fill — hex, gradient string, or qualified bare-name token
nodestringNode ID (single mode)
nodesarrayBatch: [{node, fill?, bg?}]

No output schema declared.

No examples provided.

set_layout ~406

Set auto-layout properties on a container. set_layout({node: "1:2", gap: 16, p: 24}) set_layout({node: "1:2", layout: "row", justify: "space-between"}) set_layout({node: "1:2", layout: "column", gap: 8, p: "16 24", align: "center"}) set_layout({node: "1:2", layout: "grid", cols: 3, rows: 2, gap: 16}) // Batch — bulk update in one call: set_layout({nodes: [{node: "1:2", gap: 16, p: 24}, {node: "1:3", gap: 8, p: 12}]}) Controls spacing, padding, direction, and alignment of a container's children. Grid: use layout:"grid" with cols/rows + gap (or rowGap/colGap for asymmetric). Children fill the grid in insertion order.

NameTypeReqDescription
alignstringCross axis (flex only)
colGapnumberGrid column gap (px, grid only)
colsnumberGrid column count (required when layout="grid")
gapnumberSpacing between children (px). On grid sets both row+column gap.
justifystringMain axis (flex only)
layoutstringAuto-layout mode
nodestringNode ID (single mode)
nodesarrayBatch: [{node, layout?, gap?, p?, ...}]
pnumberPadding — number, "v h", or "t r b l"
rowGapnumberGrid row gap (px, grid only)
rowsnumberGrid row count (required when layout="grid")
wrapstringWrap behaviour (flex only)

No output schema declared.

No examples provided.

set_stroke ~479

Set stroke (border) on a node. set_stroke({node: "1:2", stroke: "1 #E0E0E0"}) set_stroke({node: "1:2", stroke: "2 #333 inside"}) set_stroke({node: "1:2", color: "#E0E0E0", weight: 1, align: "inside"}) set_stroke({node: "1:2", color: "linear-gradient(90deg, #8B5CF6 0%, #F97316 100%)", weight: 1.5, align: "inside"}) // Batch — bulk stroke update in one call: set_stroke({nodes: [{node: "1:2", color: "#E0E0E0", weight: 1}, {node: "1:3", color: "#333", weight: 2}]}) Shorthand: "weight color align" (e.g. "1 #E0E0E0 inside"). Hex only in shorthand. Accepted color formats (for the explicit `color` field, not the shorthand): hex "#E0E0E0" gradient string CSS-like subset (see set_fill description for full grammar — same rules). Common: "linear-gradient(<angle>deg, <#hex> <pos>%, ...)", "radial-gradient(<stops>)". Rejected: "circle at X% Y%", named colors, hsl(). variable token qualified bare name "$Border/Default" To bind a variable to the stroke color, use the explicit `color` field — the shorthand parser silently drops bare-name tokens.

NameTypeReqDescription
alignstringStroke alignment relative to the frame edge
colorstringStroke color — hex, gradient string, or qualified bare-name token
nodestringNode ID (single mode)
nodesarrayBatch: [{node, color?, weight?, align?, stroke?}]
strokestringShorthand: "1 #E0E0E0 inside" — single-string form. Hex only; for gradient/variable use the explicit color field.
weightnumberStroke weight in px

No output schema declared.

No examples provided.

set_text ~121

Set text content on one or more nodes. set_text({node: "1:2", text: "Hello World"}) set_text({nodes: [{node: "1:2", text: "Title"}, {node: "1:3", text: "Subtitle"}]}) Use this when changing what text says. For text styling (font, size, weight), use edit.

NameTypeReqDescription
nodestringNode ID
nodesarrayBatch: [{node, text}]
textstringNew text content

No output schema declared.

No examples provided.

set_variable_mode ~164

Set a node to use a specific mode of a variable collection. This controls which variable values the node displays. For example, set a frame to use "Dark" mode of the "Theme" collection so all bound variables show dark values. Examples: set_variable_mode({node: "1:2", collection: "VariableCollectionId:1:2", mode: "1:1"}) set_variable_mode({node: "1:5", collection: "VariableCollectionId:1:3", mode: "1:2"})

NameTypeReqDescription
collectionstringyesVariableCollectionId
modestringyesMode id (e.g. "1:1")
nodestringyesNode ID (e.g. "1:2")

No output schema declared.

No examples provided.

set_variable_value ~308

Set a variable's value for a specific mode. Thin wrapper over Figma's variable.setValueForMode(modeId, value). Call once per mode. Value is a raw value (COLOR/FLOAT/STRING/BOOLEAN) OR an alias object {type: "VARIABLE_ALIAS", id: "VariableID:x:y"}. Hex strings are accepted for COLOR and normalized to {r,g,b,a} in 0-1 range. Examples: set_variable_value({variable: "VariableID:1:5", mode: "1:0", value: "#FFFFFF"}) set_variable_value({variable: "VariableID:1:5", mode: "1:1", value: {r: 0.1, g: 0.1, b: 0.1, a: 1}}) set_variable_value({variable: "VariableID:1:6", mode: "1:0", value: 16}) set_variable_value({variable: "VariableID:1:7", mode: "1:0", value: {type: "VARIABLE_ALIAS", id: "VariableID:1:9"}})

NameTypeReqDescription
modestringyesMode id from the variable's collection (e.g. "1:0")
valueobjectyesRaw value (COLOR/FLOAT/STRING/BOOLEAN) or {type: "VARIABLE_ALIAS", id}
variablestringyesVariableID to set

No output schema declared.

No examples provided.

skill ~88

Load a procedural skill — workflow + tool sequence + anti-patterns. Use FIRST when the user is changing/adjusting existing canvas, OR before creating a new design if a matching skill exists. Example: skill({ name: "restyle" })

NameTypeReqDescription
namestringyesThe skill name exactly as it appears in the KNOWLEDGE LIBRARY menu — no "skill:" prefix, no quotes.

No output schema declared.

No examples provided.

style ~102

Load a visual style preset as INSPIRATION — color tokens, typography, shape, depth. Treat as a reference library, not a cage: pick one wholesale, mix elements, or invent your own. You are not restricted to the menu. Example: style({ name: "neon-cyber" })

NameTypeReqDescription
namestringyesThe style name exactly as it appears in the KNOWLEDGE LIBRARY menu — no "style:" prefix, no quotes.

No output schema declared.

No examples provided.

subtask ~193

Delegate a focused sub-task to a typed child agent. Each type has its own tools, iteration budget, and behavioral constraints. Available agent types: - create: Build an independent UI section (header, sidebar, form, card). Default. - audit: Read-only design review — find layout issues, property omissions, report PASS/FAIL. - token: Variable system operations — create collections, bind tokens, set up aliases. Use when the prompt names 3+ distinct regions (e.g. header, sidebar, main) that share no nodes, or when specialized behavior is needed (audit, token ops). For 1-2 tool-call operations, inline calls finish faster than the subtask spin-up cost.

NameTypeReqDescription
promptstringyesDescription of the sub-task to delegate. Be specific about what to create/modify/audit.
typestringAgent type. Defaults to "create" if omitted.

No output schema declared.

No examples provided.

switch_page ~348

Navigate between pages in the Figma file. ID-driven — names are not addressable (they can collide and change). Two modes: - switch_page({}) → return the page roster only, no switch (use to discover IDs on first call) - switch_page({pageId: "1:23"}) → switch and return the updated state + roster Pages are top-level containers under the file root. Most read/write operations default to figma.currentPage. Call this when you need to operate on nodes that live on a different page than the current one. Returns: - currentPageId, currentPageName — the now-current page (always present) - pages — full roster [{id, name}] of every page in the file (always present) - previousPageId, previousPageName — what you switched from (only when an actual switch happened) - unchanged — true if target was already current Typical flow: 1. switch_page({}) // get IDs 2. switch_page({pageId: "<picked id>"}) // switch When to call: - User mentions content on a different page than the current one - A previous tool reported a node ID is on a non-current page - You need to inspect/modify nodes outside the active page Don't call: - For nodes already on the current page — figma.currentPage is the default scope, this would just waste an iteration - Repeatedly to "explore" — every call returns the full pages roster, cache it

NameTypeReqDescription
pageIdstringTarget page ID (e.g., "0:1"). Omit to just fetch the page roster without switching.

No output schema declared.

No examples provided.

write_plugin_data ~189

Write plugin data (private or shared) to a Figma node. If `namespace` is omitted, writes private pluginData (`node.setPluginData(key, value)`). If `namespace` is provided, writes sharedPluginData (`node.setSharedPluginData(namespace, key, value)`). Pass an empty string as `value` to delete a key. Examples: write_plugin_data({node_id: "1:5", key: "ref", value: "home_title"}) write_plugin_data({node_id: "1:5", namespace: "i18n", key: "ref", value: "home.welcome_title"})

NameTypeReqDescription
keystringyesKey to write.
namespacestringOptional sharedPluginData namespace.
node_idstringyesFigma node id.
valuestringyesValue (string). Pass "" to delete.

No output schema declared.

No examples provided.