open-figma-mcp
by RHK1335
README.md
# open-figma-mcp
**Let any AI agent read and edit your live Figma file — no API token, no rate limits.**
<p>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-yellow.svg" alt="License: MIT" /></a>
<img src="https://img.shields.io/badge/tools-85-blue" alt="85 tools" />
<img src="https://img.shields.io/badge/tests-36%20passing-brightgreen" alt="36 tests passing" />
<a href="https://github.com/Hemil4/open-figma-mcp"><img src="https://img.shields.io/badge/fork%20of-Hemil4%2Fopen--figma--mcp-lightgrey" alt="Fork of Hemil4/open-figma-mcp" /></a>
</p>
An MCP server that talks to Figma through a local plugin instead of the REST API. Works with Claude, Cursor, Codex, GitHub Copilot and any MCP client.
> This is a fork of [Hemil4/open-figma-mcp](https://github.com/Hemil4/open-figma-mcp) by Hemil Patel, maintained by [RHK1335](https://github.com/RHK1335). It focuses on giving agents **everything they need to turn a design into code**.
---
## Why
- **No token, no limits.** REST-based servers stop at ~6 calls/month on free plans and 200/day on Dev seats. This one runs inside Figma Desktop, so the only limit is your machine.
- **Read and write.** 85 tools covering nodes, styles, variables, components, prototypes and exports.
- **Stays local.** The bridge listens on `127.0.0.1` only. No OAuth, no hosted service.
## What this fork adds
| Area | What the agent now sees |
|------|-------------------------|
| Strokes | Weight per side, inside/outside/center, dash pattern |
| Sizing | Fixed / Hug / Fill, grow, stretch, absolute position, min/max, clipping |
| Components | Main component (library or local), properties, variants, which property drives which layer |
| Tokens | Names of bound variables and styles, with collection and library info |
| Text | Weight, case, decoration, truncation, mixed-style ranges, pixel line height for `AUTO` |
| Fills & effects | Hidden fills flagged, gradient stops, mask flag, per-corner radii, hex effect colors |
| Search | Components on every page; `scope: "document"` to search the whole file |
| Export | Multi-node SVG export runs in parallel (28 icons in ~30 ms) |
Empty or default fields are no longer written, so output is shorter and easier for agents to read.
## How it works
```
AI agent ⇄ MCP server (Node.js) ⇄ ws://127.0.0.1:18765 ⇄ Figma plugin ⇄ your Figma file
```
Your AI tool starts the server. The plugin, running in Figma Desktop, connects to it, and every tool call makes the round trip. Several AI tools can share one plugin at the same time.
---
## Quick start
**1. Build**
```bash
git clone https://github.com/RHK1335/open-figma-mcp.git
cd open-figma-mcp
npm install
npm run build
```
**2. Add it to your AI tool** (use the full path to your clone)
```bash
claude mcp add -s user open-figma-mcp -- node /path/to/open-figma-mcp/server/dist/index.js
```
<details>
<summary>Codex, Claude Desktop, Cursor, VS Code</summary>
**Codex CLI**
```bash
codex mcp add open-figma-mcp -- node /path/to/open-figma-mcp/server/dist/index.js
```
**`.mcp.json`** (Claude Desktop and most MCP clients)
```json
{
"mcpServers": {
"open-figma-mcp": {
"command": "node",
"args": ["/path/to/open-figma-mcp/server/dist/index.js"]
}
}
}
```
**`.vscode/mcp.json`** (Cursor, VS Code, GitHub Copilot)
```json
{
"servers": {
"open-figma-mcp": {
"type": "stdio",
"command": "node",
"args": ["/path/to/open-figma-mcp/server/dist/index.js"]
}
}
}
```
</details>
**3. Install the Figma plugin**
1. In Figma Desktop: **Plugins → Development → Import plugin from manifest…**
2. Pick `plugin/manifest.json` from your clone.
3. Open a file and run **Plugins → Development → Open Figma MCP**. It should say **Connected**.
If it says **Disconnected**, start a session in your AI tool first, then click **Reconnect**. After pulling new plugin code, just close and reopen the plugin window.
> The `open-figma-mcp` package on npm is the original upstream release and does not include this fork's changes.
---
## Tools
| Group | Count | Examples |
|-------|------:|----------|
| Read | 19 | `figma_get_design_context`, `figma_get_node`, `figma_search_nodes`, `figma_get_variable_defs` |
| Create & modify | 32 | `figma_create_frame`, `figma_set_auto_layout`, `figma_set_fills`, `figma_find_replace_text` |
| Styles & variables | 13 | `figma_create_text_style`, `figma_bind_variable_to_node`, `figma_create_variable` |
| Pages, components, prototype | 11 | `figma_add_page`, `figma_swap_component`, `figma_set_reactions` |
| Export & generation | 6 | `figma_get_screenshot`, `figma_export_tokens`, `figma_generate_screen` |
| Screens & status | 4 | `figma_status`, `figma_create_screen_frames`, `figma_get_screen` |
<details>
<summary>Full tool list</summary>
**Read — document & selection**
| Tool | Description |
|------|-------------|
| `figma_get_document` | Serialized file tree (depth + detail level) |
| `figma_get_metadata` | File name, pages, current page, selection count |
| `figma_get_pages` | List pages without loading trees |
| `figma_get_selection` | Currently selected nodes |
| `figma_get_node` | Single node by ID |
| `figma_get_nodes_info` | Multiple nodes by ID |
| `figma_get_design_context` | Depth-limited tree for selection, page, node(s) or screen |
| `figma_search_nodes` | Find nodes by name/type (page, whole document or subtree) |
| `figma_scan_text_nodes` | All text nodes under a scope |
| `figma_scan_nodes_by_types` | All nodes of given types under a scope |
| `figma_get_viewport` | Viewport center and zoom |
**Read — styles, variables, libraries**
| Tool | Description |
|------|-------------|
| `figma_get_styles` | Local paint, text, effect and grid styles |
| `figma_get_variable_defs` | Variable collections and values |
| `figma_get_local_components` | Components and sets with variants, across all pages |
| `figma_get_annotations` | Plugin-data annotations |
| `figma_get_fonts` | Fonts used, optionally available fonts |
| `figma_get_reactions` | Prototype reactions on a node |
| `figma_get_libraries` | Components, styles, variables, fonts, pages, file metadata |
| `figma_search_design_system` | Search components, styles, variables, fonts, pages |
**Create**
| Tool | Description |
|------|-------------|
| `figma_create_frame` | Frame with optional auto-layout, fill, parent |
| `figma_create_rectangle` | Rectangle with optional fill and radius |
| `figma_create_ellipse` | Ellipse or circle |
| `figma_create_text` | Text node (font loaded automatically) |
| `figma_import_image` | Base64 image as a rectangle fill |
| `figma_create_component` | Turn a frame into a component |
| `figma_create_section` | Section to organize frames |
**Modify**
| Tool | Description |
|------|-------------|
| `figma_set_text` | Update text content |
| `figma_set_fills` / `figma_set_strokes` | Set or append solid fill / stroke |
| `figma_set_opacity` | Opacity 0–1 |
| `figma_set_corner_radius` | Uniform or per-corner radius |
| `figma_set_auto_layout` | Direction, padding, spacing, alignment |
| `figma_set_visible` | Show or hide |
| `figma_lock_nodes` / `figma_unlock_nodes` | Lock or unlock |
| `figma_rotate_nodes` | Absolute rotation |
| `figma_reorder_nodes` | Bring to front, send to back, … |
| `figma_set_blend_mode` | Multiply, screen, overlay, … |
| `figma_set_constraints` | Horizontal and vertical constraints |
| `figma_move_nodes` / `figma_resize_nodes` | Move or resize |
| `figma_rename_node` / `figma_batch_rename_nodes` | Rename one, or many by regex, prefix, suffix, numbering |
| `figma_clone_node` / `figma_reparent_nodes` | Clone or move under a new parent |
| `figma_find_replace_text` | Find and replace across text (regex) |
| `figma_set_effects` | Shadows and blurs |
| `figma_align_distribute` | Align and distribute nodes |
| `figma_set_layout_grid` | Layout grid on a frame |
| `figma_measure_spacing` | Bounds, gaps, overlaps, alignment deltas |
| `figma_delete_nodes` | Delete nodes |
**Styles & variables**
| Tool | Description |
|------|-------------|
| `figma_create_paint_style` / `figma_create_text_style` / `figma_create_effect_style` / `figma_create_grid_style` | Create styles |
| `figma_update_paint_style` | Rename or recolor a paint style |
| `figma_delete_style` | Delete a local style |
| `figma_apply_style_to_node` | Link a style to a node |
| `figma_bind_variable_to_node` | Bind a variable to a node property |
| `figma_create_variable_collection` | New collection |
| `figma_add_variable_mode` | Add a mode (e.g. Light/Dark) |
| `figma_create_variable` | Color, number, string or boolean variable |
| `figma_set_variable_value` | Value for a mode |
| `figma_delete_variable` | Delete a variable |
**Pages, components, prototype**
| Tool | Description |
|------|-------------|
| `figma_navigate_to_page` / `figma_add_page` / `figma_rename_page` / `figma_delete_page` | Manage pages |
| `figma_group_nodes` / `figma_ungroup_nodes` | Group or ungroup |
| `figma_create_component_set` | Combine components into a set |
| `figma_swap_component` | Swap an instance's main component |
| `figma_detach_instance` | Detach an instance |
| `figma_set_reactions` / `figma_remove_reactions` | Prototype reactions |
**Export & generation**
| Tool | Description |
|------|-------------|
| `figma_get_screenshot` | PNG, JPG, SVG or PDF as base64 |
| `figma_save_screenshots` | Export straight to files |
| `figma_export_frames_to_pdf` | Multi-frame PDF |
| `figma_export_tokens` | Styles and variables as design tokens |
| `figma_generate_diagram` | Diagram frame with boxes and connectors |
| `figma_generate_screen` | App screen from a JSON element list |
**Screens & status**
| Tool | Description |
|------|-------------|
| `figma_status` | Bridge and plugin status |
| `figma_create_screen_frames` | Sitemap → frames + screen registry |
| `figma_get_screen_registry` | Read the registry |
| `figma_get_screen` | One screen by key, with live node details |
</details>
### Screen registry
Turn a sitemap into frames once, then refer to screens by a stable key instead of node IDs:
```jsonc
// figma_create_screen_frames
{ "projectName": "CRM", "screens": [{ "key": "login", "title": "Login", "route": "/login" }] }
// any create/modify tool afterwards
{ "screenKey": "login", "text": "Welcome back", "fontSize": 32 }
```
The registry is saved to `.open-figma-mcp/screen-registry.json` and keeps working when frames move or get renamed.
---
## Configuration
| Variable | Default | Purpose |
|----------|---------|---------|
| `FIGMA_MCP_PORT` | `18765` | Bridge port (all servers must use the same one) |
| `FIGMA_MCP_EXPORT_DIR` | current folder | Where exported files may be written |
| `FIGMA_MCP_ALLOW_ANY_PATH` | off | `1` allows writing exports anywhere |
| `FIGMA_MCP_REGISTRY_PATH` | `.open-figma-mcp/screen-registry.json` | Screen registry location |
## Security
- The bridge has **no authentication**. Keep it on `127.0.0.1` and never expose the port.
- The plugin manifest allows all network domains for easier development. Treat it as a development plugin, not a Community release.
## Development
```bash
npm run build # server + plugin
npm test # 36 tests, Node's built-in runner
npm run typecheck # server types
npm run dev # run the server from source
```
A new tool needs two matching edits: a `ToolSpec` in `server/src/index.ts` and a `case` in `handleCommand` in `plugin/src/code.ts`. Then run `npm run build`.
## Credits & license
Original project by [Hemil Patel](https://github.com/Hemil4/open-figma-mcp). Fork changes by [RHK1335](https://github.com/RHK1335). Released under the [MIT License](LICENSE).
Related projects: [figma-mcp-go](https://github.com/vkhanhqui/figma-mcp-go) · [figma-mcp-bridge](https://github.com/magic-spells/figma-mcp-bridge) · [cursor-talk-to-figma-mcp](https://github.com/grab/cursor-talk-to-figma-mcp) · [gethopp/figma-mcp-bridge](https://github.com/gethopp/figma-mcp-bridge)
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo recent community issues