# figma-mcp-go [Health: Active]

**Category:** 📐 Architecture & Design  
**Repository:** https://github.com/tunglt1810/figma-mcp-go  
**GitHub Stars:** 16  
**npm Downloads (last month):** 1219  
**Views:** 6  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/figma-mcp-go

## Description
Figma MCP server with full read/write access via plugin — no API token, no rate limits. 73 tools.

## Tools
Capabilities this server exposes over MCP:

- **apply_style_to_node** — Apply a local style to a node.
- **batch_execute_pipeline** — Run write steps in order. A step can use earlier results through $variables. With stop_on_error, a failure undoes created nodes and changed properties, but not deletes, group/ungroup, detach, reparent, or steps that target nodes by name.
- **batch_rename_nodes** — Rename nodes: set `name`, or find/replace (regex allowed), or prefix/suffix. `name` cannot mix with the others.
- **boolean_operation** — Combine 2+ shapes (same parent): UNION, SUBTRACT (cut the rest from the first), INTERSECT, or EXCLUDE. Pipeline rollback cannot undo it.
- **clone_node** — Copy a node, optionally to a new position or parent.
- **combine_as_variants** — Combine 2+ components (same parent) into a variant set. Add VARIANT properties with manage_component_properties.
- **create_component** — Turn a FRAME into a COMPONENT, in place.
- **create_component_instance** — Create an instance of a local (componentId) or library (componentKey) component. A component set uses its default variant.
- **create_connector** — Create a connector line. This tool operates only in a FigJam file.
- **create_node** — Create a shape. Args per `type`: FRAME: width, height, fillColor, auto layout args. RECTANGLE: width, height, fillColor, cornerRadius. ELLIPSE: width, height, fillColor, startAngle, endAngle, innerRadiusRatio. STAR: pointCount, outerRadius, innerRadius, fillColor, cornerRadius. POLYGON: pointCount, radius, fillColor, cornerRadius. LINE: length, rotation, strokeColor, strokeWeight. SECTION: width, height (no parent). All: x, y, name. The tool rejects other args. For text, use create_text.
- **create_style** — Create a local style. Args per `type`: PAINT: color. TEXT: fontSize, fontFamily, fontStyle, textDecoration, lineHeightValue/Unit, letterSpacingValue/Unit. EFFECT: effectType, color, opacity, radius, offsetX, offsetY, spread. GRID: pattern, count, gutterSize, offset, alignment, sectionSize, color, opacity. The tool returns the style ID. Apply the style with apply_style_to_node.
- **create_text** — Create a text node (loads the font). To edit text, use set_text.
- **create_vector** — Create a vector from SVG markup (e.g. an icon). Several paths become a frame of vectors.
- **delete_nodes** — Delete nodes. You cannot undo this from here.
- **delete_style** — Delete a style by ID.
- **detach_instance** — Detach instances into plain frames (same look, no component link).
- **export_frames_to_pdf** — Export frames as one PDF, one page per frame, in order.
- **export_screenshots** — Export nodes as images. The tool saves items with outputPath to file. It returns the other items (PNG/JPG as image, SVG as text, PDF as base64). Without items, the tool exports the selection. Prefer outputPath if you only need the file.
- **export_tokens** — Export variables and paint styles as JSON or CSS variables.
- **find_replace_text** — Find and replace text in TEXT nodes, on the current page or inside nodeId.
- **flatten_nodes** — Merge nodes (same parent) into one vector. Pipeline rollback cannot undo it.
- **get_annotations** — Get Dev Mode annotations on the page, or on one node and its children.
- **get_document** — Get the node tree of the selection, page, or file (`scope`). The tool returns {fileName, scope, currentPage, nodes}. The tool stops at 500 nodes by default. It then sets `truncated`, and nodes with hidden children show `childCount`.
- **get_fonts** — List fonts used on the current page, most used first.
- **get_image_bytes** — Get the original image files in nodes' image fills, as base64. The tool returns each image once. Nodes without images go in `skipped`. To see how a node looks, use export_screenshots.
- **get_instance_overrides** — Get an instance's component properties with type and value. Use this tool before set_instance_overrides.
- **get_local_components** — Get all components in the file.
- **get_metadata** — Get file name, current page, and all pages (ID, name). The tool loads no node trees.
- **get_nodes_info** — Get full node details by ID. The tool returns {nodes}, plus globalVars.styles for repeated fills/strokes. Unknown IDs go in `missing`. The tool stops at 500 descendants by default. It then sets `truncated` and `childCount`.
- **get_reactions** — Get a node's prototype reactions (trigger + actions). Edit them with set_reactions.
- **get_selection** — Get selected nodes, or nodes pinned in the plugin panel. The result is [] if there are none. For detail, use get_nodes_info.
- **get_styles** — Get local styles (paint, text, effect, grid) with ID, name, type, values. For variables, use get_variable_defs.
- **get_variable_defs** — Get local variables (design tokens): collections, modes, values.
- **get_viewport** — Get viewport center, zoom, and visible bounds.
- **group_nodes** — Group 2+ nodes that share a parent.
- **import_image** — Add an image from a URL (preferred) or base64, as a rectangle sized to the image, or as nodeId's fill.
- **manage_component_properties** — Add, edit, delete, or bind component properties. bind links a layer: BOOLEAN shows/hides it, TEXT sets its text, INSTANCE_SWAP swaps it. Names work without the '#1:2' suffix.
- **manage_page** — Add, delete, rename, or go to a page. Args per `action`: add: name, index. delete, navigate: pageId or pageName. rename: pageId or pageName, newName. List pages with get_metadata.
- **manage_plugin_data** — Store string key/values on a node, saved in the file. Use JSON for complex values.
- **manage_variable** — Manage variables (design tokens). Args per `action`: create_collection: name, initialModeName. add_mode: collectionId, modeName. create: name, collectionId, type, value. set_value: variableId, modeId, value. delete: variableId, or collectionId (deletes all its variables). bind: nodeId, variableId, field (node property to link). Get IDs from get_variable_defs. Free plan: 1 mode per collection. If add_mode fails with 'Limited to 1 modes only', do not retry. Put the mode in the name (e.g. 'light/bg') and tell the user multi-mode needs a paid plan.
- **outline_stroke** — Turn each node's stroke into a filled shape. Nodes without a stroke go in `skipped`.
- **reparent_nodes** — Move nodes into another frame, group, or section.
- **save_version_checkpoint** — Save a named version in file history, before big or risky changes. This tool operates only in a Design file.
- **search_nodes** — Find nodes by name, type, or both, on the current page by default. The tool returns up to `limit` nodes (default 50). It sets `truncated` if there are more.
- **set_annotations** — Set Dev Mode annotations on nodes ([] clears them). The tool needs a paid Dev Mode seat.
- **set_auto_layout** — Set auto layout (flexbox) on frames, components or instances: direction, padding, gap, align, sizing (HUG/FILL with layoutSizing*). layoutPositioning, layoutAlign, layoutGrow set how a node sits in its parent. Results are per node.
- **set_codegen_result** — Save code on a node for Dev Mode's Code panel. The whole team sees it. Code on a component shows on its instances. [] removes the code.
- **set_effects** — Replace a node's effects ([] clears them), in the shape of get_nodes_info's styles.effects.
- **set_export_settings** — Set a node's Export presets. This tool does not export. To export, use export_screenshots.
- **set_instance_overrides** — Set an instance's component properties. The tool fails on unknown names or wrong types.
- **set_layout_grids** — Set layout grids (columns, rows, square) on frames. [] removes them.
- **set_node_properties** — Set node properties: position, size, radius, visibility, lock, opacity, rotation, blend, constraints, z-order, mask, stroke. Pass only what changes. Results are per node.
- **set_paint** — Set a node's fill or stroke. SOLID: color, opacity. GRADIENT_*: stops, geometry, opacity.
- **set_reactions** — Set or remove prototype reactions. mode: replace (default) or append. To remove, pass removeIndices (from get_reactions, [] = all), not reactions.

Reaction: {"trigger":{"type":...},"actions":[...]}.
Triggers: ON_CLICK, ON_HOVER, ON_PRESS, ON_DRAG, AFTER_TIMEOUT (+timeout ms), MOUSE_ENTER, MOUSE_LEAVE, MOUSE_UP, MOUSE_DOWN.
Actions: NODE (+destinationId, navigation NAVIGATE|OVERLAY|SCROLL_TO|SWAP|CHANGE_TO, transition, preserveScrollPosition), BACK, CLOSE, URL (+url).
Transitions: DISSOLVE, SMART_ANIMATE, or PUSH, MOVE_IN, MOVE_OUT, SLIDE_IN, SLIDE_OUT (these also need direction LEFT|RIGHT|TOP|BOTTOM and matchLayers).
Example: {"nodeId":"1:2","reactions":[{"trigger":{"type":"ON_CLICK"},"actions":[{"type":"NODE","destinationId":"1:3","navigation":"NAVIGATE","transition":{"type":"DISSOLVE","duration":0.3,"easing":{"type":"EASE_OUT"}},"preserveScrollPosition":false}]}]}
- **set_selection** — Select and zoom to nodes (switches page if needed) to show the user your work. No IDs clears the selection. Nodes must share a page.
- **set_text** — Change a TEXT node's text and whole-node settings (resize, truncation, alignment, spacing). To style parts of the text, use set_text_ranges.
- **set_text_ranges** — Style parts of a TEXT node (bold, color, link, list). Each range is characters [start, end). Later ranges win on overlap. Omitted properties stay.
- **swap_component** — Swap an instance to another component, keeping position and size.
- **ungroup_nodes** — Ungroup GROUP nodes. The children move to the parent.
- **update_paint_style** — Update a paint style's name, color, or description. For other types, delete the style and create it again.

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

```json
"mcpServers": {
  "figma-mcp-go": {
    "command": "npx",
    "args": ["-y","@tunglt1810/figma-mcp-go@latest"]
  }
}
```

## Documentation & README

# figma-mcp-go

Figma MCP — Local Plugin Integration [![tunglt1810/figma-mcp-go server](https://glama.ai/mcp/servers/tunglt1810/figma-mcp-go/badges/score.svg)](https://glama.ai/mcp/servers/tunglt1810/figma-mcp-go)
<p>
  <a href="https://www.npmjs.com/package/@tunglt1810/figma-mcp-go"><img src="https://img.shields.io/npm/v/@tunglt1810/figma-mcp-go?color=blue" alt="npm version" /></a>
  <a href="https://registry.modelcontextprotocol.io/?q=figma-mcp-go"><img src="https://img.shields.io/badge/MCP-Registry-purple" alt="MCP Registry" /></a>
  <a href="https://github.com/tunglt1810/figma-mcp-go/blob/HEAD/LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT" /></a>
  <a href="https://github.com/tunglt1810/figma-mcp-go/stargazers"><img src="https://img.shields.io/github/stars/tunglt1810/figma-mcp-go?style=social" alt="GitHub stars" /></a>
</p>

Open-source Figma MCP server with full read and write access through a Figma plugin. Turn text into designs and designs into code. Works with Claude, Cursor, GitHub Copilot, and any MCP client.

**Highlights**
- Runs locally through the Figma Plugin API. No REST API token needed.
- Reads and edits the open Figma file live — 60 tools.
- Covers styles, variables, components, prototypes, text, and multi-step batches with undo.
- Built-in prompts such as `read_design_strategy` and `design_strategy`.
- Lean on tokens: short tool descriptions, capped node trees, and images returned as images.

**Styles, Variables, Components, Prototypes, and Content**

https://github.com/user-attachments/assets/eae41471-fc72-4574-8261-4f42c38b8c99

**Text to Design, Design to Code**

https://github.com/user-attachments/assets/17bda971-0e83-4f18-8758-8ac2b8dcba62

---

## Why this exists

Most Figma MCP servers use the cloud **Figma REST API**. AI tools make hundreds of quick calls per session, and every cloud round trip adds delay.

This server talks to a **Figma plugin** on your own machine instead. You get fast, live read and write access to the open file, with no API token.

---

## Setup

Install with `npx` or `bunx`. No build step. Watch the setup video or follow the steps below.

[![Watch the video](https://img.youtube.com/vi/DjqyU0GKv9k/sddefault.jpg)](https://youtu.be/DjqyU0GKv9k)

### 1. Add the server to your AI tool

**Claude Code CLI**
```bash
# via npx
claude mcp add -s project figma-mcp-go -- npx -y @tunglt1810/figma-mcp-go@latest

# or via bunx
claude mcp add -s project figma-mcp-go -- bunx @tunglt1810/figma-mcp-go@latest
```

**Codex CLI**
```bash
# via npx
codex mcp add figma-mcp-go -- npx -y @tunglt1810/figma-mcp-go@latest

# or via bunx
codex mcp add figma-mcp-go -- bunx @tunglt1810/figma-mcp-go@latest
```

**.mcp.json** (Claude and other MCP-compatible tools)
```json
{
  "mcpServers": {
    "figma-mcp-go": {
      "command": "npx",
      "args": ["-y", "@tunglt1810/figma-mcp-go"]
    }
  }
}
```

**.vscode/mcp.json** (Cursor / VS Code / GitHub Copilot)
```json
{
  "servers": {
    "figma-mcp-go": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y",
        "@tunglt1810/figma-mcp-go"
      ]
    }
  }
}
```

### 2. Install the Figma plugin

1. In Figma Desktop: **Plugins → Development → Import plugin from manifest**
2. Pick `manifest.json` from [plugin.zip](https://github.com/tunglt1810/figma-mcp-go/releases)
3. Run the plugin in any Figma file

### 3. Use more than one AI tool (optional)

Each AI tool starts its own server, but only one can hold the plugin connection on a port.

**Same file:** change nothing. The first server takes port 1994; the others forward their calls to it. If it stops, another takes over in a few seconds.

**Different files:** give each tool its own port, and set the same port in that file's plugin (settings gear):

```json
{
  "mcpServers": {
    "figma-mcp-go": {
      "command": "npx",
      "args": ["-y", "@tunglt1810/figma-mcp-go", "--port", "1995"]
    }
  }
}
```

The plugin remembers the last port for all files, so check it when you open the plugin elsewhere.

`--ip 0.0.0.0` accepts connections from other machines.

> **Security:** the plugin connection has no login. On the default `127.0.0.1` only your machine can reach it. On any other address, anyone who can reach the port can read and edit your open file. The server warns you and the plugin turns on `confirm` mode. Prefer an SSH tunnel.

### 4. Read-only mode (optional)

Add `--read-only` to offer only the 17 tools that cannot change the Figma file. These are the read tools, `export_screenshots`, `export_frames_to_pdf`, and `get_image_bytes`. The tool list that the AI loads is about 84% smaller.

```json
{
  "mcpServers": {
    "figma-mcp-go": {
      "command": "npx",
      "args": ["-y", "@tunglt1810/figma-mcp-go", "--read-only"]
    }
  }
}
```

The flag limits one server only. Another AI tool on the same port can still edit the file, unless it also uses the flag.

### Plugin panel

The panel shows the connected file, the selection, and what the AI is doing.

| Control | What it does |
| ------- | ------------ |
| **Guard** | `off` (default) runs everything. `confirm` asks before deletes and bulk changes. `read-only` blocks all changes. |
| **Undo** | Undoes the last change. A whole `batch_execute_pipeline` run is one undo step. |
| **Log** | Shows every request with tool, time, and error. `Copy` exports it for bug reports. |
| **Pin** | Saves the current selection. `get_selection(source: "pinned")` returns it even after the user clicks elsewhere. |

Settings and panel size are saved per machine. The panel follows Figma's light and dark theme.

### Dev Mode

`set_codegen_result` saves code on a node. It shows in Dev Mode's **Code** panel for everyone on the file. Code on a component shows for all its instances. The **Language** menu filters blocks; if a language has no block, all blocks show.

---

## How it works

The first server to start becomes the leader and holds the only WebSocket to the plugin. Other servers are followers and forward their calls to the leader.

```mermaid
flowchart LR
    client([MCP client]) -- stdio --> tools
    client2([2nd MCP client]) -- stdio --> follower[Follower]

    subgraph leaderProc [Leader process]
        tools[tools<br/>60 tools, Check] -- Send --> leader[cluster.Leader<br/>:1994 /rpc /ws /ping]
        leader --> bridge[bridge<br/>request/response match]
    end

    follower -. POST /rpc .-> leader

    subgraph plugin [Figma plugin]
        ui[Plugin UI<br/>Svelte iframe] -- postMessage --> main[Plugin main<br/>dispatch handlers]
    end

    bridge == WebSocket ==> ui
    main -- read / write --> figma[(Figma document)]
```

One tool call, end to end:

```mermaid
sequenceDiagram
    participant C as MCP client
    participant T as tools
    participant L as cluster
    participant B as bridge
    participant U as Plugin UI
    participant M as Plugin main
    participant F as Figma

    C->>T: tools/call (stdio)
    T->>L: Send after Check
    Note over L: A follower first sends POST /rpc to the leader
    L->>B: forward
    B->>U: WebSocket request
    U->>M: postMessage
    M->>F: read / write nodes
    F-->>M: nodes
    M-->>U: response
    U-->>B: WebSocket reply
    B-->>L: matched by id
    L-->>T: (any, error)
    T-->>C: tool result
```

---

## Tools

### Read

| Tool | What it does |
| ---- | ------------ |
| `get_document` | Node tree of the selection, page, or whole file. Stops at 500 nodes by default; `depth`, `maxNodes`, `detail`, `dedupe_components` control size |
| `get_nodes_info` | Full details of nodes by ID. Unknown IDs go in `missing`; `depth` and `maxNodes` limit children |
| `get_selection` | Selected nodes, or pinned ones with `source: "pinned"` |
| `get_metadata` | File name, current page, and all pages |
| `search_nodes` | Find nodes by name and/or type on a page, in a node, or in the whole file |
| `get_viewport` | View center, zoom, and visible area |
| `get_styles` | Paint, text, effect, and grid styles |
| `get_variable_defs` | Variable collections, modes, and values |
| `get_local_components` | All components and component sets |
| `get_instance_overrides` | An instance's component properties and values |
| `get_annotations` | Dev Mode annotations |
| `get_fonts` | Fonts on the current page, most used first |
| `get_reactions` | A node's prototype reactions |

### Export

| Tool | What it does |
| ---- | ------------ |
| `export_screenshots` | Export nodes as images: saved to a file with `outputPath`, or returned (PNG/JPG as image, SVG as text). No items = the selection |
| `export_frames_to_pdf` | Save frames as one multi-page PDF |
| `get_image_bytes` | Original image files from image fills, as base64 |
| `export_tokens` | Variables and paint styles as JSON or CSS |
| `set_export_settings` | Set a node's Export presets |

### Create

| Tool | What it does |
| ---- | ------------ |
| `create_node` | FRAME, RECTANGLE, ELLIPSE, STAR, POLYGON, LINE, or SECTION |
| `create_text` | Text node (loads the font) |
| `create_vector` | Vector from SVG, e.g. an icon |
| `import_image` | Image from a URL or base64, as a new rectangle or into a node |
| `create_component` | Turn a frame into a component |
| `create_component_instance` | Instance of a local or library component |
| `combine_as_variants` | Combine components into a variant set |
| `manage_component_properties` | Add, edit, delete, or bind component properties |
| `create_connector` | Connector line. This tool operates only in a FigJam file |
| `boolean_operation` | UNION, SUBTRACT, INTERSECT, or EXCLUDE shapes |
| `flatten_nodes` | Merge nodes into one vector |
| `outline_stroke` | Turn a stroke into a filled shape |

### Edit

| Tool | What it does |
| ---- | ------------ |
| `set_node_properties` | Position, size, radius, visibility, lock, opacity, rotation, blend, constraints, layer order, mask, stroke |
| `set_paint` | Solid or gradient fill or stroke |
| `set_auto_layout` | Auto layout: direction, padding, gap, align, HUG/FILL sizing, min/max |
| `set_layout_grids` | Column, row, or square grids |
| `set_effects` | Shadows, blurs, noise, texture, glass |
| `set_text` | Text content and whole-node text settings |
| `set_text_ranges` | Style part of a text: bold, color, link, list |
| `find_replace_text` | Find and replace text, regex allowed |
| `set_instance_overrides` | Set an instance's component properties |
| `swap_component` | Swap an instance to another local or library component |
| `detach_instance` | Turn instances into plain frames |
| `clone_node` | Copy a node |
| `reparent_nodes` | Move nodes into another parent |
| `group_nodes` / `ungroup_nodes` | Group or ungroup |
| `batch_rename_nodes` | Rename by name, find/replace, regex, prefix, or suffix |
| `set_annotations` | Dev Mode annotations (paid seat) |
| `set_reactions` | Prototype reactions: set, append, or remove |
| `delete_nodes` | Delete nodes |

### Styles, variables, pages

| Tool | What it does |
| ---- | ------------ |
| `create_style` | PAINT, TEXT, EFFECT, or GRID style |
| `update_paint_style` | Rename or recolor a paint style |
| `apply_style_to_node` | Apply a style to a node |
| `delete_style` | Delete a style |
| `manage_variable` | Create collections, modes, and variables; set values; delete; bind to nodes |
| `manage_page` | Add, delete, rename, or go to a page |

### Workflow

| Tool | What it does |
| ---- | ------------ |
| `batch_execute_pipeline` | Run many write steps in one call, pass results between steps, undo on error |
| `set_selection` | Select and zoom to nodes to show the user |
| `save_version_checkpoint` | Save a named version before big changes |
| `set_codegen_result` | Save code for Dev Mode's Code panel |
| `manage_plugin_data` | Store key/value notes on a node in the file |

### Prompts

| Prompt | What it does |
| ------ | ------------ |
| `read_design_strategy` | How to read designs well |
| `design_strategy` | How to create and edit designs |
| `text_replacement_strategy` | Replace text across a design in chunks |
| `annotation_conversion_strategy` | Turn manual notes into Figma annotations |
| `swap_overrides_instances` | Copy overrides between instances |
| `reaction_to_connector_strategy` | Turn prototype links into flow diagrams |

---

## Upgrading

**Update the plugin when you update the server.** `npx` updates the server, but the plugin is installed by hand. An old plugin rejects new commands with `Unknown request type`.

See [CHANGELOG.md](https://github.com/tunglt1810/figma-mcp-go/blob/HEAD/CHANGELOG.md) for what changed in each release, including removed tools and what to use instead.

---

## Development

- **Server:** Go 1.27+ (`make test-go`, `make build-go`)
- **Plugin:** Bun 1.4+ (`cd plugin && bun install && bun run build`)
- **All tests:** `make test`
- **Logs:** stderr. `FIGMA_MCP_LOG=debug` shows tool parameters and traffic.
- **Package rules:** `make deps-check` fails on wrong-way imports. `internal/` has `bridge` (plugin WebSocket), `cluster` (leader election), `figma` (rules), and `tools` (tool table). Allowed: `tools → figma`, `cluster → bridge`.

macOS binaries need macOS 13 or later (Go 1.27).

## Contributing

Issues and PRs are welcome.

## Star History

<a href="https://www.star-history.com/?repos=tunglt1810%2Ffigma-mcp-go&type=date&legend=top-left">
 <picture>
   <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=tunglt1810/figma-mcp-go&type=date&theme=dark&legend=top-left" />
   <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=tunglt1810/figma-mcp-go&type=date&legend=top-left" />
   <img alt="Star History Chart" src="https://api.star-history.com/chart?repos=tunglt1810/figma-mcp-go&type=date&legend=top-left" />
 </picture>
</a>

