MCPInstall

cursor-talk-to-figma-mcp

MCP server enabling AI agents to read and modify Figma designs programmatically through WebSocket communication

Installs
146
Last 24h
—
Trending rank
—
Security
Not audited

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/reason-machines/design-skills --skill cursor-talk-to-figma-mcp
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads cursor-talk-to-figma-mcp automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

SKILL.md

The instructions your agent reads when the skill is triggered.

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

  1. Install from Figma Community
  2. 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_channel was called successfully
  • For WSL, ensure hostname is set to 0.0.0.0

MCP Server Not Found

  • Verify ~/.cursor/mcp.json configuration 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_info or get_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_mode must 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

  1. Always establish connection first - Call join_channel before any other commands
  2. Get context before modifying - Use get_document_info and get_selection to understand structure
  3. Use batch operations - Prefer set_multiple_text_contents over multiple set_text_content calls
  4. Chunk large operations - Use chunking parameters for designs with many nodes
  5. Verify changes - Use get_node_info after modifications to confirm success
  6. Handle errors gracefully - All commands can throw exceptions, implement proper error handling
  7. Use component instances - Prefer instances over duplicating elements for consistency
  8. Organize with frames - Use frames with auto-layout for structured, responsive designs
  9. Clean up legacy elements - Delete old nodes after migrating to new patterns
  10. Test incrementally - Verify each step when building complex automation workflows

FAQ

What does the cursor-talk-to-figma-mcp skill do?

MCP server enabling AI agents to read and modify Figma designs programmatically through WebSocket communication

How do I install cursor-talk-to-figma-mcp?

Run npx skills add https://github.com/reason-machines/design-skills --skill cursor-talk-to-figma-mcp in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/cursor-talk-to-figma-mcp/ (personal) or .claude/skills/cursor-talk-to-figma-mcp/ (project).

Which AI agents can use cursor-talk-to-figma-mcp?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is cursor-talk-to-figma-mcp safe to install?

No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.

Who maintains cursor-talk-to-figma-mcp?

It is published by reason-machines in reason-machines/design-skills. It has 146 recorded installs.

More from reason-machines/design-skills

View all →

awesome-claude-design

reason-machines/design-skills

Open the skill to read its SKILL.md instructions.

205 installs

design-md-format

reason-machines/design-skills

Create and validate DESIGN.md files that give AI coding agents structured understanding of design systems through machine-readable tokens and human-readable rationale.

178 installs

open-codesign-ai-design

reason-machines/design-skills

Use Open CoDesign to generate prototypes, slides, and PDFs from prompts with Claude, GPT, Gemini, or local models

AI & Agents175 installs

open-design-ai-prototyping

reason-machines/design-skills

Open the skill to read its SKILL.md instructions.

174 installs

keychron-hardware-design

reason-machines/design-skills

Access and work with Keychron keyboard and mouse industrial design files (STEP, DXF, DWG, PDF) for 135+ models to create compatible accessories, remixes, and modifications.

Docs & Writing167 installs

design-md-chrome-extractor

reason-machines/design-skills

Open the skill to read its SKILL.md instructions.

166 installs

Popular ai & agents skills

View category →

google-agents-cli-publish

google/agents-cli

This skill should be used when the user wants to "publish an agent", "publish my ADK agent", "register an agent with Gemini", "publish to Gemini" (formerly Gemini Enterprise), or needs guidance on the agents-cli publish gemini command. Also use when the user wants to "manage agents in Agent Registry", "list/update/delete registered agents", or "register an MCP server". Covers ADK vs A2A registration modes, programmatic and interactive usage, flag reference, auto-detection from deployment metadata, Agent Registry fleet management, and troubleshooting. Part of the agents-cli skills suite. Do NOT use for deployment (use google-agents-cli-deploy).

AI & Agents513.9K installs

google-agents-cli-eval

google/agents-cli

This skill should be used when the user wants to "run an evaluation", "evaluate my agent", "evaluate my ADK agent", "write an eval dataset", "analyze eval failures", "compare eval results", "optimize agent", or needs guidance on the Gemini platform eval methodology and the Quality Flywheel. Covers eval metrics, dataset schema, LLM-as-judge scoring, and common failure causes. Applies to any agents-cli project, whatever framework the agent is written in. Do NOT use for agent API code patterns (ADK: use google-agents-cli-adk-code), deployment (use google-agents-cli-deploy), or project scaffolding (use google-agents-cli-scaffold).

AI & Agents513.5K installs

skill-creator

anthropics/skills

Create new skills, modify and improve existing skills, and measure skill performance. Use when users want to create a skill from scratch, edit, or optimize an existing skill, run evals to test a skill, benchmark skill performance with variance analysis, or optimize a skill's description for better triggering accuracy.

OfficialAI & Agents416.4K installs

codex-pet

prime-skills/runcomfy-agent-skills

Codex Pet generator on RunComfy. Build a Codex-compatible Codex Pet spritesheet.webp + pet.json from a single reference image, drop it into ${CODEXHOME:-$HOME/.codex}/pets/ / and Codex picks it up as a custom Codex Pet next to the 8 built-ins. This skill produces the exact Codex Pet atlas Codex expects (1536x1872 PNG/WebP, 8 cols x 9 rows, 192x208 cells, 9 animation states — idle, running-right, running-left, waving, jumping, failed, waiting, running, review). Calls OpenAI GPT Image 2 edit ONCE via the local RunComfy CLI as runcomfy run openai/gpt-image-2/edit to produce a canonical Codex Pet pose, then assembles all 9 animation rows programmatically with ImageMagick micro-transforms — no Codex Pro, no $imagegen, no OPENAIAPIKEY required, only RUNCOMFYTOKEN. Triggers on "codex pet", "create codex pet", "make codex pet", "hatch codex pet", "/hatch image", "desktop pet codex", "codex pets", "spritesheet.webp", or any explicit ask to build a custom pet for OpenAI Codex.

AI & Agents402.1K installs

full-output-enforcement

leonxlnx/taste-skill

Overrides default LLM truncation behavior. Enforces complete code generation, bans placeholder patterns, and handles token-limit splits cleanly. Apply to any task requiring exhaustive, unabridged output.

AI & Agents401K installs

executing-plans

obra/superpowers

Use when executing an implementation plan in the current session as the implementer yourself — your human partner chose inline execution, or no subagent tool is available

AI & Agents245.7K installs