This project implements a Model Context Protocol (MCP) integration between Cursor AI and Figma, allowing Cursor to communicate with Figma for reading designs and modifying them programmatically.
cursorfigmavideo.mp4
src/talk_to_figma_mcp/- TypeScript MCP server for Figma integrationsrc/cursor_mcp_plugin/- Figma plugin for communicating with Cursorsrc/socket.ts- WebSocket server that facilitates communication between the MCP server and Figma plugin
- Install Bun if you haven't already:
curl -fsSL https://bun.sh/install | bash- Run setup, this will also install MCP in your Cursor's active project
bun setup- Start the Websocket server
bun socket- NEW Install Figma plugin from Figma community page or install locally
Bulk text content replacement
Thanks to @dusskapark for contributing the bulk text replacement feature. Here is the demo video.
Instance Override Propagation Another contribution from @dusskapark Propagate component instance overrides from a source instance to multiple target instances with a single command. This feature dramatically reduces repetitive design work when working with component instances that need similar customizations. Check out our demo video.
To develop, update your mcp config to direct to your local directory.
{
"mcpServers": {
"TalkToFigma": {
"command": "bun",
"args": ["/path-to-repo/src/talk_to_figma_mcp/server.ts"]
}
}
}Add the server to your Cursor MCP configuration in ~/.cursor/mcp.json:
{
"mcpServers": {
"TalkToFigma": {
"command": "bunx",
"args": ["cursor-talk-to-figma-mcp@latest"]
}
}
}Start the WebSocket server:
bun socket- In Figma, go to Plugins > Development > New Plugin
- Choose "Link existing plugin"
- Select the
src/cursor_mcp_plugin/manifest.jsonfile - The plugin should now be available in your Figma development plugins
- Install bun via powershell
powershell -c "irm bun.sh/install.ps1|iex"- Uncomment the hostname
0.0.0.0insrc/socket.ts
// uncomment this to allow connections in windows wsl
hostname: "0.0.0.0",- Start the websocket
bun socket- Start the WebSocket server (
bun socket). - Launch the MCP server (either via
bun run src/talk_to_figma_mcp/server.tsduring development or the published package). - Open Figma, run the “Cursor Talk to Figma” plugin, and connect it to the WebSocket channel shown in the plugin UI.
- Inside Cursor, call the
join_channeltool once to bind the MCP server to the same channel. - Invoke the
figmatool for every Plugin API interaction.
Tip: run
bun run generate:manifestwhenever you upgrade@figma/plugin-typings. The manifest ingenerated/figma-manifest.jsonplussrc/generated/figma-manifest.tsis rebuilt automatically duringbun run build.
The MCP server now exposes a single high-level tool that dynamically maps to the entire Plugin API.
-
Description: Invoke any Figma Plugin API method using manifest-driven validation.
-
Input shape:
method– required string; matches the method name in the manifest.path– optional target path (defaults tofigma). Usenodepluscontext.nodeId/context.useSelectionfor node methods.args– array or object of arguments. When object-shaped, the manifest maps keys to positional params.overload– optional index if multiple signatures exist.context– selection/node helpers (nodeId,nodeIds,useSelection,selectionIndex,propertyPath).options.subscribe/options.unsubscribe– wrapfigma.on,Node.on, and similar APIs. Subscriptions stream events back through the plugin UI and can be retrieved withget_subscription_events.
-
Response: JSON object containing the resolved invocation metadata and the normalized return value. When subscriptions are involved the result includes
subscriptionId,subscriptionAction, andsubscriptionActiveflags.
- Description: Returns the generated manifest containing every Plugin API method, overload, parameter list, return type, and doc snippet.
- Usage:
{ "filter": "viewport." }(optional case-insensitive filter).
- Description: Returns queued events emitted by active subscriptions created via the
figmatool. - Parameters:
subscriptionIdorsubscriptionIds– limit to specific subscriptions.drain(defaulttrue) – whether to remove events from the queue after fetching.
- Response: Map of subscription IDs to chronological event payloads containing the original data, event name, and timestamps.
- Description: Join the WebSocket channel announced by the Figma plugin UI.
- Usage:
{ "channel": "abc123" }once per session (subsequent API calls reuse the active channel).
- Call
figmawithoptions.subscribe: trueto attach to an event (for example:{ "method": "on", "path": "figma", "args": { "event": "selectionchange" }, "options": { "subscribe": true } }). - Receive streaming events via
get_subscription_eventsor observe them in Cursor’s logging output. - Call
figmaagain withoptions.unsubscribe: trueand the samesubscriptionIdto detach.
Events are buffered per subscription ID so long-running sessions can poll the queue without missing updates.
The MCP server includes several helper prompts to guide you through complex design tasks:
design_strategy- Best practices for working with Figma designsread_design_strategy- Best practices for reading Figma designstext_replacement_strategy- Systematic approach for replacing text in Figma designsannotation_conversion_strategy- Strategy for converting manual annotations to Figma's native annotationsswap_overrides_instances- Strategy for transferring overrides between component instances in Figmareaction_to_connector_strategy- Strategy for converting Figma prototype reactions to connector lines using the output of 'get_reactions', and guiding the use 'create_connections' in sequence
-
Navigate to the Figma plugin directory:
cd src/cursor_mcp_plugin -
Edit code.js and ui.html
When working with the Figma MCP:
- Always join a channel before sending commands
- Get document overview using
get_document_infofirst - Check current selection with
get_selectionbefore modifications - Use appropriate creation tools based on needs:
create_framefor containerscreate_rectanglefor basic shapescreate_textfor text elements
- Verify changes using
get_node_info - Use component instances when possible for consistency
- Handle errors appropriately as all commands can throw exceptions
- For large designs:
- Use chunking parameters in
scan_text_nodes - Monitor progress through WebSocket updates
- Implement appropriate error handling
- Use chunking parameters in
- For text operations:
- Use batch operations when possible
- Consider structural relationships
- Verify changes with targeted exports
- For converting legacy annotations:
- Scan text nodes to identify numbered markers and descriptions
- Use
scan_nodes_by_typesto find UI elements that annotations refer to - Match markers with their target elements using path, name, or proximity
- Categorize annotations appropriately with
get_annotations - Create native annotations with
set_multiple_annotationsin batches - Verify all annotations are properly linked to their targets
- Delete legacy annotation nodes after successful conversion
- Visualize prototype noodles as FigJam connectors:
- Use
get_reactionsto extract prototype flows, - set a default connector with
set_default_connector, - and generate connector lines with
create_connectionsfor clear visual flow mapping.
MIT
{ "method": "setRelaunchData", "path": "figma", "args": { "data": { "key": "value" } }, "context": { "nodeId": "123:456" }, "options": { "subscribe": true, "subscriptionId": "optional-fixed-id" } }