figma-reader-mcp
Provides read-only access to Figma files, including document trees, variables, styles, components, text, image fills, and screenshots, from local .fig files or live Figma files via a browser.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@figma-reader-mcpshow me the component list for https://figma.com/file/abc"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
figma-reader
Read-only Figma access for AI agents and people. No Figma plugin, no API token, no Dev Mode seat, no Enterprise plan.
It ships in two forms that share the same tools and code. Use whichever fits:
Command | Best for | |
MCP server |
| MCP clients (Claude Code, Claude Desktop, Cursor, ...). One long-lived process keeps the browser and editor tab warm, so repeated web calls are fast |
CLI |
| Shells, scripts, CI, and agents that prefer running commands over loading MCP tools. Nothing to register; output is JSON/text on stdout |
Two ways to feed it:
Local
.figfile (File › Save local copy in Figma, then pass the path). Fully offline, no browser. Everything except screenshots.Figma file key / URL. It drives figma.com in a headless Chromium-family browser over the DevTools protocol, and shows a visible window only when you need to log in:
Data | How |
Document tree, variables, styles, components, text, image fills | File › Save local copy (triggered via Quick actions) → |
Screenshots | Copy as PNG on the node; the PNG is intercepted in the page, the system clipboard is never touched |
Recent files, account | Figma's internal web API with the browser's session cookies |
Variables come straight out of the file, so modes, aliases and scopes are available on any plan (the REST variables endpoint is Enterprise-only).
Tools
MCP tool names and CLI commands map one to one: figma_get_tree is figma-reader get-tree.
Tool | Purpose |
| Account, browser mode, running browser, logged-in user. |
| Open the visible login window / wait for login |
| Local |
| Export + decode, summary (pages, counts, collections, styles) |
| Compact layer outline |
| Normalized design data: geometry, fills/strokes/effects, auto-layout, text runs, instance props, bound variables, style names |
| Find nodes by name / text; with |
| Collections, modes, values, resolved aliases; |
| FILL, STROKE, TEXT, EFFECT and GRID styles; |
| Local components, variant sets, and |
| Aggregate raw values in use (colors, type, radii, spacing, effects) to derive tokens from files without variables |
| All copy under a node, component instances expanded, with |
| PNG of a node via Copy as PNG |
| Original bitmap assets, from fill and stroke paints; per image the |
Every tool that reads a file takes one as a local .fig path, a file key, or a figma.com/design/... URL. A node-id in that URL is used by the seven tools that take a node_id — figma_get_tree, figma_get_node, figma_search, figma_token_usage, figma_get_text, figma_screenshot, figma_export_image_fills — when the argument is omitted. The four that answer about the whole file (figma_load_file, figma_get_variables, figma_get_styles, figma_get_components) have no node to scope to and ignore it. figma_status, figma_login and figma_list_files name no file at all; figma_list_files lists local .fig files by default (source: "web" for the account's recent files). figma_screenshot is the exception among the rest: the image always comes from the live file in the browser, so it takes a key or URL, and a local path only when its name carries the key.
MCP inputs are strict: every tool's schema is additionalProperties: false, so an unknown argument is an error rather than a silently dropped one. Only the tools that cannot write are published with readOnlyHint: true — the ones taking out_file, out_dir or save_path are not, nor are figma_status and figma_login, which write account state.
Linking local files to Figma URLs
Name saved copies <anything> [<file key>].fig (the key is the id after /design/ in the URL) and put them under FIGMA_FILES_DIRS:
~/Downloads/My App [AbCdEf1234567890XyZ].figThen a pasted URL such as https://www.figma.com/design/AbCdEf1234567890XyZ/My-App?node-id=8-77 is served from that file offline (newest match wins); node ids are identical. refresh: true ignores local copies and exports the live file, and is answered only by an export that begins after it was asked for, never by one already under way; on a path to a .fig there is nothing to export from, so it is ignored and the result says refreshIgnored: true.
A dated result names the date after what it dates, because the two are not the same claim. exportedAt is the ISO-8601 time this tool exported that snapshot through the browser: report what the design said then rather than as current, and figma_load_file adds source and snapshotAgeMinutes beside it. A .fig the user supplied carries fileModifiedAt instead, that copy's own file time, and no age: copying, syncing or re-downloading the file resets it, so the design data can be older than the field says and nothing here can date it. Six tools date their results — figma_load_file, figma_get_node, figma_search, figma_get_components, figma_token_usage, figma_get_text. figma_get_tree, figma_get_variables, figma_get_styles and figma_export_image_fills answer with no date at all, so an answer built on them cannot be dated from the result.
figma_screenshot always renders the live file and works from a local path only when its name carries the key.
Related MCP server: ai-sdlc-figma-mcp-server
Setup
Node 22+. For web mode, a Chromium-family browser: the first of Brave, Chromium, Chrome found on PATH, or FIGMA_BROWSER_PATH. Playwright's "Chrome for Testing" is only a last resort because Google sign-in rejects it as insecure.
npm install -g @leogcode/figma-reader # puts figma-reader and figma-reader-mcp on PATHOr without installing, for a one-off: npx -y @leogcode/figma-reader@latest help. To work on it instead:
git clone https://github.com/LeoGCode/figma-reader && cd figma-reader
npm install && npm run build
npm link # optional: puts figma-reader and figma-reader-mcp on PATHCLI
figma-reader help # all commands
figma-reader help get-node # one command's arguments
figma-reader load-file ~/Downloads/app.fig
figma-reader get-tree "https://www.figma.com/design/<key>/App?node-id=8-77" --depth 1
figma-reader search <file> "sign in" --include-text --types TEXT
figma-reader get-variables <file> --format css > tokens.css
figma-reader screenshot <file> --node-id 8:77 --save-path out/login.pngArguments are the MCP tool arguments in kebab-case. Required strings are positional (<file>, then <query> or <out_dir>), booleans are bare flags (--refresh, --no-refresh) or take a value (--refresh=false), lists repeat or take commas (--types FRAME,TEXT), and --json '{"node_id":"8:77"}' passes raw arguments. -- ends the options, so a query such as --help can follow it. Results go to stdout (pipe JSON into jq), errors to stderr. Exit code 0 is success, 1 a failed call, 2 bad usage. Images go to --save-path or, without it, to a new file in a private per-user temp directory ($TMPDIR/figma-reader-<uid>/, mode 0700), whose path is printed.
Installed from a clone without npm link, run node /path/to/figma-reader/dist/cli.js. The CLI reads the same environment variables as the server (see below).
Each CLI call is its own process. Local .fig files and cached snapshots answer in well under a second, but a call that needs figma.com starts the headless browser and loads the editor, so it takes tens of seconds. The browser closes when the call ends, unless an MCP server on the same profile is still using it. For many web calls in a row, the MCP server is faster.
For agents
skills/figma-reader/SKILL.md is a ready-made agent skill that teaches the CLI. Install it into a project with
npx skills add https://github.com/LeoGCode/figma-reader --skill figma-readerwhich writes .agents/skills/figma-reader/ and registers it for Claude Code and the other agents that read that directory. Or copy the file into .claude/skills/ (project) or ~/.claude/skills/ (user) by hand, or paste its body into another agent's instructions (AGENTS.md, rules files). Agents without a skill can also run figma-reader help.
MCP server, per project
Register it only in the projects that need it (writes .mcp.json in the project root, shareable in git):
cd /path/to/project
claude mcp add --scope project figma-reader -- npx -y @leogcode/figma-reader@latest figma-reader-mcpInstalled globally, -- figma-reader-mcp works instead; from a clone, -- node /path/to/figma-reader/dist/mcp.js.
or add to the project's .mcp.json by hand (Claude Code expands ${VAR}):
{
"mcpServers": {
"figma-reader": {
"command": "npx",
"args": ["-y", "@leogcode/figma-reader@latest", "figma-reader-mcp"],
"env": { "FIGMA_FILES_DIRS": "${PWD}/design:${HOME}/Downloads" }
}
}
}Accounts: one Figma login per project
If different projects need different Figma accounts (a client's workspace, your personal one), give each its own account. An account is a name with its own browser profile, so its own Figma login, and its own cache of exported files. Projects on different accounts never share a session, and a file exported by one account is never served to a project using another.
A project picks its account with a .figma-reader.json in its root, found by walking up from the working directory:
cd ~/work/acme-app
figma-reader use acme # writes .figma-reader.json: { "account": "acme" }
figma-reader login # opens a browser window to sign "acme" into Figma, once
figma-reader accounts # every account, its login and email, and which one this directory usesThe same file serves the CLI and the MCP server: Claude Code and most MCP clients start the server in the project directory, so no extra MCP configuration is needed. The account is fixed when the server starts; after changing it, restart the server (in Claude Code, /mcp). figma_status reports the account in use and where the choice came from.
Which account applies, first match wins:
--account <name>on any CLI commandFIGMA_ACCOUNT, e.g. in the MCP server'senvfor clients that do not start servers in the project directoryaccountin the nearest.figma-reader.jsondefault
.figma-reader.json can also set the project's .fig folders; relative paths resolve against the file's directory:
{ "account": "acme", "filesDirs": ["design", "~/Downloads"] }Only the nearest file applies; files further up are not merged in. So figma-reader use in a subdirectory of a project that already has a .figma-reader.json writes a new file there that starts as a copy of the project's other settings (relative filesDirs rebased), so only the account changes for that subdirectory, and says which file it copied. Later edits to the project's file do not reach the subdirectory.
Commit it if your team uses the same account names, or add it to .gitignore (or .git/info/exclude) to keep it to yourself.
Account data lives in ~/.local/share/figma-reader/accounts/<name>/ (profile, last verified email) and ~/.cache/figma-reader/accounts/<name>/ (snapshots, under $FIGMA_READER_CACHE/accounts/<name>/ when that is set). Delete those two directories to remove an account.
Browser and login
Mode | Set | Behavior |
Managed (default) | nothing | Launches the detected browser headless on the account's profile, |
Managed, own browser/profile |
| Same, with that executable and profile (an existing logged-in profile skips the login step) |
Attached |
| Uses a browser you started with |
Login flow (managed): the first web call checks the session cookies. If the profile is not logged in, the headless browser is closed and the same profile opens in a normal visible window on figma.com/login, with no DevTools port (Google and others refuse sign-in in remotely controlled browsers). Log in and retry: once Figma's auth cookie shows up in the profile's cookie DB (read-only, no DevTools needed) the window is closed gracefully and the login is verified headless; if verification fails the login window reopens. figma_login with wait_seconds blocks until then. The login persists in the profile.
Headless needs two workarounds, applied automatically: the user agent's HeadlessChrome is rewritten (CloudFront answers 403 otherwise) and focus is emulated (Figma ignores shortcuts without it).
A managed browser is shared by all servers and CLI calls using the same profile (found via Chromium's DevToolsActivePort) and closed when the last of them exits. A profile can be open in only one browser process: if you have it open normally (without a DevTools port) the server reports it instead of launching.
Env | Default | |
| from | Account: which Figma login and snapshot cache to use |
|
| Colon-separated dirs scanned (2 levels) for |
| Brave › Chromium › Chrome › Playwright | Browser executable |
|
| Browser profile holding the Figma login (one per browser: cookie keys differ). Without an account set, a custom profile gets its own cache |
|
|
|
| unset | Attach to a running browser instead of launching |
|
| Root of the snapshot cache ( |
|
| Re-export after this age (or pass |
Concurrency
Each server process uses its own editor tab, marked with its pid; tabs of exited servers are reused. Calls within one server run one at a time on that tab; separate agents run in parallel on separate tabs, and concurrent exports share the browser-wide download setting safely (per-frame download matching plus lease files, in a directory named after the profile so that processes given different caches still agree on it). Processes sharing a cache also wait for each other's export of a file rather than each exporting it. Each editor tab costs hundreds of MB to over a GB of RAM. In a visible browser (attached or FIGMA_HEADLESS=0) keep the windows un-minimized: hidden tabs stop rendering and Copy as PNG never fires.
node scripts/concurrency.ts <key> <nodeA> <nodeB> same|multi and node scripts/concurrency.ts x <keyA> <keyB> export exercise the concurrent paths. node scripts/call.ts lists the MCP tools; node scripts/call.ts <tool> '<json>' calls one.
npm test typechecks src/, test/ and scripts/, then runs the unit tests. Tests and scripts run straight from the TypeScript source with Node's built-in type stripping (Node 22.18+), so they need no build; src/ sticks to erasable syntax (no enums or constructor parameter properties) to keep that working. npm run build compiles src/ to dist/ for the published commands.
Unit tests build their scene graphs in code (test/fixtures.ts), since real design files cannot be published, plus one real export (test/files/real-export.fig, 35 KB, made for this purpose and holding no design work) that pins what the format actually looks like: bindings recorded in parameterConsumptionMap, a property value an enclosing instance sets on a nested one, and an opacity variable of 50 driving a layer at 0.5. Coded fixtures encode what we believe the format is; that one fails when the belief is wrong. To check changes against real files you have, run npm run corpus -- <file.fig | dir>... (or set FIGMA_CORPUS_DIR): it decodes each file and runs it through outline, instance-text, normalize, tokens (variables, their CSS and DTCG, styles and their CSS), component-usage and token-usage. It checks that no step throws, and these invariants: no two text items share an id, and no unresolved id repeats for the same reason; every instance layer's text is as long as what Figma last rendered for it, and no layer an instance still renders is left neither answered nor reported as unresolved — derivedSymbolData is Figma's last layout and is never pruned, so entries for layers an instance has since stopped showing are excused; no property definition without a name; no duplicate CSS custom property in :root, no var() reference to a name nothing declares, and none in :root to a name declared only in a mode block; every collection with variables has a mode; no DTCG collections merged into another, every {a.b.c} reference naming a token with a value, no token dropped by a name collision or nested inside another; every component use naming a component the file holds, none recorded on a soft-deleted or superseded instance and none naming a superseded copy, one use per instance of a component, an instance's swaps at least the distinct (path, property) pairs it sets — two properties set to one component are two uses — and at most the swap records it holds, and the per-component totals adding up to the uses; every colour a hex value, every typography entry carrying typography and none reported twice, every count a positive whole number, every text node walked accounted for by a typography count or by textWithoutTypography with that counter holding exactly the text that records none, and no value counted more often with hidden layers skipped than with them included. It prints counts only, never design content, among them keyIdCollisions, the guids one layer uses as an override key and another as a node id, and instancesGone/supersededComponents, which say whether the file has anything for the two skips above to decide about. Add --save base.json before a change and --compare base.json after it to see what moved. Snapshots exported through the browser are under ~/.cache/figma-reader/accounts/<account>/.
For behaviour on real files, keep private tests in test/private/ (gitignored) and run them with npm run test:private, which fails when that directory holds no tests, since a green step that ran nothing proves nothing (FIGMA_PRIVATE_OPTIONAL=1 skips it instead, and also skips the tests whose pinned file is missing). Check expectations against what Figma renders (a figma-reader screenshot of the frame), not against the tool's own output. Pin copies of the files there too rather than pointing at the export cache, which is overwritten on refresh. node:test snapshots (t.assert.snapshot, accepted with npm run test:private:update) can then catch any change in output, for you to review.
Limits
Relies on figma.com internals (Quick actions
data-testid="save-as",_fullscreen_.isReady,/api/recent_files). Breaks if Figma changes them. The Quick actions box itself is recognised by any of three signals — its placeholder or aria-label text, its CSS-module class name, or an ancestor[data-testid*="quick-action"]— none of which has been verified against the live product. If none match,saveLocalCopyfails closed with a diagnostic naming the focused element, rather than typing the query into whatever field happens to have focus.Files whose owner disabled copying/exporting cannot be saved locally.
A collapsed instance's contents are not stored in the
.fig; they are derived from its main component plus overrides.figma_get_textandfigma_searchdo that derivation (text overrides and properties, boolean properties that show or hide layers, instance swaps, and properties set on nested instances), tagging each string withvia(direct/instance), its component, variant and enclosing frame, and counting anything they could not resolve asunresolvedInstances.figma_get_nodeandfigma_get_treestill do not expand instances: they report the main component, variant and property values instead.Layer names inside a collapsed instance are likewise not in the file, so
figma_searchcannot match them; search the main component.Library variables/styles/components appear only when the file uses them (Figma copies them in); they are flagged
remote/fromLibrary.Token export (
figma_get_variables,figma_get_styles):CSS numbers are
px, except variables scoped to font weight or font axes (unitless) and opacity (Figma's 0-100 written as 0-1).DTCG aliases reference the full token path
{Collection.Mode.path}; an alias into another collection uses that collection's default mode, as Figma does. An alias to a library variable the file has no copy of becomes a CSS comment, or a DTCG node with$extensions["com.figma"].aliasOfand neither$valuenor$type: a token is an object with a$valueand a group is one without, so what has no value is left as the group it is rather than as a token consumers split between dropping and erroring on.Names are unique: collections, modes and styles sharing a name are numbered (
colors-2,Colors 2). Withcollectionorinclude_remote: falsethe names stay those of the full export, and an alias into a collection left out is written as its resolved value.Soft-deleted styles and older copies of an updated library variable or style are left out. Stacked fills are composited (or layered when they cannot be), and gradient angles are approximate on non-square layers.
Selecting a different node for a screenshot reloads the editor tab (a few seconds).
Available Tools
14 toolsfigma_export_image_fillsA
Write the original image assets (photos, bitmaps) a node or the whole file uses, in a fill or a stroke paint, to a directory. Answers with an array, one entry per distinct image: hash, the path written, its size in bytes, and up to five of the layers using it (with usedByTotal when there are more). An image whose bytes this export does not carry is reported as {hash, missing: true} and nothing is written for it.
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | Path to a local .fig file, or a Figma file key / figma.com/design/... URL. A node-id in the URL is used when this tool takes node_id and it is omitted; a tool that answers about the whole file ignores it. A key or URL uses a local '<name> [<key>].fig' from FIGMA_FILES_DIRS when one exists, otherwise exports through the browser. | |
| node_id | No | ||
| out_dir | Yes | Directory to write the images into, created if it is missing. A relative path is resolved against this process's working directory, which for an MCP server is wherever the client started it | |
| refresh | No | Skip local/cached copies and export the live file through the browser. Has no effect when file is a path to a .fig: that file is read as it is on disk and the result carries refreshIgnored; pass the key or URL to export the live file instead. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses concrete side effects: it writes files to a directory, creates the directory if missing, resolves relative paths against the process working directory, reports missing images, and explains refreshIgnored behavior. This goes well beyond the annotations and is consistent with readOnlyHint=false, since the tool writes to the local filesystem.
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 description is dense but well-structured, front-loading the core action and then detailing output, missing-image behavior, and file resolution semantics. Every sentence adds value, though the file semantics could be slightly tighter without losing important detail.
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 compensates by specifying the exact array shape, per-image fields, missing-image reporting, and layer usage information. It also covers file source resolution, refresh behavior, and directory creation, giving an agent nearly everything needed to call the tool 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?
The description adds substantial semantics beyond the schema for file (path/key/URL forms and node-id in URL), out_dir (creation and relative path resolution), and refresh (ignored for local .fig files). However, node_id itself is only indirectly mentioned and its expected format is not fully specified, leaving a small gap.
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 states a specific verb and resource: "Write the original image assets ... to a directory" for a node or the whole file. It clarifies the domain (image fills and stroke paints) and describes the return format, making it easily distinguishable from sibling tools like figma_screenshot or figma_get_node.
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?
The description gives clear context for when the tool is appropriate: it can target a node or the whole file, accepts a local .fig path, a file key, or a URL, and explains refresh behavior. It does not explicitly name alternatives or say when not to use it, but the usage context is strong enough for an agent to make a reasonable selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_get_componentsARead-only
The components this file defines, and the library components it uses. componentSets are the variant sets, with their description, property definitions and one entry per variant carrying that variant's counts; components are the ones outside a set, each with a size and its own counts. A count is instances placed directly, plus swapInstances where the component is swapped into an instance (by an override or an instance-swap property). libraryComponentsUsed is a third list: components defined in other files, by name, with the variants used and the same two counts. Internal-only pages are left out of all three lists but not out of the counts: an instance placed on one still counts for the component it is of, except for a library component, whose uses on such a page are skipped. The result is dated by the copy it answers from. exportedAt is the ISO-8601 time this tool exported that snapshot through the browser: report what the design said then rather than as current, and pass refresh to export it again. For a local .fig the field is fileModifiedAt, that copy's own file time, which copying, syncing or re-downloading the file resets: the design data can be older than it says, and nothing here can date it.
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | Path to a local .fig file, or a Figma file key / figma.com/design/... URL. A node-id in the URL is used when this tool takes node_id and it is omitted; a tool that answers about the whole file ignores it. A key or URL uses a local '<name> [<key>].fig' from FIGMA_FILES_DIRS when one exists, otherwise exports through the browser. | |
| query | No | Case-insensitive filter on name; a component set matches when the set or any of its variants does | |
| refresh | No | Skip local/cached copies and export the live file through the browser. Has no effect when file is a path to a .fig: that file is read as it is on disk and the result carries refreshIgnored; pass the key or URL to export the live file instead. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true, so the description doesn't need to repeat that. It adds substantial behavioral context: it explains that internal-only pages are excluded from lists but still counted (except library components on such pages are skipped), and it clarifies the meaning of 'exportedAt' and 'fileModifiedAt' including the fact that local .fig file times can be unreliable. This goes beyond annotations and helps the agent understand the data's freshness.
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 description is a single dense paragraph, which is somewhat heavy but every sentence adds important technical detail about the tool's output and edge cases. It is front-loaded with the core content and then explains nuances; a slight structure improvement would be splitting into bullet points, but it's efficient overall.
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?
The description covers the tool's output structure, counting logic, edge cases (internal-only pages), and staleness semantics, including the difference between URL and local file paths. Given the complexity of the tool and the absence of an output schema, the description is remarkably complete for an agent to understand what it returns and how to interpret it.
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 fully documents parameters. The description adds no new parameter semantics beyond what the schema already says; it mentions 'refresh' but not in a way that expands on the parameter description. Thus a 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?
The description clearly identifies the tool as returning component definitions and usage counts from a Figma file, with a specific structure distinguishing componentSets, components, and libraryComponentsUsed. It is distinct from siblings like figma_get_tree or figma_get_node because it focuses on components specifically.
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?
The description implicitly covers when to use this tool (when you need component definitions and usage counts) and provides important guidance on staleness: it explains the exportedAt field, when refresh is needed, and the caveat about local .fig files. Sibling tools are not explicitly named, but the clear scope and context make usage clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_get_nodeARead-only
Detailed design data for a node and its subtree: geometry, fills/strokes/effects (hex), auto-layout, text styling and runs, component/instance info, bound variables and style names. Instances are not expanded (see mainComponentId). The result is dated by the copy it answers from. exportedAt is the ISO-8601 time this tool exported that snapshot through the browser: report what the design said then rather than as current, and pass refresh to export it again. For a local .fig the field is fileModifiedAt, that copy's own file time, which copying, syncing or re-downloading the file resets: the design data can be older than it says, and nothing here can date it.
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | Path to a local .fig file, or a Figma file key / figma.com/design/... URL. A node-id in the URL is used when this tool takes node_id and it is omitted; a tool that answers about the whole file ignores it. A key or URL uses a local '<name> [<key>].fig' from FIGMA_FILES_DIRS when one exists, otherwise exports through the browser. | |
| depth | No | Child levels to include (default 3) | |
| node_id | No | ||
| refresh | No | Skip local/cached copies and export the live file through the browser. Has no effect when file is a path to a .fig: that file is read as it is on disk and the result carries refreshIgnored; pass the key or URL to export the live file instead. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the readOnlyHint annotation by disclosing that instances are not expanded, that the result is tied to a snapshot timestamp (exportedAt vs fileModifiedAt), and that local .fig copies can silently carry stale data whose age cannot be determined. It also explains the refresh parameter's effect and the refreshIgnored case. This is rich, actionable behavioral context.
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 description is a single dense paragraph, but every clause carries useful information: content list, instance expansion, timestamp semantics, and local-file caveat. It front-loads the tool's primary purpose before diving into snapshot timing. Slightly long but justifiably so for a tool with this much behavioral nuance.
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 data-retrieval tool with no output schema, the description enumerates the returned design aspects and explains the critical freshness limitations that could otherwise mislead an agent. It does not detail the output structure or how to obtain node_id, but the schema's file parameter covers node-id-in-URL, and the listed content areas are sufficient to set expectations. Minor gaps exist around error cases and depth defaults, but these are already 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?
The input schema already describes file, depth, and refresh, covering 75% of parameters. The description adds meaning for refresh ('pass refresh to export it again') and clarifies the local-file behavior, but it does not explain node_id or depth beyond what the schema/name implies. With partial schema coverage, this is adequate but not exhaustive.
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 clearly states the tool returns 'Detailed design data for a node and its subtree' and enumerates the content (geometry, fills/strokes/effects, auto-layout, text styling, component/instance info). It distinguishes from siblings by noting 'Instances are not expanded', but it lacks an explicit verb and doesn't name alternative tools, so it falls just short of full differentiation.
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?
There is no explicit when-to-use guidance or comparison to sibling tools such as figma_get_tree or figma_get_text. The description provides operational cautions about data freshness ('The result is dated by the copy it answers from', 'pass refresh to export it again') but these are behavioral caveats, not selection criteria. The intended use must be inferred from the tool name and content list.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_get_stylesB
Local (and imported library) styles with their values: FILL (color), STROKE, TEXT, EFFECT and GRID. Formats: json (default) or css. A file with no styles, or none of the type asked for, answers empty in that format.
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | Path to a local .fig file, or a Figma file key / figma.com/design/... URL. A node-id in the URL is used when this tool takes node_id and it is omitted; a tool that answers about the whole file ignores it. A key or URL uses a local '<name> [<key>].fig' from FIGMA_FILES_DIRS when one exists, otherwise exports through the browser. | |
| type | No | Only styles of this type | |
| format | No | ||
| refresh | No | Skip local/cached copies and export the live file through the browser. Has no effect when file is a path to a .fig: that file is read as it is on disk and the result carries refreshIgnored; pass the key or URL to export the live file instead. | |
| out_file | No | Also write the result to this path | |
| css_prefix | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses the empty-result behavior, the refresh option to bypass local copies, and the ability to write output via out_file. However, it does not explicitly state whether the tool modifies any state beyond optional file writing, and it omits authentication requirements or network effects. Since annotations provide no read-only guarantee (readOnlyHint=false), the description carries the burden but does not fully clarify.
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 description is three short, focused sentences that front-load the core purpose and types before mentioning formats and edge-case behavior. It is efficient and avoids redundancy, though it could be slightly more structured with bullet points for readability.
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 6-parameter tool with no output schema, the description explains the main behavior and output formats but leaves css_prefix undefined and does not describe the structure of the returned data. The empty-result note is helpful, but the lack of details on authentication, pagination, or error cases makes it incomplete for an agent needing to call 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?
The schema covers 67% of parameters with descriptions. The tool description adds the default format ('json (default)') and lists the style types, complementing the schema. However, css_prefix is entirely undocumented in both schema and description, and the description does not clarify the interaction between type and format beyond what is in the enum.
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 clearly identifies the resource (styles) and the verb (get) along with the supported types (FILL, STROKE, TEXT, EFFECT, GRID) and formats (json/css). It distinguishes itself from siblings like figma_get_variables and figma_get_components by focusing specifically on styles, though it does not name an alternative 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?
The description provides context about behavior (e.g., empty result if no styles) and formats, but does not mention when to prefer this tool over related ones like figma_get_variables or figma_get_components. There is no guidance on prerequisites (e.g., authentication) or typical use cases.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_get_textARead-only
All text content under a node (or the whole file) in reading order, with node ids. Component instances are expanded, so strings that only exist as instance overrides or component property values are included, each tagged with via (direct/instance) and, where they apply, its component, variant and enclosing frame. A field that does not apply is absent: text on the canvas has no component. Hidden layers are excluded unless include_hidden. The result always reports total/truncated/unresolvedInstances: a non-zero unresolvedInstances means text is missing, at that many places; unresolved lists each missing component once, with its count and some of those places, the most common first, and unresolvedComponentsOmitted counts the components past that listing. The result is dated by the copy it answers from. exportedAt is the ISO-8601 time this tool exported that snapshot through the browser: report what the design said then rather than as current, and pass refresh to export it again. For a local .fig the field is fileModifiedAt, that copy's own file time, which copying, syncing or re-downloading the file resets: the design data can be older than it says, and nothing here can date it.
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | Path to a local .fig file, or a Figma file key / figma.com/design/... URL. A node-id in the URL is used when this tool takes node_id and it is omitted; a tool that answers about the whole file ignores it. A key or URL uses a local '<name> [<key>].fig' from FIGMA_FILES_DIRS when one exists, otherwise exports through the browser. | |
| limit | No | Default 500 | |
| node_id | No | ||
| refresh | No | Skip local/cached copies and export the live file through the browser. Has no effect when file is a path to a .fig: that file is read as it is on disk and the result carries refreshIgnored; pass the key or URL to export the live file instead. | |
| include_hidden | No | Include layers hidden in the design (default false) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark it read-only and open-world, but the description goes far beyond that. It discloses how component instances are expanded, that hidden layers are excluded by default, the meaning of unresolvedInstances and the snapshot timing with exportedAt and refresh. It even explains local file quirks with fileModifiedAt. This is exemplary transparency with no contradiction to 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?
The description is long but every sentence contributes critical edge-case information. It front-loads the primary purpose and then systematically covers instances, hidden layers, unresolved instances, and timing. It is not verbose for the complexity, though it could be better structured with bullet points. Overall, it earns its length.
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?
There is no output schema, so the description compensates by explaining the result fields (total/truncated/unresolvedInstances, unresolved, unresolvedComponentsOmitted) and their meanings. It also covers snapshot dating, refresh behavior, and local file caveats. For a tool with this many nuances, the description is remarkably complete.
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 80% (node_id lacks a description). The description adds meaningful semantics for file (local resolution, URL handling, node_id inheritance), refresh (skip caches, no effect on .fig), and include_hidden (default false). It also indirectly clarifies node_id via the file parameter. This exceeds the schema baseline, though limit remains generic.
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 opens with 'All text content under a node (or the whole file) in reading order, with node ids', which is a specific verb and resource. It clearly distinguishes this from sibling tools like figma_get_tree or figma_get_node by focusing exclusively on text extraction and detailing instance expansion. The purpose is unambiguous and well-scoped.
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?
While the description never explicitly names alternatives or says 'use this instead of X', it strongly implies usage by describing exactly what it returns and when. The coverage of node vs. file, hidden layers, and refresh behavior makes the appropriate use cases obvious. However, it does not explicitly state what it is NOT for or compare to siblings, so it misses the top score.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_get_treeARead-only
Compact outline of the layer tree (id, type, name, size, hints). Omit node_id for all pages.
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | Path to a local .fig file, or a Figma file key / figma.com/design/... URL. A node-id in the URL is used when this tool takes node_id and it is omitted; a tool that answers about the whole file ignores it. A key or URL uses a local '<name> [<key>].fig' from FIGMA_FILES_DIRS when one exists, otherwise exports through the browser. | |
| depth | No | Levels of children below the start node (default 2). With no node_id the start is the document, whose pages are level 0, so the default shows three: pages, their top-level layers, and one level under those | |
| node_id | No | Start node id like 12:34 (or 12-34) | |
| refresh | No | Skip local/cached copies and export the live file through the browser. Has no effect when file is a path to a .fig: that file is read as it is on disk and the result carries refreshIgnored; pass the key or URL to export the live file instead. | |
| max_nodes | No | Default 400 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds behavioral context by noting the output is a 'compact outline' and that omitting node_id returns all pages, which is useful beyond the schema. However, it does not describe pagination behavior, output structure nuances, or the meaning of 'hints', so it only partially complements 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, tight sentence that front-loads the core purpose ('Compact outline of the layer tree') and immediately follows with the most important behavioral tip (omit node_id for all pages). Every word earns its place; there is no fluff or repetition.
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 read-only outline tool with a well-documented schema and safety annotations, the description conveys the essential purpose and key default behavior. It does not explicitly guide selection among the many sibling tools, but the term 'compact outline' offers enough distinction. Given the absence of an output schema, a brief note on return shape or the meaning of 'hints' would improve completeness, but the current definition is adequate for correct invocation.
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 baseline is 3. The description adds meaning beyond the schema by instructing 'Omit node_id for all pages,' which clarifies the default behavior of the node_id parameter. This is a meaningful semantic addition that helps an agent correctly use the tool without opening 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?
The description clearly states the tool retrieves a 'compact outline of the layer tree' with specific fields (id, type, name, size, hints), which identifies the verb and resource. It does not explicitly name a sibling alternative, but the phrase 'compact outline' and the instruction to omit node_id for all pages differentiate it from more detailed or targeted tools like get_node or search.
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?
The description gives one explicit usage instruction: 'Omit node_id for all pages.' This implies when the tool is appropriate (whole-file tree overview) but does not state when to prefer a sibling like get_node or token_usage, nor does it provide when-not-to-use guidance. The usage context is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_get_variablesA
Design variables (tokens) with collections, modes, per-mode values and resolved aliases. Works on any plan (no Enterprise REST API). Formats: json (default), css (custom properties, extra modes as [data-collection=mode]), dtcg (W3C design tokens). A file that defines none answers empty in that format; figma_token_usage derives tokens from the raw values instead, and figma_get_styles reads the styles.
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | Path to a local .fig file, or a Figma file key / figma.com/design/... URL. A node-id in the URL is used when this tool takes node_id and it is omitted; a tool that answers about the whole file ignores it. A key or URL uses a local '<name> [<key>].fig' from FIGMA_FILES_DIRS when one exists, otherwise exports through the browser. | |
| format | No | ||
| refresh | No | Skip local/cached copies and export the live file through the browser. Has no effect when file is a path to a .fig: that file is read as it is on disk and the result carries refreshIgnored; pass the key or URL to export the live file instead. | |
| out_file | No | Also write the result to this path | |
| collection | No | Only this collection name; a name no collection in the file has is an error listing the ones it has | |
| css_prefix | No | ||
| include_remote | No | Include library variables copied into the file (default true) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the sparse annotations (readOnlyHint false, openWorldHint true), the description discloses meaningful behavior: supported output formats and their semantics, the empty-result behavior, and the distinction from sibling tools. It also clarifies via refresh semantics that file paths are read as-is while keys/URLs may require browser export, which is useful behavioral context.
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 dense sentences deliver the core purpose, format semantics, plan availability, and sibling differentiation with no filler. Every sentence earns its place, and the most decision-relevant information is front-loaded.
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 7-parameter tool with no output schema, the description covers the key behavioral decisions: how to interpret output, how to pick among formats, what happens when no variables exist, and which sibling to choose instead. Combined with the schema's parameter descriptions, this is sufficient for correct invocation.
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?
With 71% schema coverage, the schema already documents most parameters. The description adds value by explaining the format enum (json default, css custom properties with extra modes, dtcg W3C design tokens), which maps directly to the format parameter, and by explaining which sibling tools cover alternative extraction approaches.
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 states the resource ('Design variables (tokens)') and what the tool provides: collections, modes, per-mode values, and resolved aliases. It also explicitly contrasts itself with figma_token_usage and figma_get_styles, so an agent can distinguish it from siblings without opening schemas.
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 gives clear selection guidance: use this for variables/tokens, figma_token_usage for deriving tokens from raw values, and figma_get_styles for styles. It also clarifies plan availability ('Works on any plan') and that a file with no variables answers empty in the selected format.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_list_filesARead-only
List Figma files. source=local (default): .fig files under FIGMA_FILES_DIRS, which the result names in searchedDirs. source=web: recently viewed files of the account logged in the browser. With query, totalUnfiltered says how many files there were before it.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Default 30 | |
| query | No | Case-insensitive filter on file name | |
| source | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, and the description adds valuable context about the source-specific behavior (local .fig files vs. recently viewed web files) and the totalUnfiltered field with query. This goes beyond the annotations and enriches the agent's understanding of what the tool does.
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 description is two sentences with no wasted words. It front-loads the core purpose and then efficiently explains the key nuances of source and query. Every sentence earns its place.
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?
There is no output schema, so the description should explain what the tool returns. It mentions searchedDirs and totalUnfiltered but does not describe the overall structure of the returned list (e.g., file names, paths, pagination). This leaves some ambiguity about the exact output format, making it only partially complete for a listing tool.
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 67%, and the description adds meaning to the source parameter by explaining the local/web distinction and to the query parameter by mentioning totalUnfiltered. It does not add meaning to limit, but limit is already described in the schema. Overall, it compensates well for the gaps.
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 states a specific action and resource: 'List Figma files.' It further distinguishes between local and web sources, making the tool's scope clear and distinct from siblings like figma_load_file or figma_search. The verb 'list' is precise and the resource is unambiguous.
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?
The description provides clear context on how to use the tool (source selection, query behavior) but does not explicitly mention when to choose this tool over alternatives like figma_search or figma_get_tree. Usage is implied by the purpose, but no exclusions or alternatives are named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_load_fileARead-only
Export (Save local copy) and decode a Figma file, returning a summary: pages, node counts, variable collections, styles, components. Snapshots are cached; other tools reuse them. Export of large files can take a minute. The result is dated by the copy it answers from. exportedAt is the ISO-8601 time this tool exported that snapshot through the browser: report what the design said then rather than as current, and pass refresh to export it again. For a local .fig the field is fileModifiedAt, that copy's own file time, which copying, syncing or re-downloading the file resets: the design data can be older than it says, and nothing here can date it.
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | Path to a local .fig file, or a Figma file key / figma.com/design/... URL. A node-id in the URL is used when this tool takes node_id and it is omitted; a tool that answers about the whole file ignores it. A key or URL uses a local '<name> [<key>].fig' from FIGMA_FILES_DIRS when one exists, otherwise exports through the browser. | |
| refresh | No | Skip local/cached copies and export the live file through the browser. Has no effect when file is a path to a .fig: that file is read as it is on disk and the result carries refreshIgnored; pass the key or URL to export the live file instead. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotation Contradiction: annotations mark readOnlyHint=true, but the description explicitly says 'Export (Save local copy)' and describes caching and re-exporting, which are state-writing behaviors. The description adds useful staleness context (exportedAt, fileModifiedAt, refreshIgnored), but the read-only signal is directly contradicted.
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 text is dense but well organized: purpose, caching/performance, and date semantics each get a distinct passage. It is longer than strictly needed for two parameters and repeats the export/cache idea, but every sentence carries real operational guidance.
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 snapshot/load tool with no output schema, the description covers the return summary, cache reuse, large-file latency, refresh behavior, and the fileModifiedAt staleness caveat. There is enough for an agent to call it correctly and interpret its results without inspecting siblings or schemas.
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?
Even though schema coverage is 100%, the description adds substantial meaning: node-id handling in URLs, the local '<name> [<key>].fig' fallback from FIGMA_FILES_DIRS, the distinction between live export and disk read, and refreshIgnored behavior. An agent gains much more than the bare schema would provide.
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 specific action and resource: 'Export (Save local copy) and decode a Figma file' and lists the returned summary (pages, node counts, variable collections, styles, components). It also separates this tool from the many sibling tools by presenting it as the cached snapshot source: 'Snapshots are cached; other tools reuse them.'
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 explains when to use a cached result versus refreshing ('pass refresh to export it again'), and gives a clear when-not for paths ('Has no effect when file is a path to a .fig ... pass the key or URL'). The note that other tools reuse the snapshots implies this is the intended entry-point loader.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_loginA
Ensure this project's account is logged into figma.com. If not, opens a normal (not remote-controlled) browser window on the login page; after the user logs in the window closes by itself and work continues headless. wait_seconds blocks until then.
| Name | Required | Description | Default |
|---|---|---|---|
| wait_seconds | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the annotations (readOnlyHint=false, openWorldHint=true) by disclosing that it opens a non-remote-controlled browser, that the window self-closes, that headless work resumes afterward, and that wait_seconds blocks until login completes.
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 description is two sentences with no filler. Purpose, trigger condition, user interaction, and headless continuation are front-loaded in a compact, readable form.
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 one-optional-parameter tool with no output schema, the description covers the essential behavior, UI side effect, and blocking semantics. The only noticeable gap is timeout/failure behavior, which is minor given the tool's simplicity.
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 0%, so the description must carry the parameter meaning. It states that wait_seconds blocks until login completes, which adds semantic value beyond the schema's min/max, but it does not explain the default behavior when omitted or what happens if the timeout is reached.
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 specific operation and resource ('ensure ... logged into figma.com') and explains the trigger condition ('if not') and action. It is clearly distinct from all sibling tools, none of which handle authentication or login.
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 communicates the use case (before headless work that requires an authenticated account) and behavior ('if not, opens a normal browser window'). It does not name alternatives, but no sibling tool provides this function, so no exclusions are needed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_screenshotA
Render a node to PNG using Figma's own 'Copy as PNG' in the browser (the system clipboard is not touched). Uses the live file, not the snapshot. Returns the image, downscaled to max_dimension.
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | A Figma file key or figma.com/design/... URL (a node-id in the URL is used when node_id is omitted). The image always comes from the live file in the browser, so a local .fig path works only if its name carries the key ('<name> [<key>].fig'), and is read only to tell whether node_id is a page. | |
| node_id | No | ||
| save_path | No | Also save the PNG (at returned size) to this path | |
| max_dimension | No | Longest side in px of the returned image (default 1568) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description adds valuable behavioral detail: the system clipboard is not touched, the live file is used instead of a snapshot, and the returned image is downscaled to max_dimension. This provides meaningful transparency about side effects and data source, though it doesn't cover auth or 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, each carrying distinct information: rendering method, side-effect negation, source, and output scaling. There is no filler, repetition, or unnecessary detail.
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 absence of an output schema, the description conveys the core behavior—returns an image, downscaled, from the live file—and the key side-effect it avoids. It is slightly thin on edge cases like omitted node_id or error behavior, but the schema covers file format details, so an agent has enough to call 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?
The input schema already provides descriptions for 75% of parameters, and the tool description mostly restates or reinforces that information, such as downscaling to max_dimension and using the live file. It adds little meaning beyond the schema, and node_id remains only indirectly described.
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 states a specific verb ('Render'), a resource ('a node'), and an output format ('PNG'), making the tool's purpose immediately clear. It also distinguishes itself from snapshot-based or export-related siblings by noting it uses Figma's own 'Copy as PNG' with the live file, not the snapshot.
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?
The description gives useful context, such as 'Uses the live file, not the snapshot,' which implies when this tool is appropriate, but it does not explicitly state when to use it versus alternatives or name exclusions. An agent must infer usage rather than receiving direct guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_searchARead-only
Find nodes by name (and optionally text content). The query is a literal substring, case-insensitive unless case_sensitive: a name like Icons/Arrow/Left or /Card [v2]/ matches itself. Only regex=true reads it as a pattern, bare or /pattern/flags, and an invalid pattern is an error. With include_text, component instances are expanded, so strings that only exist as instance overrides or component property values are matched too, each tagged with via (direct/instance) and, where they apply, component, variant and frame. Name matching sees only real layers: layer names inside a collapsed instance live in its main component, so search that component instead. A hit's characters is a preview: longer text is cut to its first 120 characters followed by ... and flagged charactersTruncated (truncated, next to it, is about the number of results); figma_get_text returns the strings whole. When the text pass runs, unresolvedInstances counts the instances whose text could not be resolved and so was not searched (figma_get_text names the components); it is absent when the pass did not run. The result is dated by the copy it answers from. exportedAt is the ISO-8601 time this tool exported that snapshot through the browser: report what the design said then rather than as current, and pass refresh to export it again. For a local .fig the field is fileModifiedAt, that copy's own file time, which copying, syncing or re-downloading the file resets: the design data can be older than it says, and nothing here can date it.
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | Path to a local .fig file, or a Figma file key / figma.com/design/... URL. A node-id in the URL is used when this tool takes node_id and it is omitted; a tool that answers about the whole file ignores it. A key or URL uses a local '<name> [<key>].fig' from FIGMA_FILES_DIRS when one exists, otherwise exports through the browser. | |
| page | No | Restrict to page name | |
| limit | No | Default 50 | |
| query | Yes | Name or text to find. A literal substring unless regex is set, so slashes and characters like [ ] ( ) . * match themselves | |
| regex | No | Read the query as a regex, bare or /pattern/flags, and report an invalid one. Default false: the query is a literal substring however it is written | |
| types | No | Node types to match, e.g. FRAME, COMPONENT, INSTANCE, TEXT. A list without TEXT also turns include_text off, since every text hit is a TEXT node; an empty list is no filter at all | |
| node_id | No | Search only this node and everything under it, like 12:34 (or 12-34); a node-id in the file URL is used when it is omitted | |
| refresh | No | Skip local/cached copies and export the live file through the browser. Has no effect when file is a path to a .fig: that file is read as it is on disk and the result carries refreshIgnored; pass the key or URL to export the live file instead. | |
| include_text | No | Also match text content, including text rendered inside instances | |
| case_sensitive | No | Match case (default false, for a regex too) | |
| include_hidden | No | Include text on layers hidden in the design (default false) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint=true and openWorldHint=true, so the description carries the burden of behavioral disclosure. It does this thoroughly: it discloses that the result is dated by the snapshot copy (exportedAt vs fileModifiedAt), that refresh re-exports, that characters is truncated to 120 chars with charactersTruncated flag, that unresolvedInstances counts unresolved text, and that local .fig file times can be misleading. This is rich behavioral context beyond 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense and information-rich, with the core purpose front-loaded in the first sentence. Every sentence adds meaningful behavioral detail. It is long, but the length is justified by the tool's complexity (11 parameters, subtle text-search semantics). A slight deduction for density: the paragraph on exportedAt/fileModifiedAt could be tightened, but it earns its place.
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 tool with 11 parameters, no output schema, and only readOnly/openWorld annotations, the description is remarkably complete. It covers search semantics, regex behavior, instance expansion, truncation, result dating, refresh behavior, and error conditions (invalid regex). It also names sibling tools for follow-up (figma_get_text). Nothing critical is missing for an agent to select and invoke this tool 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 description coverage is 100%, so the baseline is 3. The description adds meaning beyond the schema: it explains the interaction between types and include_text ('A list without TEXT also turns include_text off'), the semantics of regex patterns (bare or /pattern/flags), and the meaning of via tags. It doesn't enumerate every parameter, but the schema already covers them; the description adds the non-obvious interactions.
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 opens with a specific verb and resource: 'Find nodes by name (and optionally text content).' It immediately distinguishes the tool from siblings like figma_get_node and figma_get_text by stating it searches by name/text across nodes, and the rest of the description clarifies scope (literal substring vs regex, instance expansion). This is a clear, non-tautological purpose statement.
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?
The description gives explicit when-to-use guidance: it explains when regex=true is appropriate, when include_text is needed, and when to search a component instead of a collapsed instance ('Name matching sees only real layers... search that component instead'). It also names figma_get_text as the alternative for retrieving full strings, and figma_get_text for naming unresolved components. This is explicit routing to alternatives with conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_statusA
Account, browser and login state. Does not launch anything: local .fig paths never need the browser.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations are sparse (readOnlyHint=false, openWorldHint=true) and do not explain side effects. The description adds a valuable behavioral guarantee: it does not launch anything, which is safety-relevant for an agent deciding whether to call it. This goes beyond the annotations, though it does not disclose return format or network behavior.
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 short sentences with no redundancy. The core state information is front-loaded, and the clarifying no-launch note is placed immediately after.
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-parameter status tool with no output schema, the description is largely complete: it names what is reported and clarifies a key side-effect constraint. It could briefly mention what the agent will receive in the response, but the low complexity keeps this from being a major gap.
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?
The tool has zero parameters and the schema is an empty object with 100% coverage, so there is nothing the description needs to add. The 0-parameter baseline of 4 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?
The description identifies the resource as 'account, browser and login state', which clearly signals a status-checking tool. It lacks an explicit verb like 'reports' or 'checks', but the follow-up 'Does not launch anything' differentiates it from file-loading and login 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?
There is no explicit when-to-use guidance or mention of alternatives. The note about local .fig paths never needing the browser implies a use context, but the description never says 'use this to verify login state before...' or contrasts it with figma_login or figma_load_file.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_token_usageARead-only
Scan a subtree (or whole file) and aggregate the raw design values actually used: colors, typography combos, corner radii, auto-layout gaps/paddings, stroke widths, effects, each with counts and the variable/style bound where present. Useful to derive a token set from files that do not define variables or styles. A typography entry carries only the properties the file records, and always at least one: text that records none of them is counted in textWithoutTypography instead, so it is accounted for without standing in the list as an entry naming no value. The result is dated by the copy it answers from. exportedAt is the ISO-8601 time this tool exported that snapshot through the browser: report what the design said then rather than as current, and pass refresh to export it again. For a local .fig the field is fileModifiedAt, that copy's own file time, which copying, syncing or re-downloading the file resets: the design data can be older than it says, and nothing here can date it.
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | Path to a local .fig file, or a Figma file key / figma.com/design/... URL. A node-id in the URL is used when this tool takes node_id and it is omitted; a tool that answers about the whole file ignores it. A key or URL uses a local '<name> [<key>].fig' from FIGMA_FILES_DIRS when one exists, otherwise exports through the browser. | |
| node_id | No | ||
| refresh | No | Skip local/cached copies and export the live file through the browser. Has no effect when file is a path to a .fig: that file is read as it is on disk and the result carries refreshIgnored; pass the key or URL to export the live file instead. | |
| min_count | No | Drop values used fewer times (default 1) | |
| include_hidden | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only say readOnlyHint and openWorldHint; the description adds substantial behavioral context: counts, variable/style binding, typography edge cases, textWithoutTypography accounting, exportedAt/fileModifiedAt meaning, and the local-file staleness trap. This far exceeds what structured annotations provide and correctly aligns with readOnlyHint.
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 description is front-loaded with the core purpose and use case, then adds genuinely necessary caveats about timestamps, typography, and refresh. It is dense and somewhat tangled, but every sentence earns its place given the absence of an output 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?
The description covers result composition, counting semantics, typography edge cases, and snapshot timing, which is strong given no output schema. It still leaves node_id and include_hidden behavior underspecified, though their schema types provide some basic signal.
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 60%, and the tool description supplements refresh semantics and subtree scoping, but node_id and include_hidden are left to their bare schema types. The file parameter's key/URL/path nuance is largely schema-provided; the description adds a little extra but does not fully compensate for the undocumented parameters.
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 states a precise operation: scan a subtree or whole file and aggregate raw design values actually used, listing the value categories and counts. It also distinguishes the tool's purpose from variable/style-based tools, making it easy for an agent to tell it apart from siblings like figma_get_variables and figma_get_styles.
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 gives an explicit intended use—'derive a token set from files that do not define variables or styles'—and explains when to pass refresh versus when it is ignored. It implies alternatives but does not explicitly name them or give when-not-to-use conditions, so it falls just short of a 5.
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_export_image_fills - First observed
figma_get_components - First observed
figma_get_node - First observed
figma_get_styles - First observed
figma_get_text - First observed
figma_get_tree - First observed
figma_get_variables - First observed
figma_list_files - First observed
figma_load_file - First observed
figma_login - First observed
figma_screenshot - First observed
figma_search - First observed
figma_status - First observed
figma_token_usage
TDQS
Scored across 14 tools
Each tool has a clearly distinct purpose: auth, file listing/loading, tree/node access, search, text extraction, variables/styles/components, token usage, screenshot, and image export. Where tools seem adjacent (search vs. get_text, get_tree vs. get_node), the descriptions make the boundary explicit.
All tools share the figma_ prefix and follow a consistent verb_noun pattern: list_files, load_file, get_tree, get_node, get_text, get_variables, get_styles, get_components, export_image_fills. Even the less noun-like names like figma_status and figma_login fit the predictable style.
14 tools is well within the ideal range for a reader-focused server. Each tool covers a meaningful slice of Figma reading/export functionality without redundancy or bloat.
The surface covers the full read lifecycle: file discovery and loading, structural traversal, node-level design details, text and search, design tokens/styles/components, usage analysis, rendering, and bitmap asset export. For a "reader" server, there are no obvious dead ends or missing operations.
Related MCP Connectors
OCR, transcription, file extraction, and image generation for AI agents via MCP.
Read-only MCP tools for AI agent discovery, structured resources, and NIULAI information.
Read-only MCP server: let AI agents read your ORANO saved-video library, tasks, and memory.
Read-only MCP server exposing a user ORANO library to their own AI agent.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceMCP server for the Figma API. Lets AI agents fetch designs, nodes, and rendered images from Figma.1,589 npm-
- FlicenseNot gradedqualityCmaintenanceRead-only MCP server that wraps the Figma REST API, providing tools like get file metadata, list frames, and export node image URLs for AI SDLC agents.-

Figma MCP Serverofficial
FlicenseNot gradedqualityBmaintenanceProvides Figma design context to AI agents, enabling code generation, design system integration, and canvas manipulation through MCP.2,014-- FlicenseNot gradedqualityBmaintenanceEnables AI agents to access Figma design context, generate code from frames, extract variables, components, and layout data, and create or modify Figma files directly from MCP clients.-