Skip to main content
Glama
figma-slides-mcp

figma-slides-mcp

by luan007

figma-slides-mcp

MCP server that lets AI create and edit Figma Slides — with built-in D3, Rough.js, and Satori renderers for charts, diagrams, and custom graphics.

architecture license enjoy

What this is

An MCP server that gives AI agents (Claude, Cursor, etc.) direct control over Figma Slides. The AI can create slides, add text, draw shapes, render D3 charts, place images, and screenshot its work — all in real-time, in your actual Figma file.

This is not a design-to-code tool. It goes the other direction: AI → Figma. Your agent designs slides for you.

Related MCP server: figmad-mcp

How it works

Your AI Agent ←—stdio—→ MCP Server ←—WebSocket—→ Figma Plugin ←—API—→ Slides Canvas

Three pieces:

  1. MCP Server — Node.js process that exposes tools over stdio. Your AI client spawns it.

  2. Figma Plugin — Runs inside Figma, executes commands on the canvas. Connects via WebSocket.

  3. Design Skill (optional) — Teaches the AI how to design well: layout, typography, color, D3 patterns.

Quick start

Step 1 — Add the marketplace and install:

/plugin marketplace add luan007/figma-slides-mcp
/plugin install figma-slides-mcp@figma-slides-mcp

This clones the repo, loads the MCP server and design skill automatically.

Step 2 — Load the Figma plugin:

  1. Open a Figma Slides file

  2. Plugins → Development → Import plugin from manifest...

  3. Navigate to the cloned plugin directory — check the plugin cache:

    ~/.claude/plugins/cache/figma-slides-mcp/

    Find plugin/manifest.json inside and select it.

  4. Run the plugin — green dot = connected

You only import the manifest once. After that it's in your recent plugins.

Step 3 — Go:

Tell Claude: "Start a Figma Slides session"

Other MCP clients (Cursor, Windsurf, etc.)

git clone https://github.com/luan007/figma-slides-mcp.git
cd figma-slides-mcp && npm install

Add to your MCP config:

{
  "mcpServers": {
    "figma-slides": {
      "command": "npx",
      "args": ["-y", "figma-slides-mcp"]
    }
  }
}

Then import plugin/manifest.json into Figma (same as Step 2 above, but from your clone directory).

Graphics renderers

The Figma plugin bundles full graphics libraries. Your AI can use them to render complex visuals directly onto slides.

Renderer

What it does

Text stays editable?

D3 v7

Charts, data viz, diagrams, tables

Yes

Rough.js

Hand-drawn / sketchy style graphics

Yes

Satori

HTML/CSS → SVG (flexbox layouts)

No (becomes paths)

SVG import

Icons, logos, custom vectors

Depends

The AI writes a D3 script, the plugin runs it in a sandboxed iframe, extracts the SVG, and converts it to editable Figma nodes. Text elements become real Figma text — you can edit them after.

What the AI can do

  • Create, duplicate, delete, reorder slides

  • Add any shape: rectangles, ellipses, lines, frames, text

  • Style anything: fills, strokes, effects, opacity, corner radius

  • Set text with per-character styling (font, size, color, spacing)

  • Render D3 charts, Rough.js sketches, Satori layouts

  • Place images from URL

  • Screenshot slides to verify its own work

  • Batch multiple operations in one call

  • Search nodes, export to PNG/SVG/PDF

Design skill

The bundled skill at skills/figma-slides-mcp/SKILL.md teaches the AI:

  • Layout planning (coordinate grids, column systems)

  • Typography hierarchy (font sizes, spacing, weight)

  • Visual design theory (when to use charts vs text, color systems)

  • D3 patterns (tables, flows, comparisons, Gantt charts, donuts)

  • The screenshot-verify-fix loop

  • API gotchas (gradient transforms, fill opacity, batch limits)

It's optional but makes a big difference. Without it, the AI tends to dump text on slides. With it, the AI thinks in layers and designs visually.

Claude Code plugin install includes the skill automatically. For manual setup, copy it to ~/.claude/skills/figma-slides-mcp/.

Limitations & quirks

This is an early-stage project. It works, but has edges.

  • Single session only. One MCP server → one Figma file at a time. No multi-document support yet.

  • Port conflict. If another instance is running on port 3055, it fails. Set FIGMA_WS_PORT to use a different port.

  • Plugin must be running. The Figma plugin needs to be open and connected. If you close it, the MCP server can't reach Figma.

  • Figma Slides only. Doesn't work with regular Figma Design files. Must be a Slides file.

  • Tables are limited. createTable works but is Slides-only and can be finicky.

  • Video is broken. createVideoAsync returns empty. Figma's API limitation.

  • Satori text is paths. Text rendered through Satori becomes vector paths — not editable as text in Figma. Use D3 instead when text editability matters.

  • No undo across sessions. The AI's changes are real Figma operations. You can Cmd+Z in Figma, but only within the current session.

  • Dev plugin, not published. The Figma plugin is loaded from local manifest, not the Figma Community. You need to import it manually once.

Under construction

  • Multi-session support (multiple Figma files)

  • Published Figma Community plugin (no manual manifest import)

  • Slide templates / presets

  • Better image search integration

  • Animation / transition authoring

Environment variables

Variable

Default

Description

FIGMA_WS_PORT

3055

WebSocket port for plugin connection

Project structure

figma-slides-mcp/
├── server/           # MCP server (Node.js, no build)
│   ├── index.js      # Entry point (stdio transport)
│   ├── bridge.js     # WebSocket bridge to plugin
│   ├── tools.js      # All MCP tool definitions
│   └── utils.js      # Helpers
├── plugin/           # Figma plugin (no build)
│   ├── manifest.json # Import this in Figma
│   ├── code.js       # Plugin logic
│   └── ui.html       # UI panel + D3/Rough.js/Satori loaders
├── skills/           # AI design skill
│   └── figma-slides-mcp/
│       └── SKILL.md
├── .claude-plugin/   # Claude Code plugin manifest
│   └── plugin.json
├── .mcp.json         # MCP server config (auto-loaded by plugin system)
└── test/

Zero TypeScript, zero bundlers, zero build steps. Plain JS all the way down.

For AI agents

See AGENT-INSTALL.md for detailed setup instructions, troubleshooting, and the full tool reference.

License

MIT

Available Tools

58 tools
batch_operationsBatch OperationsA

Execute multiple commands in one round-trip. Use "$N.field" to reference results from earlier commands (e.g. "$0.nodeId"). All execute as single undo step.

Inputs: commands (required).

clear_slideClear SlideA

Remove all content from a slide, keeping the slide itself.

Inputs: slideId (required).

clone_nodeClone NodeB

Duplicate a node, optionally reparenting the clone.

Inputs: nodeId (required), parentId.

connection_statusConnection StatusA

Check if the Figma plugin is connected. Does NOT start the server — use start_session first.

Inputs: no named parameters.

create_gifCreate GIFB

Create a GIF node (Slides only, may have limited support)

Inputs: parentId (required), data.

create_nodeCreate NodeA

Create a node (FRAME, RECTANGLE, ELLIPSE, POLYGON, STAR, LINE, VECTOR, TEXT) with optional properties. For tables, shapes-with-text, etc., use dedicated tools.

Inputs: type (required), parentId (required), props.

create_shape_with_textCreate Shape With TextC

Create a shape with built-in text label (Slides/FigJam). shapeType: SQUARE, ELLIPSE, ROUNDED_RECTANGLE, DIAMOND, TRIANGLE_UP, etc.

Inputs: text (required), parentId (required), props, shapeType.

create_slideCreate SlideB

Create a new empty slide (fixed 1920x1080).

Inputs: fills, themeId, rowIndex.

create_slide_rowCreate Slide RowA

Create a new slide row in the deck grid

Inputs: index.

create_svgCreate SVGA

Import an SVG string as editable Figma vector nodes. Use for icons, logos, simple graphics. The agent generates the SVG string directly.

Inputs: svg (required), parentId (required), x, y, +2 more.

create_tableCreate TableB

Create a table (Slides/FigJam only)

Inputs: cols (required), rows (required), parentId (required), cellWidth, +1 more.

create_videoCreate VideoA

Create a video node from URL or bytes (Slides only, MP4/MOV/WebM)

Inputs: parentId (required), x, y, url, +3 more.

delete_nodeDelete NodeB

Remove a node from the canvas

Inputs: nodeId (required).

delete_slideDelete SlideB

Remove a slide from the deck

Inputs: slideId (required).

delete_slide_rowDelete Slide RowA

Remove a slide row and all slides in it

Inputs: rowId (required).

delete_table_columnDelete Table ColumnC

Remove a column from a table

Inputs: index (required), tableId (required).

delete_table_rowDelete Table RowC

Remove a row from a table

Inputs: index (required), tableId (required).

duplicate_slideDuplicate SlideB

Clone a slide with all content

Inputs: slideId (required).

export_nodeExport NodeB

Export any node to PNG, JPG, SVG, or PDF

Inputs: nodeId (required), scale, format.

find_nodesFind NodesA

Search for nodes by name (substring), type, visible, locked. All criteria AND-combined.

Inputs: criteria (required), parentId.

focus_slideFocus SlideC

Navigate to a specific slide in the editor

Inputs: slideId (required).

get_cell_contentGet Cell ContentB

Read text of a table cell

Inputs: col (required), row (required), tableId (required).

get_editor_infoGet Editor InfoA

Get editor type, document name, and page count from the connected Figma file

Inputs: no named parameters.

get_interactive_elementsGet Interactive ElementsA

List interactive elements on a slide (polls, embeds). Read-only.

Inputs: slideId (required).

get_node_propertiesGet Node PropertiesB

Read all or specific properties of a node

Inputs: nodeId (required), properties.

get_node_treeGet Node TreeA

Get structural tree: IDs, types, names, bounds. Use depth to limit recursion.

Inputs: depth, nodeId.

get_selectionGet SelectionA

Get currently selected node IDs

Inputs: no named parameters.

get_slide_contextGet Slide ContextA

Get a rich semantic dump of everything on a slide: text content, shapes, images, positions, styles. Best for understanding what is on a slide before editing.

Inputs: slideId (required).

get_slide_gridGet Slide GridA

Get the full slide deck structure: rows and slides with their IDs and names

Inputs: no named parameters.

get_text_contentGet Text ContentA

Read text content and style segments from a text node

Inputs: nodeId (required).

group_nodesGroup NodesC

Group multiple nodes together

Inputs: nodeIds (required), parentId.

insert_table_columnInsert Table ColumnC

Insert a column into a table

Inputs: tableId (required), index.

insert_table_rowInsert Table RowC

Insert a row into a table

Inputs: tableId (required), index.

list_fontsList FontsA

Search available fonts. Use query to filter by family name. Without query, returns first 50 families.

Inputs: limit, query.

list_themesList ThemesA

List available slide themes

Inputs: no named parameters.

move_slide_to_rowMove Slide to RowC

Move a slide to a different row

Inputs: rowId (required), slideId (required), index.

place_imagePlace ImageA

Place an image from URL or bytes. Creates a rectangle with IMAGE fill.

Inputs: parentId (required), x, y, url, +4 more.

render_d3Render D3 VisualizationA

Render a D3.js visualization as editable Figma vector nodes. PREFERRED for data visualizations, charts, graphs, diagrams.

The script runs in the plugin iframe with full D3 v7 available. Write JS that uses d3 to build SVG in the scratch div. The SVG is auto-extracted and converted to editable Figma nodes.

Available globals: d3, scratch (offscreen div to render into). The script should either return an SVG string or render into scratch (auto-extracted).

IMPORTANT: All text becomes editable Figma text nodes. This is the best renderer for data-driven graphics.

Inputs: script (required), parentId (required), x, y, +2 more.

render_roughRender Rough.js SketchA

Render hand-drawn / sketchy style graphics using Rough.js as editable Figma nodes.

Use for: informal diagrams, whiteboard-style visuals, creative/playful graphics. Available: rough (Rough.js), scratch div, plus a pre-created SVG element.

Write JS that uses rough.svg(svg) to draw shapes. They render with a hand-drawn aesthetic (hachure, cross-hatch, zigzag, dots fills).

IMPORTANT: All output is editable vector nodes in Figma.

Inputs: script (required), parentId (required), x, y, +2 more.

render_satoriRender HTML/CSS via SatoriA

Render HTML/CSS layout as editable Figma vector nodes using Satori (Vercel's HTML-to-SVG engine).

Use ONLY when you need complex CSS layouts that are hard to express as SVG — flexbox cards, multi-column layouts, UI components. For data viz, prefer render_d3 instead.

LIMITATIONS:

  • Text is rendered as vector PATHS, not editable text nodes. Users cannot edit text in Figma.

  • No CSS gradients (use solid colors instead)

  • No rgba() (use hex colors)

  • Requires fetching a font file (adds latency)

  • Uses JSX-object syntax, not HTML strings

The script runs in the iframe. Use the satori() function with JSX-like objects. Must fetch a font first: fetch Inter WOFF, pass as fonts array.

Available: satori (the render function), scratch div.

Inputs: script (required), parentId (required), x, y, +2 more.

reorder_slidesReorder SlidesB

Set the order of slide rows in the deck

Inputs: rowIds (required).

reparent_nodeReparent NodeB

Move a node to a different parent container

Inputs: nodeId (required), parentId (required), index.

replace_mediaReplace MediaC

Replace media content of a video/image node

Inputs: data (required), nodeId (required).

screenshot_all_slidesScreenshot All SlidesA

Capture thumbnails of all slides. Returns array of base64 PNG images.

Inputs: scale, maxSlides.

screenshot_slideScreenshot SlideA

Capture a visual screenshot of a slide as PNG. Returns base64-encoded image.

Inputs: slideId (required), scale.

set_cell_contentSet Cell ContentC

Set text of a table cell

Inputs: col (required), row (required), text (required), tableId (required), +1 more.

set_propertiesSet PropertiesA

Modify properties of any node. Supports x, y, width, height, rotation, fills, strokes, strokeWeight, effects, opacity, blendMode, cornerRadius, visible, locked, layoutMode, itemSpacing, padding.

Inputs: props (required), nodeId (required).

set_selectionSet SelectionC

Select specific nodes

Inputs: nodeIds (required).

set_slide_skippedSet Slide SkippedB

Mark slide as skipped in presentation

Inputs: slideId (required), isSkipped (required).

set_slides_view_modeSet Slides View ModeB

Switch between grid and single-slide view

Inputs: mode (required).

set_slide_themeSet Slide ThemeC

Apply a theme to a slide

Inputs: slideId (required), themeId (required).

set_slide_transitionSet Slide TransitionA

Set transition: DISSOLVE, SLIDE_FROM_LEFT/RIGHT/TOP/BOTTOM, PUSH_FROM_*, SMART_ANIMATE, NONE

Inputs: style (required), slideId (required), curve, timing, +1 more.

set_textSet TextA

Set text content of a text node. Font loading is automatic.

Inputs: text (required), nodeId (required), fontName.

set_text_range_styleSet Text Range StyleA

Apply styles to a character range: fontSize, fontName, fills, letterSpacing, lineHeight, textDecoration, textCase

Inputs: end (required), props (required), start (required), nodeId (required).

set_viewportSet ViewportC

Set editor viewport center and zoom

Inputs: zoom, center.

start_sessionStart Figma Slides SessionA

Start the WebSocket server and wait for the Figma plugin to connect. Call this when the user says "start figma session", "connect to figma", or "open slides". Returns connection status and instructions if not yet connected.

Inputs: no named parameters.

ungroup_nodeUngroup NodeA

Ungroup a group node, returning children to parent

Inputs: nodeId (required).

zoom_to_fitZoom to FitC

Zoom to fit specific nodes or all content

Inputs: nodeIds.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.1/5.0

    Scored across 58 tools

    Disambiguation4/5

    Most tools have clearly distinct purposes, with each targeting a specific resource or action. Some overlap exists between creation tools (create_node, create_table, render_svg, render_d3, etc.), but descriptions clarify intended use cases.

    Naming Consistency4/5

    The vast majority follow a verb_noun pattern (e.g., create_slide, delete_node, set_text). A few outliers like batch_operations, connection_status, and render_d3 use nouns or library names, causing minor inconsistency.

    Tool Count1/5

    58 tools is an extreme number for an MCP server, far beyond the typical well-scoped range. While the domain is complex, this many tools creates a heavy surface area that is difficult for agents to navigate efficiently.

    Completeness5/5

    The toolset provides comprehensive coverage of slide lifecycle, node manipulation, text, tables, media, rendering, viewport, selection, and export. No significant gaps are apparent, and the inclusion of batch operations and session management rounds out the surface.

    Maintenance

    ActivityInactive
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers