Talk to Figma MCP
Allows reading and writing to the currently open Figma file via a local WebSocket bridge and Figma Desktop plugin, enabling inspection of document tree, selection, nodes, components, styles, and image exports, as well as creating, editing, and deleting nodes, setting fills, auto-layout, components, and text.
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., "@Talk to Figma MCP read my current design selection"
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 MCP
A local Model Context Protocol server that connects Cursor (or any MCP client) to Figma through a Figma plugin over a local WebSocket bridge — no Figma REST API, no token, no rate limits.
Reads — inspect the file currently open in Figma Desktop: document tree, selection, nodes, local components, styles, image exports.
Writes — create/edit/delete nodes, set fills, auto-layout, components, text, and more.
Everything runs over the Figma Plugin API on the file you have open in Figma Desktop. Browser Figma is not supported.
Based on sonnylazuardi/cursor-talk-to-figma-mcp (MIT), ported to run entirely on Node (no Bun).
Desktop only — not browser
Figma Desktop | Figma in browser | |
Import a local dev plugin | Yes | No |
Connect to | Yes | No |
Read/write via Plugin API | Yes | No |
Works with this MCP | Yes | No |
You need Figma Desktop because this workflow imports a development plugin from manifest.json and connects it to a relay running on your machine. Browser Figma cannot do either of those things.
Related MCP server: Agent to Figma MCP
What must be running
A working session needs three things at once:
Terminal Figma Desktop Cursor
──────── ───────────── ──────
relay running + file open + MCP server enabled
plugin connectedPiece | How to start it |
Relay |
|
Figma file + plugin | Open a file in Desktop, run the plugin, click Connect |
MCP server | Started automatically by Cursor from |
The plugin and the MCP server both default to the shared channel cursor-figma, so
there is no manual join_channel step in the common case. If any of the three
pieces above is missing, tools will hang or return connection errors.
Quick start
1. Install
git clone <this-repo>
cd figma-mcp
npm install2. Configure Cursor
Add to ~/.cursor/mcp.json. Use an absolute path to src/server.ts:
{
"mcpServers": {
"figma-mcp-mh": {
"command": "npx",
"args": ["tsx", "/absolute/path/to/figma-mcp/src/server.ts"]
}
}
}A project-scoped equivalent is in .mcp.json (relative path — works when Cursor opens this repo as the workspace). No token or other env vars are required.
Restart Cursor (or reload MCP servers) after saving.
3. Start the relay
In a terminal, from the project root:
npm run socketListens on ws://localhost:3055 by default. Override with WS_PORT.
Leave this terminal running for the whole session.
4. Import and run the Figma plugin
All of this happens in Figma Desktop:
Open the design file you want to work on.
Plugins → Development → Import plugin from manifest…
Select
src/manifest.json.Plugins → Development → figma mcp to run it.
In the plugin panel, click Connect (leave the channel as the default
cursor-figma).
Keep the plugin panel open and connected while you work.
5. Start using it
Once connected, ask Cursor to read or edit your open Figma file. Examples:
"What's in my current Figma document?" →
get_document_info"Read my current selection" →
read_my_design"Create a 400×300 frame called Hero" →
create_frame"Set the fill of node
1:234to blue" →set_fill_color
All tools operate on whatever file is open in Figma Desktop right now.
Architecture
Cursor (MCP host)
stdio / JSON-RPC
MCP server (src/server.ts, Node + tsx)
WebSocket client -> Relay (src/socket.ts) <-> Figma plugin (read + write the open file)Three independent processes connect over ws://localhost:3055:
The relay (
src/socket.ts) — a channel-based WebSocket broker. It does not understand Figma; it forwards messages between clients in the same named channel.The MCP server (
src/server.ts) — connects to the relay as a WebSocket client and to Cursor over stdio. Each MCP tool maps to asendCommandToFigma(...)call.The Figma plugin (
src/manifest.json,code.js,ui.html) — the iframe UI (ui.html) owns the WebSocket (the plugin sandbox cannot), and relays commands to the main thread (code.js), which calls the Figma Plugin API.
The MCP server and plugin must be on the same channel or commands go nowhere. Both default to cursor-figma and the server auto-joins it on startup, so they line up automatically; use join_channel only to switch to a custom channel.
How a command flows
Cursor calls create_frame
→ server.ts sends { command, params, id } over WebSocket
→ relay broadcasts to the plugin peer in the channel
→ ui.html → code.js → figma.createFrame(), etc.
→ result bubbles back with the same id
→ Cursor receives the tool resultReads work the same way. The plugin calls figma.getNodeByIdAsync(), node.exportAsync({ format: "JSON_REST_V1" }), and similar — all local, no HTTP to Figma.
Requirements
Node.js 18+ (developed on Node 24). No Bun required.
Figma Desktop with a file open.
No Figma personal access token needed.
Tools
All tools need the relay running and the plugin connected. The server auto-joins the default channel, so join_channel is only needed for a custom channel.
Read tools
Tool | Purpose |
| Current document/page overview |
| Currently selected nodes |
| One or more nodes by ID |
| The current selection in detail |
| Components defined in the open file |
| Color/text/effect/grid styles |
| Render a node to PNG (returns base64 image bytes) |
Write tools
create_frame, create_text, create_rectangle, set_fill_color, set_stroke_color, move_node, resize_node, clone_node, delete_node, auto-layout (set_layout_mode, set_padding, set_item_spacing, ...), component instances, annotations, text scanning, and more — see src/server.ts.
Comments (unsupported)
get_figma_comments and post_figma_comment are stubs only. Figma comments are exposed exclusively through the REST API, and the Plugin API has no access to them. Use Figma directly for comments.
Troubleshooting
Tools hang or time out
Is
npm run socketstill running?Does the plugin show "Connected"?
Does the plugin's channel match the server's (both default to
cursor-figma)? If you changed the channel in the plugin, calljoin_channelwith that exact name.Is the plugin panel still open?
"Not connected to Figma" / connection errors
Start the relay first, then connect the plugin.
Check nothing else is blocking port 3055.
MCP server not appearing in Cursor
Confirm
~/.cursor/mcp.jsonuses an absolute path tosrc/server.ts.Restart Cursor or reload MCP servers.
Check MCP logs in Cursor settings.
Plugin not found in Figma
Re-import from manifest: Plugins → Development → Import plugin from manifest…
Development plugins live under Plugins → Development, not the community list.
Wrong or empty data
Switch to the correct file in Figma Desktop — reads only see the open file.
There is no "read any file by URL/key" in this build.
Smoke test after connecting
get_document_info— should return your current page tree.create_framethenset_fill_color— should create something visible on the canvas.
Verify (developers)
npm run typecheck # tsc --noEmit
node scripts/relay-smoke.mjs # relay request/response round-trip
node scripts/mcp-smoke.mjs # boot server over stdio, list toolsFor a full end-to-end check: start the relay, connect the plugin (default channel), then call get_document_info and create_frame followed by set_fill_color. No join_channel needed unless you changed the channel.
Gotchas
stdio is sacred. The MCP server must never write to stdout except JSON-RPC. It logs to stderr. The relay is a separate process, so its stdout logging is fine.
WebSocket lives in the plugin UI. The Figma plugin sandbox has no
WebSocket; the iframe (ui.html) owns the socket and relays to the main thread.Channel mismatch = silence. If write/read tools hang, confirm the plugin and the server are on the same channel (both default to
cursor-figma) and the relay is running.File must be open. Reads and writes target the file open in Figma Desktop. You cannot read a closed or remote file by key without the REST API (removed in this build).
Comments are unavailable. The Plugin API cannot access comments.
Roadmap
The shared default channel (cursor-figma) already removes the manual join_channel step (Phase 0). An optional ~/.figma-mcp/state.json ({ "channel": "...", "port": ... }) can override the channel/port; the server reads it on startup and falls back to the defaults if it's absent.
See plan.md for a planned menubar companion app that would also auto-start the relay and show live connection status — removing the manual npm run socket step. That app does not exist yet; the flow above is the current setup.
Credits
Write/read bridge and plugin: sonnylazuardi/cursor-talk-to-figma-mcp (MIT). Node port and plugin-only refactor applied here.
Available Tools
42 toolsclone_nodeA
Clone an existing node in Figma. By default x/y are PARENT-RELATIVE (same coordinate space as Figma's x/y). Set positionMode to "frame" to pass absolute canvas coordinates instead, which are converted to the parent's local space. The response returns both the parent-relative position and the absolute bounding box so you can verify placement.
Inputs: nodeId (required), x, y, positionMode.
create_component_instanceA
Create an instance of a component in Figma. For LOCAL components (from get_local_components), use componentId with the id field. For published LIBRARY components, use componentKey with the publishedKey field.
Inputs: x (required), y (required), parentId, componentId, +1 more.
create_connectionsB
Create connections between nodes using the default connector style
Inputs: connections (required).
create_frameC
Create a new frame in Figma
Inputs: x (required), y (required), width (required), height (required), +16 more.
create_rectangleC
Create a new rectangle in Figma
Inputs: x (required), y (required), width (required), height (required), +2 more.
create_textA
Create a new text element in Figma. To match an existing design-system layer (e.g. a Poppins Bold card title), set fontFamily/fontStyle, textAlignHorizontal, width, and lineHeight to the target layer's values instead of relying on the Inter defaults.
Inputs: x (required), y (required), text (required), name, +11 more.
delete_multiple_nodesB
Delete multiple nodes from Figma at once
Inputs: nodeIds (required).
delete_nodeC
Delete a node from Figma
Inputs: nodeId (required).
export_node_as_imageC
Export a node as an image from Figma
Inputs: nodeId (required), scale, format.
get_annotationsB
Get all annotations in the current document or specific node
Inputs: nodeId (required), includeCategories.
get_document_infoB
Get detailed information about the current Figma document
Inputs: no named parameters.
get_figma_commentsGet Figma Comments (unsupported)ARead-only
Stub: reading Figma comments requires the REST API, which is disabled in this build. The Figma Plugin API cannot access comments, so there is no plugin-based equivalent.
Inputs: fileKey.
get_instance_overridesA
Get all override properties from a selected component instance. These overrides can be applied to other instances, which will swap them to match the source component.
Inputs: nodeId.
get_local_componentsA
Get all local components from the Figma document
Inputs: no named parameters.
get_node_infoB
Get detailed information about a specific node in Figma
Inputs: nodeId (required).
get_nodes_infoC
Get detailed information about multiple nodes in Figma
Inputs: nodeIds (required).
get_reactionsA
Get Figma Prototyping Reactions from multiple nodes. CRITICAL: The output MUST be processed using the 'reaction_to_connector_strategy' prompt IMMEDIATELY to generate parameters for connector lines via the 'create_connections' tool.
Inputs: nodeIds (required).
get_selectionB
Get information about the current selection in Figma
Inputs: no named parameters.
get_stylesA
Get all styles from the current Figma document
Inputs: no named parameters.
join_channelA
Optional: switch the Figma communication channel. The server auto-joins the default channel ('cursor-figma') on startup, so this is only needed to use a non-default channel or to recover after a connection issue.
Inputs: channel.
move_nodeC
Move a node to a new position in Figma
Inputs: x (required), y (required), nodeId (required).
post_figma_commentPost Figma Comment (unsupported)A
Stub: posting Figma comments requires the REST API, which is disabled in this build. The Figma Plugin API cannot post comments, so there is no plugin-based equivalent.
Inputs: message.
read_my_designA
Get detailed information about the current selection in Figma, including all node details
Inputs: no named parameters.
resize_nodeC
Resize a node in Figma
Inputs: width (required), height (required), nodeId (required).
scan_nodes_by_typesC
Scan for child nodes with specific types in the selected Figma node
Inputs: types (required), nodeId (required).
scan_text_nodesC
Scan all text nodes in the selected Figma node
Inputs: nodeId (required).
set_annotationB
Create or update an annotation
Inputs: nodeId (required), labelMarkdown (required), categoryId, properties, +1 more.
set_axis_alignA
Set primary and counter axis alignment for an auto-layout frame in Figma
Inputs: nodeId (required), counterAxisAlignItems, primaryAxisAlignItems.
set_corner_radiusA
Set the corner radius of a node in Figma
Inputs: nodeId (required), radius (required), corners.
set_default_connectorB
Set a copied connector node as the default connector
Inputs: connectorId.
set_fill_colorC
Set the fill color of a node in Figma can be TextNode or FrameNode
Inputs: b (required), g (required), r (required), nodeId (required), +1 more.
set_focusA
Set focus on a specific node in Figma by selecting it and scrolling viewport to it
Inputs: nodeId (required).
set_instance_overridesA
Apply previously copied overrides to selected component instances. Target instances will be swapped to the source component and all copied override properties will be applied.
Inputs: targetNodeIds (required), sourceInstanceId (required).
set_item_spacingA
Set distance between children in an auto-layout frame
Inputs: nodeId (required), itemSpacing, counterAxisSpacing.
set_layout_modeB
Set the layout mode and wrap behavior of a frame in Figma
Inputs: nodeId (required), layoutMode (required), layoutWrap.
set_layout_sizingA
Set horizontal and vertical sizing modes for an auto-layout frame in Figma
Inputs: nodeId (required), layoutSizingVertical, layoutSizingHorizontal.
set_multiple_annotationsC
Set multiple annotations parallelly in a node
Inputs: nodeId (required), annotations (required).
set_multiple_text_contentsB
Set multiple text contents parallelly in a node
Inputs: text (required), nodeId (required).
set_paddingB
Set padding values for an auto-layout frame in Figma
Inputs: nodeId (required), paddingTop, paddingLeft, paddingRight, +1 more.
set_selectionsA
Set selection to multiple nodes in Figma and scroll viewport to show them
Inputs: nodeIds (required).
set_stroke_colorB
Set the stroke color of a node in Figma
Inputs: b (required), g (required), r (required), nodeId (required), +2 more.
set_text_contentA
Set the text content of an existing text node in Figma
Inputs: text (required), nodeId (required).
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 42 tools
There are redundant tools like get_selection and read_my_design which both retrieve selection info with unclear distinction. scan_text_nodes and scan_nodes_by_types also overlap, as you can filter by type. While most tools are distinct, these overlaps make misselection likely.
Most tool names follow a verb_noun pattern (get_, set_, create_, delete_, move_, etc.). A few outliers like read_my_design, get_figma_comments, and post_figma_comment break the convention slightly, but overall it's fairly consistent.
42 tools is excessive for the scope, with many granular variants (single vs multiple) that could be consolidated with parameters. Stub tools for comments add to the clutter, making it heavy and potentially overwhelming for agents.
The set covers many core Figma operations (read nodes, create shapes, edit layout, export), but lacks common operations like modifying text font properties, grouping nodes, deleting annotations, and comments are non-functional stubs. These gaps will require workarounds or cause failures.
Maintenance
Related MCP Connectors
The Figma MCP server brings Figma design context directly into your AI workflow.
Give AI agents your deeepSpace design system: components, tokens, styles and code mappings.
Connect AI coding agents to Anima Playground, Figma, and your design system.
Agent-Native design tool - create and edit visual designs with agent assistance
Related MCP Servers
- -licenseCqualityNot gradedmaintenanceEnables AI agents to interact with Figma in real-time through a WebSocket connection. Supports comprehensive design operations including text manipulation, layouts, components, variables, and export functionality.72207 npm-
- AlicenseNot gradedqualityNot gradedmaintenanceEnables AI agents like Claude to interact with Figma designs through 50+ tools for creating, styling, and manipulating design elements, components, and variables via a WebSocket relay and Figma plugin.-
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants like Claude and Cursor to interact directly with Figma to create, modify, and analyze design elements in real-time. It provides a comprehensive suite of tools for document inspection, styling, component management, and automated layout via a bidirectional WebSocket connection.679 npmMIT
- AlicenseNot gradedqualityDmaintenanceEmpowers AI assistants to control Figma via natural language, enabling creation and modification of designs, components, variables, and exports through a WebSocket bridge.2,341 npm2MIT