# figsnap-mcp [Health: Active]

**Category:** 📐 Architecture & Design  
**Repository:** https://github.com/arimunandar/figsnap-mcp  
**GitHub Stars:** 0  
**npm Downloads (last month):** 235  
**Views:** 1  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/figsnap-mcp

## Description
The Figma file you have open, as MCP tools. Extract, edit, and keep a saved set.

## Tools
Capabilities this server exposes over MCP:

- **figma_get_selection** — The layers the designer has selected on the canvas right now, with their ids, names, types and sizes. Start here when the request says "this", "the selected frame", or names nothing at all.
- **figma_get_tree** — The top-level layers of the page the designer is looking at. Increase depth to walk further down, but note that a deep page is thousands of rows: prefer figma_get_children on one branch.
- **figma_get_children** — The direct children of one node, by id. The cheap way to explore a page a branch at a time.
- **figma_extract** — The full extraction of one node: HTML measured against what Figma draws, byte-exact figmaCss, a React component, plain CSS and CSS modules. Images are inlined and icons come out as real SVG, so the HTML stands on its own. This is the tool that answers "what does this design actually say".

Several nodes at once, instead of one call each: nodeIds, urls, selection: true, or saved: true with an optional folder. A batch answers {results:[…]}, one entry per input, each {ok:true,extraction} or {ok:false,error}, so one bad id never sinks the rest. It is capped at 20 entries, and no batch returns an image — ask figma_export_png for a picture, a node at a time.
- **figma_export_png** — Renders one node and returns the picture itself, so a model that can see gets to look at the design rather than read a description of it. Nothing is stored anywhere.
- **figma_resolve_url** — Turns one or more Figma links into the nodes they name, without exporting anything.
- **figma_list_saved** — The nodes the designer curated in the panel, by folder. A shortlist of what matters in this file, which is usually a better starting point than the whole page.
- **figma_saved** — Read and change the designer’s shortlist of nodes in this file, and the folders it is grouped into. One action argument: list, folders, save, unsave, clear, move, newFolder, renameFolder, deleteFolder.

list — the entries, optionally in one folder. folders — the folders with their counts; "" is the root. save — add nodeIds, or whatever is selected when you give none. unsave — remove nodeIds. clear — empty one folder, or the whole set when you name none. move — put nodeIds in folder. newFolder / renameFolder / deleteFolder — the folders themselves; deleteFolder keeps the entries and returns them to the root unless deleteEntries is true.

This is a bookmark list, not the design: it lives in the plugin’s own storage, so none of it is behind the Edits switch and none of it can be undone with Cmd-Z. Saving what a long job is about is a cheap way to leave the designer something to look at afterwards.
- **figma_list_library** — The components, styles and variables this file has, with the ids the other tools need. Read this before "make it match our button" or "use our brand colour" — instantiating the real component or binding the real variable is what makes a change survive contact with the design system, rather than a hex code that looks right today.
- **figma_select** — Selects one or more layers and scrolls the canvas to them, so the designer is looking at whatever you are talking about. Use it before describing a node you found by walking the tree — pointing is faster than naming an id — and after an edit, so the change is on screen.

It changes no design data, which is why it works whether or not Edits is on, and why it leaves no undo step. It does move the designer’s viewport, so say what you are showing them.
- **figma_set_fill** — Replaces a node’s fills with one solid colour, and answers with the colour read back off the node — so a write that did not land is visible without a screenshot. It replaces every fill the node had, which is worth knowing before pointing it at a gradient or a photograph; the answer names what was there. Borders are strokes, not fills: use figma_set_stroke for those. One call is one undo step, so the designer takes it back with a single Cmd-Z.
- **figma_set_stroke** — Replaces a node’s strokes with one solid colour, and optionally sets the stroke weight. Pass remove: true to take the stroke off entirely. Borders in Figma are strokes, not fills — a row outline or an icon drawn as an outline needs this rather than figma_set_fill.
- **figma_set_text** — Replaces the text of one TEXT node. The font is loaded first; a layer whose font is missing from this machine is refused rather than silently retyped in a substitute.
- **figma_set_auto_layout** — Turns auto layout on for a frame and sets its direction, spacing, padding and alignment. Pass mode "NONE" to turn it off. Only the properties you name are changed.
- **figma_create_frame** — Creates an empty frame, on the current page or inside a parent you name. Returns the new node’s id so the next call can fill it.
- **figma_create_text** — Creates a TEXT layer with the words you give it. The font is loaded before anything is typed, and a font this machine does not have is refused rather than substituted. Give a width to make it wrap; without one it hugs its text.
- **figma_create_rectangle** — Creates a rectangle. The workhorse shape: dividers, bars, backgrounds, placeholders. Omit the fill for an empty one.
- **figma_create_ellipse** — Creates an ellipse. Equal width and height give a circle — an avatar, a dot, a radio button.
- **figma_create_svg** — Turns SVG markup into real Figma vectors — not an image, but editable paths in a frame. This is how to add an icon, a logo or any shape the other create tools cannot express. Extraction returns icons as SVG too, so a shape can be read out of one place and drawn into another unchanged.
- **figma_create_instance** — Creates an instance of a component in this file. Get the id from figma_list_library. Naming a variant set places its default variant. Prefer this over drawing a lookalike: an instance keeps its link to the component and updates with it.
- **figma_clone_node** — Copies a node, with everything inside it, into the same parent or one you name. The cheapest way to make a second row, card or list item that matches the first exactly.
- **figma_move_node** — Moves a node into another parent, or to a different position among its siblings. Index 0 is the back of the canvas and the top of a layer list; leaving it out puts the node last.
- **figma_delete_node** — Removes a node and everything inside it. One undo step, so the designer can take it back with a single Cmd-Z — but say what you are deleting before you do it.
- **figma_set_bounds** — Sets position and size. Position is ignored inside an auto-layout frame, where the parent decides it — use figma_set_layout_sizing and the parent’s spacing there instead.
- **figma_set_corner_radius** — Sets one radius for every corner, or each corner on its own.
- **figma_set_node_name** — Renames a layer. Layer names are what the generated code turns into class names, so tidying them is a real change and not cosmetic.
- **figma_set_visibility** — Sets opacity, visibility and lock. Hidden layers are skipped by extraction, which is often the point.
- **figma_set_effects** — Replaces a node’s effects with the list you give. An empty list clears them. Elevation in most design systems is a drop shadow, so this is what "make it look raised" means.
- **figma_set_text_style** — Font, size, line height, letter spacing, alignment and colour, on a TEXT layer. Only what you name is changed. Prefer figma_apply_style where the file has a text style for it — a named style survives a redesign and a hard-coded 14px does not.
- **figma_set_layout_sizing** — How a child behaves inside an auto-layout frame: HUG shrinks to its contents, FILL stretches to the parent, FIXED keeps its size. This, not figma_set_bounds, is how widths are set inside auto layout.
- **figma_apply_style** — Applies a paint, text or effect style from this file by id, from figma_list_library. The right way to make something "match": the layer follows the style afterwards, where a copied hex code does not.
- **figma_bind_variable** — Binds a variable from this file to a property, so the value follows the token rather than being a copy of it. Use "fill" or "stroke" for a colour variable; for a number use the property name, like cornerRadius, itemSpacing, paddingLeft, width or opacity.
- **figma_save_version** — Saves a named point in the file’s version history. Call this before a run that will change several things, so there is one place to fall back to that is not a stack of undos.
- **figma_find_nodes** — Finds layers by type, by name and by the words in them. Every filter is optional and they narrow together.

This is the cheap way to locate something. Walking with figma_get_tree and figma_get_children costs a round trip per level and returns every sibling; asking here for {types:["INSTANCE"], name:"button"} costs one call. Searches the current page unless you pass nodeId to search inside one branch, or allPages to search the whole file — which is the only way to find something that is not on the page the designer happens to have open.
- **figma_pages** — list — every page in the file, and which is current. open — switch to one, by pageId or by name.

Worth calling before concluding something is missing: every other reading tool answers about the current page only, so a frame on another page looks exactly like a frame that does not exist. Opening a page moves the designer’s view, which is the same kind of act as figma_select — nothing in the file changes and there is nothing to undo, so it is not behind the Edits switch.
- **figma_component_properties** — The properties a component, component set or instance has: the variants, and the text, boolean and instance-swap properties, with what this instance currently has them set to.

Call this before figma_set_instance_properties. The key that setter needs carries an id suffix for everything but a variant — "Label#8:2", not "Label" — and there is no way to guess it.
- **figma_group** — group — puts nodeIds in a new group, inside the first one’s own parent. ungroup — dissolves a group or frame and returns the children it let go.

A group is the honest answer when several layers are one thing but need no layout of their own; reach for figma_create_frame with auto layout when they do.
- **figma_insert_image** — Places a PNG, JPG or GIF, passed as base64. With nodeId it becomes that layer’s fill, which is how a placeholder gets its picture; without one it arrives as a new rectangle at its own pixel size.

Base64 rather than a URL on purpose: the plugin’s manifest allows only the relay and the local daemon as network destinations, so the plugin cannot fetch an image from anywhere a designer keeps one. Read the file yourself and send the bytes. The cap is 700KB of base64, which is roughly a 500KB image.
- **figma_set_instance_properties** — Sets which variant an instance is, and the text and booleans its component exposes. Take the keys from figma_component_properties; a key given without its id suffix is matched anyway, and one that matches nothing is refused with the list of what does.

This is the difference between placing a component and using it. figma_create_instance gives you the default variant — this is how it becomes the large one, or the disabled one, with the right label.
- **figma_ios_spec** — One node and its children as the properties Figma actually holds, in points: per-axis sizing, auto layout with its padding, stroke weight and alignment, corner smoothing, effects, the whole text block, and every fill and stroke marked with whether it is painted.

Read this rather than figmaCss when the answer becomes code. Dev Mode CSS answers what a node would look like on the web, which drops what an implementation needs — which side of the bounds a stroke sits on, whether a height was authored or measured, whether the corners are smoothed — and it also reports paint that is never painted: a stroke switched off still comes back as "border: 1px solid". Here a fill or stroke carries `painted`, so a border that is not drawn cannot be mistaken for one that is.

A stroke also reports layoutFrame and visualFrame, because a CENTER stroke puts half its weight outside the bounds and UIKit draws borders inside them. Effects report uikitShadowRadius, which is half the blur. And the answer names the scale it read: a 750-wide artboard is a 375pt design drawn at 2x, and treating it as points doubles every number silently.

One limit worth knowing: a gradient paint reports its type, opacity and whether it is painted, but not its stops — so you learn a gradient is there and cannot yet reproduce it. Ask figma_export_png for the node and read the colours off the render until that lands.
- **figsnap_skill** — Whether this project has the figsnap skill installed, and the skill itself when it does not.

The skill is what stops the usual mistakes: an agent handed figmaCss gets the geometry right and the type wrong, because Dev Mode CSS cannot say whether a height was authored or measured, which side of the bounds a stroke sits on, or that line-height is a box rather than a font metric. It also carries the artboard-to-device widths, the frame-versus-glyph padding an icon export has to keep, and the fact that a design system’s font is probably not on iOS.

install answers with the file and where it goes; it does not write it. Whatever is calling this already asks before it writes into a repository, which is the right place for that question. Statuses are missing, current, or modified — an edited skill is the caller’s, so it is reported rather than replaced.

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `npx` (confidence: high):

```json
"mcpServers": {
  "figsnap-mcp": {
    "command": "npx",
    "args": ["-y","figsnap-mcp"],
    "env": {
      "FIGSNAP_MCP_TOKEN": "",
      "FIGSNAP_MCP_URL": ""
    }
  }
}
```

**Requires environment variables:** `FIGSNAP_MCP_TOKEN`, `FIGSNAP_MCP_URL` — the values above are empty placeholders; fill in real credentials before running (see the repository for what each one is for).

## Documentation

## What figsnap-mcp MCP server does

The figsnap-mcp MCP server connects an MCP client to the Figma file currently open in Figma desktop. Its tool set can inspect the design, extract selected nodes as PNG, React, HTML, or CSS, edit the canvas when editing is enabled, and share a saved set of components. The package contains the MCP server, a local daemon, and the Figma plugin needed to connect them.

The project is intentionally limited to this workflow. It does not include the broader Figsnap ACP client, relay, account system, chat interface, API browser, session store, harness discovery, or code-export UI.

## How it works

The MCP client starts `figsnap-mcp` over stdio. That process acts as a stateless proxy to the local daemon, which listens on port 3058. The daemon maintains a WebSocket connection to the plugin panel running inside Figma. Figma-specific `figma.*` access is available only while the plugin is open.

The daemon binds to loopback and uses a token for authenticated communication. On first launch it creates a token at `~/.figsnap-mcp/agent-token` with restrictive permissions, then reuses it on later launches. The MCP client normally reads this file itself, so the client configuration does not need a token. The panel receives the token once through its Connect pane and stores the connection details in Figma storage.

## Setup and configuration

Install the package globally or let an MCP client fetch it with `npx`:

```bash
npm install -g figsnap-mcp
```

Start the bridge with `figsnap-mcp-daemon`, then import the package's `manifest.json` into Figma desktop through Plugins → Development → Import plugin from manifest. Run the Figsnap MCP plugin, paste the daemon token into its Connect pane, and connect it. Finally, register the stdio process with the MCP client:

```bash
claude mcp add figsnap-mcp -s user -- npx -y figsnap-mcp
```

A health request to `http://127.0.0.1:3058/health` can confirm that the daemon and plugin are connected. Start the daemon with `--allow-edits` or enable Allow edits in the plugin when write operations are needed.

`FIGSNAP_MCP_TOKEN` supplies a fixed token instead of the token file. `FIGSNAP_MCP_URL` changes the address used by the MCP client. The daemon supports token rotation with `--new-token`.

## Tools and capabilities

The figsnap-mcp MCP server provides 41 tools covering the following supported operations:

- Read information from the open Figma file and current canvas context.
- Extract a node as PNG, React, HTML, or CSS.
- Edit the Figma canvas when editing is enabled.
- Maintain and share a saved set of components.

The exact available responses depend on the plugin being open and connected to the daemon. With the plugin closed, the MCP process cannot reach Figma's `figma.*` interface.

## Limitations and notes

The daemon and plugin must both be running; installing or registering the MCP process alone does not provide Figma data. Editing is disabled by default unless enabled in the plugin or at daemon startup. The connection is local-only, using loopback port 3058, and this package does not provide a relay, login, or network service.

The plugin manifest must use `localhost` in its allowed domains rather than a literal `127.0.0.1` address, because Figma can reject an IP literal in that field. The project can run beside Figsnap, but it uses its own port, token path, plugin identifier, and prefixed storage keys.

_Full upstream README: https://allmcps.com/mcp/figsnap-mcp/readme_

