figwright
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Capabilities
Features and capabilities supported by this server
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
| prompts | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| pingA | Health check. Returns server info plus, when a plugin is connected, end-to-end info from the Figma sandbox. On a follower it also reports the leader’s version and warns (versionSkew) when a stale older server still owns the plugin. |
| get_selectionA | Return the current selection on the active Figma page: { pageId, pageName, nodes }, where each node is a full flat serialization — geometry, fills/strokes/effects, text properties, style/variable ids, mainComponent — without children. The zero-argument "what is the user looking at" call: use it to identify the selected node ids (and page), then walk deeper with get_design_context or get_node. An empty nodes array means nothing is selected. |
| get_documentA | Return the full node tree (recursive children) of the active Figma page, with base geometry, rotation, opacity, cornerRadius, and fills enrichment. |
| get_nodeA | Return one node by id with its full recursive subtree at maximum fidelity — every serialized field (geometry, paints, effects, auto-layout, text with per-run segments, style/variable ids, mainComponent), no depth limit, no deduplication. Best for inspecting a single component or a node you are about to modify; for exploring or grounding anything large, prefer get_design_context (depth-limited, deduped, tokens resolved to names). Returns { node }, null when the id matches nothing. |
| get_nodes_infoA | Return multiple Figma nodes by id. Output preserves input order; missing ids slot null. |
| get_metadataA | Return file metadata: fileName, current page, and all page references. |
| get_pagesA | Return id+name of every page in the active Figma file. |
| search_nodesA | Search the node tree by case-insensitive name substring and/or exact node type. At least one of name or type is required. Scope to a subtree with root (a node id); defaults to the current page. Returns a flat array of matching nodes. |
| scan_text_nodesA | Return every TEXT node within a subtree, each with its characters / fontSize / fontName. Scope with root (a node id); defaults to the current page. |
| scan_nodes_by_typesA | Return a flat list of every node whose type is in |
| get_stylesA | Return the document's local styles grouped as { paints, texts, effects, grids }. Paint styles carry their paints; text styles carry fontName / fontSize / lineHeight / letterSpacing; effect styles carry their effects; grid styles carry their layout grids. |
| get_variable_defsA | Return the document's local variables as { collections, variables }. Each collection lists its modes and defaultModeId; each variable lists its resolvedType and valuesByMode (primitives, RGBA colors, or { type: "VARIABLE_ALIAS", id } references to other variables). |
| get_local_componentsA | Return the components and component sets within a node subtree (or the current selection) as { components, componentSets }. Scans a subtree, not the whole document — pass nodeId, or select the frames to scan. Components carry their variantProperties (when part of a set); component sets carry their variantGroupProperties (available values per axis) and the ids of their variant components. |
| get_component_apiA | Return a component's full property API — the prop contract behind its instances. Pass a COMPONENT, COMPONENT_SET, or INSTANCE id (an instance resolves to its main component / set). Returns { id, name, type, properties } where properties maps each property name to { type (VARIANT|BOOLEAN|TEXT|INSTANCE_SWAP|SLOT), defaultValue, variantOptions?, preferredValues?, description? }. Property names come back verbatim for set_instance_properties: VARIANT by bare name (e.g. "Size"), BOOLEAN/TEXT/INSTANCE_SWAP suffixed with #id (e.g. "Label#2:0"). Unlike get_local_components (a subtree inventory), this targets one component and is safe on large files. |
| get_viewportA | Return the current page viewport as { center, zoom, bounds } — the on-screen center point, zoom level (1.0 = 100%), and visible bounds rect. |
| get_fontsA | Return every font used on the current page as { fonts: [{ fontName, count }] }, sorted by usage frequency (descending). Mixed-font text contributes one count per styled segment. |
| get_annotationsA | Return Dev Mode annotations as { annotations: [{ nodeId, nodeName, annotations }] }. With nodeId, returns that node's annotations; without it, scans the current page for all annotated nodes. |
| get_reactionsA | Return the prototype reactions on a node as { nodeId, reactions: [{ trigger, actions }] }. Each reaction pairs an interaction trigger (click, hover, timeout…) with its actions (navigate to node, open URL, back/close…). |
| list_filesA | Return the files reachable from the plugin as { files: [{ fileKey, fileName, currentPage }] }. A plugin only sees its host document, so this is a single-element list describing the current file. |
| get_design_contextA | Get a depth-limited, token-efficient node tree — the main design-grounding read; prefer it over get_document / get_node for anything large. Starts from nodeId (a pasted Figma URL also works), else the current selection; errors when neither is available. detail: minimal (id/name/type) / compact (+ geometry) / full (+ styling, layout, text and design-system tokens resolved to names plus a deduped globalVars style table). Defaults to full with dedupeComponents true — the code-generation view; pass detail: compact explicitly for a cheap structure scan. An over-budget full result degrades gracefully: first to the compact structure of the same tree (note attached), then to a sectionPlan. depth limits child levels (omit or 0 = unlimited; cut nodes are flagged truncated). dedupeComponents collapses repeated instances of an already-expanded main component (flagged deduped); a deduped instance still carries textOverrides ({ name, characters } — the visible text it actually renders) and propertyOverrides (its per-instance visual diffs), so per-instance content survives without re-expanding the collapsed subtree. A tree too large to return whole comes back as a sectionPlan instead ({ sections: [{ nodeId, name, nodes, … }] } + a note): do not retry unscoped — call again per section nodeId at detail full and build section by section. On a full result, raw color values that exactly equal a project design token are annotated in projectTokens ({ '#6266F0': { ref, name, matchedBy: ['value'] } }, or { matchedBy, candidates: [...] } when several tokens share the value). matchedBy: ['value'] marks every entry as name-blind value-equality evidence — a hypothesis to verify, not a resolved binding: emit the ref only when the token fits the context semantically, keep the raw value otherwise, and let a bound Figma variable win over a raw-value match. |
| get_screenshotA | Export nodes as images the model can see, one image block per node: { images: [{ nodeId, format, base64, width?, height?, scale?, recovered?, empty? }] }. format is PNG (default) / JPG / SVG. scale applies to raster formats; when omitted, each node is auto-fitted to a legible size (long edge into ~512–1536px: oversized frames scale down, tiny icons scale up ≤4x) — pass an explicit scale to force one. Each raster label reports the exported width×height px and the scale, the anchor for mapping raster px back to design px. base64 is null for missing or non-exportable nodes. Nodes that are fully clipped or off-canvas (carousels, masks, off-screen states) are auto-recovered at their intrinsic bounds and flagged recovered:true. empty:true means the node genuinely renders nothing even unclipped (hidden / no content) so the export is blank. |
| save_screenshotsA | Export nodes and write them to disk under outDir: { saved: [{ nodeId, format, path, recovered?, empty? }] }. format is PNG (default) / JPG / SVG; scale applies to raster formats (default 1). path is null for missing or non-exportable nodes. Nodes that are fully clipped or off-canvas (e.g. a carousel's edge items) are auto-recovered at their intrinsic bounds and flagged recovered:true. empty:true means the node genuinely renders nothing even unclipped (hidden / no content) so the file is blank. Files are named after a sanitized node id. |
| save_image_fillsA | Extract the ORIGINAL image bytes behind each node's IMAGE fills and write them to disk under outDir — the source asset exactly as uploaded (no mask, clip, crop, scale, or effects applied), unlike save_screenshots / get_screenshot which re-render the composited node. Returns { nodes: [{ nodeId, images: [{ index, imageHash, format, path, width?, height?, scaleMode? }], mixed? }] }. index is the fill position in node.fills; width/height are the image intrinsic size; scaleMode is how the fill is displayed (FILL / FIT / CROP / TILE); format is sniffed from the bytes (PNG / JPG / GIF / WEBP, or BIN if unrecognized). Identical images (same imageHash reused across nodes) are fetched once and share one file named by hash. path is null when the fill image can't be resolved; images:[] means the node has no image fill; mixed:true means the node's fills are per-text-range and were not enumerated. For a rendered/composited raster use save_screenshots; for a vector node use export_pdf. |
| export_pdfA | Export a node (or the current page) to a single-page vector PDF file on disk. Figma's plugin API renders one PDF page per node and cannot paginate a page into one-frame-per-page or merge multiple nodes into a multi-page file. Pass a frame / section / component id for a vector PDF of that node; omit nodeId for the current page (large pages can be slow). For raster output (PNG/JPG) use save_screenshots instead. Returns { nodeId, path, empty? }; path is null if the target is missing or not exportable, and empty:true means it rendered a blank PDF. |
| analyze_projectA | Detect the local project profile (framework, language, styling system, component file extensions, svg handling) by reading manifests and config — the foundation scan_components / component_map switch on. Optional standalone probe: those tools run detection internally and return the same profile, so call this only to inspect detection in isolation (no Figma, no file scan). Runs on the server filesystem. rootDir defaults to the server cwd. Detects Tailwind v3 (config file) and v4 (CSS-first @import/@theme) and reports tailwindVersion; detects svg loader (svgr / vite-svg-loader / …) → svg.mode component vs url + an import hint. |
| scan_componentsA | Scan the local project for existing UI components so they can be reused instead of regenerated. Runs on the server filesystem, not in Figma. Identifies components by AST signature (exported, PascalCase, function-ish) rather than by folder layout, so any structure works. React (.tsx/.jsx) is parsed for name + props; Vue/Svelte derive the name from the file and parse props from the block (defineProps / export let / $props). extensions defaults to the detected profile's; rootDir defaults to the server cwd. Returns { components, profile }. |
| component_mapA | Map the Figma component instances in a selection/subtree to existing local code components, so they can be reused instead of regenerated. Joins the grounded Figma component names (and their variant axes) against an AST scan of the project; an explicit docs/figma-component-map.md row (FigmaName | code/path) overrides the fuzzy match — this file is the durable record a verified mapping is written back to, so the next run reuses it instead of re-guessing. A row whose target no longer resolves (deleted/renamed) is reported in staleOverrides and degrades to the fuzzy result rather than a phantom import. Each distinct component is mapped once with all its instance ids. A mapped candidate also reports matchedProps (Figma axes the component already has) and unmatchedProps (axes it lacks → component-extension TODOs). Returns { mappings (candidate + confidence + status high/medium/low/unmapped), unmapped, staleOverrides, profile }. |
| token_mapA | Map the document's Figma variables — and its shared paint styles (single solid color styles, the design-token mechanism of pre-variables files; such rows carry source: 'style') — to the project's design tokens, so generated code references existing tokens instead of hard-coded values. Joins the grounded Figma names + values against tokens parsed from the project CSS (Tailwind v4 @theme or :root custom properties); the match is name-based with an exact color value-match as confirmation. When several project tokens share the exact same color value and the name cannot pick one, the mapping is capped below 'high' and candidate.ambiguousWith lists the other same-value tokens — verify that pick semantically instead of trusting it blindly. On a Tailwind project a variable that hits a framework built-in scale (spacing/N, line-height/N, weight/*) is reported as status 'framework-builtin' with { builtin: { scale, step } } rather than unmapped — it has no @theme token but the utility (p-4 / gap-4, leading-7, font-bold) is still usable. A variable in a multi-mode collection whose value differs per mode (a Light/Dark theme) carries figmaModes (mode name → value per theme; figmaValue is only the default mode), and the result lists themedCollections — keep such tokens theme-aware (a token that itself switches per theme, or the non-default values wired through the project's dark-mode mechanism), never just the default-mode literal. tokenSource overrides the detected styling config; rootDir defaults to the server cwd. Tailwind v3 JS configs are not yet parsed (pass tokenSource to a CSS file). An explicit docs/figma-token-map.md row (FigmaName | ref) overrides the fuzzy join with matchedBy ["map-file"] — this file is the durable record a verified token mapping is written back to, so the next run reuses it instead of re-guessing an ambiguous or value-only match. A row whose ref no longer resolves to a project token is reported in staleOverrides and degrades to the normal join. Returns { mappings (candidate + confidence + status + matchedBy + builtin), unmapped, staleOverrides, tokenSource, profile }. |
| icon_mapA | Map the Figma icon nodes in a selection/subtree to the project's existing |
| design_diffA | Diff a Figma node against a saved baseline of itself, so after a design changes you edit only the affected code instead of regenerating. First call on a node saves a baseline (its get_design_context, full detail) under .figwright/snapshots/ and returns status 'baseline-created'; a later call returns status 'diff' with the per-node, per-property changes (added / removed / changed nodes; fills, layout/padding, text, token bindings — resolved to readable values, not opaque ids) or 'no-changes'. Pass update:true to accept the current design as the new baseline (re-snapshot). nodeId defaults to the selection; rootDir defaults to the server cwd. The baseline is a plain file the tool writes under the project — committing it (so teammates share the baseline) or gitignoring it is your call; the tool never changes git. It never mutates Figma. Scope by a component / section nodeId, the same unit codegen works on. |
| set_fillsA | Set a node's fills. SOLID: { type:'SOLID', color:{r,g,b} } (0–1). Gradient: { type:'GRADIENT_LINEAR'|…, gradientStops:[{position,color:{r,g,b,a}}], gradientTransform } (round-trips get_node output). Returns { ok, nodeId }. |
| set_textA | Replace the entire text content of a TEXT node; the plugin loads the node's current fonts first and preserves existing character styling where possible. For formatting (font, size, color, spacing) use set_text_properties, and to substitute text across many nodes use find_replace_text. Returns { ok, nodeId }. |
| set_text_propertiesA | Set a TEXT node's typography and layout/overflow properties. Typography: fontName ({ family, style }), fontSize, lineHeight, letterSpacing, textCase, textDecoration, paragraphSpacing / paragraphIndent (px between / indenting the paragraphs the text splits into at "\n" — the write half of the same fields get_design_context reads) — these load the required fonts first. Layout/overflow: textTruncation (ellipsis), maxLines (line clamp), textAutoResize. Any field may be omitted to leave it unchanged. maxLines applies when textTruncation is ENDING. Returns { ok, nodeId }. |
| set_text_rangeA | Style character ranges of an existing TEXT node — the write-side mirror of a read segment, for inline rich text (a link inside a sentence, a bold word, a coloured span, a bulleted list, a smaller /mo after a price). Each range gives start/end (char offsets into the node's characters) plus any subset of run properties: fontName / fontSize / fills / textDecoration / textCase / lineHeight / letterSpacing / hyperlink / listOptions / indentation, and design-system bindings textStyleId / fillStyleId / boundVariables. Ranges apply in order (a later range overrides an earlier one on overlap). Fonts are loaded automatically. Set the whole node first with create_text / set_text; use set_text_properties for node-level typography & overflow. Returns { ok, nodeId }. |
| create_frameA | Create a frame — the primary container for UI and the only node that hosts auto-layout — optionally sized/positioned and appended to a parent (default: current page). Enable auto-layout afterwards with set_auto_layout; for a canvas-level grouping container use create_section instead. Returns { ok, nodeId, name, type }. |
| set_opacityA | Set a node's layer opacity from 0 (transparent) to 1 (opaque); this multiplies with any fill or stroke alpha. Opacity 0 still renders, exports, and hit-tests — to exclude a node from rendering use set_visible(false), and to remove it use delete_nodes. Returns { ok, nodeId }. |
| set_visibleA | Show or hide a node by toggling its |
| rename_nodeA | Rename a single canvas node's layer name; does not affect a component's name elsewhere or its instances. To rename a document page use rename_page; to rename many nodes by pattern use batch_rename_nodes. Returns { ok, nodeId }. |
| delete_nodesA | Permanently delete nodes by id; missing or non-removable nodes are skipped. To hide nodes reversibly instead of deleting them, use set_visible(false). Returns { ok, affected } — the ids actually removed. |
| create_textA | Create a new TEXT node with the given characters (default font loaded automatically), optionally sized/positioned and appended to a parent (default: current page). To change the text of an existing node use set_text; for font, size, or color use set_text_properties. Returns { ok, nodeId, name, type }. |
| create_rectangleA | Create a rectangle, optionally sized/positioned and appended to a parent (default: current page). Useful for solid shapes, dividers, and color blocks; for a container that holds other layers use create_frame, and for placed bitmaps use import_image. Returns { ok, nodeId, name, type }. |
| set_corner_radiusA | Set a node's corner radius. Pass radius for a uniform radius, and/or per-corner topLeftRadius / topRightRadius / bottomRightRadius / bottomLeftRadius (for nodes that support individual corners, e.g. a card rounded only on top, a tab or a chat bubble). A per-corner value overrides radius for that corner. At least one of radius or a corner is required. Returns { ok, nodeId }. |
| set_strokesA | Set a node's strokes (SOLID or gradient paints, same shape as set_fills) plus optional strokeWeight, strokeAlign (INSIDE / OUTSIDE / CENTER), dashPattern (dashes), and per-side weights (strokeTopWeight / strokeRightWeight / strokeBottomWeight / strokeLeftWeight — for nodes that support individual stroke weights, e.g. a border-bottom-only divider). A per-side weight overrides strokeWeight for that side. Any field may be omitted to leave it unchanged. Returns { ok, nodeId }. |
| move_nodesA | Translate nodes by (dx, dy). Nodes without a position are skipped. Returns { ok, affected }. |
| set_positionA | Set a node's exact position (x / y), relative to its parent — for a top-level node these are canvas coordinates; for an absolutely-positioned child they are relative to its auto-layout parent. Use this to place an overlay / badge / pinned element at a known spot, or to position a top-level frame on the canvas; to nudge by a delta instead use move_nodes. A node that sits in-flow inside an auto-layout frame is positioned by the layout — set layoutPositioning ABSOLUTE (set_layout_props) first to place it freely. Either coordinate may be omitted to leave it unchanged. Returns { ok, nodeId }. |
| resize_nodesA | Resize nodes to the given width × height (positive). Non-resizable nodes are skipped. Returns { ok, affected }. |
| set_auto_layoutA | Configure a frame's auto layout. layoutMode NONE disables it; HORIZONTAL/VERTICAL enable flex (padding / itemSpacing / alignment / wrap, plus counterAxisSpacing / counterAxisAlignContent for the wrapped cross axis — the CSS row-gap / align-content — and itemReverseZIndex / strokesIncludedInLayout for paint order and stroke-in-layout); GRID enables CSS-Grid-style layout (padding / gridRowCount / gridColumnCount / gridRowGap / gridColumnGap). Returns { ok, nodeId }. |
| set_layout_propsA | Set a node's auto-layout sizing and child properties. layoutSizingHorizontal / layoutSizingVertical (HUG = shrink to fit children, FILL = stretch to fill the auto-layout parent, FIXED = keep the current size) are the preferred way to size a frame to its content (HUG) or make a child fill its container (FILL) — reach for these instead of guessing pixel sizes with resize_nodes. layoutAlign (STRETCH = fill the counter axis, INHERIT = default) and layoutGrow (1 = fill the primary axis, 0 = hug) are the older per-axis equivalents. layoutPositioning (ABSOLUTE = ignore the flow and position freely, AUTO = participate in layout). minWidth / maxWidth / minHeight / maxHeight set responsive size bounds (→ min-w / max-w); pass null to clear a bound. Bounds apply to auto-layout frames and their direct children. HUG needs an auto-layout frame (or text); FILL needs an auto-layout parent. Any field may be omitted to leave it unchanged. Returns { ok, nodeId }. |
| set_layout_gridsA | Set a frame's own layout grids — the responsive column/row scaffold laid over it (the 12-column grid, the 8pt baseline), distinct from auto-layout (set_auto_layout arranges children). Each grid is COLUMNS / ROWS (count + gutterSize + alignment, e.g. a 12-col grid) or GRID (uniform squares via sectionSize, a baseline). Replaces the frame's grids with the array given; pass [] to clear them. Only frames (and components/instances) carry layout grids. Returns { ok, nodeId }. |
| set_blend_modeA | Set how a node composites with the layers beneath it (NORMAL, MULTIPLY, SCREEN, OVERLAY, DARKEN, LIGHTEN, COLOR_DODGE, etc.). PASS_THROUGH is only meaningful on groups/frames (lets children blend with content outside the group). Affects compositing only, not the node's own fills — use set_fills or set_opacity for those. Returns { ok, nodeId }. |
| set_maskA | Set whether a node is a mask — a mask clips its later siblings to its own shape. Pass isMask true/false, and optionally maskType (ALPHA / LUMINANCE / GEOMETRY) when enabling. Returns { ok, nodeId }. |
| set_arcA | Turn an ellipse into a pie slice / gauge or a ring / donut by setting its arc data. startingAngle / endingAngle are in radians and carve out the visible wedge (a full circle is 0 → 2π ≈ 6.28319; a half is π ≈ 3.14159); innerRadius is 0–1 of the radius (0 = a solid disc, > 0 = a ring with a hole, e.g. 0.6 for a donut or progress ring). Only ellipses have arc data. Pass any subset — omitted fields keep their current value. At least one is required. Returns { ok, nodeId }. |
| set_constraintsA | Set how a node responds when its parent frame is resized, via horizontal and vertical constraints: MIN pins to the left/top, MAX to the right/bottom, CENTER keeps it centered, STRETCH pins both edges (grows with the parent), and SCALE resizes proportionally. Constraints apply inside plain frames only — auto-layout frames position children by layout rules and ignore them. Returns { ok, nodeId }. |
| rotate_nodesA | Set absolute rotation (degrees) on nodes. Nodes without rotation are skipped. Returns { ok, affected }. |
| lock_nodesA | Lock nodes so they can't be selected or edited on the canvas (e.g. backgrounds); locking a parent also locks its descendants. Locked nodes still render and export — this only affects canvas interaction and is reversed by unlock_nodes. Returns { ok, affected } with the ids actually locked. |
| unlock_nodesA | Unlock nodes so they can be selected and edited on the canvas again — the inverse of lock_nodes. Ids that no longer exist are skipped. Returns { ok, affected } with the ids actually unlocked. |
| clone_nodeA | Duplicate a node — including its full subtree — and place the copy as a sibling right after the original under the same parent. Cloning a component instance keeps it an instance; to make a fresh instance of a component use create_instance instead. Returns { ok, nodeId, name, type } for the copy. |
| set_effectsA | Set a node's effects. Shadows (DROP_SHADOW / INNER_SHADOW) need color + offset; blurs need radius. Returns { ok, nodeId }. |
| create_paint_styleA | Create a reusable local paint (color) style from SOLID or gradient paints (same shape as set_fills); use slashes in the name for folder grouping. Apply it to nodes with apply_style_to_node, or edit it later with update_paint_style. Returns { ok, styleId, name }. |
| create_text_styleA | Create a reusable local text style (a typography token) that can be applied to TEXT nodes with apply_style_to_node. The font is loaded before assignment. lineHeight unit is AUTO / PIXELS / PERCENT (AUTO omits value); letterSpacing unit is PIXELS / PERCENT. For one-off formatting of a single node use set_text_properties instead. Returns { ok, styleId, name }. |
| create_effect_styleA | Create a local effect style. Shadows (DROP_SHADOW / INNER_SHADOW) need color + offset; blurs (LAYER_BLUR / BACKGROUND_BLUR) need radius. Returns { ok, styleId, name }. |
| create_grid_styleA | Create a reusable local layout-grid style for aligning content. Each grid pattern is GRID (uniform squares via sectionSize) or ROWS / COLUMNS (count + gutterSize + alignment). Apply it to frames with apply_style_to_node. Returns { ok, styleId, name }. |
| update_paint_styleA | Update an existing paint style by id. Any of name / paints / description may be omitted to leave unchanged. Returns { ok, styleId, name }. |
| update_text_styleA | Update an existing text style (typography token) by id. Any of name / fontName / fontSize / lineHeight / letterSpacing / description may be omitted to leave unchanged. A new font is loaded before assignment. lineHeight unit is AUTO / PIXELS / PERCENT (AUTO omits value); letterSpacing unit is PIXELS / PERCENT. Use this to keep a shared style in sync with code instead of creating a duplicate. Returns { ok, styleId, name }. |
| update_effect_styleA | Update an existing effect style by id. Any of name / effects / description may be omitted to leave unchanged; effects, when given, replaces the whole list. Shadows (DROP_SHADOW / INNER_SHADOW) need color + offset; blurs (LAYER_BLUR / BACKGROUND_BLUR) need radius. Use this to keep a shared style in sync with code instead of creating a duplicate. Returns { ok, styleId, name }. |
| apply_style_to_nodeA | Bind a shared style to a node. |
| delete_styleA | Delete a local style (paint / text / effect / grid) by id. Returns { ok, styleId, name }. |
| create_variable_collectionA | Create a variable collection. Figma auto-creates a default mode. Returns { ok, collectionId, defaultModeId, name }. |
| add_variable_modeA | Add a mode (e.g. "Dark") to a variable collection. Returns { ok, modeId, name }. Mode count is gated by the file's Figma plan (Starter allows 1 per collection) — when the plan blocks a new mode this fails with guidance: fall back to a paired collection (e.g. "Color/Dark") holding the same variable names with that theme's values. |
| create_variableA | Create a variable in a collection with resolvedType BOOLEAN / FLOAT / STRING / COLOR. The variable starts empty — set per-mode values with set_variable_value, then attach it with bind_variable_to_node or bind_variable_to_paint. Returns { ok, variableId, name }. |
| set_variable_valueA | Set a variable's value for one mode (modeId comes from the variable's collection). value must match the variable resolvedType: a boolean, a number (FLOAT), a string, a color { r, g, b, a } (0–1), or an alias { type: "VARIABLE_ALIAS", id } pointing at another variable. Create the variable first with create_variable. Returns { ok, variableId, name }. |
| bind_variable_to_nodeA | Bind a variable to a node field (e.g. width, height, characters, itemSpacing, topLeftRadius, or cornerRadius to bind all four corners at once), or unbind by passing variableId: null. The variable's resolvedType must match the field's type. To bind a fill or stroke color use bind_variable_to_paint instead; get bindable variable ids from get_variable_defs. Returns { ok, nodeId }. |
| bind_variable_to_paintA | Bind a COLOR variable to a SOLID fill or stroke paint (the design-token way to colour a node) — or unbind by passing variableId: null. Figma stores fill/stroke colour bindings on the paint, not the node, so this is separate from bind_variable_to_node (which covers scalar fields like width / padding / radius). target is fills (default) or strokes; index selects which paint (default 0). The paint at that index must be SOLID. Returns { ok, nodeId }. |
| rename_variableA | Rename a variable (e.g. "color/primary" → "color/brand"); use slashes in the name for folder grouping in the Variables panel. The variable id is unchanged, so existing bindings keep working. Returns { ok, variableId, name }. |
| set_variable_code_syntaxA | Declare a variable's code-side token name per platform (codeSyntax) — the write half of the codeSyntax that get_design_context / get_variable_defs surface to codegen as the authoritative name (e.g. WEB: "--color-primary"). Per platform (WEB / ANDROID / iOS): a non-empty string sets the declaration, null removes it, an omitted platform is untouched. When authoring design-system variables from existing code tokens, declare the source token name here so future codegen resolves to the exact token instead of deriving a name. Returns { ok, variableId, name, codeSyntax } with the declarations now in effect. |
| delete_variableA | Delete a single variable by id; any node or paint bound to it reverts to its raw value. To delete an entire collection and all its variables use delete_variable_collection. Returns { ok, variableId, name }. |
| delete_variable_collectionA | Delete a variable collection by id, removing the collection and every variable and mode in it; bindings to those variables revert to their raw values. To delete a single variable instead, use delete_variable. Returns { ok, collectionId, name }. |
| group_nodesA | Group nodes under their shared parent. nodeIds must be a non-empty list. Returns { ok, nodeId, name, type } for the new group. |
| ungroup_nodesA | Ungroup GROUP nodes by id; non-group nodes are skipped. Returns { ok, affected } — the ids of the children promoted out of the groups. |
| reparent_nodesA | Move nodes into a different parent, optionally inserting at |
| reorder_nodesA | Reorder nodes within their current parent by inserting each at |
| find_replace_textA | Replace a substring across all TEXT nodes under a scope. Without rootId the whole current page is searched; matching is case-insensitive unless caseSensitive is true. Fonts are loaded before each edit. Returns { ok, affected } — the text node ids changed. |
| batch_rename_nodesA | Rename many nodes at once from a [{ nodeId, name }] list. Missing nodes are skipped. Returns { ok, affected }. |
| add_pageA | Create a new page (optionally named). Returns { ok, nodeId, name, type }. |
| delete_pageA | Delete a page by id. The current page and the last remaining page cannot be deleted. Returns { ok, nodeId }. |
| rename_pageA | Rename a Figma page (a top-level page/tab in the document) by id. Affects only the page name; its node id and contents are unchanged. To rename a layer/node on the canvas use rename_node instead. Returns { ok, nodeId }. |
| navigate_to_pageA | Switch the active page. Subsequent selection / read tools operate on this page. Returns { ok, nodeId }. |
| set_reactionsA | Replace all of a node's prototype reactions — this overwrites existing reactions rather than appending. Each reaction pairs a trigger (e.g. { type: 'ON_CLICK' }) with an actions array (e.g. { type: 'NODE', destinationId, navigation, transition }). Best used to round-trip get_reactions output; to clear all reactions instead use remove_reactions. Returns { ok, nodeId }. |
| remove_reactionsA | Clear every prototype reaction from a node (equivalent to set_reactions with an empty array). Use this to strip interactivity; to replace reactions with new ones use set_reactions. Returns { ok, nodeId }. |
| swap_componentA | Swap an instance's main component. Provide componentKey (published component, imported via the API) or componentId (a local COMPONENT node). Returns { ok, nodeId } (the instance id). |
| set_instance_propertiesA | Set an instance's component properties (variant / boolean / text / instance-swap). Keys are the property names from get_component_api, used verbatim: VARIANT by bare name (e.g. "Size": "Large"), BOOLEAN/TEXT/INSTANCE_SWAP suffixed with #id (e.g. "Label#2:0": "Sign in", "Disabled#1:2": true). An INSTANCE_SWAP value is the target component node id. Unspecified properties keep their value; SLOT properties are not settable. Returns { ok, nodeId }. |
| add_component_propertyA | Declare a component property on a component (or its variant set): BOOLEAN (show/hide a layer), TEXT (editable text), or INSTANCE_SWAP (swappable nested instance). The property starts inert — attach it to a layer with bind_component_property (BOOLEAN→visible, TEXT→characters, INSTANCE_SWAP→mainComponent) for it to do anything. defaultValue must match the type (boolean / string / a component key string); preferredValues (INSTANCE_SWAP only) pre-populates the swap menu. VARIANT properties come from combine_as_variants, not here. Returns { ok, componentId, propertyId, name } — pass propertyId to bind / edit / delete / set_instance_properties. |
| bind_component_propertyA | Attach a declared component property (from add_component_property) to a sublayer field so it drives that layer: field "visible" for a BOOLEAN, "characters" for a TEXT (the node must be a TEXT node), "mainComponent" for an INSTANCE_SWAP (the node must be an INSTANCE). The same property can be bound to several layers (call once per layer). Pass propertyId: null to remove the binding on that field. The property's type must match the field and it must exist on the containing component. Returns { ok, nodeId }. |
| edit_component_propertyA | Change an existing component property: rename it, change its defaultValue, or (INSTANCE_SWAP only) change its preferredValues. Supply at least one. Renaming returns a new propertyId (the #id suffix is kept but the name part changes), so use the returned propertyId for later calls; existing bindings keep working. Get current property ids from get_component_api. Returns { ok, componentId, propertyId, name }. |
| delete_component_propertyA | Remove a BOOLEAN / TEXT / INSTANCE_SWAP property from a component and every sublayer reference to it. VARIANT properties are the variant-set structure — delete their variants instead; this refuses a VARIANT. Get current property ids from get_component_api. Returns { ok, componentId, propertyId, name }. |
| detach_instanceA | Detach a component instance into a plain frame, permanently breaking its link to the main component; the frame keeps its current appearance and its layers become directly editable. To switch an instance to a different component instead of detaching, use swap_component. Returns { ok, nodeId, name, type } for the resulting frame. |
| import_imageA | Import a raster image (PNG / JPG / GIF) and place it as a rectangle with an IMAGE fill. Provide data (base64-encoded image bytes) or url. The rectangle defaults to the image size unless width/height are given. scaleMode is FILL / FIT / CROP / TILE (default FILL). For vector SVG (logos / icons) use import_svg instead. Returns { ok, nodeId, name, type }. |
| import_svgA | Import an SVG and place it as editable vector nodes (a FRAME of VECTOR paths) via createNodeFromSvg — use this for vector logos, brand marks, and icons. Provide the SVG's raw markup string (read it from the project asset, or inline it). The frame defaults to the SVG intrinsic size unless width/height are given. For raster photos (PNG / JPG) use import_image instead; when a matching icon component already exists, create_instance it rather than re-pasting the SVG. Returns { ok, nodeId, name, type }. |
| create_ellipseA | Create an ellipse (a circle when width equals height), optionally sized/named/positioned under a parent (default: current page). To turn it into a pie, arc, or ring afterwards use set_arc. Returns { ok, nodeId, name, type }. |
| create_componentA | Create a reusable main component. Pass fromNodeId to convert an existing node into a component (e.g. a frame of vectors from import_svg, or a built layout) — it keeps the node's position and parent unless parentId is given; omit fromNodeId to create an empty component to build into. Then create_instance the result to reuse it. Optionally sized / named / positioned and placed under a parent (default: current page). Returns { ok, nodeId, name, type }. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| figma_to_code | Generate framework-aware code from a Figma selection that reuses the project’s existing components and design tokens instead of regenerating them (the cross-client form of the figma-codegen workflow: get_design_context + component_map + token_map). |
| code_to_figma | Build a Figma design from code or a description in the connected file, reusing the file’s existing components / variables / styles instead of drawing primitives (the cross-client form of the figma-build workflow: get_variable_defs + scan_components + create_instance + bind_variable_to_paint / bind_variable_to_node). |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/awdr74100/figwright'
If you have feedback or need assistance with the MCP directory API, please join our Discord server