Skip to main content
Glama

figme — read local Figma .fig files from an AI agent

figme is an MCP server that lets an AI agent read everything inside a local .fig / .figma file — document structure, geometry, fills, strokes, effects, auto-layout, text (including mixed-format runs), components and instances, variables, prototype links and embedded bitmaps.

It is fully offline. No Figma account, no access token, no REST API, no network at runtime. It parses the file's own bytes, using the Kiwi schema that Figma ships inside every .fig.

It is also token-aware: the reference file used to develop it holds 116,142 nodes, and no tool response ever exceeds ~20 KB. Everything is shallow by default, filterable, and paginated with cursors.

you: "what does the tab component in design.fig look like?"

fig_overview  → 10 pages, 2,046 components, 273 variables, 212 images
fig_find      → "lv2/tab/large" is 2:1337, on page "Page 1"
fig_style     → display:flex, direction:row, gap:8, padding:"8px 16px",
                cornerRadius:4, stroke #FFFFFF bound to variable "tab/large/underline"
                (active #FFFFFF / inactive #333333)

Non-goals

These are deliberate, permanent limits — not missing features:

  • Rendering is best-effort, not pixel-perfect. A .fig contains no rendered pixels of your frames, but it does contain everything needed to draw them again: Figma bakes outlined strokes, combined booleans, per-glyph outlines and per-instance geometry into the file at save time. fig_render uses that to produce a real picture offline — see Rendering for exactly what is exact and what is approximated. It is not a screenshot of Figma and never will be: read the report before trusting fine detail.

  • No writing. Nothing is ever written back into a .fig. The only write paths in the whole server are fig_image { savePath } and fig_render { savePath }, which write to a path you name.

  • No Figma API and no network. Nothing here talks to figma.com. Library assets published from other files (styles, variables, components) cannot be resolved offline; they come back as their opaque assetRef so you can see that they exist and where they point.

  • No vector-network decoding (v1). Vector geometry lives in a separate binary blob format. fig_node reports the blob indices and fig_blob hands you the raw bytes, but this server does not interpret them.

  • Not a diffing or version-history tool. A saved .fig is a full snapshot, not a delta.

Related MCP server: ai-ready-ds-auditor

Requirements

  • Node.js ≥ 22.15 (needs zlib.zstdDecompressSync; developed on Node 24).

  • Runtime dependencies: @modelcontextprotocol/sdk and zod. The parser itself uses only Node built-ins.

Install

figme is published on npm, so there is nothing to clone and nothing to build — your MCP client downloads it on first start with npx.

You need two things:

  • Node.js >= 22.15 (see Requirements above).

  • A .fig file on disk. This server reads a local file and never contacts figma.com, so there is no account, token or sign-in — but there is also nothing to read until you save one. In Figma: File -> Save local copy....

The part every client shares

Nearly every MCP client spawns a stdio server from the same two fields:

{ "command": "npx", "args": ["-y", "figme-mcp"] }

On Windows, some clients cannot resolve npx on their own. If the server fails to start, route it through cmd:

{ "command": "cmd", "args": ["/c", "npx", "-y", "figme-mcp"] }

Claude Code

claude mcp add figme -- npx -y figme-mcp           # this project
claude mcp add -s user figme -- npx -y figme-mcp   # every project

Or commit a .mcp.json at the repository root so collaborators get it too:

{
  "mcpServers": {
    "figme": {
      "command": "npx",
      "args": ["-y", "figme-mcp"]
    }
  }
}

The Claude Code extensions for VS Code and JetBrains run Claude Code underneath and share its configuration: register the server once with the command above and the extension sees it. They do not read the editor's own MCP settings.

Cursor

~/.cursor/mcp.json for every project, or .cursor/mcp.json for a single one:

{
  "mcpServers": {
    "figme": {
      "command": "npx",
      "args": ["-y", "figme-mcp"]
    }
  }
}

VS Code — GitHub Copilot agent mode

VS Code uses its own key, servers rather than mcpServers, in .vscode/mcp.json:

{
  "servers": {
    "figme": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "figme-mcp"]
    }
  }
}

The same entry works in your user settings.json under "mcp". From a terminal:

code --add-mcp '{"name":"figme","command":"npx","args":["-y","figme-mcp"]}'

Then pick Agent mode in the Chat view.

Windsurf

~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "figme": {
      "command": "npx",
      "args": ["-y", "figme-mcp"]
    }
  }
}

Anything else

Spawn npx -y figme-mcp and talk MCP over stdio.

Client UIs and config paths move between releases. The command and args pair above is the stable part; if a path here does not match what you see, check that client's own MCP documentation.

Two things to know before the first call

Use absolute paths. A file argument may be relative, but it resolves against the server's working directory — whichever directory your client happened to launch it from. An absolute path removes the guesswork:

Using figme, run fig_overview on /Users/me/Desktop/design.fig

Watch memory. --max-files N (default 4) caps how many parsed files stay cached. A 39 MB .fig decodes to roughly 900 MB of live objects, so lower it on a small machine and raise it only with memory to spare:

{ "command": "npx", "args": ["-y", "figme-mcp", "--max-files", "1"] }

The usual job: implement this component from our design, starting from a link someone pasted into a ticket.

1. Save the file locally

This server reads a .fig on your disk and never contacts figma.com, so a link by itself is not enough. Open it in Figma and use File -> Save local copy.... For a Community file, click Open in Figma first — that duplicates it into your drafts, which is what makes the copy possible.

https://www.figma.com/design/<file key>/<slug>?node-id=3017-121&t=<share token>
                             ~~~~~~~~~~                ~~~~~~~~
                             which file                which node

Figma writes node ids with a dash in links; the .fig format uses a colon, so node-id=3017-121 is guid 3017:121. You do not have to convert it yourself — every guid argument accepts all of these:

You pass

Server reads

3017:121

3017:121

3017-121

3017:121

3017%3A121

3017:121

node-id=3017-121

3017:121

the whole https://www.figma.com/design/...?node-id=3017-121

3017:121

Anything else is passed through untouched, so a typo still fails loudly rather than being guessed at.

The file key is a cloud identifier with no counterpart in the saved file, so nothing can work out which local .fig a link refers to. Always give the path yourself.

3. Ask for the component

Using figme, read /abs/path/UX Case Study Template.fig and implement node 3017:121 as a React component.

A good agent then works roughly in this order:

  1. fig_render — see it. The fastest orientation there is; check the approximated and unsupported lists before trusting fine detail.

  2. fig_node — size, corner radii, auto-layout, constraints, children.

  3. fig_style — resolved fills, strokes, effects and typography, already shaped for code.

  4. fig_text — the exact copy, including per-run styling.

  5. fig_instance — if the node is an INSTANCE, what it came from and what is overridden. This is what decides reusable component against one-off.

  6. fig_variables — token names, so the code references your theme instead of raw hex.

  7. fig_render again, and compare it against a screenshot of what you built.

That last step is why the renderer exists: you get a pixel oracle, not just a description.

If the guid does not resolve

Node ids are intrinsic to the document, so the id in the link should be the id in the saved file. If it is reported missing anyway you are most likely in the wrong file — compare fig_overview's document name with the link's slug — or find the layer by name with fig_find, or browse the page with fig_tree.

A Figma URL is auth-gated and rendered by JavaScript, so fetching it yields nothing useful. Worse, the slug reads like a description, which is enough for a model to invent a plausible component and present it with confidence. The server says as much to every agent at connect time; if yours reaches for the web regardless, tell it not to.

From source

For development, or to run a revision that is not published yet:

git clone https://github.com/ntson9p/figme-mcp.git
cd figme-mcp
npm install
npm run build      # tsc -> dist/
npm test           # builds, then runs the full node:test suite

Register node /abs/path/to/figme-mcp/dist/mcp/server.js in place of npx -y figme-mcp. This repository ships a .mcp.json that already does so for Claude Code.


Tools

Every tool takes file (path to the .fig). Node references are guid strings of the form "sessionID:localID", e.g. "2:1339". Responses that were cut set truncated: true and return an opaque nextCursor you can pass back.

The intended workflow: fig_overviewfig_tree a page → fig_node / fig_style a guid, with fig_find to jump straight to something by name or copy, and fig_render whenever seeing the thing is faster than reading it.

1. fig_overview — orient yourself

Document name, export date, format version, node counts by type, the page list, and how many components / variables / images the file holds.

// → fig_overview { "file": "figma-input/sample.fig" }
{
  "name": "Sample Design", "formatVersion": 106, "nodes": 116142,
  "pages": [ { "guid": "0:2", "name": "Page 1", "children": 1137 }, /* … */ ],
  "nodeTypes": { "INSTANCE": 38164, "FRAME": 32160, "TEXT": 16894, /* … */ },
  "components": 2046, "variables": 273, "images": 212, "blobs": 9651
}

2. fig_tree — explore structure

root (default DOCUMENT), depth (default 2, max 6), types filter, format, cursor. Returns a flat list in document order; each entry has depth (relative to the root) and parent, so the hierarchy is reconstructable, plus children (a count) so you can see where it is worth going deeper.

// → fig_tree { "file": "…", "root": "2:1339", "depth": 3, "format": "outline" }
root 2:1339 "Frame 39" depth<=3
[FRAME] 134x40 "Frame 39" (2:1339) x4
  [INSTANCE] 16x16 "lv1/ic/setting" (2:1340)
  [TEXT] 64x24 "text" (2:1341)
  [INSTANCE] 6x6 "lv1/ic/arrow-down" (2:1342)
  [FRAME] 28x24 "Frame 6" (2:1343) x1
    [INSTANCE] 28x22 "lv2/notification" (2:1344)

format: "outline" is roughly 4× denser than JSON and is the best way to browse.

3. fig_node — inspect one node

detail is summary, full (default) or raw.

// → fig_node { "file": "…", "guid": "2:1339" }
{
  "guid": "2:1339", "type": "FRAME", "name": "Frame 39",
  "page": "Page 1", "path": "Page 1 / lv2/tab/large",
  "geometry": { "width": 134, "height": 40, "x": 0, "y": 0, "absoluteX": 0, "absoluteY": 0 },
  "cornerRadius": 4, "strokeWeight": 1,
  "strokes": [ { "type": "SOLID", "color": "#FFFFFF",
                 "colorVar": { "variable": "tab/large/underline", "guid": "2:1319",
                               "values": { "active": "#FFFFFF", "inactive": "#333333" } } } ],
  "autoLayout": { "mode": "HORIZONTAL", "spacing": 8,
                  "padding": { "top": 8, "right": 16, "bottom": 8, "left": 16 },
                  "primaryAlign": "CENTER", "counterAlign": "CENTER" },
  "children": [ { "guid": "2:1340", "type": "INSTANCE", "name": "lv1/ic/setting", "size": "16x16" } ]
}

detail: "raw" returns the decoded Figma record verbatim (bytes as hex, int64 as strings). It is the forward-compatibility escape hatch: anything the mappers do not understand yet is still reachable there. Limited to one node per call.

4. fig_find — search names and copy

query (case-insensitive substring, matched against layer names and text content), plus optional types, scope, limit, cursor. Omit query to list all nodes of some types.

// → fig_find { "file": "…", "query": "sample", "types": ["TEXT"], "limit": 3 }
{ "totalMatches": 1428, "returned": 3, "results": [
  { "guid": "8917:139951", "type": "TEXT", "name": "#number1", "size": "224x24",
    "matchedOn": "text", "page": "Page 1",
    "path": "Page 1 / Popup/Variant 7 / Frame 2608806 / …",
    "text": "Sample notification text" } ] }

5. fig_text — copy inventory

All text in the file or in one scope, in document order, with a compact style block. includeRuns: true adds the styled runs — the mixed-format spans Figma stores per UTF-16 code unit — each showing only the fields it overrides.

// → fig_text { "file": "…", "scope": "2:7098", "includeRuns": true }
{ "totalTextNodes": 2, "texts": [
  { "guid": "2:7099", "name": "✏️  Time", "characters": "Yesterday 9:41",
    "page": "Page 1", "hasStyledRuns": true,
    "style": { "font": "SF Pro Text Regular", "size": 11, "lineHeight": "13px", "color": "#3C3C43" },
    "runs": [ { "start": 0, "end": 9,  "text": "Yesterday", "styleID": 12,
                "style": { "styles": { "text": { "name": "Caption2/Medium" } } } },
              { "start": 9, "end": 10, "text": " ",  "styleID": 10, /* … */ },
              { "start": 10, "end": 11, "text": "9", "styleID": 9,  /* … */ },
              { "start": 11, "end": 14, "text": ":41", "styleID": 10 } ] } ] }

6. fig_style — resolved style, shaped for code

Auto-layout translated into CSS flexbox terms, paints as hex, typography flattened, plus how the node behaves inside its parent's layout.

// → fig_style { "file": "…", "guid": "2:1339" }
{ "style": {
  "guid": "2:1339", "type": "FRAME", "width": 134, "height": 40, "cornerRadius": 4,
  "strokes": [ { "type": "SOLID", "color": "#FFFFFF", "colorVar": { "variable": "tab/large/underline" } } ],
  "strokeWeight": 1, "strokeAlign": "INSIDE",
  "layout": { "display": "flex", "direction": "row", "gap": 8, "padding": "8px 16px",
              "justifyContent": "center", "alignItems": "center", "primarySizing": "fixed" },
  "inParentLayout": { "flexGrow": 1, "alignSelf": "stretch" } } }

For TEXT nodes it also returns typography and resolves shared text/fill styles to the values they define (styles.text.defines).

7. fig_components — the component catalogue

SYMBOL nodes with their component set, property definitions and defaults, and instance counts — most-used first, so the load-bearing parts of the design system come back first.

// → fig_components { "file": "…", "query": "lv2/tab/large" }
{ "totalComponents": 2046, "components": [
  { "guid": "2:1337", "name": "lv2/tab/large", "page": "Page 1",
    "size": "134x40", "instances": 599,
    "propDefs": [ { "name": "show badge(🔴)", "type": "BOOL", "default": false },
                  { "name": "icon", "type": "INSTANCE_SWAP" } ] } ] }

8. fig_instance — how an instance differs from its component

// → fig_instance { "file": "…", "guid": "2:1329" }
{ "instance": { "guid": "2:1329", "name": "lv1/color/GL/#FFFFFF",
                "page": "Page 1",
                "symbol": { "guid": "2:1325", "name": "lv1/color/GL/#FFFFFF", "inFile": true } },
  "overrideCount": 1,
  "overrides": [ { "path": ["0:2528"], "targetGuid": "2:1325", "targetName": "lv1/color/GL/#FFFFFF",
                   "fields": { "size": "22x22", "fillsCleared": true } } ] }

An instance that sets component properties reports them with the names resolved, e.g. propAssignments: [ { "defID": "108:1543", "name": "text", "type": "TEXT", "value": "Back" } ]. A path segment is the target's overrideKey when it has one and its guid otherwise, and a nested path is walked through swapped instances exactly as the renderer expands them.

9. fig_variables — design tokens

Every collection with its modes, and every variable with a value per mode. Alias chains are followed when the target lives in the same file.

// → fig_variables { "file": "…", "query": "tab/large" }
{ "totalSets": 27, "totalVariables": 273,
  "sets": [ { "guid": "2:1312", "name": "active/inactive",
              "modes": [ { "id": "509:1300", "name": "active" }, { "id": "509:1301", "name": "inactive" } ],
              "variableCount": 38 } ],
  "variables": [ { "guid": "2:1313", "name": "tab/large/bg", "type": "COLOR", "set": "active/inactive",
                   "values": { "active": "#FFFFFF", "inactive": "#EEEEEE" } } ] }

10. fig_image — embedded bitmaps

Pass hash (the 40-hex id that fig_node / fig_style report on image paints), or guid to use the images on a node, or hash: "thumbnail" for the document preview. Images ≤ 2 MB come back as viewable image content; larger ones return metadata, and savePath writes the exact bytes to disk.

// → fig_image { "file": "…", "hash": "01ef2f8cd2d276901473acb9ddd7afb2421198e3" }
// [image content] + { "mime": "image/png", "byteLength": 4553, "width": 88, "height": 84 }

11. fig_blob — raw payload bytes

index into the file's blob table (fig_node reports these as vector.networkBlob / vector.fillBlobs), encoding (base64 | hex), maxBytes (default 65536).

// → fig_blob { "file": "…", "index": 16, "maxBytes": 8, "encoding": "hex" }
{ "index": 16, "byteLength": 96, "returnedBytes": 8, "data": "0100000000020080",
  "truncated": true, "blobCount": 9651 }

12. fig_render — a picture of a node

guid (any node, or a page), format (png | svg, default png), scale (default 2), maxSize (longest edge, default 1568), background (transparent | page), savePath, maxNodes (default 20000, counted in layers).

// → fig_render { "file": "…", "guid": "2:1339" }
// [image content, 268x80 PNG]
{ "root": { "guid": "2:1339", "name": "Frame 39", "type": "FRAME" },
  "bounds": { "x": 0, "y": 0, "w": 134, "h": 40 }, "width": 268, "height": 80, "scale": 2,
  "nodesVisited": 9, "nodesDrawn": 8, "svgBytes": 4757, "renderMs": 4.6, "rasterMs": 55.3,
  "unsupported": [], "approximated": [], "format": "png" }

Rendering (fig_render)

Nothing is fetched and no font is needed: Figma stores outlined strokes, combined booleans, per-glyph outlines and per-instance resolved geometry in the file, so the renderer consumes what Figma already computed. The SVG it builds is rasterized by @resvg/resvg-wasm, an optional dependency — with it uninstalled, everything still works and fig_render returns SVG instead of PNG.

Exact: solid fills, linear and radial gradients, image fills in all four scale modes, strokes including inside/outside alignment, boolean operations, text (glyph outlines, per-run colours, underline and strikethrough, truncation with an ellipsis), component instances with their overrides, their component properties (text, visibility, instance swap) and the sizes the enclosing instance gives them, colour and effect styles resolved to their live definition, frame clipping, layer opacity, the fifteen shared blend modes, drop and inner shadows, layer blur, and all three mask types.

Approximated, and always reported: background blur (drawn flat — a backdrop filter cannot see behind an isolated subtree), LINEAR_DODGE and LINEAR_BURN (drawn as screen and multiply), angular and diamond gradients (drawn as their average colour), image crop and image rotation.

Skipped, and always reported: emoji glyphs, FigJam-style nodes (WIDGET, CONNECTOR, SHAPE_WITH_TEXT), text without stored outlines (including a text property whose words have no outlines in the file), and strokes on text.

Fidelity was measured against a Figma export of a 1440×3026 form built from component instances: 0.18 % of pixels differ, all anti-aliasing. That export came from a design that is not public, so it is not distributed here — npm run visual runs levels 1-2 until you supply your own export.

Every response carries unsupported and approximated lists naming the feature and up to five example guids. An empty pair means the renderer believes it drew the node exactly. Exact values always remain available from fig_node, fig_style and fig_text.

There is also a CLI for the same thing:

npm run build
node scripts/render.mjs figma-input/sample.fig 2:1339 out.png --scale 2 --background page

How it stays inside a context window

  • Default response budget 20,000 characters, hard cap 50,000.

  • Never more than 300 nodes per response, and never more than one raw node per call.

  • Trees are shallow by default (depth 2) and every entry carries a child count, so the agent chooses where to spend tokens.

  • Unset fields are omitted, floats are rounded to 2 decimals, colours become #RRGGBB, and sizes collapse to "134x40".

  • Anything cut sets truncated: true and returns an opaque nextCursor; paging is stable because it follows document order.

  • There is deliberately no "dump everything" tool.

How it works

.fig bytes
  ├─ Stage A  container   ZIP? unwrap canvas.fig (+ meta.json, thumbnail.png, images/<sha1>)
  ├─ Stage B  framing     "fig-kiwi" magic, u32 version, length-prefixed chunks
  ├─ Stage C  codec       sniffed per chunk: zstd / raw deflate / zlib / stored
  ├─ Stage D  Kiwi        chunk[0] = the binary SCHEMA, chunk[1] = the data decoded WITH it
  └─ Stage E  tree        rebuild the layer tree from parentIndex + fractional-index order

The decisive detail is Stage D: the schema ships inside the file. Nothing here hardcodes a field id, so Figma's constant schema additions do not break the reader.

src/
  fig/            LAYER 1 — mechanical decode, knows bytes, knows nothing about design
    bytebuffer.ts   Kiwi primitives (varuint, zigzag, the rotated float32, NUL strings)
    zip.ts          central-directory ZIP reader (Figma zeroes the local-header sizes)
    container.ts    container sniffing, chunk framing, per-chunk decompression
    kiwi.ts         binary-schema decode + schema-driven data decode
    imagemeta.ts    image magic-byte + dimension sniffing
    invariants.ts   post-parse checks; warnings, not failures
    parse.ts        the whole pipeline in one call
  model/          LAYER 2 — Figma semantics, never touches bytes
    tree.ts         guid keys, tree build, fractional-index sibling order
    index.ts        FileIndex: by-guid, by-type, by-asset-key, override keys, prop defs, search
    access.ts       typed accessors over open records + presentation helpers
    summarize.ts    node summary / full detail / style block builders
    text.ts         characters + styled-run resolution
    instance.ts     what an instance looks like: identity paths, records, property assignments
    components.ts   symbols, instances, the fig_instance view
    variables.ts    collections, modes, alias chains
  render/         LAYER 2½ — fig_render: node subtree → SVG → (optional) PNG
    export.ts       the traversal; instance.ts / style.ts / bounds.ts / text.ts / paint.ts /
                    effects.ts each own one concern; report.ts the frozen feature vocabulary
  mcp/            LAYER 3 — protocol
    create.ts       server factory (used by the entry point and by tests)
    server.ts       stdio entry point
    respond.ts      budgets, cursors, truncation
    tools/*.ts      one file per tool
  cache.ts        LRU of parsed files, invalidated on mtime/size change

mcp/ and model/ never touch bytes; fig/ knows nothing about Figma semantics.

Testing

npm test              # build + full node:test suite (unit + golden)
npm run typecheck     # type-checks src, test and scripts
npm run smoke         # spawns the built server and walks the demo script over real stdio
npm run crosscheck    # deep-compares our decode against the official kiwi-schema package
  • Unit tests need no asset: Kiwi primitives against a transcribed reference encoder, a synthetic ZIP with data-descriptor entries, fractional-index ordering, the response budgeter, image sniffing, and corrupt-input handling.

  • Golden tests run against figma-input/sample.fig and assert measured values (116,142 nodes, 638 schema definitions, 10 pages, specific node geometry, …). They skip with a clear message if the asset is absent.

  • Fixture identifiers are placeholders. The design this was developed against is not public. Page, component, variable and layer names in this README, in docs/ and in the golden tests were replaced with neutral stand-ins, and node guids were renumbered. The structure and the measured numbers are real; the names are not, so the string assertions will not match your own .fig until you update them.

  • Cross-check decodes the same buffers with Evan Wallace's official kiwi-schema package and deep-compares every field: currently 0 differences across 17,353,242 compared values. It skips cleanly if kiwi-schema is not installed.

tools/fig2json.mjs is the original dependency-free reference CLI that Layer 1 was ported from. It is kept working as a debugging aid:

node tools/fig2json.mjs figma-input/sample.fig /tmp/out
# writes schema.kiwi.txt, nodes.ndjson, tree-outline.txt, meta.json

Dumping schema.kiwi.txt is the fastest way to look up a field this server does not map yet; then read it with fig_node detail:"raw".

Documentation

License

MIT.

Available Tools

12 tools
fig_blobRaw blob bytesA
Read-only

Return the raw bytes of one entry in the file's blob table. Vector geometry, glyph outlines and similar bulk payloads are stored there and referenced by index from fields such as vectorData.vectorNetworkBlob and Path.commandsBlob (fig_node reports these as vector.networkBlob / vector.fillBlobs). This server does not decode the vector-network format — you get the bytes, base64 or hex, truncated to maxBytes with a flag when longer.

ParametersJSON Schema
NameRequiredDescriptionDefault
fileYesPath to the .fig / .figma file (absolute, or relative to the server CWD).
indexYesBlob index, as reported by fig_node `vector.*`.
encodingNoDefault "base64".
maxBytesNoBytes to return before truncating (default 65536).

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint annotation, the description discloses truncation behavior ('truncated to maxBytes with a flag when longer'), output encodings (base64/hex), and the non-decoding limitation. These are meaningful behavioral traits that an agent needs to interpret results correctly.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with zero fluff. The first sentence states the core operation, the second gives context about blob table contents and how indexes are referenced, and the third flags the format and truncation caveat. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description compensates by stating what the caller receives ('the bytes, base64 or hex, truncated to maxBytes with a flag when longer'). It covers parameter semantics and the key caveat (no decoding). Minor gaps exist around the exact response flag name and error cases for invalid indexes, but the description is adequate for a focused retrieval tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Even though schema coverage is 100%, the description adds real semantic value: it explains that `index` comes from fig_node's `vector.*` fields and what `maxBytes` does (truncation with a flag), grounding the parameters in actual usage. This goes beyond merely restating the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a precise verb and resource: 'Return the raw bytes of one entry in the file's blob table.' It further clarifies the payload types (vector geometry, glyph outlines) and explicitly states what the tool does not do ('does not decode the vector-network format'), making its unique role obvious and separating it from structural tools like fig_node.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly conveys when to use the tool: whenever raw blob bytes are needed, with references to how indexes are obtained via fig_node fields. It also provides an explicit exclusion (no vector-network decoding), though it does not name a specific alternative tool for decoded output, leaving that to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fig_componentsComponent catalogueA
Read-only

List the components (SYMBOL nodes) defined in the file: guid, name, description, the component-set it belongs to when it is a variant, its property definitions with defaults, and how many instances of it exist. Filter with query (case-insensitive substring of the name). Sorted by instance count, most-used first, so the load-bearing parts of the design system come back before one-off symbols. Follow up with fig_instance on a specific INSTANCE guid.

ParametersJSON Schema
NameRequiredDescriptionDefault
fileYesPath to the .fig / .figma file (absolute, or relative to the server CWD).
limitNoDefault 50.
queryNoCase-insensitive substring of the component name.
cursorNoOpaque nextCursor from a previous truncated response; resumes where it stopped.

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, so the description does not need to restate safety. It adds useful behavioral details beyond the schema: sorting by instance count (most-used first), the variant nuance (component-set when variant), and the filtering behavior. It does not contradict annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each adding value: the first lists outputs, the second explains filtering and sorting, the third suggests a follow-up. It is front-loaded with the core purpose and avoids fluff. Slightly long but well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (4 params, no output schema) and the read-only annotations, the description covers the essential behavior: what it returns, sorting, filtering, and a follow-up path. It does not describe pagination explicitly, but the cursor parameter in the schema covers that. No critical gaps for an agent to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so all four parameters are documented in the schema. The description reiterates the query parameter (case-insensitive substring) and implicitly references sorting but adds no new semantic detail beyond what the schema already provides. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists components (SYMBOL nodes) in a file and enumerates the returned fields (guid, name, description, component-set, properties, instance count). It is specific and distinguishable from fig_instance (which is referenced as a follow-up), though it does not explicitly contrast with other siblings like fig_find or fig_node.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use it (to get a catalogue of components) and gives a follow-up suggestion ('Follow up with fig_instance on a specific INSTANCE guid'), but it does not explicitly state when not to use it or name alternatives. The guidance is adequate but not exhaustive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fig_findSearch layers and textA
Read-only

Search a file for nodes by name and by text content (case-insensitive substring), optionally restricted to node types and/or a subtree. Each hit comes back with the page it lives on, a breadcrumb of ancestor names, and which field matched — so you can jump straight to a guid and then call fig_node / fig_style. Omit query to list every node of the given types.

ParametersJSON Schema
NameRequiredDescriptionDefault
fileYesPath to the .fig / .figma file (absolute, or relative to the server CWD).
limitNoDefault 50.
queryNoCase-insensitive substring matched against layer names AND text content.
scopeNoOnly search inside this guid subtree.
typesNoRestrict to node types, e.g. ["TEXT"].
cursorNoOpaque nextCursor from a previous truncated response; resumes where it stopped.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations limited to readOnlyHint=true and openWorldHint=false, the safety profile is already covered, and the description adds substantial behavioral context: case-insensitive substring matching against names AND text content, per-hit contents (page, ancestor breadcrumb, matched field), and the list mode when query is omitted. Nothing in the description contradicts the read-only annotation — this is purely a query operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with zero waste: the core purpose and filters are front-loaded, the return shape plus downstream workflow comes second, and the list-mode tip closes it out. Nothing repeats what the schema already states.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 6-parameter search tool with no output schema, the description covers matching semantics, result composition (page, breadcrumb, matched field), the list-all behavior, and the follow-up workflow into fig_node / fig_style. Combined with 100% schema coverage — including the cursor resumption note and the limit default — nearly everything an agent needs is present; only truncation/pagination behavior is left to the cursor parameter instead of the description.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so file, limit, query, scope, types, and cursor are already documented in the input schema, making 3 the baseline. The description adds only modest value by clarifying that omitting `query` switches to a list-all mode, which ties query and types together semantically, but it provides no per-parameter detail beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource — 'Search a file for nodes by name and by text content' — then pins down the matching semantics (case-insensitive substring) and optional filters (node types, subtree). It also differentiates itself from siblings by framing the tool as the find-and-jump entry point that leads to fig_node / fig_style, which is clearly distinct from fig_tree or fig_node.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear workflow context: hits include a guid so you can 'jump straight to a guid and then call fig_node / fig_style,' telling the agent when this tool is the right entry point. It also documents the list-all mode ('Omit `query` to list every node of the given types'). It stops short of a 5 because it never explicitly names exclusions, such as preferring fig_tree when the full hierarchy is needed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fig_imageEmbedded imageA

Fetch a bitmap stored inside the .fig: pass hash (the 40-hex image id reported by fig_node / fig_style on an image paint), or guid to take the image(s) used by that node, or hash:"thumbnail" for the document preview. Small images come back as viewable image content; larger ones come back as metadata (mime, byte size, pixel dimensions) — give savePath to write the exact bytes to disk instead. NOTE: a .fig contains no rendered pictures of frames, only the bitmaps placed in image fills plus thumbnail.png, so this cannot screenshot a design.

ParametersJSON Schema
NameRequiredDescriptionDefault
fileYesPath to the .fig / .figma file (absolute, or relative to the server CWD).
guidNoNode guid; uses the image fills on that node.
hashNo40-hex image hash, or the literal "thumbnail" for thumbnail.png.
savePathNoWrite the bytes to this path (parent directories are created) instead of inlining.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations, the description discloses key behavioral traits: small images return viewable content, larger ones return metadata, and `savePath` writes exact bytes to disk. The limitation about .fig containing no rendered frame pictures is valuable and prevents misuse. It does not contradict the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences carry all essential information with no filler. The core action and input modes are front-loaded, and the limitation is saved for last. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and sparse annotations, the description carries the full burden and covers retrieval modes, output behavior, and limitations. The only minor gap is not defining the size threshold between 'small' and 'large' images, but this does not prevent correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds substantial meaning: hash is a 40-hex id reported by fig_node/fig_style, guid resolves to image fills on the node, and hash can be the literal "thumbnail". It also explains the practical difference between inline results and savePath, which the schema alone does not convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb (Fetch) and resource (bitmap stored inside the .fig), and clarifies scope with the note that it cannot screenshot a design. It also distinguishes itself from fig_render via the explicit limitation. An agent knows exactly what this tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear mode-selection guidance: use `hash`, `guid`, or `hash:"thumbnail"` depending on what is known, and `savePath` for exact bytes versus inline content. It also warns against using it for screenshot-like rendering. It does not explicitly name sibling alternatives, but the practical usage contexts are well covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fig_instanceInstance overridesA
Read-only

Explain one component INSTANCE: which SYMBOL it points at, its component-property assignments with the property names resolved, and every override it applies — each with the path down into the component, the node that path addresses, and the fields it changes. Use it to see how an instance differs from its component without diffing two subtrees.

ParametersJSON Schema
NameRequiredDescriptionDefault
fileYesPath to the .fig / .figma file (absolute, or relative to the server CWD).
guidYesGuid of an INSTANCE node, e.g. "2:1329".

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish readOnlyHint=true, and the description adds valuable detail about what the tool returns: the referenced symbol, resolved property assignments, and each override with its path, node, and changed fields. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the action and a detailed but efficient list of output components. Every clause earns its place and no filler is present.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only explain tool with no output schema, the description sufficiently covers return values and scope. It lacks only minor details such as error conditions or nesting behavior, which are not critical for invoking the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema fully documents both parameters. The description adds no additional meaning about 'file' or 'guid' beyond what the schema already says, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description has a specific verb and resource ('Explain one component INSTANCE') and details exactly what the output covers: symbols, property assignments, and overrides with paths and fields. It is clear but does not explicitly name a sibling tool to differentiate from, so it falls short of the 5 criterion.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a clear use case: 'Use it to see how an instance differs from its component without diffing two subtrees.' This tells when to use the tool, though it does not explicitly mention alternatives or when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fig_nodeInspect a nodeA
Read-only

Inspect one node by guid (e.g. "2:1339"). detail:"full" (default) gives geometry, fills/strokes/effects as hex colours, corner radii, auto-layout, text basics, component and variable links, plus child summaries. detail:"raw" returns the decoded Figma record verbatim — the escape hatch for fields this server does not map yet; it is limited to one node per call and can be large.

ParametersJSON Schema
NameRequiredDescriptionDefault
fileYesPath to the .fig / .figma file (absolute, or relative to the server CWD).
guidYesNode guid, "sessionID:localID", e.g. "2:1339".
detailNoDefault "full".
includeChildrenNoInclude summaries of direct children (default true).

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint annotation, the description discloses rich behavioral context: exactly what full mode returns (geometry, fills/strokes/effects, corner radii, auto-layout, text basics, links, child summaries), what raw mode does, the one-node-per-call limit, and the potential for large payloads. This is substantial non-obvious behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler. The action is front-loaded, and the second sentence packs the detail-level semantics into a compact, scannable format. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description compensates well by explaining the main return modes and warning about raw size. The main gap is that detail=summary is not described, and includeChildren's effect on full output is only implied. These are minor omissions for a tool with such rich description coverage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds real meaning to the detail parameter by explaining what full and raw return, and reiterates the guid format. However, it does not explain the summary enum value, which remains ambiguous for agents choosing between detail levels.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool inspects one node by guid, with a concrete example ("2:1339"), and enumerates what the response contains. The focus on a single node distinguishes it from siblings like fig_tree or fig_find.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies this is for looking up a specific node when you have its guid, but it never names alternative tools or says when not to use this one. It gives explicit guidance for choosing between detail variants (raw as escape hatch) but not for choosing among sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fig_overviewFigma file overviewA
Read-only

Open a local Figma .fig file and summarise it: document name, export date, node counts by type, the page list, and how many components / variables / images it holds. START HERE. Then fig_tree a page, then fig_node / fig_style on interesting guids; fig_find jumps straight to a name or a piece of text. Everything is read-only and offline.

ParametersJSON Schema
NameRequiredDescriptionDefault
fileYesPath to the .fig / .figma file (absolute, or relative to the server CWD).

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark readOnlyHint true and openWorldHint false, and the description reinforces them with 'Everything is read-only and offline' and 'local' file handling. It does not contradict annotations and adds the concrete context of summarizing without external calls, though it does not go into failure modes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short sentences front-load the core purpose and summary contents, then the workflow. Every clause earns its place and there is no padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a single parameter, no output schema, and read-only annotations, the description supplies enough context: what file is opened, what the summary contains, and how to proceed afterward. Nothing important is missing for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the one parameter (file) is already documented as a .fig/.figma path. The description's 'local .fig file' and 'summarise' framing adds mild context but not much beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb ('Open... and summarise'), a concrete resource (local .fig file), and enumerates summary contents, so an agent immediately knows what fig_overview does and how it differs from the more granular sibling tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly says 'START HERE' and gives a recommended workflow: overview, then fig_tree, then fig_node/fig_style, with fig_find as a jump shortcut. This tells the agent when to use this tool and which siblings to prefer next.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fig_renderRender a node to an imageA

Render a node — frame, component, instance, group, shape, text, or a whole page — to a PNG the model can look at, or to SVG. Fully offline: geometry, text outlines and images all come from the file. Rendering is best-effort: read approximated and unsupported in the report before trusting fine details; exact values remain available from fig_node / fig_style / fig_text. Default output is PNG at 2x, capped to 1568 px on the longest edge; use savePath to write a file instead of inlining it.

ParametersJSON Schema
NameRequiredDescriptionDefault
fileYesPath to the .fig / .figma file (absolute, or relative to the server CWD).
guidYesNode to render, e.g. "2:1339". A page guid renders the whole page, downscaled to fit maxSize.
scaleNoDevice scale factor. Default 2. Lowered automatically to respect maxSize.
formatNoDefault "png". Falls back to SVG text when the optional rasterizer is not installed.
maxSizeNoLongest edge in pixels. Default 1568.
maxNodesNoRefuse subtrees larger than this. Default 20000.
savePathNoWrite the PNG/SVG to this path (directories are created) instead of inlining it. Required when the PNG exceeds 2097152 bytes or the SVG exceeds 50000 characters.
backgroundNoDefault "transparent". "page" fills with the page background colour.

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnlyHint false, etc.), the description discloses key behaviors: best-effort rendering with approximation/unsupported flags, fallback to SVG text when the rasterizer is missing, automatic scale lowering to respect maxSize, refusal of subtrees over maxNodes, and directory creation with savePath. These are not captured by 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single dense paragraph is front-loaded with the core purpose, then limitations, then defaults and parameter-specific nuances. Every sentence adds operational value without redundancy, and the structure is easy to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 8 parameters and no output schema, this description covers all parameters' defaults, constraints, fallbacks, and output modality (inline vs saved file). It also explains the report's role (approximated/unsupported) and points to alternative tools for exact values, giving an agent everything needed to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds deep meaning: defaults for scale (2), maxSize (1568), and background (transparent); the condition for savePath (required when PNG > 2097152 bytes or SVG > 50000 chars); and the behavior that a page guid downscales to fit maxSize. This goes well beyond the schema's per-parameter descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific verb ('Render') and resource ('a node') with explicit node types (frame, component, instance, group, shape, text, or whole page) and output formats (PNG or SVG). It also distinguishes from siblings by noting the offline nature and that this is for visual inspection.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says 'Rendering is best-effort: read `approximated` and `unsupported` in the report before trusting fine details; exact values remain available from fig_node / fig_style / fig_text.' This names alternative tools and the exact condition under which to prefer them. It also clarifies when to use savePath (when output exceeds size limits) versus inline return.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fig_styleResolved style of a nodeA
Read-only

The flattened style of one node, shaped for writing code: hex fills / strokes / effects, corner radii, typography, and auto-layout translated into CSS flexbox terms (display, direction, gap, padding, justifyContent, alignItems, sizing) plus how the node behaves inside its parent layout (flexGrow, alignSelf, margin). Shared styles and variable bindings are named whenever they resolve inside this file.

ParametersJSON Schema
NameRequiredDescriptionDefault
fileYesPath to the .fig / .figma file (absolute, or relative to the server CWD).
guidYesNode guid, e.g. "2:1339".
includeRunsNoFor TEXT nodes, also return styled runs (default false).

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true, so the safety profile is covered. The description adds useful behavior: it flattens style, translates to CSS, and names shared styles/variables that resolve within the file. This goes beyond annotations by explaining the resolution behavior and output format, though it does not detail every output field.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, information-dense sentence that front-loads the purpose and lists key attributes. It is not overly verbose, though it is longer than ideal. Structure is logical and everything earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (many style aspects, parent-layout behavior), the description covers a broad range of output features. It explains the translation to CSS and the naming of shared styles. The includeRuns parameter is documented in the schema, so the description need not mention it. Overall, it is complete for an agent to understand the tool's scope.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so all parameters are documented. The description does not add substantial meaning to file, guid, or includeRuns beyond what the schema already provides; it focuses on output content rather than parameter semantics. Thus, baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: returning the flattened style of one node, translated to CSS terms. It lists specific style aspects (fills, strokes, effects, corner radii, typography, auto-layout) and even parent layout behavior, making it distinct from siblings like fig_node or fig_text which serve different purposes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage by stating it produces the style 'shaped for writing code', which suggests when to use it (e.g., when generating CSS). However, it does not explicitly contrast with siblings or state when not to use it. This is a minor gap, but the purpose is clear enough that an agent can infer appropriate usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fig_textText inventoryA
Read-only

Extract every string of copy in the file (or in one subtree via scope), in document order: guid, layer name, the characters, the page, and the base typography (font, size, line-height, colour). With includeRuns:true each node also carries its styled runs — the mixed-format spans Figma stores per UTF-16 code unit — with only the fields each run overrides. Use this for copy audits and translation passes rather than walking the tree.

ParametersJSON Schema
NameRequiredDescriptionDefault
fileYesPath to the .fig / .figma file (absolute, or relative to the server CWD).
scopeNoOnly collect text inside this guid subtree.
cursorNoOpaque nextCursor from a previous truncated response; resumes where it stopped.
includePathNoInclude the ancestor breadcrumb per node (default false; costs tokens).
includeRunsNoInclude per-run style overrides (default false; costs many more tokens).
includeStyleNoInclude font / size / line-height / colour per node (default true).

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark readOnlyHint=true, and the description does not contradict that. It adds meaningful behavior: document order, per-run style overrides for Figma's UTF-16 code-unit spans, only-overridden fields being emitted, and token-cost warnings for includeRuns and includePath. This goes well beyond the annotation signal.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two dense sentences, with the core purpose front-loaded and the usage guidance placed at the end. Every phrase earns its place; no filler or repetition of schema boilerplate.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

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: document order, guid, layer name, characters, page, and base typography. It also addresses scoping, styled runs, and cost implications, making it complete enough for an agent to select and invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds real value beyond the schema by explaining what includeRuns actually returns (mixed-format spans per UTF-16 code unit, only overridden fields) and by describing scope's subtree filtering. This justifies a small uplift.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Extract every string of copy in the file', then lists exactly what is returned (guid, layer name, characters, page, base typography). It also distinguishes itself from generic tree walking and positions it for copy audits and translation passes, clearly differentiating it from sibling tools like fig_tree and fig_find.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use this tool: 'Use this for copy audits and translation passes rather than walking the tree.' This gives both a positive use case and a clear exclusion, and the mention of subtree scope tells the agent when scope applies.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fig_treeExplore the layer treeA
Read-only

List the layers under a node, breadth-limited by depth (default 2, max 6). Returns a FLAT list in document order; each entry carries depth (relative to the requested root) and parent, so the hierarchy is reconstructable, and children (count) so you can see where to deepen. format:"outline" returns indented text lines instead of JSON and is roughly 4x denser for browsing. Large subtrees are truncated with truncated:true and a nextCursor you can pass back to continue.

ParametersJSON Schema
NameRequiredDescriptionDefault
fileYesPath to the .fig / .figma file (absolute, or relative to the server CWD).
rootNoGuid to start from, e.g. "2:1339". Defaults to the DOCUMENT node.
depthNoLevels below the root to include (default 2, max 6).
typesNoOnly include these node types, e.g. ["FRAME","TEXT"]. Depth still applies.
cursorNoOpaque nextCursor from a previous truncated response; resumes where it stopped.
formatNoDefault "json".

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint=true and openWorldHint=false, and the description adds substantial behavioral detail beyond that: results are flat rather than nested, order is document order, hierarchy is reconstructable via depth/parent, subtrees can be truncated, and outline mode changes both format and density. This is exactly the kind of non-obvious runtime behavior an agent needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Every sentence in the description earns its place: the core action is front-loaded, followed by output structure, format trade-offs, and truncation handling. There is no filler or repetition, and despite its density it remains easy to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with six parameters and no output schema, the description provides a remarkably complete picture: what the response looks like, how to reconstruct hierarchy, how to detect/continue truncation, and when to switch formats. Parameter details like root default, file path, and types filtering are already fully covered by the input schema, so nothing important is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real value: it explains the default depth, the meaning of depth relative to the requested root, the purpose of children counts for deepening exploration, and the behavioral difference between json and outline formats. It also clarifies that cursor resumes a truncated traversal.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'List the layers under a node', and immediately defines the tool's distinguishing behavior with breadth/depth limits. It also clarifies the output shape (flat list, document order) and the outline alternative, making it easy to tell apart from broader siblings like fig_overview or fig_find.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly states when to use the outline format ('4x denser for browsing') and how to continue truncated results via nextCursor. It does not explicitly contrast this tool with sibling tools such as fig_find or fig_node, but it gives enough contextual cues that an agent can infer the intended use case.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fig_variablesVariables and modesA
Read-only

List the design tokens in the file: every variable collection (VARIABLE_SET) with its modes, and every variable with its value per mode — colours as hex, numbers and strings verbatim. Aliases are followed when the target variable lives in this file; a variable published from another library is returned as its opaque assetRef instead. Filter with set (collection name or guid) or query (substring of the variable name).

ParametersJSON Schema
NameRequiredDescriptionDefault
setNoOnly variables from this collection (name or guid).
fileYesPath to the .fig / .figma file (absolute, or relative to the server CWD).
limitNoDefault 100.
queryNoCase-insensitive substring of the variable name.
cursorNoOpaque nextCursor from a previous truncated response; resumes where it stopped.
includeSetsNoInclude the collection list with their modes (default true).

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint annotation, the description discloses important behavior: aliases are resolved only when the target is in the same file, external variables become opaque assetRefs, and values are formatted per type (hex, verbatim strings/numbers). This gives an agent meaningful expectations about output and cross-file behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded with the core purpose, then expands into output semantics and filters. Every sentence carries necessary information; there is no filler or repetition of schema details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only retrieval tool with rich annotations and fully described parameters, the description covers the essential semantics: what is listed, how values are represented, how aliases are handled, and how to filter. The lack of an output schema is compensated by the detailed return-value explanation in the description.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds value by explaining that 'set' accepts a collection name or guid and that 'query' is a case-insensitive substring match, which clarifies the two primary filtering parameters beyond the schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'List the design tokens in the file' and precisely enumerates what is returned (variable collections, modes, per-mode values, aliases, assetRefs). This clearly distinguishes it from sibling tools like fig_style or fig_components by focusing on variables and tokens.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context on what the tool returns and how to narrow results via 'set' and 'query'. It does not explicitly name sibling tools or say when not to use it, but the purpose and filtering instructions make the intended usage unmistakable.

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.

  1. 12 tool updatesv1.0.0
    • First observedfig_blob
    • First observedfig_components
    • First observedfig_find
    • First observedfig_image
    • First observedfig_instance
    • First observedfig_node
    • First observedfig_overview
    • First observedfig_render
    • First observedfig_style
    • First observedfig_text
    • First observedfig_tree
    • First observedfig_variables

TDQS

A4.2/5.0

Scored across 12 tools

Disambiguation4/5

Each tool targets a distinct concern: overview, tree, node, find, text, style, components, instances, images, blobs, render, variables. The only mild overlap is fig_node vs fig_style (both inspect a single node) and fig_image vs fig_blob (both fetch raw bytes), but descriptions clarify the different purposes.

Naming Consistency4/5

All tools share the fig_ prefix and use lowercase snake_case, which is consistent. The verbs are mostly clear (overview, tree, node, find, text, style, components, instance, image, blob, render, variables), though fig_overview is a noun-ish name rather than a verb_noun pattern like fig_list_pages or fig_get_overview.

Tool Count5/5

12 tools is well-scoped for a Figma file inspection server. Each tool covers a distinct aspect of the domain: navigation, inspection, text extraction, style extraction, components, instances, images, blobs, and rendering. No tool feels redundant or unnecessary.

Completeness4/5

The server covers the read-only Figma file inspection domain thoroughly: overview, tree navigation, node lookup, search, text extraction, style extraction, components, instances, images, blobs, and rendering. Minor gaps include no direct way to list all pages as a standalone tool (only via fig_overview) and no tool for comparing two nodes, but these are workarounds.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    B
    quality
    D
    maintenance
    Enables AI agents to read, inspect, and export Figma designs programmatically. Provides tools for listing components, styles, and exporting assets in various formats.
    5
    1
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI IDEs to query Figma design tokens, component specs, and audit issues via MCP tools, without cloud subscriptions.
    MIT
  • A
    license
    B
    quality
    B
    maintenance
    Enables offline reading and rendering of Figma .fig files, allowing AI agents to extract design specs, export assets, and generate code without needing the Figma API or network access.
    26
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables AI coding agents to read Figma file hierarchies, node properties, and rendered images locally via MCP, using a personal access token without Figma's hosted MCP integration.
    -