Mokido
A zero-dependency MCP server that gives coding agents read/write access to a live Figma canvas — run arbitrary JS in the Figma sandbox, then see the rendered PNG and undo anything it did.
Design & write
figma_execute_code— run JS in the open Figma document to create, edit, move, style, delete nodes (top-levelawait,return,capturefor a PNG of just what changed).Macros in the sandbox:
bridge.replaceWithInstance,setProps,setText(preserves mixed fonts),shift,moveInto,fitSection,componentize,openOverlay/closeOverlay,setReactionfor prototype links.bridge.define/bridge.require— persist helper modules inside the.figfile across calls and restarts.figma_insert_component_instance— instantiate components/component sets with variant props and text overrides.figma_insert_svg— insert raw SVG with scaling, recoloring, optional component wrapping.
Read & verify
figma_inspect— one-call reads of many nodes: compact outline,props,map,table,flow(prototype links),find/find_text,likeandcomparediffs against a reference,checkexpectations,offsetpaging.figma_read_canvas— token-optimized Pseudo-JSX/tree/JSON of the live document with abudget_tokenscap.figma_screenshot— PNG of specific nodes or the selection, sized bymax_px.figma_get_selection,figma_get_canvas_layout(artboard bounds + safe next position, row or grid packing).figma_find_components— cached fuzzy search for components, variants, properties, keys.figma_get_variables/figma_set_variables_mode— read design tokens; switch Light/Dark/Brand modes on a frame or page.
Safety & long jobs
figma_rollback— undo a write call's checkpoint (removes created nodes, restores modified properties).figma_job_status— blocking wait for calls that exceeded 45s or ran withasync: true.figma_list_targets— enumerate connected files and target a specific one viatarget.Auto-lint
warnings(text overflow, low contrast, zero-size nodes) plusHINT:/codeerror messages.
Optional: with FIGMA_PERSONAL_ACCESS_TOKEN, 7 REST tools add unopened cloud files (get_file, get_node, get_image, get_styles, get_components, get_comments, post_comment).
Provides read and write access to a live Figma canvas, allowing AI agents to create and modify nodes, capture rendered PNGs for visual self-critique, undo changes via checkpoints, and read token-optimized document structure.
⚡ Mokido
MCP server for Figma design. Let an AI agent design in Figma — and actually see what it drew.
Formerly figma-mcp-bridge (@kolganovr/figma-mcp-bridge on npm). Old links redirect here.
A zero-dependency MCP server that gives coding agents read and write access to a live Figma canvas, then closes the loop by handing the rendered PNG back to the model for visual self-critique.

Agent generates the design, visually audits the rendered output, detects layout defects, and self-corrects in real time — zero human in the loop.
The problem
Coding agents are effectively blind inside Figma. Most Figma MCP servers are read-only —
they flatten a design into text so a model can turn it into code, and the traffic stops there.
The ones that can write are either gated behind a paid Figma seat with a monthly tool-call
quota, or expose a fixed vocabulary of commands (create_rectangle, set_fill) that runs out
the moment the task gets specific.
And none of them answer the question that actually matters after a write: did it look right?
An agent that draws a card, gets back {"ok": true}, and moves on has no way to notice that its
text overflowed, its contrast failed, or its frame landed on top of someone else's work.
This bridge closes that loop, and adds the safety rails an autonomous agent needs to be trusted with a real design file.
Related MCP server: figma-mcp-express
How it's different
This bridge | Figma Dev Mode MCP (official) | |||
Writes to the canvas | ✅ arbitrary JS in the sandbox | ✅ code-to-canvas | ❌ read-only | ✅ fixed command set |
Visual feedback loop | ✅ auto-framed PNG on any write ( | ⚠️ separate screenshot call | ❌ | ❌ |
Undo the agent's work | ✅ | ❌ | n/a | ❌ |
Works on the Figma Free plan | ✅ | ❌ Dev/Full seat, paid plan¹ | ✅ | ✅ |
Tool-call quota | none — it's local | 6 / month on Starter seats¹ | inherits REST rate limits | none |
Token-optimized read of the live doc | ✅ 86–91% smaller² | ⚠️ partial | ❌ REST only | ❌ |
Persistent code modules in-sandbox | ✅ | ❌ | ❌ | ❌ |
Long jobs survive their own timeout | ✅ async | ❌ | n/a | ❌ |
Token budget per call | ✅ capped text, sized images, compact JSON | ❌ | ⚠️ read-side only | ❌ |
Install footprint | 0 npm deps, | Figma desktop + paid seat |
| Bun + a second server process |
The short version: Framelink is the best choice if you only want to turn an existing design into code. The official server is the safest choice if you're already on a paid Figma plan and want Code Connect. This bridge is for the case where the agent is doing the designing — where it needs to write freely, check its own work, and be undoable when it gets it wrong.
How it works
flowchart LR
subgraph AI ["🤖 Coding Agent"]
LLM["Claude Code · Cursor<br/>Antigravity · Windsurf"]
end
subgraph Bridge ["⚡ MCP Server — Node.js, 0 deps"]
Router["Tool Router<br/>+ Job Ledger<br/>+ Target Router"]
Opt["Token Optimizer<br/>REST + LIVE"]
end
subgraph Figma ["🎨 Figma Desktop"]
Plugin["Bridge Plugin<br/>Checkpoint Journal<br/>Component Index"]
Canvas["Live Canvas"]
end
LLM -->|"stdio JSON-RPC"| Router
Router <-->|"WebSocket :8765"| Plugin
Plugin -->|"execute in sandbox"| Canvas
Canvas -->|"export PNG"| Plugin
Plugin -->|"raw node tree"| Opt
Opt -.->|"86% smaller"| LLM
Plugin ==>|"screenshot + warnings"| LLMThe agent speaks plain MCP over stdio. The server owns a hand-rolled RFC 6455 WebSocket on
:8765, which the Figma plugin connects to — so commands reach the canvas with no polling
latency, and results (including multi-megabyte base64 PNGs) stream straight back.
Quickstart
npx mokidoOr, to read the installer before it touches your machine — it's the same script either way, just fetched differently:
git clone https://github.com/kolganovr/mokido.git
cd mokido
node install.mjsBoth copy the server and plugin into place and register the MCP server in every AI client config
they find — Claude Desktop, Claude Code, Cursor, Windsurf, Antigravity. The npm package exists
purely for a shorter first command; it doesn't add a single runtime dependency — dependencies
is empty in its package.json too, and no Python is needed either. node is the only runtime
this project ever needs, for the installer and the server alike.
Then, in Figma Desktop:
Plugins → Development → Import plugin from manifest… → pick
figma-plugin/manifest.jsonPress
Ctrl + Alt + P(macOS:Cmd + Option + P) to launch MokidoStatus turns green —
CONNECTED
Restart your AI client so it picks up the new tools. Verify anytime with:
npx mokido --doctor # or: node install.mjs --doctorThe live canvas tools need no token. If you also want to read unopened cloud files
(get_file, get_node, get_styles, …), supply a personal access token:
npx mokido --token "your_figma_personal_access_token"
# or: node install.mjs --token "your_figma_personal_access_token"Without a token these 7 tools aren't registered at all — see Tool reference.
What it gives the agent
1. Write freely, then look at the result
capture: true returns a PNG of exactly what the call just created or modified — auto-framed
to the changed nodes, never the whole page, and never by hijacking the user's selection.
// agent calls figma_execute_code
{ "code": "const f = figma.createFrame(); /* ... */ return f.id;", "capture": true }
// agent gets back — text + image in one response
{
"ok": true,
"created": ["12:34"],
"warnings": ["Text \"Total\" has ~3.1:1 contrast against its parent fill (WCAG AA wants 4.5:1)."],
"checkpoint_id": "cp_mfk3p2a_7",
"duration_ms": 840
}The warnings array is a cheap auto-lint over the touched subtree — text overflow, low contrast,
zero-size nodes. It catches the obvious mistakes without spending a screenshot round trip.
2. Undo anything the agent did
Every write opens a checkpoint automatically. One call reverses it — no Ctrl+Z rolling back over
the human's own unrelated work.
// agent calls figma_rollback
{ "checkpoint_id": "last" }
// gets back
{
"ok": true,
"checkpoint_id": "cp_mfk3p2a_7",
"label": "Generate checkout flow",
"removed": ["12:34", "12:35"], // nodes the call created — deleted
"restored": ["9:11"], // nodes it modified — properties put back
"missing": [] // ids that no longer exist
}Created nodes are tracked automatically via a Proxy around figma.create*(). Property edits are
tracked when snapshotted. Deletions are honestly reported as unrecoverable rather than silently lost.
3. Read the live canvas for ~700 tokens instead of ~5,000
The same pruning + Pseudo-JSX pipeline that powers the cloud tools, pointed at whatever is open right now. Measured on a realistic 6-card layout: 20 KB of raw API JSON → 2.7 KB (86% smaller).
<Frame id="1:1" name="Landing" w="1440" h="900" row gap="20">
<Frame id="2:0" name="Card" w="300" h="200" col gap="12" pad="20" bg="#FFFFFF" radius="16">
<Icon id="3:0" name="ic_check" size="24" strokeWidth="2" />
<Text id="4:0" color="#1A1A1F" font="Inter 18px">Feature 0</Text>
</Frame>
</Frame>budget_tokens caps the response: if the requested depth overshoots, the server re-serializes the
already-fetched tree shallower — no second round trip — and appends a comment saying what it did
and which id to fetch for more.
4. Teach the sandbox new tricks that survive restarts
Every figma_execute_code call is a fresh function scope, so helpers normally die instantly.
bridge.define compiles and stores a module inside the .fig document:
// once
bridge.define("kit", `
async function label(parent, text) { /* ... */ }
module.exports = { label };
`);
// in any later call — including next week, after a Figma restart
const { label } = bridge.require("kit");5. Long jobs that don't die at the timeout
A generation still running after 45s hands back a job_id instead of failing while the plugin
keeps working. figma_job_status then blocks until the job finishes (up to wait_ms, 45s by
default) — one call, not a polling loop. Progress from progress(step, of, note) is included while
it runs; a job silent for 2 minutes is flagged stalled, and one whose plugin disconnected fails
at once with PLUGIN_DISCONNECTED instead of running out the clock. A call that times out behind a
still-running job says so (PLUGIN_BUSY, naming the job) instead of inviting a blind retry.
6. Built for the token bill
In an agent loop a tool call is paid for twice: once when it returns, and again on every later turn, because its output stays in the context that each turn re-reads. So the bridge optimizes for fewer turns and smaller residue:
Default | Why | |
Screenshots |
| image tokens scale with pixel area (~w·h/750); each image is described as |
| off | the auto-lint |
Text results | compact JSON; every response is kept under | some clients (Antigravity) spill output over ~4 KB into a file the model must open with an extra call; the full value stays in |
Cheap reads |
| one-line-per-node outlines and pass/fail lists instead of one hand-written dump per call |
Plugin reloads | calls wait up to 8s for the plugin to reconnect | a failure costs a turn to read and another to retry |
Server instructions | ≈1.9k chars, economy rules first | some clients truncate instructions at ~2000 chars |
Every default is overridable per call, and per install through env: FIGMA_MCP_SCALE,
FIGMA_MCP_MAX_PX, FIGMA_MCP_MAX_IMAGES, FIGMA_MCP_MAX_OUTPUT_BYTES, FIGMA_MCP_MAX_OUTPUT_CEILING (0 = no ceiling), FIGMA_MCP_JOB_WAIT_MS,
FIGMA_MCP_ESCALATE_MS, FIGMA_MCP_RECONNECT_GRACE_MS.
What's new
4.2.7: compare / like diffs end with a REF line of exact reference values, so the agent fixes copies
without an extra props read; find returns the subtree of what it found; view: "flow" works without
node_ids; bridge.setText keeps mixed fonts. On the internal bench (Gemini Flash, seeded tasks) model turns
per series went 112 -> 83 and verify turns after a write 11 -> 1. Reload the Figma plugin after updating.
History: CHANGELOG.md.
Tool reference
Tools are served in tiers, so the schema list sent to the model on every turn stays proportional to what's actually usable:
Tier | Count | Registered when |
Core | 8 | always |
Extended | 5 | always |
REST | 7 | only with |
Legacy | 3 | only with |
Without a REST token an agent sees 13 tools instead of 23 — and never wastes a call on
something that would only return REST_TOKEN_MISSING.
Core — live canvas
Tool | Description |
| Run JS in the Figma sandbox. Injects |
| Read many live nodes in one call: compact outline (or |
| Token-optimized read of the live document ( |
| PNG of specific |
| Cached, tokenized, fuzzy component search — variants, properties, keys. |
| Instantiate a component/variant, apply text overrides, place into AutoLayout. |
| Insert raw SVG with proportional scaling, recoloring, optional component wrapping. |
| Variable collections, modes, and token values. |
| Undo a previous write call's checkpoint. |
Extended — live canvas
Tool | Description |
| Geometry, compact hex fills, parent/page, AutoLayout context of the selection. |
| Artboard bounds + a safe |
| Switch theme mode (Dark/Light/Brand) on a frame or page. |
| Wait (blocking, |
| List connected Figma documents for multi-file targeting. |
REST — Figma Cloud (needs a token)
Tool | Description |
| Token-optimized cloud file/subtree. Supports |
| Render nodes to PNG/SVG/PDF via Figma's renderer. |
| Published styles and design-system components. |
| Read and post file comments. |
Legacy — opt-in via FIGMA_MCP_LEGACY_TOOLS=1
figma_create_ui_card · get_me · get_image_fills
Engineering notes
The parts that were harder than they look — and why the code is shaped the way it is.
The obvious way to persist helpers between calls is "stash the source, eval it next time." It
fails silently: eval is a bound function in Figma's sandbox, which by spec makes every call
an indirect eval — declarations inside it reach neither the caller's scope nor globalThis.
Nothing is defined, nothing throws.
bridge.define is built on new Function instead, whose bodies are ordinary function scopes.
The runtime's bridge.info() reports this contract to the agent on request, so it can ask instead
of guessing.
Zero npm dependencies isn't a vanity metric here — it means git clone && node install.mjs works
on a locked-down machine with no registry access, and there's no supply chain to audit for something
that executes arbitrary JS inside your design files.
The cost is owning the framing: masking, fragmented continuation frames (a 4 MB screenshot arrives split, and treating each fragment as a whole message silently dropped it until the tool call timed out 40s later), ping/pong liveness, and a 64 MB ceiling so one frame can't exhaust memory.
Figma caps pluginData entries at roughly 100 KB — measured in bytes. The original chunker
sliced by JS string length, so a module written in Cyrillic (~2 bytes/char) produced "60,000-char"
chunks that were really 120 KB, and setPluginData threw. The splitter now walks the real UTF-8
budget and never tears a surrogate pair.
Every agent spawns its own copy of the server; the first to bind :8765 owns the plugin socket and
the rest proxy to it. When the owner exits, a proxy has to be able to take over — otherwise every
surviving agent stays permanently broken until restarted. A 5-second watchdog retries the bind, and
a failed proxy call triggers an immediate takeover attempt.
The original collision engine rescanned every top-level node for each of up to 200 candidate positions, then did it again in a second function in the same tick — and only ever stepped along one axis, so 20 generated screens became a mile-long ribbon nobody could zoom out to see.
Bounds are now computed once and shared; collisions go through a 500px grid hash; and layout:"grid"
shelf-packs into a compact rectangle.
Raw Plugin API errors are famously unhelpful. Failures are matched against known modes and rewritten
with a HINT: line naming the API that actually works, plus a stable machine-readable code
(FONT_NOT_LOADED, INSTANCE_TRANSFORM_LOCKED, STALE_NODE_ID, AUTOLAYOUT_HUG_RESIZE,
AMBIGUOUS_TARGET, …) so agents and tooling can branch on the failure type without parsing prose.
:8765 is loopback, but loopback is reachable by any web page the user happens to have open.
Two independent gates: an Origin allowlist (a browser cannot forge Origin, so a page on
evil.com is rejected at the handshake) and a shared token that install.mjs generates and bakes
into both the MCP config and the installed plugin — which also covers the sandboxed-iframe case,
where a hostile page can present Origin: "null" too.
Running straight from a clone with no token, the Origin gate still applies and the server prints a warning, so it degrades rather than silently opening up.
On startup the server compares the commit it was installed from (recorded by install.mjs into a
version.json beside the copied code) against the latest commit on main via one GitHub API
request, and prints a one-line notice to stderr if they differ. It never applies anything itself —
node install.mjs --update is still a manual, deliberate step.
This is the one thing in this project that assumes network access, so it's built to disappear
cleanly when there isn't any: the check is fired without being awaited (never delays initialize
or the first tool call), a failed/slow/offline request is caught and silently skipped, and results
are cached for 24h so it doesn't hit GitHub's unauthenticated rate limit or run once per spawned
copy of the server. Set FIGMA_MCP_NO_UPDATE_CHECK=1 to turn it off entirely — worth doing on the
locked-down machines the previous note is about.
Testing
Seven dependency-free suites, all runnable with bare node:
node tests/bridge-runtime.test.js # sandbox runtime, module persistence, checkpoint/rollback
node tests/layout-packer.test.js # row/grid packing, collision grid
node tests/optimizer.test.js # jsx/tree/json serialization, budget truncation
node tests/mcp-protocol.test.js # real server over stdio: initialize, tools/list, tiering
node tests/install.test.js # config merge/reuse, token persistence, stale-file cleanup
node tests/token-economy.test.js # fake plugin over a real WebSocket: budgets, long-poll, proxy
node tests/output-shrink.test.js # line-wise shrinking, offset paging, output ceiling, syntax pre-checkmcp-protocol.test.js spawns the actual server as a child process and speaks NDJSON to it — the
same transport a real MCP client uses — rather than importing internals.
Repository layout
mokido/
├── figma/ # MCP server (Node.js, stdio + WebSocket)
│ ├── index.js # protocol, tool router, job ledger, target router
│ ├── optimizer/ # AST pruner, style collapser, JSX/tree serializers
├── figma-plugin/ # Figma Desktop plugin
│ ├── code.js # sandbox executor, bridge runtime, checkpoints, capture
│ └── ui.html # HUD — stream, settings, control (pause / undo)
├── docs/GUIDE.md # long-form agent guide (server instructions are inline in index.js)
├── tests/ # 7 suites, 0 dependencies
├── install.mjs # cross-platform installer, updater, doctor (Node only)
└── AGENTS.md # onboarding protocol for AI agentsSources
Seat and quota requirements for the official server — Figma: Guide to the Figma MCP server, Figma Developer Docs: Rate limits & access
Token reduction measured on a 6-card layout fixture that mimics real REST output: 20,587 B raw → 2,862 B Pseudo-JSX (86.1%) / 1,912 B tree (90.7%). The fixture is checked in and asserted — run
node tests/optimizer.test.jsto reproduce the exact figures.
Comparison reflects publicly documented behaviour as of August 2026. Alternatives are actively developed — verify current capabilities before making a decision on this table alone.
License
MIT · Built by Roman Kolganov
Available Tools
14 toolsfigma_execute_codeADestructive
WRITE tool: run JavaScript in the open Figma document (Figma Desktop + 'Mokido' plugin) to create, edit, move, style or delete nodes. To READ (explore a section, list children, find layers, check texts / fonts / variants / table columns) call figma_inspect instead: every id in one call, one line per node, view:"table" for tables; a read script here costs a model turn per question and its reply names the figma_inspect call to use (use_instead). Every call is a full model turn, so make the whole change in ONE call — all screens / breakpoints, verified in the same code with bridge.check — and put capture_node_ids on that same call instead of a separate figma_screenshot. Globals: figma, await ensureFont(family, style), getFreePosition(w, h), bridge: bridge.check({ '1:2': { width: 320, fill: '#FFFFFF' } }) -> pass/fail list; bridge.define(name, src) + bridge.require(name) keep helpers between calls (each call is a fresh function body — never eval); return bridge.info() lists the rest. Macros: bridge.replaceWithInstance(target, comp, {props, text}), bridge.setProps(inst, {Status: 'Dropdown'}), bridge.setText(root, {layer: '…'}) or bridge.setText(textNode, 'new text') (keeps mixed font styles by words: THE way to replace the text of a label with several font styles — never characters =, which flattens them, and never a per-character getRangeFontName/setRangeFontName loop), bridge.shift(ids, {dx, dy}), bridge.moveInto(ids, section, {layout, gap}), bridge.fitSection(s), bridge.context(id), bridge.componentize(nodeObject) -> new COMPONENT, same name/size/look, NEW id (never raw createComponentFromNode), prototype links: await bridge.openOverlay(triggerId, overlayFrameId, { position: 'BOTTOM_CENTER', dim: 0.4, closeOnOutside: true }) (the overlay look is read-only in the Plugin API: the reply names the MANUAL STEP for the user), bridge.closeOverlay(id), bridge.setReaction(id, { to: frameId, nav: 'NAVIGATE' }); read links with figma_inspect view:"flow". Call macros directly, don't read their source. Never findAll the whole page — scope to a section. Return only the ids/flags you need: responses over max_output_bytes (3500) are shrunk, the full value stays in bridge.state.lastResult.
| Name | Required | Description | Default |
|---|---|---|---|
| code | Yes | JavaScript to run in the Figma sandbox, compiled as an async function body (top-level await and return allowed; import/export are not). Example: const frame = figma.createFrame(); frame.resize(400, 600); frame.name = 'Card'; figma.currentPage.appendChild(frame); return 'Created frame'; | |
| diff | No | Currently ignored (the "before" screenshot stalls the plugin); the reply has the after image only. | |
| async | No | Return { status: 'running', job_id } immediately instead of waiting — collect it later with figma_job_status. Calls that run past 45s do this automatically. | |
| scale | No | Screenshot resolution scale (default: 1). | |
| max_px | No | Longest side of each returned image in px (default: 1024). Image tokens grow with pixel count, not file size. | |
| target | No | fileName of a specific connected Figma document to run this in, when more than one is open (see figma_list_targets). Defaults to whichever is currently focused. | |
| capture | No | Set to true to capture a PNG of what this call created/modified and return it for visual verification. Never touches the user's selection — see capture_node_ids. | |
| description | No | Short human-readable description of the action (e.g. 'Create login modal', 'Update brand colors') shown in Figma toasts and logs. | |
| capture_node_ids | No | Node ids to screenshot instead of the default (whatever this call created/modified, falling back to the user's current selection only if neither exists). The user's selection is never mutated to enable a capture. | |
| max_output_bytes | No | Cap on the whole text response in UTF-8 bytes (default: 3500 — under the ~4 KB at which some clients spill output to a file and cost an extra turn; in clients that spill big outputs to a file, 0 and values above 3900 become 3900). Larger results are shrunk structurally (multi-line text is cut by whole lines), cuts marked with …. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (write, destructive, non-idempotent), and the description adds substantial context they cannot carry: every call is a full model turn so batch the whole change, responses over max_output_bytes are shrunk with the full value in bridge.state.lastResult, overlay appearance is read-only and yields a manual step, and state persists between calls via bridge.define/require. It also discloses hazards: never eval, never findAll the whole page, never assign `characters`.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The critical framing (WRITE tool, use figma_inspect to read, do it in one call) is front-loaded, but the body is a dense semicolon-chained wall enumerating every bridge macro, which is hard to scan. Most sentences carry load-bearing information, yet the macro catalog dilutes the routing guidance an agent needs first.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 10-parameter, high-destructiveness write tool with no output schema, the definition covers execution model, return-value behavior, size limits, batching expectations, and the read/write split against siblings. Nothing an agent needs to invoke it safely or correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so parameters are already documented. The description still adds real meaning: it specifies the sandbox globals available inside `code` (figma, ensureFont, getFreePosition, bridge) and the specific bridge macros to prefer over raw Plugin API calls, plus where to put capture_node_ids and why output size matters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with an explicit label ('WRITE tool') and a precise verb list (create, edit, move, style, delete) against a named resource (nodes in the open Figma document). It immediately draws the boundary against the sibling that could be confused with it (figma_inspect for reads).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States when to use the alternative explicitly ('To READ ... call figma_inspect instead') and enumerates the read tasks that belong there (list children, find layers, check fonts/variants/table columns). It also routes specific sub-tasks to other tools/calls: capture_node_ids instead of a separate figma_screenshot, and figma_job_status for async results.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_find_componentsARead-onlyIdempotent
Find and inspect components, component sets, variants, and component property definitions in the active Figma file without flooding LLM context. Returns names, variant values, keys, and IDs.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of components to return to prevent token bloat (default: 30) | |
| query | No | Search query to filter components by name, description, or variant name (optional, if empty returns all top components) | |
| target | No | fileName of a specific connected Figma document, when more than one is open (see figma_list_targets). | |
| page_name | No | Optional page name filter (e.g. '🎨 Design System' or 'Components') | |
| refresh_index | No | Force a fresh scan instead of using the cached component index (normally at most 60s stale — see figma_read_canvas / instructions for how the index works). | |
| include_variants | No | Whether to collect and return all available variant property keys and values (default: true) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and closed-world, so the safety profile is covered. The description adds genuinely new behavior: it enumerates what comes back (names, variant values, keys, IDs) and states the context-protection intent, which matters because there is no output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the verb and resource scope, then the distinguishing constraint and return payload. Nothing is redundant with the title or schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a six-optional-parameter, zero-required read tool with no output schema, the description covers scope and return shape adequately, and cache/index details are correctly delegated to the schema and instructions. Pagination or result-count behavior beyond the limit parameter is not addressed, keeping it from a 5.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter including caching semantics and the variants toggle is already documented. The description adds no syntax, format, or default information beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Uses a specific verb ('Find and inspect') with an enumerated resource set (components, component sets, variants, property definitions) scoped to the active Figma file, which distinguishes it from single-node figma_inspect and from figma_get_variables. It stops short of naming a sibling alternative explicitly, so it lands at 4 rather than 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the goal statement ('without flooding LLM context') and by the schema pointing to figma_list_targets for the target param and figma_read_canvas for index behavior. The description itself gives no explicit when-to-use / when-not-to-use guidance or named alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_get_canvas_layoutARead-onlyIdempotent
Inspect top-level frames and artboards on the active Figma page to prevent overlap. Returns all screen coordinates, bounding box, and a calculated 'suggestedNextPosition' for placing new artboards safely.
| Name | Required | Description | Default |
|---|---|---|---|
| gap | No | Spacing in pixels between artboards (default: 80) | |
| limit | No | Maximum number of artboards to list, to prevent token bloat on pages with hundreds of frames (default: 200) | |
| layout | No | 'row' (default) places along one axis per `direction`, like before. 'grid' shelf-packs into a `columns`-wide grid so a run of generated screens fills a compact rectangle instead of one long ribbon. | |
| target | No | fileName of a specific connected Figma document, when more than one is open (see figma_list_targets). | |
| columns | No | Column count for layout: 'grid' (default: 4). | |
| direction | No | Placement direction relative to existing screens ('RIGHT' or 'BOTTOM', default: 'RIGHT') |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false and openWorldHint=false, so the safety profile is covered and the bar is lower. The description adds that it returns coordinates, a bounding box and a computed suggested position, but it never clarifies that the layout/gap/columns/direction parameters only shape the *suggestion* and do not mutate the canvas — a real ambiguity for a tool whose name implies layout changes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the purpose followed by the return payload, with zero filler. Nothing in the text is redundant with the schema or annotations.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a six-parameter read tool with no output schema and no annotations gap, the description should at least sketch the shape of the returned frame list and explain the relationship between the layout parameters and the suggestion. It covers the return values at a headline level but leaves the parameter-to-output mechanics and the overlap with sibling read tools unexplained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter including the two enums is already documented in the schema; baseline 3 applies. The description contributes nothing about how gap, layout, columns or direction interact with the suggestedNextPosition calculation, so it adds no meaning beyond the structured fields.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a concrete verb and resource ('Inspect top-level frames and artboards on the active Figma page') and states the derived output ('suggestedNextPosition'), which is far more specific than the tool name alone. It does not, however, distinguish itself from overlapping siblings such as figma_read_canvas or figma_inspect, so an agent cannot tell from the description which one to reach for.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the phrase 'to prevent overlap' and 'for placing new artboards safely', giving a motivation but not a decision rule. There is no explicit when-not guidance and no alternative tool named, even though figma_read_canvas and figma_get_selection are plausible substitutes.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_get_selectionARead-onlyIdempotent
Get information and properties (dimensions, coordinates, text, fills, parent, page, AutoLayout context) of the currently selected nodes on the Figma canvas.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No | fileName of a specific connected Figma document, when more than one is open (see figma_list_targets). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, closed-world and non-destructive, so the bar is lower, but the description still adds value by enumerating what the payload contains (dimensions, coordinates, text, fills, parent, page, AutoLayout context). It does not state what happens when nothing is selected (empty result vs error), which is the main remaining behavioral gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One front-loaded sentence with the verb first and the property list tucked into a parenthetical; nothing is wasted. The parenthetical enumeration is dense but each item carries real information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description must convey return contents, and the property list does that adequately for a read-only, zero-required-param tool. Only the empty-selection behavior and shape of the returned structure are left unspecified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is a single optional parameter whose schema description is fully covered (100%) and already points at figma_list_targets. The description adds nothing beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (get) and resource (currently selected nodes on the Figma canvas) and enumerates the properties returned, which lets an agent distinguish it from selection-agnostic siblings like figma_read_canvas or figma_inspect. It stops short of explicitly contrasting itself with those siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the phrase 'currently selected nodes' – the tool only makes sense when something is selected – but there is no explicit statement of when to prefer this over figma_inspect, figma_read_canvas, or figma_screenshot. No prerequisites or exclusions are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_get_variablesARead-onlyIdempotent
Retrieve all Figma Variable collections, modes (e.g. Light/Dark), and design tokens (colors, numbers, strings, booleans) from the active document.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of tokens to return across all matched collections, to prevent token bloat on large design-token files (default: 300) | |
| target | No | fileName of a specific connected Figma document, when more than one is open (see figma_list_targets). | |
| collection_name | No | Optional filter by variable collection name (e.g. 'Theme', 'Tokens', 'Spacing') |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and closed-world, so safety is covered. The description adds useful framing (scope spans all collections, modes and all four token types) but omits return shape, whether truncated results are signaled, and how the default limit behaves when exceeded.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler; the resource scope lands first and the token-type enumeration is compact and informative.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the burden of describing return content, and it does name collections, modes and token value types. It stops short of describing result structure or truncation behavior at the 300-token default, which would matter on large design-token files.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all three parameters are fully documented in the schema itself (limit default 300, target fileName, collection_name filter). The description adds no syntax, format, or filtering semantics beyond that, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Retrieve) and a precise resource (Figma Variable collections, modes, design tokens) with the token types enumerated. An agent can distinguish it from mutation sibling figma_set_variables_mode or canvas readers like figma_read_canvas without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied — the reader infers 'call this when you need design tokens'. There is no explicit when-to-use, when-not-to-use, or named alternative; the reference to figma_list_targets appears only inside a parameter description, not in the tool description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_insert_component_instanceA
Create and insert an instance of a master component or component set into the canvas or target AutoLayout container. Supports selecting variants, applying text overrides with auto font loading, and can return a PNG screenshot (capture: true) for visual verification.
| Name | Required | Description | Default |
|---|---|---|---|
| scale | No | Screenshot resolution scale (default: 1) | |
| target | No | fileName of a specific connected Figma document, when more than one is open (see figma_list_targets). | |
| capture | No | Whether to capture and return a PNG screenshot of the inserted instance (default: false) | |
| position | No | Optional placement coordinates or child index in AutoLayout container | |
| properties | No | Key-value map of variant properties and component properties to apply (e.g. {'Type': 'Primary', 'Size': 'MD', 'State': 'Default'}) | |
| component_id | No | Direct node ID of the master component or ComponentSet (optional alternative to component_name) | |
| component_name | No | Name of the master component or ComponentSet to instantiate (e.g. 'Button', 'Card', 'Input') | |
| text_overrides | No | Key-value map of text overrides for text layers inside the component (e.g. {'Label': 'Submit', 'Description': 'Confirm order'}) | |
| target_parent_id | No | Target container/frame node ID to insert the instance into. If omitted, inserts into current selected frame or active page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly=false, destructive=false, idempotent=false), and the description adds genuine context beyond them: auto font loading when applying text overrides, the PNG screenshot return path via capture:true, and the AutoLayout insertion target. It stops short of stating what happens on duplicate insertion or undo semantics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two front-loaded sentences with no filler: the first establishes the action and destination, the second enumerates the optional capabilities. Nothing redundant with the schema is repeated.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 9-parameter, zero-required, nested-object tool with no output schema, the description covers the outcome (inserted instance) and notes the optional PNG return, which substitutes for missing return documentation. It omits multi-document targeting and placement fallback behavior, but those are covered in the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all nine parameters including nested position/properties are documented in the schema, which sets the baseline at 3. The description adds only marginal meaning beyond that: it names variant selection and auto font loading for text_overrides, but does not clarify position/index behavior or scale semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: create and insert an instance of a master component or component set into canvas or an AutoLayout container. This distinguishes it implicitly from figma_insert_svg (SVG content) and figma_find_components (discovery), though no sibling is named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied by the description ('insert an instance... into the canvas or target AutoLayout container'). It notes capture:true for visual verification but never says when to prefer this over figma_find_components for discovery or figma_insert_svg for raw assets, and gives no prerequisites or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_insert_svgA
Insert raw SVG/vector code directly into Figma canvas or target AutoLayout container with automatic scale-proportional resizing, fill/stroke color overrides, optional component creation, and an optional PNG screenshot (capture: true).
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Optional layer name for the created SVG node (e.g. 'Icon / Shield', 'Brand / Google') | |
| scale | No | Screenshot resolution scale factor (default: 2.0) | |
| width | No | Desired width in pixels (e.g. 24, 32, 48) | |
| height | No | Desired height in pixels (e.g. 24, 32, 48) | |
| target | No | fileName of a specific connected Figma document, when more than one is open (see figma_list_targets). | |
| capture | No | Whether to capture and return a PNG screenshot of the inserted SVG (default: false) | |
| position | No | Optional placement coordinates or child index in AutoLayout container | |
| svg_code | Yes | Raw XML/SVG string (e.g. '<svg xmlns="..." viewBox="0 0 24 24">...</svg>') | |
| as_component | No | Whether to wrap the resulting SVG node into a reusable master ComponentNode (default: false) | |
| fill_override | No | Specific fill color override (Hex e.g. '#FFFFFF' or RGB) applied to vector shapes with non-empty fills | |
| color_override | No | Universal color override (Hex '#6366F1' or RGB) applied to all active fills and strokes | |
| stroke_override | No | Specific stroke color override (Hex e.g. '#6366F1' or RGB) applied to vector paths with non-empty strokes | |
| target_parent_id | No | Target container/frame node ID to insert the SVG into. If omitted, inserts into current selected frame or active page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare non-readOnly, non-destructive, non-idempotent, and closed-world behavior. The description adds useful context beyond annotations: automatic scale-proportional resizing, fill/stroke overrides, optional component creation, and optional PNG screenshot return. It does not mention permission requirements or effects on existing canvas selection.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence that names the core action and key options without filler. It is dense but every clause maps to a real capability or parameter.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex 13-parameter tool with a nested position object and no output schema, the description plus full schema coverage is sufficient for correct invocation. It omits what the tool returns beyond the optional PNG screenshot, but annotations and schema carry the remaining safety and parameter detail.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all 13 parameters thoroughly. The description mentions overrides, component creation, capture, and AutoLayout placement, but mostly restates capabilities already covered by the schema and adds no precedence rules for competing color overrides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Insert) and resource (raw SVG/vector code) and scopes it to the Figma canvas or a target AutoLayout container. It does not explicitly compare itself to related tools such as figma_insert_component_instance, so sibling differentiation is indirect.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides no explicit when-to-use or when-not-to-use guidance and does not name alternatives like figma_insert_component_instance or figma_execute_code. Usage is only implied by the tool's action and optional features.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_inspectARead-onlyIdempotent
READ the live Figma document in ONE call — the tool for any read (not figma_execute_code); pass every node id you need at once instead of one call per node. Default: a compact outline, one line per node (TYPE "name" #id WxH @x,y [V gap8 pad16 fill/hug a:start/center] size:fill/hug fill:#FFF stroke:#E8EAF0/0,1,1,1 r0,0,3,3 shadow:… font "text…"; non-defaults only; a TEXT named after its text drops the name; a:P/C = primaryAxisAlignItems/counterAxisAlignItems, start = MIN, center = CENTER, end = MAX, between = SPACE_BETWEEN, absent = MIN/MIN), as deep as fits the reply unless depth is given; children:N marks a node with more below. like: "<ref id>" (or several) FINDS every copy of the reference under node_ids (screens/sections; default: its section) — instances of the same component, or same name — and diffs each against it: the call for "redo these like the reference" when you don't know where the copies are. compare: "<ref id>" lists, per node_id, every difference from that reference (layout, sizing, stroke, radius, effects, clip, font, variant; children matched by name) and ends with REF lines, the reference's exact values to copy into the write (no props read needed) — one call for "make these like that one", and the check after the write. props returns exact values instead: { id: { prop: value } } (also fill, stroke, text, font, layout, padding, parent, children, main, variant, props, absolute, reactions, connector). find searches node names under node_ids (or the current page); find_text searches text content. view: "map" = canvas map (sections, breakpoints). view: "flow" = the prototype links under node_ids (a section or screens): per screen, source, trigger, action, target, transition, plus the overlay settings of overlay targets — never scan the page for reactions. context: true adds ancestor sections, breakpoints and component variants. offset skips the first N outline lines when a reply ends with pass offset=K. check returns only mismatches. Combine them freely. Changes nothing.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | No | Alias of node_ids. | |
| find | No | Case-insensitive substring of node names to search for under node_ids (or the current page). Up to 8 matches come back with their subtree outline (as deep as fits, no extra read needed); more matches as one line each. | |
| like | No | Reference node id (several: comma-separated): find its copies under node_ids (default: the reference's top section) and list, per copy, its frame and how it differs (missing children come with the reference's own line, and REF lines at the end give the reference's exact values, so no extra read is needed). Copies that already match are listed as identical. | |
| view | No | "outline" (default) = one line per node; "map" = canvas map: sections, frames, breakpoints and component sets in a few lines; "table" = per table (found by structure) the columns: header, width, sizing, cell contents, plus row and cell ids; "flow" = prototype links (screen, source, trigger, action, target, transition, overlay settings) under node_ids (without node_ids: every top-level screen of the current page). | |
| check | No | Expectations to verify: { "12:34": { "width": 320, "fill": "#FFFFFF", "layout": "V gap8 pad16" } }. Returns { pass, fail: [{ id, key, want, got }], missing }. | |
| depth | No | Outline levels below each node (0 = the nodes only, max 6). Omit it: the outline goes as deep as fits the reply. | |
| limit | No | Max find matches (default 30). | |
| props | No | Return these properties per node instead of an outline, e.g. ["width", "layoutSizingHorizontal", "fill", "text"]; also "reactions" (prototype interactions) and "connector" (FigJam connector ends). | |
| offset | No | Skip the first N lines of the outline / found list (use the K from a '… pass offset=K' line to read the next page). | |
| target | No | fileName of a specific connected Figma document, when more than one is open (see figma_list_targets). | |
| compare | No | Reference node id: instead of an outline, list how each node_id differs from it (x/y/width and text content are skipped; height, stroke sides/align are compared). Ends with REF lines: the exact values of the differing reference nodes, to copy in figma_execute_code without a props read. 'identical' = nothing to fix. | |
| context | No | Also return, per node: ancestor sections, breakpoint siblings and component variants ({ id: context }). | |
| node_id | No | Alias of node_ids for one id. | |
| node_ids | No | Node ids to read ("12:34" or "12-34"). Omit to use the current page. | |
| find_text | No | Case-insensitive substring of TEXT content to search for under node_ids (or the current page). One line per match: #id "layer" «text» in <parent layer #id>, screen "<top frame>" (the parent is the frame to click or edit). | |
| find_type | No | Restrict find to one node type, e.g. FRAME, TEXT, INSTANCE. | |
| max_output_bytes | No | Cap on the text response in UTF-8 bytes (default 3500; in clients that spill big outputs to a file, 0 and values above 3900 become 3900). A cut outline ends with '… pass offset=K': use `offset` to page instead of raising this. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, and the description confirms with "Changes nothing." rather than contradicting. Beyond that it discloses non-obvious behavior the annotations can't: the default is a truncated compact outline, truncation ends with "… pass offset=K", and max_output_bytes caps spill at 3900 — the things that actually bite an agent on a read tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded correctly — the one-call, use-this-not-figma_execute_code rule is the first clause. But the bulk is a single run-on paragraph cramming an outline format legend, alignment abbreviations, and five mode definitions into one block, which is hard to scan and partly duplicates the schema descriptions.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 17-param, nested-schema, no-output-schema tool this is nearly exhaustive: default mode, each alternative mode, pagination, size caps, document targeting via target/figma_list_targets, and the exact shape of what comes back. An agent can call it correctly without consulting any other source.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents all 17 params. The description adds real meaning on top: the outline line grammar (TYPE "name" #id WxH @x,y, a:P/C mapping to MIN/CENTER/SPACE_BETWEEN, fill/hug), the REF-line payload of compare, and the ids-at-once batching rule. The inline legend is arguably output semantics more than parameter semantics, which keeps this off a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ("READ the live Figma document") and immediately differentiates from the sibling write path ("not figma_execute_code"). The mode verbs (like, compare, props, find, find_text, view out/map/flow, check) are each given a concrete job, so an agent can pick a mode without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit routing rules: "the tool for any read (not figma_execute_code)", "pass every node id you need at once instead of one call per node", and "never scan the page for reactions". It also names the exact intent each mode serves ("redo these like the reference" for like, "make these like that one" plus post-write check for compare).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_job_statusARead-only
Wait for a figma_execute_code call that came back as { status: 'running', job_id } (it ran past 45s, or was called with async: true). BLOCKS until the job finishes or wait_ms passes, then returns the same result/screenshot the synchronous call would have — so call it once, not in a polling loop. stalled: true means the plugin looks frozen: STOP, ask the user to check Figma; a second figma_job_status for that job returns at once with the same advice. A finished job is forgotten after being read once.
| Name | Required | Description | Default |
|---|---|---|---|
| job_id | Yes | The job_id from figma_execute_code's { status: 'running', job_id } response. | |
| wait_ms | No | How long to block waiting for the job to finish (default: 45000, max: 55000; 0 = just peek). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses that the call BLOCKS, that it returns the same result/screenshot a synchronous call would, that stalled:true means the plugin may be frozen, that a repeat call short-circuits with the same advice, and that a finished job is forgotten after one read. These are non-obvious behavioral traits (blocking + single-read retention) not captured by readOnlyHint/idempotentHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the triggering condition and the blocking behavior, then layers the operational rules (no polling, stalled handling, retention). Dense but every clause carries actionable information with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, yet the description explains what is returned (same result/screenshot as the synchronous call) and covers the stalled edge case and read-once retention. An agent has everything needed to call and interpret it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so job_id origin and wait_ms default/max/peek semantics are already documented in the schema. The description reinforces job_id's provenance from figma_execute_code's running response but adds nothing about wait_ms, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific action (wait/block for a job) tied to a specific resource (a figma_execute_code job_id) and names the sibling tool that produces the job_id. An agent can immediately distinguish it from figma_execute_code or other read tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use it (after figma_execute_code returns status 'running' due to 45s timeout or async:true) and gives a hard usage rule: 'call it once, not in a polling loop.' It also adds the stalled-case escalation path (stop and ask the user), which is a genuine when-not-to-continue instruction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_list_targetsARead-onlyIdempotent
List every Figma document currently connected to this bridge (fileName, current page, which one is focused). Use this when a LIVE tool call fails with AMBIGUOUS_TARGET, or before working with a specific file among several open at once — pass the fileName as target on any LIVE tool.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, closed-world, non-destructive, so no credit is needed for safety. The description adds real value beyond them by naming the returned fields (fileName, current page, focused) and the cross-tool contract for `target`. It stops short of covering edge cases such as what happens when zero documents are connected.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no filler. The resource and its returned fields come first, and the actionable guidance follows immediately.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description compensates by enumerating the returned fields and explaining how the output feeds into other tools. For a zero-parameter discovery tool, nothing an agent needs in order to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Zero parameters, so baseline is 4. The description instead documents the `target` parameter semantics of the downstream LIVE tools, which is useful but does not affect this tool's own schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("List every Figma document currently connected to this bridge") plus the exact fields returned (fileName, current page, focused). It is clearly distinguishable from siblings like figma_get_selection or figma_inspect, which operate on content rather than the connection registry.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives two explicit triggers: recovering from an AMBIGUOUS_TARGET failure, and proactively disambiguating when several files are open. It also closes the loop by telling the agent what to do with the result — pass the fileName as `target` on any LIVE tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_read_canvasARead-onlyIdempotent
Read the LIVE, currently-open Figma document as token-optimized Pseudo-JSX/Tree/JSON — the same pipeline get_file/get_node use for the cloud API, applied to whatever is open in Figma Desktop right now. Prefer this over hand-writing a tree walk in figma_execute_code; it is far cheaper in tokens and its output format matches get_file/get_node exactly.
| Name | Required | Description | Default |
|---|---|---|---|
| depth | No | Traversal depth from each requested node, hard-capped at 12 (default: 6). | |
| format | No | Output format — same meaning as get_file/get_node (default: 'jsx'). | |
| target | No | fileName of a specific connected Figma document, when more than one is open (see figma_list_targets). | |
| node_ids | No | Comma-separated node IDs to read. Omit to read the top-level frames of the current page. | |
| budget_tokens | No | Target response size in tokens (default: 4000). If the requested depth overshoots this, depth is reduced and re-serialized (no extra round trip) until it fits, with a trailing comment noting the reduction. | |
| include_hidden | No | Whether to include hidden (visible=false) layers (default: false). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the bar is lower, and the description still adds real context: it reads live desktop state rather than cloud state, output format matches get_file/get_node, and token cost is bounded. It does not mention failure behavior when no document is open or how target resolution errors surface, which keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the distinguishing fact (LIVE document) before the comparison to siblings. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Six optional parameters with full schema coverage and no output schema, and the description covers the live-vs-cloud distinction, format parity and token budgeting. Minor gaps remain around multi-document targeting and no-document-open behavior, but nothing critical for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so depth, format, target, node_ids, budget_tokens and include_hidden are all already documented. The description reinforces that the output format semantics are identical to get_file/get_node, which helps interpret the format enum, but adds no new per-parameter detail beyond the schema baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (read) and a precisely scoped resource (the LIVE, currently-open Figma document) with the output shape (Pseudo-JSX/Tree/JSON). It also distinguishes itself from the cloud-API siblings get_file/get_node and from figma_execute_code, so an agent can pick it without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says to prefer this over hand-writing a tree walk in figma_execute_code and gives the reason (cheaper, format parity). It does not spell out the complementary case (use get_file/get_node when the document is not open locally) or point to figma_list_targets for multi-document targeting in the prose, so the routing guidance is clear but not exhaustive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_rollbackADestructive
Undo what a previous write call (figma_execute_code, figma_insert_component_instance, figma_insert_svg) did: removes nodes it created and restores properties on nodes it modified. Deletions the code performed on pre-existing nodes are never recoverable. Every write call's response includes the checkpoint_id to pass here.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No | fileName of a specific connected Figma document, when more than one is open (see figma_list_targets). | |
| checkpoint_id | No | The checkpoint_id from a previous write call's response. Omit (or pass "last") to roll back the most recent not-yet-rolled-back checkpoint. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare destructiveHint=true and idempotentHint=false, but the description adds crucial behavioral detail: it removes nodes created by the write and restores modified properties, and deletions of pre-existing nodes are never recoverable. This gives the agent precise expectations about what rollback can and cannot undo, beyond the structured annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the core action and immediately followed by scope and irreversibility constraints. Every sentence carries useful information, and the checkpoint_id prerequisite is placed naturally at the end.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the destructive annotations, complete input schema, and absence of an output schema, the description supplies everything needed: what rollback does, which write calls it covers, what it cannot restore, and where checkpoint_id comes from. No essential behavioral or usage context is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters are already documented. The description reinforces that checkpoint_id comes from a previous write call's response, but it does not add syntax or selection rules beyond what the schema already states. The baseline of 3 is appropriate when schema coverage is complete.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses the specific verb 'Undo' and precisely scopes it to previous write calls, naming the sibling write tools it applies to. It also states exactly what is affected (created nodes removed, modified properties restored), so the agent can distinguish it from all other siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly explains the intended context: undoing a previous figma_execute_code, figma_insert_component_instance, or figma_insert_svg call. It also states the prerequisite that every write call returns a checkpoint_id to pass here. It does not explicitly name when not to use it beyond the irrecoverable-deletion warning, so it falls short of full when/when-not/alternative guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_screenshotARead-onlyIdempotent
Capture PNG screenshots of specific nodes or the current selection in Figma, to check layout, contrast, typography and spacing. Each image costs ~1k tokens at the default max_px, and stays in context: check mechanical things through write-call warnings or bridge.check first, and take one screenshot per finished stage rather than after every edit. Right after a figma_execute_code edit, put capture_node_ids on that call instead — this tool is then an extra turn.
| Name | Required | Description | Default |
|---|---|---|---|
| scale | No | Export resolution scale factor (default: 1). | |
| max_px | No | Longest side of each image in px (default: 1024). Raise only to read fine detail; crop with node_ids instead where possible. | |
| target | No | fileName of a specific connected Figma document, when more than one is open (see figma_list_targets). | |
| node_ids | No | Optional comma-separated list of Figma node IDs to screenshot (e.g. '123:456, 123:457'). If omitted, captures current selection or entire page. | |
| description | No | Optional action description for Figma toast and logs. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only/idempotent, but the description adds genuinely non-obvious behavior: each image costs ~1k tokens at default max_px and stays in context, plus the advice to capture at stage boundaries. That cost/context-persistence disclosure is exactly the kind of thing an agent cannot infer from structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the action and purpose, then cost implications, then the alternative-call routing. No filler; every clause carries operational information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-required-parameter capture tool with a fully described schema and annotations covering safety, the description supplies the remaining decision-relevant context: cost per call, context persistence, and the preferred sibling path. Nothing needed to call it correctly appears missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema descriptions already explain scale, max_px, target, node_ids and description in detail, so the description adds little parameter-level detail. Its mention of default max_px reinforces cost but does not decode any parameter beyond what the schema states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Capture PNG screenshots of specific nodes or the current selection in Figma') plus the intent (layout, contrast, typography, spacing check), which separates it cleanly from siblings like figma_inspect, figma_read_canvas and figma_get_selection.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use and when-not-to-use guidance: prefer write-call `warnings` or bridge.check for mechanical checks, take one screenshot per finished stage rather than after every edit, and use capture_node_ids on figma_execute_code instead of this tool right after an edit. Alternatives and exclusion conditions are both named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_set_variables_modeAIdempotent
Switch the active Figma Variables mode (e.g. Dark Mode, Light Mode, Brand theme) for a specific artboard/frame or the entire page.
| Name | Required | Description | Default |
|---|---|---|---|
| scale | No | Screenshot resolution scale (default: 1) | |
| target | No | fileName of a specific connected Figma document, when more than one is open (see figma_list_targets). | |
| capture | No | Whether to capture a PNG screenshot of the target after switching mode (default: false) | |
| mode_name | Yes | Target mode name to activate (e.g. 'Dark', 'Light', 'Compact') | |
| target_id | No | Target node ID (frame/artboard) to set mode on. If omitted, applies to current selection or active page. | |
| collection_name | Yes | Name of the variable collection (e.g. 'Theme', 'Mode', 'Brand') |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare it non-destructive, idempotent, and not open-world, so the safety profile is covered. The description adds scoping (specific node vs entire page) but omits notable behaviors visible in the schema such as the optional screenshot capture side effect and what happens if the mode/collection is not found.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler; examples are compact and relevant. Slightly under-informative rather than verbose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema and full schema coverage mean the description needn't explain returns. For a non-destructive, idempotent state-change tool it covers purpose and scope adequately, though it could note prerequisites (connected document, existing collection/mode).
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all six parameters are already documented. The description only restates the mode concept and scope split, adding no syntax, naming, or format detail beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Switch the active Figma Variables mode') plus scope (artboard/frame or entire page), with concrete mode examples. Distinguishable from the read-only sibling figma_get_variables, though it doesn't name it.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied through the Dark/Light/Brand examples and the artboard-vs-page scope, but there is no explicit when-to-use guidance, no mention of consulting figma_get_variables to discover mode names or figma_list_targets to pick a document.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
14 tool updates
v0.1.0- First observed
figma_execute_code - First observed
figma_find_components - First observed
figma_get_canvas_layout - First observed
figma_get_selection - First observed
figma_get_variables - First observed
figma_insert_component_instance - First observed
figma_insert_svg - First observed
figma_inspect - First observed
figma_job_status - First observed
figma_list_targets - First observed
figma_read_canvas - First observed
figma_rollback - First observed
figma_screenshot - First observed
figma_set_variables_mode
TDQS
Scored across 14 tools
Several read-oriented tools overlap: figma_inspect, figma_read_canvas, figma_get_selection, and figma_find_components all inspect live document content, and figma_inspect itself claims to be the tool for any read. figma_screenshot also overlaps with the capture option on write calls. Descriptions give strong guidance, but an agent could still hesitate between plausible read paths.
All tools share the figma_ prefix and most follow a verb_noun pattern such as figma_get_selection, figma_find_components, and figma_insert_svg. Minor deviations include noun-like names (figma_screenshot, figma_job_status) and mixed read verbs (inspect, read, get, find), but the set remains predictable.
14 tools is well within a reasonable range for a Figma bridge that spans reading, writing, component insertion, variables, screenshots, rollback, and async job handling. Each tool has a plausible role, and the count does not feel bloated.
The surface covers a broad design-editing lifecycle: live inspection, arbitrary writes, component and SVG insertion, variables, screenshots, rollback, and job status. Some operations such as explicit export, selection mutation, or variable creation are not first-class, though figma_execute_code can handle them as workarounds.
Maintenance
Related MCP Connectors
Live React design-system APIs, patterns, and code validation so AI agents build real UI, not slop.
Create and edit architecture diagrams from your AI agent; get an SVG and a live editable canvas.
Headless browser primitives for AI agents when sites need real JS rendering.
Hosted browser for AI agents: screenshots, post-JS DOM, console, WCAG. No install, no API key.
Related MCP Servers
- AlicenseAqualityBmaintenanceEnables AI agents to read and draw on Figma canvas safely, with built-in safeguards for layout, overlays, and verification.5104MIT
- AlicenseNot gradedqualityBmaintenanceFast, quota-free Figma automation for coding agents, enabling AI agents to read, edit, migrate, audit, screenshot, and prototype inside Figma Desktop files.9MIT
- AlicenseNot gradedqualityBmaintenanceEnables MCP-compatible AI clients to read and modify the user's currently open Figma file by executing JavaScript in Figma's sandbox, all through a local bridge with status monitoring, node jumping, and automatic rollback on errors.1MIT
- AlicenseNot gradedqualityCmaintenanceEnables a locally run agent or script to read and write a real Figma layer tree through a local bridge — inspecting node structure and variables, exporting screenshots into the model's context, and performing batched create/update/move/rename/delete operations that collapse into a single undo step. All traffic stays on localhost between the bridge and the Figma plugin, with design-token auditing, binding, and creation included.1 npmMIT