cursor-talk-to-figma-mcp
MCP server enabling AI agents to read and modify Figma designs programmatically through WebSocket communication
How do I install this agent skill?
npx skills add https://github.com/reason-machines/design-skills --skill cursor-talk-to-figma-mcpIs this agent skill safe to install?
- Gen Agent Trust Hubfail
This skill enables AI agents to interact with Figma designs via the Model Context Protocol (MCP). It involves installing the Bun runtime and an MCP server. While the installation sources for Bun and the Figma connection are well-known, the skill exposes design data to the agent, creating a surface for indirect prompt injection from potentially untrusted design files.
- Socketpass
No alerts
- Snykwarn
Risk: MEDIUM · 2 issues
What does this agent skill do?
Cursor Talk to Figma MCP
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 design files. The integration uses a WebSocket server to bridge AI agents (Cursor, Claude Code) with a Figma plugin.
Installation
Prerequisites
Install Bun runtime:
curl -fsSL https://bun.sh/install | bash
Quick Setup
Run the automated setup which installs the MCP server in your Cursor configuration:
bun setup
Manual MCP Configuration
Add to ~/.cursor/mcp.json:
{
"mcpServers": {
"TalkToFigma": {
"command": "bunx",
"args": ["cursor-talk-to-figma-mcp@latest"]
}
}
}
For local development, use direct file path:
{
"mcpServers": {
"TalkToFigma": {
"command": "bun",
"args": ["/absolute/path/to/src/talk_to_figma_mcp/server.ts"]
}
}
}
Start WebSocket Server
bun socket
Figma Plugin Installation
- Install from Figma Community
- Or develop locally: Plugins > Development > New Plugin > Link existing plugin > Select
src/cursor_mcp_plugin/manifest.json
Core Workflow
1. Establish Connection
// First, join a channel to communicate with Figma
await use_mcp_tool("TalkToFigma", "join_channel", {
channelId: "my-design-session"
});
2. Read Design Information
// Get document overview
const docInfo = await use_mcp_tool("TalkToFigma", "get_document_info", {});
// Get current selection
const selection = await use_mcp_tool("TalkToFigma", "get_selection", {});
// Get detailed node information
const nodeInfo = await use_mcp_tool("TalkToFigma", "get_node_info", {
nodeId: "123:456"
});
// Read current selection details without parameters
const selectionDetails = await use_mcp_tool("TalkToFigma", "read_my_design", {});
3. Create Elements
// Create a frame
const frame = await use_mcp_tool("TalkToFigma", "create_frame", {
x: 0,
y: 0,
width: 375,
height: 812,
name: "iPhone Frame"
});
// Create a rectangle
const rect = await use_mcp_tool("TalkToFigma", "create_rectangle", {
x: 20,
y: 20,
width: 335,
height: 200,
name: "Header Background"
});
// Create text
const text = await use_mcp_tool("TalkToFigma", "create_text", {
x: 40,
y: 100,
characters: "Welcome to the App",
fontSize: 24,
fontName: { family: "Inter", style: "Bold" },
name: "Header Title"
});
4. Modify Existing Elements
// Set fill color (RGBA 0-1 range)
await use_mcp_tool("TalkToFigma", "set_fill_color", {
nodeId: "123:456",
r: 0.2,
g: 0.4,
b: 0.8,
a: 1.0
});
// Set stroke
await use_mcp_tool("TalkToFigma", "set_stroke_color", {
nodeId: "123:456",
r: 0.1,
g: 0.1,
b: 0.1,
a: 1.0,
strokeWeight: 2
});
// Set corner radius
await use_mcp_tool("TalkToFigma", "set_corner_radius", {
nodeId: "123:456",
radius: 12
});
// Move node
await use_mcp_tool("TalkToFigma", "move_node", {
nodeId: "123:456",
x: 100,
y: 200
});
// Resize node
await use_mcp_tool("TalkToFigma", "resize_node", {
nodeId: "123:456",
width: 300,
height: 150
});
Auto Layout Configuration
// Set layout mode
await use_mcp_tool("TalkToFigma", "set_layout_mode", {
nodeId: "123:456",
layoutMode: "VERTICAL", // "NONE", "HORIZONTAL", "VERTICAL"
layoutWrap: "NO_WRAP" // "NO_WRAP", "WRAP"
});
// Set padding
await use_mcp_tool("TalkToFigma", "set_padding", {
nodeId: "123:456",
paddingTop: 24,
paddingRight: 16,
paddingBottom: 24,
paddingLeft: 16
});
// Set alignment
await use_mcp_tool("TalkToFigma", "set_axis_align", {
nodeId: "123:456",
primaryAxisAlignItems: "CENTER", // "MIN", "CENTER", "MAX", "SPACE_BETWEEN"
counterAxisAlignItems: "CENTER" // "MIN", "CENTER", "MAX", "BASELINE"
});
// Set sizing behavior
await use_mcp_tool("TalkToFigma", "set_layout_sizing", {
nodeId: "123:456",
layoutSizingHorizontal: "HUG", // "FIXED", "HUG", "FILL"
layoutSizingVertical: "FIXED"
});
// Set item spacing
await use_mcp_tool("TalkToFigma", "set_item_spacing", {
nodeId: "123:456",
itemSpacing: 12
});
Bulk Text Operations
Scan Text Nodes
// Scan all text nodes with chunking for large designs
const textNodes = await use_mcp_tool("TalkToFigma", "scan_text_nodes", {
chunkSize: 50, // Process 50 nodes at a time
startIndex: 0, // Start from beginning
parentNodeId: null // Scan entire document (or specify parent)
});
// Response includes:
// - nodes: Array of text node info
// - hasMore: Boolean indicating more chunks available
// - nextIndex: Index for next chunk
// - total: Total number of text nodes
Update Single Text
await use_mcp_tool("TalkToFigma", "set_text_content", {
nodeId: "123:456",
characters: "Updated heading text"
});
Batch Update Multiple Texts
await use_mcp_tool("TalkToFigma", "set_multiple_text_contents", {
updates: [
{ nodeId: "123:456", characters: "New Title" },
{ nodeId: "123:789", characters: "New Description" },
{ nodeId: "123:101", characters: "Updated Label" }
]
});
Annotations
Get Annotations
// Get all annotations in document
const annotations = await use_mcp_tool("TalkToFigma", "get_annotations", {});
// Get annotations for specific node
const nodeAnnotations = await use_mcp_tool("TalkToFigma", "get_annotations", {
nodeId: "123:456"
});
Create/Update Annotation
await use_mcp_tool("TalkToFigma", "set_annotation", {
nodeId: "123:456",
text: "This component needs **accessibility** improvements:\n- Add ARIA labels\n- Improve color contrast",
category: "DESIGN" // "DESIGN", "ENGINEERING", "CONTENT", "OTHER"
});
Batch Create Annotations
await use_mcp_tool("TalkToFigma", "set_multiple_annotations", {
annotations: [
{
nodeId: "123:456",
text: "Update to new brand colors",
category: "DESIGN"
},
{
nodeId: "123:789",
text: "Implement loading state",
category: "ENGINEERING"
}
]
});
Components and Instances
Get Components
const components = await use_mcp_tool("TalkToFigma", "get_local_components", {});
Create Component Instance
const instance = await use_mcp_tool("TalkToFigma", "create_component_instance", {
componentKey: "abc123def456",
x: 100,
y: 100
});
Instance Override Management
// Extract overrides from source instance
const overrides = await use_mcp_tool("TalkToFigma", "get_instance_overrides", {
sourceInstanceId: "123:456"
});
// Apply overrides to target instances
await use_mcp_tool("TalkToFigma", "set_instance_overrides", {
targetInstanceIds: ["123:789", "123:101"],
overrides: overrides.overrides
});
Prototyping and Connections
Get Prototype Reactions
// Get all prototype reactions with visual highlights
const reactions = await use_mcp_tool("TalkToFigma", "get_reactions", {});
// Response includes source/destination nodes and interaction details
Create FigJam Connectors
// First, copy a connector in FigJam and set it as default
await use_mcp_tool("TalkToFigma", "set_default_connector", {});
// Create connections based on prototype flow
await use_mcp_tool("TalkToFigma", "create_connections", {
connections: [
{ from: "123:456", to: "123:789" },
{ from: "123:789", to: "123:101" }
]
});
Selection and Focus
// Focus on specific node (selects and scrolls viewport)
await use_mcp_tool("TalkToFigma", "set_focus", {
nodeId: "123:456"
});
// Select multiple nodes
await use_mcp_tool("TalkToFigma", "set_selections", {
nodeIds: ["123:456", "123:789", "123:101"]
});
Node Management
Clone Nodes
const clone = await use_mcp_tool("TalkToFigma", "clone_node", {
nodeId: "123:456",
offsetX: 20, // Optional X offset
offsetY: 20 // Optional Y offset
});
Delete Nodes
// Delete single node
await use_mcp_tool("TalkToFigma", "delete_node", {
nodeId: "123:456"
});
// Delete multiple nodes efficiently
await use_mcp_tool("TalkToFigma", "delete_multiple_nodes", {
nodeIds: ["123:456", "123:789", "123:101"]
});
Get Multiple Nodes Info
const nodesInfo = await use_mcp_tool("TalkToFigma", "get_nodes_info", {
nodeIds: ["123:456", "123:789", "123:101"]
});
Export
// Export node as image
const imageData = await use_mcp_tool("TalkToFigma", "export_node_as_image", {
nodeId: "123:456",
format: "PNG", // "PNG", "JPG", "SVG", "PDF"
scale: 2 // Optional: 1, 2, 3, 4
});
// Returns base64 encoded image data
Scan Nodes by Type
// Find all nodes of specific types (useful for finding annotation targets)
const frames = await use_mcp_tool("TalkToFigma", "scan_nodes_by_types", {
types: ["FRAME", "COMPONENT", "INSTANCE"],
parentNodeId: null // Optional: limit to specific parent
});
Common Patterns
Pattern: Create a Card Component
// 1. Create container frame
const card = await use_mcp_tool("TalkToFigma", "create_frame", {
x: 0, y: 0, width: 300, height: 400, name: "Card"
});
// 2. Set auto layout
await use_mcp_tool("TalkToFigma", "set_layout_mode", {
nodeId: card.id, layoutMode: "VERTICAL"
});
await use_mcp_tool("TalkToFigma", "set_padding", {
nodeId: card.id,
paddingTop: 20, paddingRight: 20,
paddingBottom: 20, paddingLeft: 20
});
await use_mcp_tool("TalkToFigma", "set_item_spacing", {
nodeId: card.id, itemSpacing: 16
});
// 3. Style the card
await use_mcp_tool("TalkToFigma", "set_fill_color", {
nodeId: card.id, r: 1, g: 1, b: 1, a: 1
});
await use_mcp_tool("TalkToFigma", "set_corner_radius", {
nodeId: card.id, radius: 8
});
// 4. Add shadow via stroke as workaround
await use_mcp_tool("TalkToFigma", "set_stroke_color", {
nodeId: card.id, r: 0.9, g: 0.9, b: 0.9, a: 1, strokeWeight: 1
});
Pattern: Bulk Content Replacement
// 1. Scan all text nodes in chunks
let allTextNodes = [];
let hasMore = true;
let nextIndex = 0;
while (hasMore) {
const result = await use_mcp_tool("TalkToFigma", "scan_text_nodes", {
chunkSize: 50,
startIndex: nextIndex
});
allTextNodes = allTextNodes.concat(result.nodes);
hasMore = result.hasMore;
nextIndex = result.nextIndex;
}
// 2. Filter and prepare updates
const updates = allTextNodes
.filter(node => node.characters.includes("old-text"))
.map(node => ({
nodeId: node.id,
characters: node.characters.replace("old-text", "new-text")
}));
// 3. Batch update
await use_mcp_tool("TalkToFigma", "set_multiple_text_contents", {
updates: updates
});
Pattern: Convert Legacy Annotations
// 1. Scan for text nodes with numbered markers
const textNodes = await use_mcp_tool("TalkToFigma", "scan_text_nodes", {});
const markers = textNodes.nodes.filter(n => /^\d+\./.test(n.characters));
// 2. Find potential annotation targets
const targets = await use_mcp_tool("TalkToFigma", "scan_nodes_by_types", {
types: ["FRAME", "COMPONENT", "INSTANCE", "RECTANGLE"]
});
// 3. Match markers to targets (by proximity, naming, or path)
const annotations = markers.map(marker => {
const targetNode = findClosestTarget(marker, targets.nodes);
return {
nodeId: targetNode.id,
text: marker.characters.replace(/^\d+\.\s*/, ""),
category: "DESIGN"
};
});
// 4. Create native annotations
await use_mcp_tool("TalkToFigma", "set_multiple_annotations", {
annotations: annotations
});
// 5. Delete old marker nodes
await use_mcp_tool("TalkToFigma", "delete_multiple_nodes", {
nodeIds: markers.map(m => m.id)
});
Pattern: Prototype to Connector Visualization
// 1. Get prototype reactions
const reactions = await use_mcp_tool("TalkToFigma", "get_reactions", {});
// 2. Copy and set default connector style in FigJam
await use_mcp_tool("TalkToFigma", "set_default_connector", {});
// 3. Extract connections from reactions
const connections = reactions.reactions.map(r => ({
from: r.node.id,
to: r.action.destinationId
}));
// 4. Create connector lines
await use_mcp_tool("TalkToFigma", "create_connections", {
connections: connections
});
Windows + WSL Configuration
For Windows with WSL, uncomment the hostname in src/socket.ts:
// Uncomment for Windows WSL
hostname: "0.0.0.0",
Install Bun via PowerShell:
irm bun.sh/install.ps1|iex
Troubleshooting
WebSocket Connection Issues
- Ensure WebSocket server is running:
bun socket - Verify Figma plugin is active and connected
- Check that
join_channelwas called successfully - For WSL, ensure hostname is set to
0.0.0.0
MCP Server Not Found
- Verify
~/.cursor/mcp.jsonconfiguration is correct - Restart Cursor after configuration changes
- Check that Bun is installed and in PATH
- For local development, use absolute paths
Commands Fail Silently
- Always join a channel first with
join_channel - Verify node IDs exist using
get_document_infoorget_selection - Check WebSocket server logs for errors
- Ensure Figma file is open and plugin is running
Text Update Failures
- Verify node is actually a TEXT node type
- Check that text layer is not locked
- For batch updates, process in smaller chunks if needed
- Missing fonts may cause failures - ensure fonts are available
Color Values
All color values use 0-1 range (not 0-255):
- Convert:
rgbValue / 255 - Example: RGB(51, 102, 204) = r: 0.2, g: 0.4, b: 0.8
Auto Layout Constraints
set_layout_modemust be called before other auto-layout properties- Cannot set padding on non-auto-layout frames
- Item spacing only works in auto-layout frames
- Some sizing modes require specific layout configurations
Best Practices
- Always establish connection first - Call
join_channelbefore any other commands - Get context before modifying - Use
get_document_infoandget_selectionto understand structure - Use batch operations - Prefer
set_multiple_text_contentsover multipleset_text_contentcalls - Chunk large operations - Use chunking parameters for designs with many nodes
- Verify changes - Use
get_node_infoafter modifications to confirm success - Handle errors gracefully - All commands can throw exceptions, implement proper error handling
- Use component instances - Prefer instances over duplicating elements for consistency
- Organize with frames - Use frames with auto-layout for structured, responsive designs
- Clean up legacy elements - Delete old nodes after migrating to new patterns
- Test incrementally - Verify each step when building complex automation workflows
How can the creator link this skill?
Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.
<a href="https://skillzs.dev/skills/reason-machines/design-skills/cursor-talk-to-figma-mcp">View cursor-talk-to-figma-mcp on skillZs</a>