Figxel
Lets an AI agent read, design and animate inside the Figma desktop file you have open, via a local Figma plugin. Capabilities include reading layers, design context, variables, styles, fonts, screenshots and exports (PNG, JPG, SVG, PDF); building and editing frames or whole sections in one call; working with components, variants, styles, variables with modes and library assets; prototyping and animating with keyframes, storyboards and video export; validating its own work (layout checks for overflowing text, clipped/overlapping content, low contrast, placeholder copy) and reading FigJam boards and Figma Slides decks.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Figxel build a landing hero in my open Figma file and check the layout"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Figxel is an MCP server with a small Figma desktop plugin. With it, an AI app such as Claude, ChatGPT, Cursor or VS Code can read, build and animate real designs in the file you have open, guided by skills that teach it to work like a designer. It runs on your computer, or through a hub on a server that your team runs or that you are invited to (Figxel Cloud and hubs).
Figxel is not affiliated with, endorsed or sponsored by Figma, Inc. Figma is a trademark of Figma, Inc.
Tested live on Windows; macOS has not been run live yet.
Why Figxel
It works with the AI app you already use. Claude, Cursor, VS Code, Codex, Gemini CLI or any other app that runs local MCP servers, whatever model it runs.
It reads and writes your real Figma file. A plugin runs in Figma desktop, so the agent makes editable layers, components and variables in the file you have open.
It never silently overwrites your edits. When you change something the agent read earlier, its next write to it is refused until it reads again
[C-397]; each instruction can be taken back in one step, and only when that takes back nothing of yours.The agent works like a designer, in the role the work needs. UI/UX, graphic, illustration, brand, presentation, design system, board or motion: each role has its own workflow, with planning before the work and testing after it. The tools enforce it: new work starts with a brief, ends with a sign-off that runs the role's checks, and a final export waits for that sign-off. For motion, a plan comes before the first keyframe.
It is local by default and open source. The server runs on your machine and listens only on
127.0.0.1; a team can run its own hub instead. MIT licensed.
Related MCP server: figma-proxy-mcp
What you can do
Ask in plain words; the agent picks the tools.
Read a design: layers, design context for writing code, screenshots and exports (PNG, JPG, SVG, PDF), variables, styles and fonts.
Build and edit: a whole section in one call (
figma_create_from_spec) or frame by frame. Each call is one Ctrl+Z step in Figma.Work with a design system: components and variants, styles, variables with modes, and library assets.
Prototype and animate: prototype flows, keyframes, storyboards and video export, checked with
figma_check_motion.Check its own work:
figma_check_layoutfinds overflowing text, clipped or overlapping content, low contrast and placeholder copy, and its audits measure target sizes, focus and error states, copy, the brief's grid and type scale, a mark at its smallest size, a deck's density and how much is bound to your variables, each with the fix.Stress-test a design:
figma_stress_testmakes copies with translated, longer and bigger content and many or no items, checks each, and says what broke, before real content arrives.FigJam and Figma Slides: reads work today; board and deck writes stay refused until a live run verifies them.
Follow a process: fourteen skills, from design and motion to critique, reach every app through
figma_get_guide, MCP prompts andskill://resources.
That is 140 tools by default: see the tool catalog.
Requirements
Figma desktop on macOS 12 or later, or Windows 10 or later (64-bit) or Windows on Arm
[C-273].Node.js 22 or later.
An AI app that runs local (stdio) MCP servers (setup per app).
Optional: ffmpeg on your PATH, so the agent can review its video renders frame by frame.
Quickstart
Quit Figma desktop completely, then run setup in a terminal. On Windows, closing Figma's window is not enough: quit it from its icon in the notification area
[C-341].npx -y figxel-mcp@latest setup --registerSetup creates a token, copies the plugin into
~/.figxel/plugin, lists it in Figma's development plugins[C-323], and prints the token and the entries for your AI app.Run the plugin. Open Figma and a file, choose Plugins → Development → Figxel, paste the token and press Save. You paste the token once, and run the plugin once per Figma session (why).
Add the server to your AI app. In Claude Desktop, Settings → Developer → Edit Config opens
claude_desktop_config.json[C-277]. Add Figxel undermcpServers:{ "mcpServers": { "figxel": { "command": "npx", "args": ["-y", "figxel-mcp@latest"] } } }On Windows, start it through
cmd, because an app that startsnpxwithout a shell fails there[C-281]:{ "mcpServers": { "figxel": { "command": "cmd", "args": ["/c", "npx", "-y", "figxel-mcp@latest"] } } }In Claude Code, this command works on every operating system
[C-279][C-280]:claude mcp add -s user figxel -- npx -y figxel-mcp@latestOther apps: docs/clients.md.
Try it. Restart your AI app (quit Claude Desktop completely
[C-277]) and ask it to call figma_status: it should list your open file. Then ask for real work, such as "Design a landing hero for Slow Wheel, a fictional pottery studio." Using Figxel shows how to brief the agent and review its work.
Setup's backup of Figma's settings, --dry-run, --force, --unregister, the manual import and the macOS status: Install details.
Figxel Cloud and team hubs
A hub runs the bridge on a server, so the plugin and your AI apps meet there instead of on your computer, and apps that cannot start a local server, such as claude.ai and ChatGPT, connect with a URL. Each person signs in with Figma or Google and reaches only their own Figma.
Figxel Cloud is the hub at
mcp.figxel.moirelabs.dev, by invitation for now. Install the plugin withnpx -y figxel-mcp@latest install(quit Figma first), press Sign in in it, and addhttps://mcp.figxel.moirelabs.dev/mcpto your AI app (connecting).Your team's own hub: docs/hub.md runs one, with the people, sign-in and security it needs.
See it in action
Design a landing hero for Slow Wheel, a fictional pottery studio.
The build at the top of this page, finished: four sections in four calls, then figma_check_layout found seven warnings (low contrast, a chip outside its frame, a sizing conflict) and the agent fixed them in one undoable figma_batch.
Animate this end card for a fictional run club: hook, schedule, call to action.
Keyframes set in Figma, rendered by figma_export_video and checked frame by frame with figma_review_video:
More to try, with what to expect, in Using Figxel:
"Set up colour, spacing and type tokens for this file, then make a Button component with size and state variants."
"Rebuild the settings screen from
src/app/settings/page.tsxin Figma.""Critique the selected frame as a panel of senior designers, then fix what you find."
"Summarize the stickies on this FigJam board by theme."
Configuration
Settings are environment variables in your AI app's server entry. The two you are most likely to change:
BRIDGE_TOOLSETtrims the tool list for apps with a tool limit, such as VS Code (128 tools[C-286]) and Windsurf (100[C-289]):coreregisters 20 tools.BRIDGE_PROCESSsets how strictly the design process is enforced:strict(the default: new work waits for a brief, a final export for a sign-off, keyframes for a motion plan),guided(warnings instead of refusals) oroff.
Every setting, its default and where to set it: docs/configuration.md.
Troubleshooting
"No Figma plugin is connected" (
NO_SESSION): run the plugin in Figma, Plugins → Development → Figxel. Not in that menu? See Install details."Its token does not match": run setup again, paste the token it prints into the plugin window and press Save.
The server does not start on Windows (
spawn npx ENOENTin the app's log): use thecmd /c npx …form[C-281].Too many tools in VS Code or Windsurf: set
BRIDGE_TOOLSET(Configuration).figma_statusasks for a restart: run the plugin again, or restart your AI app, as its hint says.
Port conflicts, timeouts, video exports, macOS and logs: docs/troubleshooting.md.
Privacy
Figxel runs on your machine. The server listens only on
127.0.0.1, the plugin connects only to it, and Figxel sends nothing to any other service.Your AI app sends what the agent reads to its model provider: file, page and layer names, text, the images it exports to look at, and your Figma user name and id.
Your token stays local. It lives in
~/.figxel/token; the server never sends it to your AI app and never logs it.On a hub, the plugin's requests and answers pass through that server over TLS, and files written for a web client stay there for an hour; the hub keeps no design data beyond that, and its people table keeps hashes, not tokens (docs/hub.md).
More, including the tools that take a URL: Privacy details.
Updating and uninstalling
With @latest in the entry, restarting your AI app picks up a new version [C-283]; then close the Figxel plugin window and run it again. With Figxel Cloud alone, run npx -y figxel-mcp@latest install again instead, then run the plugin again; the plugin window says when an update is out. To uninstall, remove the figxel entry from each app, remove Figxel from Figma's development plugins and delete ~/.figxel. Details: Updating and uninstalling.
FAQ
Is Figxel an official Figma product?
No. Figxel is an independent open-source project; it is not affiliated with, endorsed or sponsored by Figma, Inc.
Which AI apps does it work with?
Any app that runs local (stdio) MCP servers, with any model: Claude Desktop, Claude Code, Cursor, VS Code, Codex, Gemini CLI and more (setup per app). Apps with a tool limit need a smaller BRIDGE_TOOLSET (Configuration).
Do I need a paid Figma plan?
No. Plugins run on the Starter plan and with a Full seat on paid plans; a Dev, Collab or View seat cannot run them in Figma Design [C-308]. Your plan's limits still apply [C-045]: a Starter file has at most 3 pages [C-048] and no variable modes [C-047].
Why do I have to start the plugin myself?
Figma has no command or link that runs a plugin from outside [C-016]. Run it once per Figma session; it reconnects by itself when your AI app restarts the server.
Does my design data leave my machine?
On your computer, Figxel itself sends nothing off your machine. Through a hub, the plugin's requests and answers pass through that server. Either way, your AI app sends what the agent reads to its model provider, as it does with anything else you share with it (Privacy).
Does it run on Linux?
No. Figma desktop has no Linux build, and development plugins run only in the desktop app [C-273] [C-274].
Documentation
Document | What is in it |
How to work with the agent: the first session, writing a brief, example requests, reviewing and undoing its work, tips | |
Setup per app, install details, updating and uninstalling, installing the skills, tool-call timeouts, sharing one Figma connection | |
Every setting, its default and where to set it | |
A hub on a server: the container, the TLS route, people, sign-in with Figma or Google, security | |
Known problems with their fixes, and the privacy details | |
How an agent should work: the loop, the skills, prompts and resources, choosing a tool, the safety rules | |
Every tool and its parameters, toolsets, resources, and which editor runs each tool | |
The wire protocol between the server and the plugin | |
Architecture, configuration, limits, safety, errors, testing and decisions | |
Phases, next steps, locked decisions, and why Figxel uses a plugin | |
Every external fact the design relies on, with source and date: the ids such as | |
Development setup, conventions, tracked claims, pull requests |
Figxel was called figma-mcp during development, so dated documents (the design spec's file name, plans and spike results) keep that name.
Contributing
Contributions are welcome. Start with CONTRIBUTING.md; everyone who takes part follows the Code of Conduct. Report security problems privately, as SECURITY.md describes. Changes are listed in the changelog.
License
MIT. The npm package bundles third-party code under its own licences, listed in dist/THIRD_PARTY_NOTICES.md.
Available Tools
140 toolsfigma_add_component_propertyAdd component propertyAIdempotent
Give a component (or component set) a property that instances can change: TEXT (wire it to text layers with bindNodeIds — instances then edit the label without detaching), BOOLEAN (show/hide the bound layers), INSTANCE_SWAP (swap a nested icon instance; default = a component id), VARIANT (on a set only). Returns the property key (name + #id) that figma_set_instance_properties accepts — the plain name works too. Called again with a name and type that exist, it reuses that property (reused: true) and wires the new layers; to rename, re-default or unwire use figma_edit_component_property. A slot is figma_create_slot. Editors: Design; unverified: FigJam, Slides.
Inputs: name (required), type (required), componentId (required), defaultValue (required), +5 more.
figma_add_variable_modeAdd variable modeAIdempotent
Add a mode (e.g. "Dark") to a variable collection; returns its modeId. Modes beyond the first need a paid plan — on a Starter file Figma refuses, and its message is returned. Then set values per mode with figma_set_variable_value. Editors: Design; unverified: FigJam, Slides.
Inputs: name (required), collectionId (required), force, session, +1 more.
figma_apply_style_to_nodeApply styleAIdempotent
Apply a local style (paint, text, effect or grid) by id or by name — the node then follows the style. Give type when a name is shared across kinds, or to apply a paint style as the stroke (default: fill). figma_get_styles lists local styles; a style from a library (not listed there) is applied by the id that figma_get_design_context returns in stylesUsed. For a raw colour use figma_set_fills. Returns per-item results: { updated, items: [{ id, ok, error? }] } — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeIds (required), type, force, session, +3 more.
figma_batchBatch editsAIdempotent
Several edits in ONE call and ONE undo step — a polish pass over what you built: fills, strokes, radius, effects, auto-layout, sizes, text, constraints, names. steps is a JSON array of { "op": "set_fills", "params": { … } } (tool names without figma_, 1–50), each checked against that tool's own parameters before anything runs. Modify and style edits only: no creates (figma_create_from_spec builds), no deletes, nothing that replaces nodes with new ids (group, boolean, flatten, clone). Steps run in order and stop at the first failure without rolling back: the error's partial.steps and partial.failedAt say what was applied, and one Ctrl+Z undoes the whole batch. Success: { steps: [{ index, op, ok, result }], completed, itemsFailed? }. A step's ok means it ran; each node it could not change is listed in itemsFailed: [{ step, op, id, error }]. Keyframe steps pass the same motion gate as figma_set_keyframes (BRIDGE_PROCESS).
Inputs: steps (required), force, session, idempotencyKey.
figma_batch_rename_nodesBatch renameAIdempotent
Bulk rename by find/replace over names. Scope, optional type filter, optional regex. Useful for turning Frame 12 into Card / 12. Returns per-item results: items: [{ id, ok, error? }] — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: pattern (required), replace (required), force, regex, +5 more.
figma_bind_variable_to_nodeBind variableAIdempotent
Bind a variable (design token) to a property of nodes so it follows the variable. field: fill, stroke (COLOR; index picks the paint, which must be SOLID — a gradient or image is refused, not replaced), radius, gap, padding (all four sides), width, height, opacity, visible; "effect.color" / "effect.radius" / "effect.spread" / "effect.offsetX" / "effect.offsetY" and "grid.count" / "grid.gutterSize" / "grid.offset" / "grid.sectionSize" with index for the effect or grid; on text, the text fields (fontSize, lineHeight, letterSpacing, fontFamily, fontStyle, fontWeight) go to Figma as is, a refusal coming back per item; or any Figma bindable field (paddingLeft, topLeftRadius, characters). Library variables bind by the id figma_get_variable_defs { nodeId } reports; a token inside a style: figma_update_style. Returns per-item results: { updated, items: [{ id, ok, error? }] } — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: field (required), nodeIds (required), force, index, +4 more.
figma_boolean_nodesBoolean operationAIdempotent
Combine shapes into one boolean shape, as Figma's toolbar does: union (merge), subtract (cut the upper shapes out of the BOTTOM one), intersect (keep the overlap), exclude (keep what does not overlap). The shapes must share a parent; the result takes the lowest one's place and its id is returned. Builds icons, badges, cut-out shapes and logos. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeIds (required), operation (required), name, force, +2 more.
figma_check_layoutCheck a design for defectsARead-only
After each section and before calling anything done: a designer's last look, in numbers (figma_export_node shows the picture). Per node, with a number and fix: text overflowing, collapsed, overlapping or covered; content clipped or sticking out; a fill child in a hug parent; stacked frames; placeholder copy; low contrast (WCAG); zero-size, empty or default-named nodes; text off or cut by a slide. audit adds: tokens (unbound values), names (duplicates), fonts (expectFonts), board (FigJam), craft (finish: sizes, edges, near-touches, contrast; safeArea, minTextSize), tells (generated look; warning if the brief avoids it), handoff (share bound), a role's: a11y (targets, focus, labels), states, copy, system (format, scale, grid), deck (words, headlines, floor), mark (size, versions, clear space), icons (canvas, stroke, pixels), library (modes, aliases). briefId: against that brief's numbers. ok: true = no errors or warnings. Default: the selection, then the page (Slides: focused slide). Reads only.
Inputs: audit, limit, nodeId, briefId, +7 more.
figma_check_motionCheck motion frame by frameARead-only
A motion designer's frame-by-frame check of an animated top-level frame from its keyframes, no render: figma_check_layout for motion. Each issue names layer, field, frame and numbers at fps, with a fix. It finds pops and vanishes mid-move, one frame carrying most of a move, fast moves without blur, blur out of phase, one-frame peaks, arrivals never held, dead stretches (outside holds), a cold open, template moves, missing staggers, keys between frames, HOLD, beat offsets (bpm or beatTimes), text too brief, a late brand or short CTA (brandId, ctaId). The frame's plan (figma_set_motion_plan) fills bpm, holds, brandId and ctaId when left out; its accept lists intended findings apart. ok: true = no errors or warnings. A whole passing check (no rules, from, to, nothing looser than the plan) at the delivery fps unlocks figma_export_video { final: true } until the file changes. Then figma_review_video. UNSUPPORTED: no Figma Motion here. Skill: critique. Editors: Design only, unverified.
Inputs: to, bpm, fps, from, +16 more.
figma_clone_nodeClone nodeAIdempotent
Duplicate a node with its whole subtree, optionally into another parent and at a new position. A slide is duplicated into a slide row — right after itself, or at the end of the row parentId names — and the result gives its row and col. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeId (required), x, y, name, +4 more.
figma_combine_as_variantsCombine as variantsAIdempotent
Combine components into one component set (variants), like Figma's Combine as variants. Name each component "Property=Value, Other=Value" first (figma_rename_node) — Figma derives the variant properties from those names. The components must share a parent; the set is laid out as a wrapping row unless arrange: false. columns: "State" lays it out as a grid instead — a column per State value, a row per combination of the other properties — and returns the grid's page coordinates, for header labels made with figma_create_text outside the set. Then place variants with figma_create_instance and switch them with figma_set_instance_properties. Editors: Design; unverified: Slides.
Inputs: componentIds (required), gap, name, force, +5 more.
figma_convert_to_componentConvert to componentAIdempotent
Turn an existing node (usually a frame) into a reusable COMPONENT, keeping its properties and children — the toolbar's Create component. The result has its own id (returned). A node that is already a component, or sits inside a component or instance, cannot be converted. To place copies afterwards use figma_create_instance. Editors: Design; unverified: Slides.
Inputs: nodeId (required), name, force, session, +2 more.
figma_create_animaticCreate an animaticAIdempotent
Play a storyboard back at its planned pace: turn a figma_create_storyboard board into an animatic, a top-level frame Animatic · <title> with one plate per panel, each on screen on exactly the panel's frames, switched by frame-exact OPACITY cut pairs. Timing is read from the board as it is now (each duration caption), at the board's fps. A plate shows the panel's best picture: its styleframe once something is drawn in it, else its source rendered again, else its thumbnail; blank lists panels with nothing yet. dissolveFrames cross-fades out of a panel whose transition caption starts with "dissolve"; drift pushes each plate 3 %; burnIn labels plates. Every track is read back (verified, else notApplied). The result's render is the figma_export_video call; then judge the pace with figma_review_video. Plates 2–n rest at opacity 0, so figma_export_node shows panel 1. Skill: storyboard (figma_get_guide). One undo step. Editors: Design only, unverified.
Inputs: storyboardId (required), x, y, drift, +7 more.
figma_create_code_blockCreate a code block (FigJam)AIdempotent
A FigJam code block with syntax highlighting. language (case-insensitive): typescript, javascript, python, go, rust, ruby, css, html, json, graphql, sql, swift, kotlin, cpp, bash, plaintext, dart — dart is in the Plugin API but not yet confirmed on the canvas. Default plaintext; any other value is refused rather than shown as plain text, so ask for plaintext yourself. FigJam styles it: no theme, font or size to set. Editors: FigJam only, unverified.
Inputs: code (required), x, y, name, +5 more.
figma_create_connectorsCreate connectors (FigJam)AIdempotent
FigJam connector lines between nodes, 1–200 in one call. Each is made IN its final parent — by default the lowest section holding both ends, else the page — and never moved: a reparented connector keeps stale elbows, so build connectors last. Endpoints: One string: "12:34" (attach; magnet auto), "12:34@right" (magnet: auto, top, bottom, left, right, center, none), "12:34@0.5,1" (a point on the node, 0–1 of it — to be confirmed) or "120,340" (a free point). An end may not be another connector. lineType elbowed (default), straight or curved; caps default none at the start and arrow-lines at the end (ERD caps too); label is the visible text. Change one later with figma_edit_connectors. Editors: FigJam only, unverified.
Inputs: connectors (required), force, session, parentId, +1 more.
figma_create_effect_styleCreate effect styleAIdempotent
A local effect style (shadows, blurs) that nodes can then follow via figma_apply_style_to_node. Same effect entries as figma_set_effects. Change it later in place with figma_update_style. Editors: Design only.
Inputs: name (required), effects (required), force, session, +2 more.
figma_create_ellipseCreate ellipseCIdempotent
An ellipse with an optional fill. Editors: Design; unverified: FigJam, Slides.
Inputs: width (required), height (required), x, y, +7 more.
figma_create_frameCreate frameAIdempotent
A frame — the building block for structure. Build designs step by step: one frame per section, row or card, each with auto-layout (layout, gap, padding, alignX/alignY), then add content into it by parentId. An auto-layout frame hugs its content on any axis you give no size for; sizing: { horizontal: "fill" } makes it take its parent column's width. A wrapping row (wrap) spaces its rows by rowGap (default: the gap). Content is not clipped unless clipsContent: true. Name it for what it is. Editors: Design; unverified: FigJam, Slides.
Inputs: x, y, gap, name, +17 more.
figma_create_from_specCreate from specAIdempotent
Build a whole SECTION in one call (one undo step): a header, hero, card, grid of cards or footer — frames with auto-layout, text, shapes (rectangle, ellipse, polygon, star, line, vector path), SVG icons, images by URL, components and instances. To build anything new: a wrapper frame, then one call per section into it by parentId; after each, figma_check_layout and one figma_export_node, then targeted fixes. Not a whole page in one payload: a section at a time keeps every step checkable. The full spec grammar: figma_get_guide { topic: "spec" }. Minimal shape: { "type": "frame", "name": "Card", "layout": "vertical", "gap": 16, "padding": 24, "children": [ { "type": "text", "content": "Title", "fontSize": 20 } ] }. A field a type does not take is refused, never dropped. A mid-way failure does not roll back: created[] and failedAt say what exists. Supply your own idempotencyKey for a large spec. An array of roots (a slide's content) needs parentId or pageId. Editors: Design; unverified: FigJam, Slides.
Inputs: spec (required), force, pageId, session, +2 more.
figma_create_grid_styleCreate grid styleAIdempotent
A local GRID style — a named layout grid (e.g. 12 columns, 24 gutter, 64 margin) that frames follow via figma_apply_style_to_node { type: "grid" }. Entries as in figma_set_layout_grids, which sets raw grids on frames instead. Editors: Design only.
Inputs: name (required), grids (required), force, session, +2 more.
figma_create_instanceCreate instanceAIdempotent
Place an instance of a component, of a component set's default variant, or of the variant of a set you name. Local ids come from figma_get_local_components. A library component is placed by componentKey or componentSetKey: imported first, then placed (figma_import_library_assets imports several at once). Give exactly one of componentId, componentKey, componentSetKey. To change which component an existing instance shows, use figma_swap_component. Editors: Design; unverified: FigJam, Slides.
Inputs: x, y, force, sizing, +7 more.
figma_create_lineCreate lineAIdempotent
A straight line: dividers, connectors, arrows, underlines, decorative strokes. length in px from (x, y), turned by angle degrees (0 = to the right, 90 = up). cap decorates both ends: arrow, arrow-filled, triangle, circle, diamond, round, square. For a divider inside an auto-layout, a 1 px figma_create_rectangle with sizing: { horizontal: "fill" } stretches with the column; a line keeps its length. Editors: Design; unverified: FigJam, Slides.
Inputs: length (required), x, y, cap, +9 more.
figma_create_link_previewCreate a link preview (FigJam)AIdempotent
Paste a web link onto a FigJam board as a card. Figma fetches the https URL and inserts an EMBED (a page that offers oEmbed, such as a video) or a LINK_UNFURL preview (title, description and image from the page's meta tags). The parent is checked before Figma fetches; a link Figma cannot preview is refused in Figma's own words. Returns { id, type, title?, provider? }. Editors: FigJam only, unverified.
Inputs: url (required), x, y, force, +3 more.
figma_create_pageCreate pageCIdempotent
A new page. Note: a free Starter file is capped at 3 pages and Figma's own error is surfaced as-is when the cap is hit — that is a plan limit, not a bridge limit. Editors: Design; unverified: FigJam, Slides.
Inputs: name (required), force, session, activate, +1 more.
figma_create_paint_styleCreate paint styleAIdempotent
A local PAINT style: one color, or fills (several paints, gradients — entries as in figma_set_fills). variableId / variableName binds the first paint's colour to a COLOR variable, so a semantic colour style follows its token. Change it later in place with figma_update_style. A gradient style's angle is exact only on a square node — a style has no size; for an exact CSS angle on a known node use figma_set_fills, or give transform. Editors: Design only.
Inputs: name (required), color, fills, force, +6 more.
figma_create_polygonCreate polygonAIdempotent
A regular polygon — triangle (pointCount 3), diamond (4, rotated 45 with figma_rotate_nodes), pentagon, hexagon… Badges, play buttons, decorative geometry. Editors: Design; unverified: FigJam, Slides.
Inputs: width (required), height (required), x, y, +11 more.
figma_create_rectangleCreate rectangleCIdempotent
A rectangle with an optional fill, corner radius and stroke. Editors: Design; unverified: FigJam, Slides.
Inputs: width (required), height (required), x, y, +10 more.
figma_create_sectionCreate sectionAIdempotent
A section — the container designers use to organise a page by flow, and on a FigJam board the structure itself: a white wrapper, zones inside it, cards inside those (parentId = another section). name: "" leaves it untitled when a title text inside carries the label. To fill a section and fit it to its content in one call, use figma_create_from_spec with a section's arrange and hug. Editors: Design; unverified: FigJam, Slides.
Inputs: x, y, fill, name, +7 more.
figma_create_shapes_with_textCreate shapes with text (FigJam)AIdempotent
FigJam shapes with text — flowchart steps, decisions, databases, callouts — 1–200 in one call, each sized to fit its text unless width and height are given (fitted). shape: one of 30 types in kebab case (square, ellipse, rounded-rectangle, diamond, triangle-up, parallelogram-right, eng-database, eng-queue, eng-file, eng-folder, hexagon, chevron, speech-bubble, …) or label: a numbered or lettered circle marker of 1–2 characters at a fixed size. color is a preset that sets fill, stroke and text together: black, dark-gray, gray, light-gray, white, and green, teal, blue, violet, pink, red, orange, yellow each with a light- form (light-green, …); or give hex fill / stroke / textColor instead. Laid out like figma_create_stickies (columns, gap default 40). Join them with figma_create_connectors. Row and column data is figma_create_table, never a grid of shapes. Editors: unverified in FigJam, Slides.
Inputs: shapes (required), x, y, gap, +5 more.
figma_create_slidesCreate slidesAIdempotent
Add 1–20 empty 1920×1080 slides to a Figma Slides deck, in list order. Then give each its content with one figma_create_from_spec (parentId = the slide id), and check the batch with figma_check_layout — 3–5 slides per call. Per item: name, background (hex; it goes on the slide, since rows and the grid have no fill), skipped, and where: row + col, counted against the grid the earlier items left (row = the current row count opens a new last row), or neither for the end of the deck. On an empty deck the first slide makes row 0. Every position is checked before the first slide exists. Returns each slide's id, row, col and index as read back. Not for frames on a page (figma_create_frame); to reorder use figma_move_slides, to regroup figma_set_slide_grid. Do not delete and rebuild slides to restyle a deck: edit them in place. Editors: Slides only, unverified.
Inputs: slides (required), force, session, idempotencyKey.
figma_create_slotCreate slotAIdempotent
Add a slot to a component: a frame that each instance fills with its own layers, plus the SLOT property that goes with it. Pass a component or one variant, not a set. layout horizontal or vertical (Figma refuses a grid on a slot). Fill it in an instance by creating content with parentId = the slot inside that instance; figma_reset_slot empties it again. figma_set_instance_properties cannot set a slot. Editors: Design; unverified: FigJam, Slides.
Inputs: componentId (required), name, force, width, +5 more.
figma_create_starCreate starAIdempotent
A star or burst: pointCount spikes, innerRadius 0–1 (low = spiky, near 1 = almost a polygon). Rating stars, sale bursts, sparkles, decorative shapes. Editors: Design; unverified: FigJam, Slides.
Inputs: width (required), height (required), x, y, +12 more.
figma_create_stickiesCreate stickies (FigJam)AIdempotent
FigJam sticky notes, one idea each, 1–200 in one call, laid out as a grid from their REAL sizes: a sticky is 240 wide (416 with wide) and grows taller with its text, so rows are placed after the text is in and never overlap. color: white, gray, green, teal, blue, violet, pink, red, orange, yellow, or a hex — names land on FigJam's exact swatches. The size is fixed: no width or height; use wide for about 100 words or more. columns per row (default one row), gap (default 64). Prompts, labels and instructions are text, not stickies. The parent is never resized: parentOverflow says how far the block runs past it (then figma_fit_sections). Returns created [{ index, id, x, y, width, height }] and bounds. Editors: FigJam only, unverified.
Inputs: stickies (required), x, y, gap, +5 more.
figma_create_storyboardCreate a storyboardAIdempotent
Lay out a motion piece's storyboard before animating it: a board of cards in rows, one per panel, each a thumbnail frame at aspect above caption rows (time, duration, story beat, on-screen copy, action, camera, transition, audio, notes). Timing is derived from each panel's durationS, snapped to whole frames by default: start and end in seconds and frames at fps, and bar.beat with bpm. The result lists panels that start off the beat (offBeat) and copy on screen too briefly to read (readTime): fix both before building. A panel can snapshot a frame of this file (source), show an image already in it (image), or get an empty full-size styleframe beside the board (styleframe). Sketch into a thumbnail with figma_create_from_spec { parentId: thumbId }. The duration caption is the plan: edit its text to retime a panel. A plan, not an animation: figma_set_keyframes animates. Skill: storyboard (figma_get_guide). One undo step. Editors: Design; unverified: FigJam, Slides.
Inputs: title (required), aspect (required), panels (required), x, +13 more.
figma_create_tableCreate a table (FigJam)AIdempotent
A FigJam table — the tool for any row-and-column data, never a grid of shapes. Give rows (text, 1–100 rows of 1–20 cells, every row the same length; all of the user's data, no placeholders) or numRows + numColumns for an empty one: exactly one form. header (default true with rows) colours row 0 with headerColor, a table preset (default black: dark fill, white text): black, dark-gray, gray, light-gray, white, and green, teal, blue, violet, pink, red, orange, yellow each with a light- form (light-green, …), or a hex. fill colours the table; a fill is never removed ("" is refused). columnWidths / rowHeights resize; a column cannot shrink below its minimum, so the real widths come back. fontFamily, weight, fontSize apply to every cell. Cells have no ids: change them with figma_edit_table. Editors: unverified in FigJam, Slides.
Inputs: x, y, fill, name, +14 more.
figma_create_textCreate textAIdempotent
A text node, placed into a frame by parentId. Inside a vertical auto-layout it fills the column and wraps (and follows the column's centre/right alignment unless align is given); elsewhere give width for text that should wrap — text without one stays on a single line and can overflow. The font is loaded with the documented fallback chain; the result names the font used and flags fellBack: true when it is not the one requested. Editors: Design; unverified: FigJam, Slides.
Inputs: content (required), x, y, name, +13 more.
figma_create_text_styleCreate text styleAIdempotent
A local TEXT style. lineHeight and letterSpacing are STRINGS, as in figma_set_text_properties: "auto", "32" (px) or "150%"; "0.5" or "-2%" — a bare JSON number is no longer accepted here. case (e.g. upper for labels), decoration, paragraph spacing and indent are set on the style too. Change it later in place with figma_update_style. Editors: Design only.
Inputs: name (required), fontSize (required), case, force, +10 more.
figma_create_variableCreate variableAIdempotent
One design token. value is a string for every type: "#1a2b3c" for COLOR, "16" for FLOAT, text for STRING, "true"/"false" for BOOLEAN, or "alias:" of the same type. Set scopes (which pickers offer it; [] for a primitive only aliased) and a WEB codeSyntax on every token. A name the collection already has is refused. For a whole token set in one call use figma_create_variables. Bind one to nodes with figma_bind_variable_to_node; extra modes (figma_add_variable_mode) need a paid plan. Editors: Design; unverified: FigJam, Slides.
Inputs: name (required), type (required), value (required), collectionId (required), +8 more.
figma_create_variable_collectionCreate variable collectionAIdempotent
A new variable collection (a token group). Its first mode is named after modes[0], or "Default" — never Figma's "Mode 1". Extra modes beyond the first are paid-plan only — if Figma refuses one, the result carries a warnings entry rather than dropping it silently. Rename or remove modes later with figma_update_variable_collection. Editors: Design; unverified: FigJam, Slides.
Inputs: name (required), force, modes, session, +1 more.
figma_create_variablesCreate variablesAIdempotent
A token set in ONE call (one undo step): primitives first, then semantic tokens that alias them, each with a value per mode, scopes and code syntax. Values are strings: "#1a2b3c" / "#1a2b3c80", "16", text, "true", or "alias:" — the target must exist already or come EARLIER in this call, with the same type. Everything is checked before the first variable exists, so a refusal creates nothing. ifExists decides what a name the collection already has does: "error" (default), "skip" (keep it; aliases resolve to it), or "update" (set the given values and properties). Up to 200 per call, paced so Figma stays responsive. For one variable figma_create_variable is enough; to change properties later use figma_set_variable_properties. Editors: Design; unverified: FigJam, Slides.
Inputs: variables (required), collectionId (required), force, session, +2 more.
figma_create_vectorCreate vectorAIdempotent
Draw any shape from SVG path data — a blob, a wave divider, a custom arrow, a logo mark, a chart line. path is the d of an SVG (M L H V C S Q T A Z, absolute or relative). width/height scale it (one keeps its proportions). Give stroke without fill for an open line. For a whole SVG file (an icon) use figma_import_svg. Editors: Design; unverified: FigJam, Slides.
Inputs: path (required), x, y, fill, +10 more.
figma_delete_component_propertyDelete component propertyADestructiveIdempotent
Delete a TEXT, BOOLEAN, INSTANCE_SWAP or SLOT property from a component or component set: every instance loses it, overrides included. A VARIANT property cannot be deleted — it comes from the variant names, so rename the variants instead. To rename or rewire a property use figma_edit_component_property. Editors: Design; unverified: FigJam, Slides.
Inputs: property (required), componentId (required), force, session, +1 more.
figma_delete_nodesDelete nodesADestructiveIdempotent
Delete nodes by id. This is the correct way to undo agent work: pass the ids the create call returned. One Ctrl+Z reverts the whole original call. In a deck a slide row that still holds slides is refused (delete its slides first); a row its last slide left is reported in emptiedRows. Returns per-item results: items: [{ id, ok, error? }] — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeIds (required), force, session, idempotencyKey.
figma_delete_styleDelete stylesADestructiveIdempotent
Delete local styles (paint, text, effect, grid) by id. Nodes that used one keep the values it gave them. figma_get_styles lists ids. Returns per-item results: items: [{ id, ok, error? }] — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: styleIds (required), force, session, idempotencyKey.
figma_delete_variableDelete variablesADestructiveIdempotent
Delete variables (design tokens) by id. Nodes bound to one keep its last resolved value. figma_get_variable_defs lists ids. Returns per-item results: items: [{ id, ok, error? }] — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: variableIds (required), force, session, idempotencyKey.
figma_delete_variable_collectionDelete variable collectionADestructiveIdempotent
Delete a variable collection together with every variable in it. Editors: Design; unverified: FigJam, Slides.
Inputs: collectionId (required), force, session, idempotencyKey.
figma_detach_instanceDetach instanceADestructiveIdempotent
Detach instances into plain frames that no longer follow their component. The frame gets a new id, reported per item as frameId. Cannot be re-attached. Returns per-item results: items: [{ id, ok, error? }] — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeIds (required), force, session, idempotencyKey.
figma_download_assetsDownload assetsARead-only
Write a design's ASSETS to disk for implementing it in code: per node, its export presets as the designer set them (format and suffix each), or one render in format at scale when it has none; plus the ORIGINAL bytes of every image fill in its subtree (deduplicated by hash, at most 20 per call, rawImagesTruncated when there were more) — the photo under a hero's headline without the headline baked in. Re-runs overwrite the same files. Paths follow figma_export_node's saveTo rules. To SEE a design use figma_export_node; this one is for files the code ships.
Inputs: nodeIds (required), dir, scale, format, +3 more.
figma_edit_component_propertyEdit component propertyAIdempotent
Change a component property that already exists: rename it (name — the key changes and is returned), change its default, set an instance swap's preferred components, or wire / unwire layers (bindNodeIds / unbindNodeIds, matched by name path in every variant of a set). A variant id is redirected to its set. Figma's rules are checked before anything changes: no default for VARIANT or SLOT, preferredValues only on INSTANCE_SWAP and SLOT. To add a property use figma_add_component_property; to change one instance's value, figma_set_instance_properties. Editors: Design; unverified: FigJam, Slides.
Inputs: property (required), componentId (required), name, force, +6 more.
figma_edit_connectorsEdit connectors (FigJam)AIdempotent
Change existing FigJam connectors in place, 1–200 per call: re-point from / to (the endpoint strings of figma_create_connectors), or set label, lineType, caps, color, weight, dash, labelBackground. The ids stay, so it runs inside figma_batch. Every item is parsed, and every end checked, before the first change; a missing node or one that is not a connector is a per-item error. Returns per-item results. Editors: FigJam only, unverified.
Inputs: connectors (required), force, session, idempotencyKey.
figma_edit_tableEdit a table (FigJam)ADestructiveIdempotent
Change a FigJam table's structure and cells. Cells have no ids: they are { row, column }, 0-based. Applied in this order, every index checked against the table's size before anything changes: removeRows / removeColumns (their content is lost), then insertRowsAt / insertColumnsAt (positions in the table after removals; each adds one before that index, the count appends), then moveRow / moveColumn { from, to }, then columnWidths / rowHeights [{ index, width | height }], then cells (up to 2000, in the final table): text, fill (table preset or hex; "" is refused — give "#FFFFFF" to reset), textColor. Removing every row or column is refused. Returns the new size and per-cell results. Editors: unverified in FigJam, Slides.
Inputs: nodeId (required), cells, force, moveRow, +9 more.
figma_export_frames_to_pdfExport frames to PDFARead-only
Export frames to one multi-page PDF, one frame per page, in the order of nodeIds. In a Figma Slides file, deck: true instead exports every slide in presentation order, leaving out skipped slides unless includeSkipped; the result lists slideIds in page order. Each frame is rendered by the plugin and the pages are merged by the bridge. A frame that cannot be rendered is reported in failed[] and the rest still merge — an unreadable page is worse than a missing one, so nothing is silently substituted. final: true marks the delivery: under BRIDGE_PROCESS=strict every page that belongs to a brief needs a passing figma_sign_off newer than its last change.
Inputs: outputPath (required), deck, final, nodeIds, +2 more.
figma_export_nodeExport / screenshot a nodeARead-only
Render a node so you can see it — the screenshot to compare against. No nodeId: the one selected layer. Without saveTo, PNG/JPG come back as an image (≤ 5 MB) with its bounds and pixel size, and SVG as markup; an inline PNG/JPG with no scale is held to 1024 px on its longest side (maxSize changes that; capped says it happened; scale asks for an exact size instead). With saveTo, or for PDF, or when larger than 5 MB, the file is written and its path returned. A relative saveTo lands in the export directory; other folders must be listed in BRIDGE_EXPORT_ROOTS. If format is omitted, the saveTo extension decides, else PNG. An animated frame renders at rest: see its motion with figma_export_video, then figma_review_video. final: true marks the delivery: under BRIDGE_PROCESS=strict a node of a brief needs a passing figma_sign_off newer than its last change. Skill: critique (figma_get_guide). For files a codebase ships (presets, original images), use figma_download_assets.
Inputs: final, scale, format, nodeId, +3 more.
figma_export_videoExport an animation as videoARead-only
Render the animation of a top-level frame to MP4, GIF or WEBM — the way to SEE motion; figma_export_node renders only the rest state. A layer exports its top-level frame (exportedNodeId). Always writes a file (saveTo, else the export directory). Waits up to wait s (default 40, at most 45); a longer render answers status "rendering" with a jobId, and figma_export_video { jobId } collects it. Name your own jobId for long renders and start no second export meanwhile; cancel + jobId drops one. frameIndices (or frames, seconds) return those frames as PNG (long side ≤ 1024), frame-exact, with ffmpeg; ones not cut in time come back as framesPending. A render is a preview; final: true is the delivery, refused under BRIDGE_PROCESS=strict until figma_check_motion passed on the frame at this fps, the file unchanged since. Meanwhile other Figma calls answer BUSY. fps: MP4/WEBM 12|24|30|60, GIF 8|12|15|24|30. Skills: motion, critique. Editors: Design only.
Inputs: fps, wait, final, jobId, +12 more.
figma_find_replace_textFind and replace textAIdempotent
Find and replace across text: TEXT nodes and, on a board, stickies, shapes, connector labels and table cells (an item names the node, plus cell "row,column"); code blocks with includeCode. Other styled runs in a text are kept. Scope it to the page (default), the selection, or a subtree by nodeId. Returns per-item results: items: [{ id, ok, error? }] — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: find (required), replace (required), force, regex, +6 more.
figma_fit_sectionsFit sections to their contentAIdempotent
Resize sections to hug what they hold plus padding ("32" by default, or "top,right,bottom,left" — a board wrapper often takes "68,60,100,80"), never below minWidth / minHeight. Sections listed together are fitted inner-first, so an outer one fits its inner ones' final size. Children move only when they reach into the top or left padding; connectors never move — they follow their ends. An empty section is left as it is, with a note. Do not fit a participatory zone sized for the activity, or one of a grid of equal sections. Works on Figma Design sections too. A size you choose: figma_resize_nodes. Returns per-section results with the new size. Editors: unverified in Design, FigJam, Slides.
Inputs: nodeIds (required), force, padding, session, +3 more.
figma_flatten_nodesFlattenAIdempotent
Flatten nodes into one editable vector (Ctrl+E) — for a finished icon or a boolean shape that should become a single path. They must share a parent. Cannot be undone except with Ctrl+Z. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeIds (required), name, force, session, +1 more.
figma_get_annotationsGet annotationsARead-only
Annotations on a node or subtree — the notes designers leave for developers — each with its category (label, colour), plus the subtree's dev resources (links to code, tickets, docs) where Figma provides them. Empty is a normal answer, not an error. The result's scope names the root that was read. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeId, session.
figma_get_briefGet a briefARead-only
Read the brief a frame was made from — role, gear, lines, directions, system, status — with its last sign-off (and whether the frame changed since) and its motion plan; with no node, every open brief in the file. For an open brief, next: the stage the record shows (brief, directions, choice, system, build, critique, sign-off), what it lacks to move on, the call that supplies it, and what sign-off still asks for. Reading an open brief adopts it for this session, so a second agent can continue the work. Reads only.
Inputs: nodeId, target, briefId, session, +1 more.
figma_get_changesWhat changed in this fileARead-only
What changed in this file: what you report at the end of an instruction, and what a person reads to review your work. journal: the write calls this server sent to the file, newest last, each { seq, at, tool, summary, ok, error?, created? (nodes it made), targets? (nodes it named), rolledBack? }, with each savepoint as its own entry. From the plugin: changes (the latest change per node by a person here or a collaborator; one that leaves a node as you last wrote or read it is yours, however late), conflicts (such a change to a node you had read or written), pageSwitches, watchedPageId (only that page is watched). since: the calls after a seq ("12") or after a savepoint ("sp-3"); limit: the newest calls (default 100). savepoints lists this file's. The journal lives in this server process: a restart starts it empty. Reads only. Editors: Design; unverified: FigJam, Slides.
Inputs: limit, since, session.
figma_get_componentGet one componentARead-only
One component's API, as code or an instance needs it: its property definitions (key, name, type, default, variant options, preferred swap targets), its variants with their values, the default variant, and which layers each property drives. Pass a component, a component set, a variant (answered from its set, where Figma keeps the definitions) or an instance (answered from its main component — library ones too, read-only). key is what figma_import_library_assets and figma_create_instance componentKey take. figma_get_local_components lists components; figma_get_design_context shows an instance's current values. references is paginated with limit + cursor. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeId (required), limit, cursor, session.
figma_get_design_contextGet design contextARead-only
READ THIS BEFORE YOU BUILD OR CODE. The design as a designer sees it: one tree with, per node, size, position, auto-layout (gap, padding, alignment, wrap row gap, grid tracks, hug/fixed/fill, min/max), constraints, fills (gradient angles, image hashes) / strokes / effects / radius, text with its styled runs and links, styles and variables BY NAME, explicit variable modes, and an instance's component with its keys. stylesUsed / variablesUsed / componentsUsed list the tokens and components met, with ids and keys. FigJam: sticky, shape, connector (endpoints as the connector tools write them), table cells and code blocks, plus connectors, the board's edges. Slides: each slide's row, column and index. No nodeId: every selected layer (roots), else the page — in a deck the focused slide, else its outline; scope says which. Bounded by maxNodes: truncated: true and nextCursor return the rest. Text is cut at maxTextChars.
Inputs: depth, cursor, nodeId, session, +10 more.
figma_get_fontsList fontsARead-only
Fonts used by text on the current page (scope: "page", default) — every run of mixed-style text counted, and the text of stickies, shapes, connectors and table cells on a board — with how many nodes use each, missingFonts when the file uses a font this machine lacks, and missing: true on each such font. scope: "available": the families this Figma can load, each with its exact style names, 50 per call (limit up to 500; total, truncated and nextCursor say what is left). query keeps names containing a word ("serif", "grotesk"); families checks exact names and lists the ones not found in missing. query, families, limit and cursor imply scope "available".
Inputs: limit, query, scope, cursor, +2 more.
figma_get_guideHow to work in Figma (skills)ARead-only
Read this before a design, motion or review task. Returns a skill — the playbook for one kind of work — as Markdown. No arguments gives workflow (the designer's loop). State the role and the gear first: screens and flows read ux, posters, ads, print and icons graphic, logos brand; a page or more also runs design. A motion piece starts with storyboard, keyframes with motion, and a review with critique. topic names a skill (workflow, design, storyboard, motion, critique, design-system, design-to-code, code-to-design, prototype, figjam, slides, brand, graphic, ux) or one of its sections (spec is the figma_create_from_spec grammar); section picks a section of that skill; "skills" lists every skill with what it is for and its sections. Every answer ends with the exact calls for the skill's other sections and for the other skills. Works without the plugin. Under BRIDGE_PROCESS=strict new work waits for its role skill and figma_set_brief, keyframes for the motion skill.
Inputs: topic, section.
figma_get_library_variablesList library variablesARead-only
Variables from the team libraries enabled in this file — the part of a library a plugin can list (its components and styles it cannot). Without collectionKey: the enabled libraries' variable collections { key, name, libraryName }. With one: that collection's variables { key, name, resolvedType }, filtered by query (name substring) and type, paginated. Import a variable by its key before binding it. Local variables: figma_get_variable_defs. UNSUPPORTED means the plugin lacks the teamlibrary permission or no library is enabled (Assets → Libraries). Reads only. Editors: Design; unverified: FigJam, Slides.
Inputs: type, limit, query, cursor, +2 more.
figma_get_local_componentsList local componentsARead-only
Components and component sets defined in this file: page, key and description of each; a variant carries its set's id and name, a set its variant count and variant options. Scope to one page with pageId; without it every page is loaded first, which takes a moment on a large file. figma_get_component reads one component's full property definitions. Editors: Design; unverified: FigJam, Slides.
Inputs: pageId, session.
figma_get_metadataFigma file metadataARead-only
File name, page list, plugin API version and editor type, plus the current page and selection size. Start here when you know nothing about the file yet. In a FigJam board it adds board: the top-level sections and a count of each node type; in a Slides deck slides: rows, slide counts, the focused slide and the view. Note: fileKey is intentionally absent — this plugin does not request private-plugin access, so Figma returns null for it.
Inputs: session.
figma_get_motion_contextGet motion (keyframe animation)ARead-only
The timeline animation of layers, for implementing it in code: per animated layer its keyframe tracks ({ field, keyframes: [{ t (s), value, easing }] }, the same strings figma_set_keyframes takes), animation styles, its top-level frame and timeline, plus timelineCohorts (layers that play together) and motionPlans (each frame's figma_set_motion_plan). topLevelFrameId is the frame on the page, found through the parents; a cohort is keyed by that frame and lists every timelineIds seen — a timeline id is never a node id. Inside an animated frame, address layers by the ids your create calls returned: an id read from a listing there can be temporary. This is Motion, not prototype interactions — those are figma_get_reactions. Defaults to the selection, then the page, and reads descendants: a screen never animates itself, its layers do. limits says what the Plugin API cannot tell (loop mode, pivot). Motion is a Figma beta: UNSUPPORTED means this account does not have it. Editors: Design only.
Inputs: cursor, nodeId, session, maxNodes, +1 more.
figma_get_nodeGet one nodeARead-only
One node with its children down to depth, as a normalized DTO (id, name, type, childCount; with includeGeometry also layout, size, position, padding, radius, fill, scrolling). FigJam and Slides nodes also carry what they are: a sticky's or shape's text (200 characters), shapeType, a connector's endpoints and label, a table's size, a slide's row and column; a slide grid or row is opaque (only its box can be read). Depth 0 returns the node alone. Children are capped per node; the count is always reported so a cap is never mistaken for the real structure. format: "rest" returns Figma's own REST JSON for the subtree instead (cut at 200 KB, truncated says so) — for a field the DTO and figma_get_design_context leave out.
Inputs: nodeId (required), depth, format, session, +2 more.
figma_get_nodes_infoGet several nodesARead-only
The same as figma_get_node for many ids in one round-trip. Per-id failures are reported per id rather than failing the whole call.
Inputs: nodeIds (required), depth, session, includeGeometry.
figma_get_pagesList pagesARead-only
Every page in the document (id, name, which one is current). Use a page id with figma_get_local_components to scope a scan.
Inputs: session.
figma_get_reactionsGet prototype reactionsARead-only
Prototype reactions: what a layer does on click, drag, hover, and where it navigates. scope: "node" (default) reads one node; "subtree" or "page" lists every node with reactions, plus the page's flows, prototype start and background, and frames that scroll, keep fixed layers or open as overlays. Read it before generating interactive code; figma_set_reactions writes them. Editors: Design; unverified: FigJam, Slides.
Inputs: limit, scope, cursor, nodeId, +1 more.
figma_get_selectionGet the current selectionARead-only
The nodes the user has selected in Figma right now. This is the usual entry point for "make this into code": the user selects what they mean, then this returns it.
Inputs: depth, session, includeGeometry.
figma_get_slide_gridGet the slide gridARead-only
Read a Figma Slides deck as its grid — start here in a deck. Rows (each row is a section: id, name) of slides in presentation order; per slide its id, name, row, col, index, skipped, child count and speaker notes, and with includeSummary its background, title (its largest text) and interactive elements; includeTransitions adds each slide's transition. Reads the slides only, never the opaque rows or grid. unsupported names what this Figma build does not expose (speakerNotes, transition). An empty deck has no rows: the first figma_create_slides makes row 0. Paginated by slide (limit, cursor); rowIndex reads one row. A slide's layers: figma_get_design_context or figma_scan_text_nodes with the slide id; its picture: figma_export_node. Editors: Slides only.
Inputs: limit, cursor, session, rowIndex, +3 more.
figma_get_stylesList local stylesARead-only
Paint, text, effect and grid styles defined in THIS file, each with its key, a one-line value ("Inter Semi Bold 24/32 -1% upper", "#1a2b3c (var: color/bg)", "drop-shadow 0 4 12 0 #000000 10%", "columns 12, gutter 24, margin 64"), its description and the variables bound inside it — pick a style by what it is, not by its name. Local only: a library-styled file returns count 0; read library styles with figma_get_variable_defs { nodeId } or figma_get_design_context on a screen. Paginated with limit + cursor. Editors: Design; unverified: FigJam, Slides.
Inputs: type, limit, cursor, session.
figma_get_variable_defsGet variables and their valuesARead-only
Design tokens with their VALUES. Without nodeId: every local collection (modes, default mode, key) and variable with values per mode name ("#1a2b3c80", "16", "true", "alias:color/blue/500" — strings, as figma_set_variable_value takes them), scopes, codeSyntax, key and description; paginated. With nodeId (a frame, a screen, a page): only the variables and styles that subtree USES, library ones included — variables { name: value resolved for that node, so a Dark frame reads Dark }, styles { name: value line }, and details with ids, keys and code syntax. Variables work on any plan; modes beyond the first are paid-only. Editors: Design; unverified: FigJam, Slides.
Inputs: limit, cursor, nodeId, session, +2 more.
figma_group_nodesGroup nodesAIdempotent
Wrap nodes into a GROUP. All nodes must share one parent — Figma enforces this and the error says so when it applies. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeIds (required), name, force, session, +1 more.
figma_import_imageImport imageAIdempotent
Place a picture: from a url (http/https, fetched by Figma), a local path inside the export directory or BRIDGE_EXPORT_ROOTS (read by the bridge), or renderNodeId: a layer of this file rendered to a picture inside Figma — a styleframe snapshotted into a storyboard thumbnail, a frame on a mood board. With nodeId it becomes that node's fill; otherwise a new rectangle at the image's own proportions (a render: the layer's own size), or width/height. scaleMode fill / fit / crop / tile. PNG, JPEG or GIF, at most 4096 px a side. To look at a layer yourself, figma_export_node returns its picture to you instead of placing it. Editors: Design; unverified: FigJam, Slides.
Inputs: x, y, url, name, +13 more.
figma_import_library_assetsImport library assetsAIdempotent
Bring published library assets into this file by key — components, component sets, styles, variables — and get the local ids every other tool takes: figma_create_instance / figma_swap_component componentId, figma_apply_style_to_node styleId, figma_bind_variable_to_node variableId. Keys come off an existing screen (figma_get_design_context, figma_get_component) or from the library file opened as another session. Only published assets import; each one that does not carries Figma's reason: items: [{ key, kind, ok, id?, name?, type?, error? }]. To place a single library component, figma_create_instance componentKey imports it itself. Editors: Design; unverified: FigJam, Slides.
Inputs: assets (required), force, session, idempotencyKey.
figma_import_svgImport SVG (icon / vector)AIdempotent
Place SVG markup as editable vectors — icons, logos, illustrations. width (or height) scales the drawing with its vectors; color recolours every painted vector, the usual way to put an icon in the brand colour, and colorVariable binds them to a COLOR variable instead, so the icon follows the token (stroke-only icons stay stroke-only). The result lists the painted layers as vectorIds. Place it into a frame by parentId. Editors: Design; unverified: FigJam, Slides.
Inputs: svg (required), x, y, name, +9 more.
figma_move_nodesMove nodesAIdempotent
Move nodes to an absolute position, or by a delta with relative: true. Inside an auto-layout the layout owns x/y: positioning: "absolute" takes a child out of the flow so x/y place it — a badge on a card's corner, a close button on a modal — while it stays inside the frame (a fill axis becomes fixed first; the item says so). positioning: "auto" puts it back. x and y are written together and read back: an item Figma did not keep is ok: false and says where the layer is. Slides and their rows are placed by the deck: figma_move_slides moves them; figma_reparent_nodes changes the parent. Returns per-item results: items: [{ id, ok, error? }] — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeIds (required), x, y, force, +4 more.
figma_move_slidesMove slidesAIdempotent
Move slides within a Figma Slides deck as one block, in the order given, to exactly one anchor: after or before another slide (afterSlideId / beforeSlideId), or into a row (row, optional col, both counted once the moved slides are taken out; row = the row count opens a new last row). An anchor that is itself being moved is refused before anything changes. Every slide stays in the deck; a row the move empties stays as an empty section and is listed in emptiedRows. Per-slide results with the new row, col and index. To restate the whole deck's grouping use figma_set_slide_grid. Editors: Slides only, unverified.
Inputs: slideIds (required), col, row, force, +4 more.
figma_remove_keyframesRemove keyframes (Motion)AIdempotent
Remove a layer's manual keyframe tracks: the given fields, or every track when omitted. A field that is not animated is reported in notAnimated, not an error. Each removal is read back once Figma settles and repeated if the track is still there; one that will not go fails INTERNAL with partial.notRemoved. Returns removed and remaining, read back. Animation styles are not touched; figma_set_keyframes writes tracks. Under BRIDGE_PROCESS=strict (the default) PROCESS_REQUIRED until this session read the motion skill (figma_get_guide) and the frame has a plan (figma_set_motion_plan). Editors: Design; unverified: FigJam, Slides.
Inputs: nodeId (required), force, fields, session, +1 more.
figma_remove_reactionsRemove prototype reactionsAIdempotent
Remove every prototype interaction from a node. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeId (required), force, session, idempotencyKey.
figma_rename_nodeRename nodeAIdempotent
Rename one node. The previous name is returned, so a rename can be reported as a change rather than an assertion. Editors: Design; unverified: FigJam, Slides.
Inputs: name (required), nodeId (required), force, session, +1 more.
figma_reorder_nodesReorder nodesAIdempotent
Change z-order within each node's current parent. Slides keep their deck order: figma_move_slides reorders them. Returns per-item results: items: [{ id, ok, error? }] — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeIds (required), position (required), force, session, +1 more.
figma_reparent_nodesReparent nodesAIdempotent
Move nodes to a new parent (frame, group, component, section, slide or page), optionally at a given index. A node keeps its x/y numbers, now relative to the new parent; keepPosition: true keeps its place on the canvas instead (a sticky dropped into a section), or x/y place it in the new parent. A moved connector's item carries a warning: its route may need recreating. Slides move with figma_move_slides. Returns per-item results: items: [{ id, ok, error? }] — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeIds (required), parentId (required), x, y, +5 more.
figma_reset_slotReset slotADestructiveIdempotent
Put slots inside instances back to the component's own slot content, dropping what was added into them. Pass the SLOT layers of the instances (figma_search_nodes with type SLOT finds them). To empty one layer at a time use figma_delete_nodes instead. Returns per-item results: items: [{ id, ok, error? }] — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeIds (required), force, session, idempotencyKey.
figma_resize_nodesResize nodesAIdempotent
Resize nodes, or change how they size (Figma's fixed / hug / fill). Give width and/or height; the other dimension is kept — a text given only a width wraps and grows downwards. sizing: { horizontal: "fill" } makes a node take its auto-layout parent's width (the fix for text that overflows). min/max limits bound a hug or fill size — a fill paragraph with maxWidth 480 stays readable — on auto-layout frames and their direct children; clearLimits removes them. A node whose size is not its own — a sticky, a table, a connector, a code block, a 1920×1080 slide — is refused per item with the tool that sizes it. Returns per-item results: items: [{ id, ok, error? }] — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeIds (required), force, width, height, +8 more.
figma_review_videoReview a rendered videoARead-only
See a rendered video without rendering again: a contact sheet of the whole piece, every-frame close-ups of a window (the spacing between frames is the speed), frame-exact stills, and per-frame metrics that find freezes, one-frame flickers, flashes, jumps and cuts. Pass the path figma_export_video wrote. No Figma call: it answers while the plugin is busy, in any editor. Frame k is the timeline at k / fps. List the intended cuts (e.g. panel boundaries) and holds: a jump or a still stretch there is not a finding, but a declared cut that lands a frame early or late is. expectFrames checks the length. Returns JSON (numbers, then findings with frames), then up to maxImages images; every image is also written beside the video, or in saveDir. Needs ffmpeg and ffprobe on PATH, else UNSUPPORTED — figma_check_motion judges keyframes without them. Skill: critique (figma_get_guide).
Inputs: path (required), cuts, every, holds, +9 more.
figma_rollbackRoll back to a savepointADestructiveIdempotent
Take back everything you did since a savepoint, in one call, only when that is safe. Refused with ROLLBACK_BLOCKED before any undo when, since the savepoint, a person or a collaborator changed anything on the page the plugin watches, a local variable or style changed without you, or the page was switched by anyone but you: an undo would take their edit too. Your own changes reported late do not block it. The refusal lists what changed (partial.changed) and offers the safe part: figma_delete_nodes on the nodes you made since (partial.safe), which touches nobody's edits. Otherwise one undo per call since the savepoint, then a check that the nodes made since are gone: { savepointId, undone, verified, stillThere, calls }. Use it instead of figma_undo_step. Requires confirm: true. Editors: Design; unverified: FigJam, Slides.
Inputs: confirm (required), savepointId (required), force, session, +1 more.
figma_rotate_nodesRotate nodesAIdempotent
Set an absolute rotation in degrees, turning about the centre as the editor does (pivot: "origin" turns about the top-left corner, Figma's raw behaviour). Inside an auto-layout the layout re-places the node; the item reports pivot "layout". The turn is read back: an item Figma did not keep is ok: false with the rotation and position it has. figma_move_nodes moves without turning. Returns per-item results: items: [{ id, ok, error? }] — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: angle (required), nodeIds (required), force, pivot, +2 more.
figma_savepointSavepoint before an instructionAIdempotent
Mark the point before an instruction, so figma_rollback can take back everything done after it in one call. Make one at the start of every instruction a person gives: it writes nothing to the document and costs nothing. Result { savepointId, label, at, pageId, journalSeq }; figma_get_changes { since: savepointId } lists what was done since. Savepoints live in this server process: a restart forgets them, and a rollback forgets the ones made after its own. Editors: Design; unverified: FigJam, Slides.
Inputs: label (required), force, session, idempotencyKey.
figma_save_screenshotsSave screenshotsARead-only
Render several nodes to image files and return their paths — cheaper for your context than returning image data, and the way to hand a user a set of screenshots. The plugin renders; the bridge writes, so paths follow the same rules as figma_export_node's saveTo (relative lands in the export directory, other folders must be in BRIDGE_EXPORT_ROOTS). One node failing does not lose the others: the result carries failed[].
Inputs: nodeIds (required), dir, scale, format, +1 more.
figma_scan_nodes_by_typesScan for node typesARead-only
Every node of the given types in a subtree, at any depth — the "find all frames / all components" tool. Paginated. The result's scope names the root that was scanned.
Inputs: types (required), limit, cursor, nodeId, +1 more.
figma_scan_text_nodesScan all textARead-only
Every text in a subtree with its full characters — a copy audit, a translation extract, or the text behind a screen when figma_get_design_context cut it at maxTextChars. TEXT nodes, and on a board the text a sticky, shape or connector holds, code blocks, and one item per non-empty table cell (its cell); types narrows it. Paginated by item: a truncated scan says so rather than returning a partial document as if it were whole. The result's scope names the root that was scanned (in Slides, with nothing selected, the focused slide). Finding one text: figma_search_nodes { text }.
Inputs: limit, types, cursor, nodeId, +1 more.
figma_search_nodesSearch nodes by name or typeARead-only
Find nodes by name substring, by what their text says (text: a TEXT node's characters, a sticky's, shape's or connector's label, a code block, a table cell — a cell hit names its cell), and/or Figma node type, or every instance of a component (componentId; for a variant set, every variant's instances, each hit naming the variant it shows). scope picks where to look: the current page (default), the current selection, or a specific subtree; the result's scope says which root was searched. Paginated with limit + cursor. Every text in a subtree: figma_scan_text_nodes.
Inputs: text, type, limit, query, +6 more.
figma_selectSelect nodesARead-only
Select nodes on the canvas so the user sees exactly what you mean or are about to change. mode: replace (default), add, toggle. Nodes on another page switch the editor to that page first. Changes no design data.
Inputs: mode, nodeId, nodeIds, session.
figma_set_auto_layoutConfigure auto-layoutAIdempotent
Full auto-layout configuration on one node: mode, gap, padding, alignment, wrap, and axis sizing. mode: "none" removes auto-layout. alignX / alignY are screen directions (space-between only along the layout direction; baseline only as alignY of a row). wrap needs a horizontal layout; a wrapped row spaces its rows by rowGap (default: the gap) and shares the height by alignContent. A negative gap overlaps items (an avatar stack — reverseZIndex puts the first on top). Every value is checked before the frame changes. Clipping: figma_set_clips_content. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeId (required), gap, mode, wrap, +12 more.
figma_set_blend_modeSet blend modeAIdempotent
Set how nodes blend with what is beneath them (MULTIPLY, SCREEN, OVERLAY, …). PASS_THROUGH applies to frames and groups. For transparency use figma_set_opacity. Returns per-item results: { updated, items: [{ id, ok, error? }] } — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeIds (required), blendMode (required), force, session, +1 more.
figma_set_board_propertiesSet board properties (FigJam)AIdempotent
FigJam properties on 1–500 nodes, each applied by node type. color is a palette name resolved per type — sticky fill, shape preset (fill, stroke and text), connector line, table fill, text fill — or a hex; a section takes a hex only for now. wide, authorVisible (stickies), shape (shapes with text: a shape type), contentsHidden (sections), language (code blocks). A field that does not apply to a node's type is an error for that node, and that node is left unchanged. Hex paints on any node: figma_set_fills. Editors: unverified in FigJam, Slides.
Inputs: nodeIds (required), wide, color, force, +6 more.
figma_set_briefSet the brief of new workAIdempotent
Record the brief of new work before its first frame, as a senior designer writes one: role, gear, title, goal, message and success, plus the lines the gear and the role need (audience, proof, constraints, givens, tone, format, details). Roles, and the skill each reads first: ux (screens, flows, anything people operate), graphic (posters, ads, posts, print), illustration (icons, illustration; skill graphic), brand (logos, identity), presentation (decks; skill slides), design-system (tokens, components), board (FigJam; skill figjam), motion (skill storyboard). Stored in the file on a brief block drawn at an empty spot, or on nodeId; briefId updates one with directions, the choice, styleframes and the system. Under BRIDGE_PROCESS=strict a new top-level frame, a spec into an empty frame, a new deck or a new board waits for a brief, and figma_sign_off ends it. Editors: Design; unverified: FigJam, Slides.
Inputs: x, y, gear, goal, +31 more.
figma_set_clips_contentSet clip contentAIdempotent
Turn "Clip content" on or off on frames, components and instances: on crops a photo or overflow to the frame's (rounded) edge; off stops a frame cutting off a shadow or an overhanging badge — the fix for a check_layout clipped finding. A section or shape has no clipping and gets ok:false. Returns per-item results: items: [{ id, ok, error? }] — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeIds (required), clipsContent (required), force, session, +1 more.
figma_set_constraintsSet constraintsAIdempotent
Responsive constraints: how nodes follow their parent frame when it resizes. horizontal: left, right, center, left-right, scale; vertical: top, bottom, center, top-bottom, scale (Figma's MIN/MAX/CENTER/STRETCH/SCALE also accepted). Omit one axis to keep it. Children of an auto-layout frame are positioned by the layout instead. Returns per-item results: items: [{ id, ok, error? }] — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeIds (required), force, session, vertical, +2 more.
figma_set_corner_radiusSet corner radiusAIdempotent
Round the corners of nodes: one radius for all corners, or radii [topLeft, topRight, bottomRight, bottomLeft] per corner (frames and rectangles); smoothing 0–1 makes them continuous like iOS (0.6 is the iOS squircle) and can be set alone. Returns per-item results: { updated, items: [{ id, ok, error? }] } — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeIds (required), force, radii, radius, +3 more.
figma_set_descriptionSet descriptionAIdempotent
Write the description (plain or markdown) and documentation link that the assets panel and Dev Mode show, on a component, component set, local style or local variable. A set's description is the one people see — put it there rather than on a variant. One https link at most; "" clears it. Variables take plain text only, no link. Library assets are read-only here. To rename: a component or set with figma_rename_node, a style with figma_update_style name, a variable with figma_set_variable_properties name. Editors: Design; unverified: FigJam, Slides.
Inputs: targetId (required), force, session, markdown, +3 more.
figma_set_effectsSet effectsAIdempotent
Replace the effects of nodes: drop shadow, inner shadow, layer blur, background blur (either blur can ramp with progressive), noise, texture and glass. An empty effects array removes them all. Every entry is validated before any node changes, and a field of another effect type is refused. To apply a named effect style use figma_apply_style_to_node. Returns per-item results: { updated, items: [{ id, ok, error? }] } — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: effects (required), nodeIds (required), force, session, +1 more.
figma_set_fillsSet fillsAIdempotent
Replace the fill paints of nodes: solid colours, gradients, images, several stacked fills (bottom first — [{ image }, { gradient }] is a photo under a scrim on one node). A gradient is linear, radial, angular or diamond; a linear one takes a CSS angle (90 = left → right, the default; 180 = top → bottom), fitted to each node's own size; radial and diamond take center / radius, angular takes center only. An image entry reuses an image already in the file by the imageHash figma_import_image returns; to bring a new picture in use figma_import_image. An empty fills removes every fill. Every entry is validated before any node changes. This sets raw paints — to apply a named local style use figma_apply_style_to_node; for outlines use figma_set_strokes. Returns per-item results: { updated, items: [{ id, ok, error? }] } — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: fills (required), nodeIds (required), force, opacity, +2 more.
figma_set_instance_propertiesSet instance propertiesAIdempotent
Change an instance's component properties — its label text, a variant (Size, State), a boolean, a swapped icon — the way the right panel does, keeping it linked to its component. Names may be given without their #id suffix. figma_get_design_context lists an instance's properties; figma_get_component lists every option. A SLOT is not set here: create layers inside it (parentId = the slot). Editors: Design; unverified: FigJam, Slides.
Inputs: nodeId (required), properties (required), force, session, +1 more.
figma_set_keyframesSet keyframes (Motion)AIdempotent
Animate a layer on its frame's timeline: each track replaces that field's keyframes; other tracks stay. Every track is read back and re-applied if it did not land: tracks[].status is written or rewritten, timeline is { id, duration, topLevelFrameId }, and a track that never lands fails INTERNAL with partial.notApplied. The timeline grows to fit the last key and never shrinks unless timelineDuration says so (tracks: [] + timelineDuration only sets it). Refused before any change: a top-level frame (animate a child), WIDTH/HEIGHT on a group or vector, a missing or non-SOLID paint, EASE_IN_OUT (Figma spells it EASE_IN_AND_OUT); under BRIDGE_PROCESS=strict (the default) PROCESS_REQUIRED until this session read the motion skill (figma_get_guide) and the frame has a plan (figma_set_motion_plan). Not prototype transitions (figma_set_reactions). Check keys with figma_check_motion. UNSUPPORTED means stop, not retry. Skill: motion. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeId (required), force, tracks, session, +2 more.
figma_set_layout_gridsSet layout gridsAIdempotent
Replace the layout grids of frames — the column grid a page is designed on (e.g. 12 columns, 24 gutter, 80 margin), rows, or a square grid. Visible only in the editor, never in exports. An empty grids removes them. Returns per-item results: { updated, items: [{ id, ok, error? }] } — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: grids (required), nodeIds (required), force, session, +1 more.
figma_set_lockedSet lockedAIdempotent
Lock or unlock nodes. Returns per-item results: items: [{ id, ok, error? }] — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: locked (required), nodeIds (required), force, session, +1 more.
figma_set_maskUse as maskAIdempotent
Make a shape a mask (or stop it being one). A mask crops the layers ABOVE it in the same parent — put it below the image or shapes it should crop, then group them (figma_group_nodes) so the mask stays local. maskType: alpha (default), vector (the shape's outline), luminance. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeId (required), force, isMask, session, +2 more.
figma_set_motion_planSet the motion plan of a frameAIdempotent
Record the plan of one animated top-level frame before animating it, as a motion designer does: the brief (audience, message, format, durationS, fps, bpm?) and the beat sheet, beats back to back from 0 to durationS, each with its copy on screen, action and transition. A role-motion brief (figma_set_brief { role: "motion" }; briefId, or the one in force) fills the fields left out. Checked before anything is stored: times on the frame grid; no gap or overlap; each beat long enough to read its copy, max(5/6 s, 0.3 s a word); accents on the bpm grid; every transition named. Stored on the frame; a new call replaces it. figma_check_motion judges the frame against it: bpm, holds, brandId, ctaId and accept (findings the brief intends, with reasons). Under BRIDGE_PROCESS=strict the keyframe tools refuse a frame without a plan. The result gives each beat's frames and check, the figma_check_motion call. One undo step. Editors: Design only.
Inputs: beats (required), brief (required), nodeId (required), cuts, +8 more.
figma_set_opacitySet opacityAIdempotent
Set opacity, 0–1. Returns per-item results: items: [{ id, ok, error? }] — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeIds (required), opacity (required), force, session, +1 more.
figma_set_prototype_flowsSet prototype flowsAIdempotent
Replace a page's prototype flow starting points, in order — the first is where the play button starts — and/or its prototype background colour. Each flow starts at a top-level frame on that page; flows: [] removes them all. Per-layer interactions (click, hover, navigate) are figma_set_reactions. Editors: Design; unverified: FigJam, Slides.
Inputs: flows, force, pageId, session, +2 more.
figma_set_reactionsSet prototype reactionsAIdempotent
Replace a node's prototype interactions. reactions is a JSON array. Shorthand per entry: { "trigger": "ON_CLICK", "action": { "type": "NODE", "destinationId": "12:3", "transition": "SMART_ANIMATE", "duration": 0.3 } } — duration in seconds; navigation defaults to NAVIGATE. Figma's full Reaction shape (what figma_get_reactions returns) is accepted as is. Other actions: BACK, CLOSE, URL ({ type, url }). Editors: Design; unverified: FigJam, Slides.
Inputs: nodeId (required), reactions (required), force, session, +1 more.
figma_set_scroll_behaviorSet scroll and fixed layersAIdempotent
Prototype scrolling for a frame: overflow (none, horizontal, vertical, both) and which direct children stay fixed while the rest scrolls (fixedNodeIds, bottom to top; [] fixes none). Fixed layers are moved to the top of the layer list, so in an auto-layout frame each must be absolute first (figma_move_nodes positioning "absolute"), and an instance takes overflow only — Figma moves none of its layers, so fix them in its main component. This is presentation behaviour; to cut content off on the canvas use figma_set_clips_content. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeId (required), force, session, overflow, +2 more.
figma_set_slide_gridRegroup the slide gridAIdempotent
Restate a whole Figma Slides deck's grouping in one step: rows lists every slide id in its new row (section) and order, each row with an optional name (1–3 words; "" restores the default label). Every slide of the deck must appear exactly once — a missing, repeated or unknown id is refused, listed by id, before anything changes; no slide is ever removed. Returns the rows as they are afterwards, how many slides moved and rows were renamed, and rows left empty or removed. To move a few slides without restating the deck use figma_move_slides; to rename one section use figma_rename_node on its row id (figma_get_slide_grid lists them). Editors: Slides only, unverified.
Inputs: rows (required), force, session, idempotencyKey.
figma_set_slide_propertiesSet slide propertiesAIdempotent
Per slide of a Figma Slides deck: skipped (left out of the presentation, kept in the deck) and speakerNotes (the presenter's notes as markdown; "" clears). Notes keep lists, bold, italic and strikethrough; headings, code and links stay literal text and earn a warning. Write notes only when asked or for a deck meant to be presented: short bullets that add to the slide, not a script. If this Figma build does not expose speaker notes, a call that sets them is refused before anything changes. Per-slide results. Slide names: figma_rename_node; backgrounds: figma_set_fills on the slide; transitions: figma_set_slide_transition. Editors: Slides only, unverified.
Inputs: slides (required), force, session, idempotencyKey.
figma_set_slide_transitionSet slide transitionsAIdempotent
Set the transition into each of these Figma Slides slides: style (DISSOLVE, SMART_ANIMATE, SLIDE_FROM_LEFT, PUSH_FROM_RIGHT, … or NONE), duration 0.01–10 s, curve, and timing: on-click, or after-delay with delay 0–30 s (a delay with on-click is refused: Figma sets it to 0). Fields left out keep each slide's current value. Each slide's transition is read before anything changes: if this Figma build does not implement transitions the call is refused, nothing changed. Returns each slide's transition as read back. Not prototype interactions (figma_set_reactions) or layer animation (figma_set_keyframes). Editors: Slides only, unverified.
Inputs: style (required), slideIds (required), curve, delay, +5 more.
figma_set_strokesSet strokesAIdempotent
Set the outline (stroke) of nodes: exactly one of a solid color, a gradient (as in figma_set_fills), or remove: true to take it off; plus weight, alignment, dashes, line ends (cap) and corners (join). sides sets per-side weights on frames, rectangles, components and instances: a side left out is 0 — so { sides: { bottom: 1 } } is a bottom border — unless weight is given, which then fills it. This is the border — for the inside colour use figma_set_fills. Returns per-item results: { updated, items: [{ id, ok, error? }] } — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeIds (required), cap, join, align, +9 more.
figma_set_textSet textAIdempotent
Replace the content of a TEXT node — or, on a board, of a sticky, shape or connector label, or a code block's code (a table's cells: figma_edit_table). The node's current font is loaded first, so this works on text this project did not create. If the node had more than one style (a bold word, a second font), Figma gives the new text the first character's style and the rest is lost — the result then carries flattened.runs with the old segments, so you can reapply them with figma_set_text_range. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeId (required), content (required), force, session, +1 more.
figma_set_text_propertiesSet text propertiesAIdempotent
Change typography on whole text nodes, like Figma's text panel: font family, weight, size, line height, letter spacing, case, decoration, colour, paragraph spacing and indent, lists, alignment (horizontal and vertical), resizing, truncation, leading trim, wrap style. A new family keeps each run's own weight (a bold word stays bold); a new weight applies to all of it. A weight the family names differently ("SemiBold" vs "Semi Bold") is matched, and anything substituted is reported as fellBack. maxLines ends the text in an ellipsis after that many lines. On a board a sticky, shape or connector restyles its text, and a table every cell; those texts have no alignment, resizing or truncation of their own. For part of a text use figma_set_text_range. Returns per-item results: items: [{ id, ok, error? }] — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeIds (required), case, list, align, +18 more.
figma_set_text_rangeStyle part of a textAIdempotent
Style part of one text node (or a sticky's, shape's or connector's text) — a bold word, a coloured price, an underlined link, a bulleted paragraph. Pick the part with match (every occurrence, or the nth with occurrence) or with start/end character offsets. Paragraph spacing, paragraph indent, list and its indent level widen to the whole paragraphs the part touches. To tie the part to the design system, use textStyle and fillStyle (a local style's id or exact name), colorVariable (a COLOR variable), and variables per text field. One colour source per call: color, fillStyle or colorVariable. link takes a URL, or "node:" to link to a layer in this file. Everything is checked before the text changes. For whole-node properties (alignment, resizing, truncation) use figma_set_text_properties. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeId (required), end, case, link, +21 more.
figma_set_variable_modeSet variable modeAIdempotent
Show nodes in a chosen mode of a collection — Dark on this screen, Light on that one: frames, components, sections and pages pin a mode, and everything inside follows. Without it every node uses the collection's default mode, so a Dark mode can be created and valued and still never be seen. clear: true removes the pin (the node inherits again). The collection by id or name, the mode by name or id. Returns per-item results: items: [{ id, ok, error? }] — one item failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeIds (required), mode, clear, force, +4 more.
figma_set_variable_propertiesSet variable propertiesAIdempotent
Change what a token carries besides its value: name (one variable only), scopes, codeSyntax ("" removes a platform), description, hiddenFromPublishing — on many variables at once, by id or exact name. Scopes are checked against each variable's own type. Values per mode: figma_set_variable_value. Returns per-item results: items: [{ id, ok, error? }] — one item failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: name, force, scopes, session, +6 more.
figma_set_variable_valueSet variable valueAIdempotent
Set a variable's value in one mode. value is a string: "#1a2b3c" for COLOR, "16" for FLOAT, text for STRING, "true"/"false" for BOOLEAN, or "alias:color/brand" to point at another variable of the same type. modeId takes a mode id or name and defaults to the collection's first mode. Editors: Design; unverified: FigJam, Slides.
Inputs: value (required), force, modeId, session, +3 more.
figma_set_visibleSet visibilityAIdempotent
Hide or show nodes. Returns per-item results: items: [{ id, ok, error? }] — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeIds (required), visible (required), force, session, +1 more.
figma_sign_offSign off new workAIdempotent
End a piece of new work the way a studio signs it off. Runs the role's checks on the deliverables (figma_check_layout with the role's audits and the brief's floors; for motion the frame-by-frame check at the delivery fps), checks the brief is complete for its gear (directions, the choice, styleframes, the system), takes your critique lens scores, rounds and a reason for every info you keep, then records the result and a fingerprint on each deliverable and on the brief block, closes the brief, and selects and zooms to the work on a pass. At top and piece, message and originality need a reviewer other than you (the critique_cold prompt in a fresh context, or the owner); at page a self-review is recorded as one. ok: false lists each blocker with the call that clears it. A final export (figma_export_node, figma_export_frames_to_pdf or figma_export_video with final: true) needs a passing sign-off newer than the last change. Writes plugin data only. Editors: Design; unverified: FigJam, Slides.
Inputs: lenses (required), rounds (required), fps, deck, +8 more.
figma_statusFigma bridge statusARead-only
Bridge and plugin connection status: whether this process holds the Figma connection or shares it, every connected Figma file (session id, file, page, user, plugin version), each file's editor (Figma Design, FigJam or Figma Slides) with the tools that do not run there (unavailableTools), the active session, the version of the skills figma_get_guide serves (skills), the process mode, the skills read and this session's briefs (process), the stale-write guard (bridge.conflicts: refuse, warn or off), this server's token file and fingerprint (the plugin window shows its own) with refused tokens (auth), video export state (videoExport, video: ffmpeg), and a hint for what to do next. Answered by the bridge itself — works even when no plugin is connected. Call this first, and whenever another figma_ tool returns NO_SESSION, PORT_IN_USE, or UNSUPPORTED naming an editor.
Inputs: no named parameters.
figma_stress_testStress-test a design with real contentAIdempotent
Does the design survive real content? Copies the frame once per case beside it, applies the case to the copy, runs figma_check_layout (craft plus audits) on the original and on each copy, and reports what each case broke that the original does not have, by the original's layer path. Cases: expand (every text grown as translation grows it, 300 % up to 10 characters down to 130 % past 70), long (names and titles at their longest), numbers (every number large: 9 → 12,345), many (lists of three or more instances tripled), empty (those lists emptied); default all. The copies are removed unless keep: true (then they stay, selected). One undo step. Result { baseline: { ok, counts }, cases: [{ case, broke: [{ kind, severity, path, detail }], ok }], kept? }. Run it on every screen before sign-off and fix what it breaks. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeId (required), keep, cases, force, +3 more.
figma_suggest_fontsSuggest fonts that fit the designARead-only
Choose typography the way a designer would: reads the fonts and sizes the design already uses, and the fonts actually available in this Figma, then ranks heading/body pairings for the mood and use — with the exact style names to pass on — plus a type scale. When the design already has a font, consistency says so: keep it unless changing it is the point. applyPlan splits the existing text into heading and body node ids, so a choice applies in two figma_set_text_properties calls. A large page is read in part — up to 5,000 layers or 5 s; scanned says whether it was whole — so pass nodeId to fit one frame. Reads only.
Inputs: use, mood, limit, nodeId, +1 more.
figma_swap_componentSwap componentAIdempotent
Make an existing instance show a different component (a component set swaps to its default variant, or to the variant you name), keeping overrides where Figma can. A library component is given by componentKey / componentSetKey and imported first. To switch a variant of the SAME set, figma_set_instance_properties keeps the other values; to place a new instance use figma_create_instance. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeId (required), force, session, variant, +4 more.
figma_undo_stepUndo (dangerous)ADestructiveIdempotent
Trigger Figma's undo. WARNING: it returns to the last checkpoint this plugin committed, so changes the user made BY HAND since the last tool call are lost too. Prefer figma_delete_nodes with the ids a create call returned — that is the safe way to undo agent work. Requires confirm: true. Editors: Design; unverified: FigJam, Slides.
Inputs: confirm (required), count, force, session, +1 more.
figma_ungroup_nodesUngroupADestructiveIdempotent
Unwrap groups: their children move up into the group's parent and the group disappears. Only GROUP nodes — to move children out of a frame use figma_reparent_nodes. Each item reports childIds. Returns per-item results: items: [{ id, ok, error? }] — one node failing does not fail the call. Editors: Design; unverified: FigJam, Slides.
Inputs: nodeIds (required), force, session, idempotencyKey.
figma_update_styleUpdate styleAIdempotent
Change a local style IN PLACE — every node using it follows; deleting and recreating would detach them all. By styleId or styleName (+ type when a name is shared). Any kind: name, description. Paint: color or fills, with opacity; opacity alone fades every paint and keeps bound colours. A gradient style's angle is exact only on a square node — a style has no size; for an exact CSS angle on a known node use figma_set_fills, or give transform. Text: font, size, line height, letter spacing, case, decoration, paragraph spacing/indent. Effect: effects. Grid: grids. variables binds tokens inside the style: text fields by name (fontSize, fontFamily…), a paint's "color", "effect.color" / "effect.radius" …, "grid.count" …, with index for the entry. A field that does not fit the style's kind, and a library style, are refused before anything changes. Editors: Design; unverified: FigJam, Slides.
Inputs: case, name, type, color, +19 more.
figma_update_variable_collectionUpdate variable collectionADestructiveIdempotent
Rename a variable collection, hide it from publishing, rename its modes (e.g. "Mode 1" → "Light"), or remove modes. Removing a mode deletes the value every variable holds for it — the result counts them per mode; the last mode is never removed. Everything is checked before anything changes. To add a mode use figma_add_variable_mode (paid plans). Editors: Design; unverified: FigJam, Slides.
Inputs: collectionId (required), name, force, session, +4 more.
figma_zoom_toZoom to nodesARead-only
Scroll and zoom the viewport to show nodes — after building something, so the user sees it. zoom: "fit" (default) or a number as a string ("1" = 100%). Switches page if needed. In Figma Slides the nodes' slide (a slide given, else the one holding the first node) becomes the focused slide, and view switches between "grid" (every slide) and "single-slide" (the focused one); view alone needs no nodes. The result says which slide is focused and the view, or why the view did not change. Changes no design data.
Inputs: view, zoom, nodeId, nodeIds, +1 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 140 tools
Most tools have a sharply scoped purpose and the descriptions cross-reference siblings explicitly (e.g. figma_set_fills vs figma_apply_style_to_node, figma_get_reactions vs figma_get_motion_context). But the set is so large that near-neighbours abound: six-plus read tools (get_node, get_nodes_info, get_design_context, get_metadata, search_nodes, scan_text_nodes, scan_nodes_by_types) and five export tools (export_node, save_screenshots, download_assets, export_frames_to_pdf, export_video) require reading long descriptions to choose correctly. An agent will frequently pick the wrong one on first pass.
Overwhelmingly a figma_verb_noun snake_case pattern (create_frame, set_fills, get_design_context, delete_variable), which is predictable and readable. Minor deviations exist: figma_batch, figma_savepoint, figma_sign_off, figma_stress_test, figma_status, figma_batch_rename_nodes mix noun-style names into the verb scheme, but none are ambiguous.
140 tools is far beyond any reasonable single-server surface and forces the agent to triage a huge catalogue before acting. Even with excellent descriptions, the cognitive load and misselection risk are extreme; many tools (create_rectangle, create_ellipse, create_polygon, create_star, create_line, create_vector) are thin wrappers that should be consolidated into one shape tool or a spec builder.
Coverage is exceptional for the domain: full node CRUD (create/clone/move/resize/rotate/reorder/reparent/group/boolean/flatten/delete), variables and styles end-to-end, components/variants/properties/slots, FigJam board primitives, Slides decks and transitions, motion keyframes and review, plus briefs, sign-off, savepoints and rollback. The only real gap is consolidation rather than missing capability.
Maintenance
Related MCP Connectors
The Figma MCP server brings Figma design context directly into your AI workflow.
MCP server for building and testing AI agents with multi-model experimentation and insights.
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
The Canva MCP server connects AI assistants (like Claude, ChatGPT, and Cursor) to Canva's API, enabling them to create and manage designs directly within chat conversations. Key capabilities include generating new designs from prompts, autofilling templates, searching and resizing existing designs, importing files from URLs, exporting designs as PDFs or images, and managing folders and comments without switching between tools.
Related MCP Servers
- AlicenseBqualityDmaintenanceAn MCP server that integrates AI agents with Figma, enabling reading and programmatic modification of designs.41MIT
- FlicenseNot gradedqualityCmaintenanceA local MCP server that gives AI agents live access to open Figma files for design handoff and UX writing without API tokens or rate limits.3-
- AlicenseBqualityBmaintenanceA local MCP server that lets AI assistants inspect, create, and update designs in Figma Desktop through a development plugin, requiring no Figma Personal Access Token or cloud services.1216 npm1MIT

desrid-html-to-figmaofficial
AlicenseNot gradedqualityBmaintenanceThis MCP server lets AI agents connect to Figma to read, analyze, create, and modify designs, including elements, styles, assets, and code generation. It works with free Figma accounts and supports parallel multi-agent use across MCP-compatible clients.MIT