| name | figma-mcp-integration |
| description | Enable AI agents to read and modify Figma designs programmatically through Model Context Protocol integration |
| triggers | ["connect to Figma","read Figma design","modify Figma elements","create Figma components","update text in Figma","export Figma nodes","set up Figma MCP","automate Figma design"] |
Figma MCP Integration
Skill by ara.so — Design Skills collection.
This skill enables AI agents to communicate with Figma through the Model Context Protocol (MCP), allowing programmatic reading and modification of Figma designs. The integration supports creating elements, modifying layouts, batch text updates, annotations, and prototype flow visualization.
Installation
1. Install Bun Runtime
curl -fsSL https://bun.sh/install | bash
2. Quick Setup
git clone https://github.com/grab/cursor-talk-to-figma-mcp.git
cd cursor-talk-to-figma-mcp
bun setup
3. Start WebSocket Server
bun socket
4. Configure MCP in Cursor
Add to ~/.cursor/mcp.json:
{
"mcpServers": {
"TalkToFigma": {
"command": "bunx",
"args": ["cursor-talk-to-figma-mcp@latest"]
}
}
}
For local development:
{
"mcpServers": {
"TalkToFigma": {
"command": "bun",
"args": ["/absolute/path/to/src/talk_to_figma_mcp/server.ts"]
}
}
}
5. Install Figma Plugin
- Visit Figma Community Plugin
- Or in Figma: Plugins > Development > New Plugin > Link existing plugin > Select
src/cursor_mcp_plugin/manifest.json
Windows + WSL Configuration
powershell -c "irm bun.sh/install.ps1|iex"
Edit src/socket.ts to allow WSL connections:
hostname: "0.0.0.0",
Core Workflow
1. Establish Connection
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "join_channel",
arguments: {
channelId: "design-session-1"
}
});
2. Read Document Structure
const docInfo = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "get_document_info",
arguments: {}
});
const selection = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "get_selection",
arguments: {}
});
const designDetails = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "read_my_design",
arguments: {}
});
3. Query Specific Nodes
const nodeInfo = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "get_node_info",
arguments: {
nodeId: "123:456"
}
});
const nodesInfo = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "get_nodes_info",
arguments: {
nodeIds: ["123:456", "789:012", "345:678"]
}
});
Creating Elements
Create Frames and Shapes
const frame = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "create_frame",
arguments: {
x: 100,
y: 100,
width: 400,
height: 300,
name: "Hero Section"
}
});
const rect = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "create_rectangle",
arguments: {
x: 120,
y: 120,
width: 200,
height: 100,
name: "Card Background"
}
});
const text = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "create_text",
arguments: {
x: 140,
y: 140,
characters: "Welcome to our app",
name: ,
: ,
: ,
:
}
});
Create Component Instances
const components = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "get_local_components",
arguments: {}
});
const instance = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "create_component_instance",
arguments: {
componentKey: "abc123def456",
x: 200,
y: 200
}
});
Styling Elements
Colors and Fills
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_fill_color",
arguments: {
nodeId: "123:456",
r: 0.2,
g: 0.5,
b: 0.9,
a: 1.0
}
});
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_stroke_color",
arguments: {
nodeId: "123:456",
r: 0.1,
g: 0.1,
b: 0.1,
a: 1.0,
strokeWeight: 2
}
});
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_corner_radius",
arguments: {
nodeId: "123:456",
radius: 8
}
});
await use_mcp_tool({
server_name: ,
: ,
: {
: ,
: ,
: ,
: ,
:
}
});
Auto Layout Configuration
Enable Auto Layout
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_layout_mode",
arguments: {
nodeId: "123:456",
layoutMode: "HORIZONTAL",
layoutWrap: "NO_WRAP"
}
});
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_layout_mode",
arguments: {
nodeId: "123:456",
layoutMode: "VERTICAL",
layoutWrap: "WRAP"
}
});
Configure Spacing and Padding
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_padding",
arguments: {
nodeId: "123:456",
top: 24,
right: 16,
bottom: 24,
left: 16
}
});
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_item_spacing",
arguments: {
nodeId: "123:456",
spacing: 12
}
});
Alignment and Sizing
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_axis_align",
arguments: {
nodeId: "123:456",
primaryAxisAlign: "SPACE_BETWEEN",
counterAxisAlign: "CENTER"
}
});
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_layout_sizing",
arguments: {
nodeId: "123:456",
horizontal: "FILL",
vertical: "HUG"
}
});
Text Operations
Scan and Update Text
const textNodes = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "scan_text_nodes",
arguments: {
startIndex: 0,
chunkSize: 100,
nodeId: "page-node-id"
}
});
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_text_content",
arguments: {
nodeId: "123:456",
characters: "Updated heading text"
}
});
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_multiple_text_contents",
arguments: {
updates: [
{ nodeId: "123:456", characters: "New title" },
{ nodeId: "789:012", characters: "New description" },
{ nodeId: "345:678", characters: "Updated label" }
]
}
});
Bulk Text Replacement Pattern
const allTextNodes = [];
let startIndex = 0;
const chunkSize = 100;
let hasMore = true;
while (hasMore) {
const chunk = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "scan_text_nodes",
arguments: { startIndex, chunkSize }
});
allTextNodes.push(...chunk.nodes);
hasMore = chunk.hasMore;
startIndex += chunkSize;
}
const updates = allTextNodes
.filter(node => node.characters.includes("placeholder"))
.map(node => ({
nodeId: node.id,
characters: node.characters.replace("placeholder", "actual content")
}));
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_multiple_text_contents",
arguments: { updates }
});
Layout Manipulation
Move and Resize
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "move_node",
arguments: {
nodeId: "123:456",
x: 300,
y: 200
}
});
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "resize_node",
arguments: {
nodeId: "123:456",
width: 500,
height: 400
}
});
const cloned = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "clone_node",
arguments: {
nodeId: "123:456",
offsetX: 50,
offsetY: 50
}
});
Focus and Selection
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_focus",
arguments: {
nodeId: "123:456"
}
});
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_selections",
arguments: {
nodeIds: ["123:456", "789:012", "345:678"]
}
});
Delete Nodes
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "delete_node",
arguments: {
nodeId: "123:456"
}
});
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "delete_multiple_nodes",
arguments: {
nodeIds: ["123:456", "789:012", "345:678"]
}
});
Annotations
Create and Manage Annotations
const annotations = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "get_annotations",
arguments: {
nodeId: "page-id"
}
});
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_annotation",
arguments: {
nodeId: "123:456",
label: "Design Note",
text: "This button should be **bold** and use primary color",
category: "NOTE"
}
});
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_multiple_annotations",
arguments: {
annotations: [
{
nodeId: "123:456",
label: "Fix spacing",
text: "Increase padding to 24px",
category: "ISSUE"
},
{
nodeId: "789:012",
label: "Accessibility",
: ,
:
}
]
}
});
Scan Nodes for Annotation Targets
const buttons = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "scan_nodes_by_types",
arguments: {
nodeTypes: ["COMPONENT", "INSTANCE"],
namePattern: "button"
}
});
Convert Legacy Annotations Pattern
const textNodes = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "scan_text_nodes",
arguments: { startIndex: 0, chunkSize: 200 }
});
const legacyAnnotations = textNodes.nodes
.filter(node => /^\d+\./.test(node.characters))
.map(node => ({
nodeId: node.id,
number: node.characters.match(/^(\d+)\./)[1],
text: node.characters.replace(/^\d+\.\s*/, ""),
position: { x: node.x, y: node.y }
}));
const targetElements = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "scan_nodes_by_types",
arguments: {
: [, , , ]
}
});
newAnnotations = legacyAnnotations.( {
target = (targetElements, legacy.);
{
: target.,
: ,
: legacy.,
:
};
});
({
: ,
: ,
: { : newAnnotations }
});
legacyIds = legacyAnnotations.( a.);
({
: ,
: ,
: { : legacyIds }
});
Component Instance Overrides
Extract and Apply Overrides
const overrides = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "get_instance_overrides",
arguments: {
instanceId: "source-instance-id"
}
});
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_instance_overrides",
arguments: {
targetInstanceIds: [
"target-instance-1",
"target-instance-2",
"target-instance-3"
],
overrides: overrides
}
});
Bulk Override Propagation Pattern
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_focus",
arguments: { nodeId: "source-instance" }
});
const sourceOverrides = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "get_instance_overrides",
arguments: { instanceId: "source-instance" }
});
const components = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "get_local_components",
arguments: {}
});
const targetInstances = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "scan_nodes_by_types",
arguments: {
nodeTypes: ["INSTANCE"],
namePattern: "ComponentName"
}
});
const targetIds = targetInstances
.filter(node => node.mainComponent?.key === )
.( node.);
({
: ,
: ,
: {
: targetIds,
: sourceOverrides
}
});
Prototype Reactions and Connectors
Visualize Prototype Flows
const reactions = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "get_reactions",
arguments: {
nodeId: "page-id"
}
});
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_default_connector",
arguments: {}
});
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "create_connections",
arguments: {
connections: reactions.map(r => ({
sourceNodeId: r.sourceNodeId,
targetNodeId: r.destinationId
}))
}
});
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "create_connections",
arguments: {
connections: [
{ sourceNodeId: "start-node", : },
{ : , : },
{ : , : }
]
}
});
Export Operations
Export Nodes as Images
const pngExport = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "export_node_as_image",
arguments: {
nodeId: "123:456",
format: "PNG",
scale: 2
}
});
const svgExport = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "export_node_as_image",
arguments: {
nodeId: "123:456",
format: "SVG"
}
});
const jpgExport = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "export_node_as_image",
arguments: {
nodeId: "123:456",
format: "JPG",
scale: 1
}
});
Component and Style Management
Query Components and Styles
const components = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "get_local_components",
arguments: {}
});
const styles = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "get_styles",
arguments: {}
});
Common Workflows
Design System Component Creation
const buttonFrame = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "create_frame",
arguments: {
x: 100, y: 100, width: 120, height: 44,
name: "Button/Primary"
}
});
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_layout_mode",
arguments: {
nodeId: buttonFrame.id,
layoutMode: "HORIZONTAL"
}
});
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_padding",
arguments: {
nodeId: buttonFrame.id,
top: 12, right: 24, bottom: 12, left: 24
}
});
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: ,
: {
: buttonFrame.,
: ,
:
}
});
buttonText = ({
: ,
: ,
: {
: , : ,
: ,
: ,
: ,
:
}
});
({
: ,
: ,
: {
: buttonFrame.,
: , : , : , :
}
});
({
: ,
: ,
: {
: buttonFrame.,
:
}
});
Responsive Card Grid
const grid = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "create_frame",
arguments: {
x: 0, y: 0, width: 1200, height: 800,
name: "Card Grid"
}
});
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_layout_mode",
arguments: {
nodeId: grid.id,
layoutMode: "HORIZONTAL",
layoutWrap: "WRAP"
}
});
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_item_spacing",
arguments: { nodeId: grid.id, spacing: 16 }
});
const cardData = [
{ title: "Card 1", desc: "Description 1" },
{ title: "Card 2", desc: },
{ : , : }
];
( data cardData) {
card = ({
: ,
: ,
: {
: ,
: , :
}
});
({
: ,
: ,
: {
: [
{ : , : data. },
{ : , : data. }
]
}
});
}
Content Localization
const allText = [];
let index = 0;
let hasMore = true;
while (hasMore) {
const result = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "scan_text_nodes",
arguments: { startIndex: index, chunkSize: 100 }
});
allText.push(...result.nodes);
hasMore = result.hasMore;
index += 100;
}
const translations = {
"Welcome": "Bienvenido",
"Sign Up": "Registrarse",
"Learn More": "Aprende Más"
};
const updates = allText
.filter(node => translations[node.characters])
.map(node => ({
nodeId: node.id,
characters: translations[node.characters]
}));
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_multiple_text_contents",
arguments: { updates }
});
Troubleshooting
Connection Issues
WebSocket not connecting:
bun socket
MCP not available in Cursor:
cat ~/.cursor/mcp.json
Channel Connection
Commands not reaching Figma:
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "join_channel",
arguments: { channelId: "unique-session-id" }
});
Node Operations
Node not found errors:
const nodeInfo = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "get_node_info",
arguments: { nodeId: "123:456" }
});
const selection = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "get_selection",
arguments: {}
});
Text update failures:
const nodeInfo = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "get_node_info",
arguments: { nodeId: "text-node-id" }
});
if (nodeInfo.type !== "TEXT") {
throw new Error("Node is not a text node");
}
Performance
Large design handling:
const CHUNK_SIZE = 50;
const batchSize = 20;
for (let i = 0; i < updates.length; i += batchSize) {
const batch = updates.slice(i, i + batchSize);
await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "set_multiple_text_contents",
arguments: { updates: batch }
});
}
Memory issues with exports:
Auto Layout Issues
Elements not respecting layout:
const parentInfo = await use_mcp_tool({
server_name: "TalkToFigma",
tool_name: "get_node_info",
arguments: { nodeId: "parent-id" }
});
await use_mcp_tool