figma-reader-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| FIGMA_ACCOUNT | No | Account: which Figma login and snapshot cache to use. Default: from .figma-reader.json, else 'default'. | |
| FIGMA_CDP_URL | No | Attach to a running browser instead of launching. Default: unset. | |
| FIGMA_HEADLESS | No | Set to '0' to keep the work browser visible. Default: '1'. | |
| FIGMA_FILES_DIRS | No | Colon-separated dirs scanned (2 levels) for .fig files. Default: filesDirs from .figma-reader.json, else ~/Downloads. | |
| FIGMA_BROWSER_PATH | No | Browser executable. Default: Brave > Chromium > Chrome > Playwright. | |
| FIGMA_READER_CACHE | No | Root of the snapshot cache. Default: ~/.cache/figma-reader. | |
| FIGMA_USER_DATA_DIR | No | Browser profile holding the Figma login. Default: ~/.local/share/figma-reader/accounts/<account>/profile-<browser>. | |
| FIGMA_SNAPSHOT_MAX_AGE_MIN | No | Re-export after this age (minutes). Default: '30'. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| figma_statusA | Account, browser and login state. Does not launch anything: local .fig paths never need the browser. |
| 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. |
| figma_list_filesA | 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. |
| figma_load_fileB | 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. For a snapshot exported through the browser, snapshotPath is its .fig in the cache, which the next export of the key replaces. Read by that path, it is never exported again, but it is dated fileModifiedAt and names no account like any local file: for a task's calls keep passing the key, and say so if exportedAt changes between them. Dated by exportedAt and account, or fileModifiedAt for a file read from disk, as the server's instructions say (figma-reader help on the command line). |
| figma_get_treeA | Compact outline of the layer tree (id, type, name, size, hints such as ready for dev). Omit node_id for all pages. The first line is a header, '# ' followed by a JSON object holding its date (see below); the outline starts on the second line. max_nodes goes to one level before the next (pages, then top-level layers, then what is under them), so a large first section cannot crowd out later pages. A branch cut short ends in a '- ... N more children' line, a layer whose children were all left out says '(N children)', and the last line says it was truncated; when a level could not give each of its layers one line, it is left out whole and the last line says so instead: 'level 2 not shown: 40 layers have children, 30 of 400 lines left; open one with node_id, or pass max_nodes 450' (levels counted as depth counts them). A layer drawn only with vector shapes, however they are grouped, is one line counting them all, '(27 vectors)': pass its node_id to open it. Dated by exportedAt and account, or fileModifiedAt for a file read from disk, as the server's instructions say (figma-reader help on the command line). |
| figma_get_nodeA | 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). Dev Mode's handoff data where a node has it: devStatus as figma_dev_status describes it, annotations (label as markdown, category, the properties pinned) and measurements (from/to node ids and sides; the distance itself is not stored). devStatus is absent on a node never marked: a record that is none and was none, with no user or note on it, is one Figma keeps on components nobody marked, and only figma_dev_status with status none or any lists it. Where path does not split on ' / ' into its names, pathIds follows it: one id per name, page first. Dated by exportedAt and account, or fileModifiedAt for a file read from disk, as the server's instructions say (figma-reader help on the command line). |
| figma_locateA | Look up a list of node ids in one call, such as the ids a document or an earlier answer cites. One entry per id, in the order given, with the id written 12:34 whichever spelling was passed: {id, found: true, type, name, page, path} for a node the file has (path from the page down, as figma_get_node gives it), {id, found: false} for one it has not, and {id, error} for a string that is not a node id. found, missing and invalid count the entries. found: false is said only of a file that was read: one that cannot be read fails the whole call. Where path does not split on ' / ' into its names, pathIds follows it: one id per name, page first. Dated by exportedAt and account, or fileModifiedAt for a file read from disk, as the server's instructions say (figma-reader help on the command line). |
| figma_searchA | 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. Pages in exclude_pages, or by default in the project's excludePages, are skipped before the limit is counted; excludedPages names the ones this search left out. Dated by exportedAt and account, or fileModifiedAt for a file read from disk, as the server's instructions say (figma-reader help on the command line). |
| 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. |
| 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. |
| figma_get_componentsA | 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. Dated by exportedAt and account, or fileModifiedAt for a file read from disk, as the server's instructions say (figma-reader help on the command line). |
| figma_dev_statusA | Dev Mode status: the nodes marked Ready for dev or Completed, and those unmarked since, newest change first. Read off each frame's, section's or component's own status record; each entry has id, type, name, page, path and the fields figma_get_node reports as devStatus: status (ready_for_dev, completed, none, or unknown for a value this decoder has no name for), raw (the value Figma stores: BUILD for Ready for dev, COMPLETED for Completed), previous and previousRaw, changedAt (ISO-8601), and by (a Figma user id) and note when the record has them. status none with a previous status other than none is a mark that came off at changedAt; none with previous none is a record Figma keeps on a node never marked, listed only with status none or any unless a user or note on it says a person left it. With no status given, neverMarked counts those records the listing left out (absent when it left none out); status any lists them. Internal-only pages, soft-deleted nodes and superseded library copies are left out. Where path does not split on ' / ' into its names, pathIds follows it: one id per name, page first. Dated by exportedAt and account, or fileModifiedAt for a file read from disk, as the server's instructions say (figma-reader help on the command line). |
| figma_token_usageA | 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. Dated by exportedAt and account, or fileModifiedAt for a file read from disk, as the server's instructions say (figma-reader help on the command line). |
| figma_get_textA | 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. Without page, or a node_id other than the document's own (0:0), it reads every page but exclude_pages (never the project's excludePages) and shares limit between them, so one cannot crowd out the rest; byPage gives each page's returned and total: pass page for one cut short. Dated by exportedAt and account, or fileModifiedAt for a file read from disk, as the server's instructions say (figma-reader help on the command line). |
| 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, and a note that ends with the Figma account it was rendered through. |
| figma_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. |
| figma_diffA | Compare two snapshots of one file by node id. Figma keeps a node's id through renames and moves, so the id says what is the same layer: pages added, removed or renamed; top-level layers (a page's children, and the children of its sections) added, removed, renamed (same id, other name) or moved (same id, other parent, so a move to another page shows in from.page/to.page; a layer carried inside a moved section keeps its parent and is not listed); and removedNodes, the topmost node of each subtree gone from the visible pages, with the page and path it had and removedCount, how many nodes went with it (itself included); figma_locate on old and new answers for any id under it. Only ids, names and parents are compared: an edit to text, fills, sizes or any other property is reported nowhere. byPage counts each page's added, removed, renamed, moved (moved in; movedOut, moved from it to another page) and removedNodes, every page counted, excluded ones too: read it, then pass page for the one you need. page or exclude_pages (default: the project's excludePages, echoed as excludedPages) narrow the lists before the limit. Every list stops at limit, shared between the pages it covers so a page with many changes cannot crowd out the rest; counts has each total, and truncated says whether any list was cut. A node created and deleted between the two snapshots is in neither. old may be the word previous: the snapshot this account's cache held for new's key before its latest export (one per key, kept by every export that replaces a snapshot). new is then read from that cache, never from a local copy, and refresh exports it again first, which keeps the snapshot it replaces as previous: so 'previous ' with refresh compares the last export with the live file. old and new are each dated, as the server's instructions say: report the changes as between those two times. Where path does not split on ' / ' into its names, pathIds follows it: one id per name, page first. |
| figma_changesA | Top-level layers created or edited since a date or duration, from Figma's edit times per node. A top-level layer is a page's child or a child of its sections, rolled up from everything under it: lastEditedAt is the newest time in it, editedNodes how many of its nodes were created or edited at or after since, created whether the layer itself was; page and path say where it is. Newest first; the editedNodes beside the list counts each such node once. This is edit metadata from one snapshot: it shows nothing deleted (figma_diff lists removals) and never what an edit was, only when. A node that records no time counts only where Figma also moved an ancestor's; undatedNodes counts those, and text layers are among them in every export seen. byPage counts each page's layers and editedNodes, every page counted, excluded ones too; page or exclude_pages (default: the project's excludePages, echoed as excludedPages) narrow the list and its counts before the limit, which is shared between pages so one page cannot crowd out the rest. Where path does not split on ' / ' into its names, pathIds follows it: one id per name, page first. Dated by exportedAt and account, or fileModifiedAt for a file read from disk, as the server's instructions say (figma-reader help on the command line). |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 18 tools
Most tools target clearly distinct resources or actions (get_text, get_styles, get_variables, search, screenshot, diff, changes). Some overlap exists among node-inspection tools (get_node, get_tree, locate) and token-related tools (get_styles, get_variables, token_usage), but the descriptions carefully distinguish their scopes and output formats.
All names share a consistent figma_ prefix and snake_case formatting with mostly verb_noun patterns. A few are noun phrases (figma_screenshot, figma_status, figma_changes) or noun-based (figma_dev_status, figma_token_usage), which is a minor deviation from a strict verb_noun convention.
Eighteen tools is slightly heavy for a read-only Figma reader, but each covers a genuinely distinct part of the domain (loading, tree/node inspection, text, styles, variables, components, search, screenshots, image exports, diffs, change history, account state). The breadth justifies the count more than it bloats the surface.
The surface covers the core read lifecycle very well: export/load, inspect nodes and text, extract styles/variables/components, search, screenshot, export image fills, diff snapshots, and track changes. Minor gaps exist, such as reading Figma comments or version metadata, but agents can work around them for typical read-only tasks.