Skip to main content
Glama
w4ndaja

FreeMCP for Figma

by w4ndaja

FreeMCP for Figma — Universal MCP Bridge

A local MCP bridge that lets AI coding agents read and write a user's Figma file through the Figma Plugin API (native, in-desktop) instead of the public REST API. No official-MCP rate limits, no Figma API token, and no design data ever leaves the machine.

  • Offline & private — everything runs on 127.0.0.1; a startup guard blocks any outbound HTTP from the server process.

  • Native design-system writes — create frames/shapes/text, author components, insert library component instances, bind variables & styles, configure Auto Layout, constraints and effects — all executed inside Figma via the Plugin API.

  • Design-to-code — generate React (Tailwind), Vue 3, or HTML/CSS from a selected node.

  • Batched & undoablebatch_run applies 100+ ops in one consented request without blocking the Figma UI; undo reverts the last write(s).

Transport: the bridge is HTTP long-poll (POST /register, GET /next, POST /result) on 127.0.0.1:3700, not WebSocket. The Figma plugin sandbox has no WebSocket global — only fetch — so the plugin long-polls a loopback HTTP server hosted by the local MCP process.

Architecture

┌──────────────┐  MCP/STDIO   ┌────────────────────────────┐  HTTP long-poll  ┌──────────────────┐
│  AI client   │ ◀──────────▶ │  local MCP server (Node)   │ ◀───────────────▶ │  Figma plugin     │
│ Claude/VS    │  JSON-RPC     │  packages/server            │  /register       │  packages/plugin   │
│ Cursor/Ollama│              │  127.0.0.1:3700             │  /next  /result  │  (Plugin API)     │
└──────────────┘              └────────────────────────────┘                   └──────────────────┘

Every MCP tool is a thin dispatch. The server validates arguments (Zod), translates the call into a typed bridge frame, and forwards it over loopback HTTP to the Figma plugin, which executes the actual Plugin API call and returns the result. Deep-dive: docs/ARCHITECTURE.md.

Related MCP server: figma-developer-mcp

Quickstart (< 5 min)

1. Install

npm install
npm run build:plugin

2. Load the plugin in Figma

Figma → Plugins → Development → Import plugin from manifest… → select packages/plugin/manifest.json. The plugin auto-connects to http://127.0.0.1:3700 (a small status panel shows connection state).

3. Start the server (own terminal)

npm run start:server

Expect: FreeMCP Figma bridge on http://127.0.0.1:3700. Open the plugin in Figma to connect.

4. Point your AI client at the MCP server (STDIO)

{
  "mcpServers": {
    "figma-free-mcp": {
      "command": "node",
      "args": ["C:/path/to/repo/packages/server/dist/index.js"]
    }
  }
}

Claude Desktop: Settings → Developer → Edit Config. VS Code / Cursor: .mcp.json. You can also run the built bundle directly: node packages/server/dist/index.js.

Using it

Intent

What the agent does

"Describe this design"

get_design_context / get_selection → full node tree, fills, typography, effects, Auto Layout

"What tokens exist?"

get_variables / get_styles → local variables, collections, text/effect/grid styles

"Create a card component"

create_frame (Auto Layout) + create_text children → native Figma nodes

"Insert our primary button"

create_component_instance by key → reuses the design system (local or library)

"Make 100 variants"

batch_run → many ops in one consented request, no UI block

"Undo last change"

undo → reverts creates/duplicates/fills/layout

"Generate React for this"

to_react / to_vue / to_html

Consent: the first write always prompts for consent — every write tool requires confirm: true in its params (FR-504). Nothing is written silently.

Tool reference

Every input is validated by the Zod schema in packages/contracts/src/tool-schemas.ts (single source of truth) before dispatch (FR-404). The per-tool contract lives in specs/001-freemcp-figma-bridge/contracts/tools.md.

Read

Tool

Purpose

Key params

get_selection

Current selection → DesignContext[] (optionally a node by id)

nodeId?, maxDepth?

get_design_context

Deep hierarchical context for a node subtree

nodeId, maxDepth?

get_metadata

Lightweight tree: ids, types, names, bounds

nodeId?

get_screenshot

Raster/SVG export of a node (base64)

nodeId, format (png|jpg|svg), scale?

get_variables

Local variables + collections + mode values

get_styles

Local text/effect/grid styles

get_components

Local components + component sets with importable keys

get_page_children

Top-level nodes on the current page (id/name/type/bounds)

Write (all require confirm: true)

Tool

Purpose

Key params

create_frame

Frame at position/size, optional Auto Layout + sizing

x, y, width, height, layout?, parent?, primaryAxisSizing?, counterAxisSizing?, stroke?, strokeWeight?, cornerRadius?

create_shape

Rectangle / ellipse / polygon

type, x, y, width, height, fill?, stroke?, layoutAlign?, layoutGrow?, parent?

create_text

Text node with font props + text polish

characters, x, y, fontFamily?, fontSize?, fontWeight?, color?, lineHeight?, letterSpacing?, textCase?, textDecoration?, textAutoResize?, layoutAlign?, layoutGrow?, parent?

apply_fill

Apply solid/gradient fill to a node (image fills deferred — need a Figma imageHash)

nodeId, fill

set_auto_layout

Auto Layout direction, padding, spacing, alignment

nodeId, mode, itemSpacing?, padding?, primaryAxisAlignItems?, counterAxisAlignItems?

duplicate_node

Clone preserving properties + children

nodeId, offset?

delete_node

Delete a node (not undoable)

nodeId

create_component_instance

Insert an instance by key (local or published library)

componentKey, x?, y?, parent?, overrides?

create_component

Author a reusable ComponentNode (design-system library)

x, y, width, height, layout?, parent?

set_variable

Bind a variable to a node property; "" unbinds

nodeId, property (fill|strokes|cornerRadius|opacity), variableId

apply_style

Apply a text/effect/grid style; "" clears

nodeId, kind (text|effect|grid), styleId

set_constraints

Layout constraints (align/grow + frame sizing)

nodeId, layoutAlign?, layoutGrow?, primaryAxisSizing?, counterAxisSizing?

set_effect

Set arbitrary effect array (e.g. DROP_SHADOW); [] clears

nodeId, effects

Batch

Tool

Purpose

Key params

batch_run

Run many write ops in one consented batch (100+ < 3s)

ops: { tool, params }[], confirm

Code generation

Tool

Purpose

Key params

to_react

JSX + Tailwind classes

nodeId, includeStyles?

to_vue

Vue 3 Composition API SFC

nodeId

to_html

Semantic HTML + CSS

nodeId

Utility

Tool

Purpose

Key params

undo

Revert last executed write op(s)

count? (1–100)

ping

Health check; returns bridge connectivity + latency

Error envelope (FR-405): every tool result is { ok: true, data } or { ok: false, error: { code, message, suggestion } }, serialized as a JSON string in the MCP text content. suggestion carries a fixable hint.

Security & privacy model

  • No tokens, no cloud (FR-501/502/503) — the server binds only to 127.0.0.1; a startup guard (installOfflineGuard) monkey-patches global fetch to reject any non-loopback request, and an OpLog records every dispatch so an operator can assert only local calls happened.

  • Consent before writes (FR-504) — write tools require confirm: true; the plugin never re-prompts for a single consented batch.

  • Sandbox-bound — design data only ever crosses loopback HTTP between the MCP process and the Figma plugin. Nothing is transmitted off-machine.

Configuration

Env

Default

Purpose

FREEMCP_PORT

3700

Server port. Note: the plugin's target port is compiled in (DEFAULT_PORT in packages/contracts/src/messages.ts), so changing this also requires rebuilding the plugin.

Troubleshooting

Symptom

Fix

NO_PLUGIN: No plugin connected

Open the plugin in Figma (Plugins → Development) so it registers with the server.

Connection refused

Start the server first, then load the plugin.

Port conflict

Set FREEMCP_PORT on the server and rebuild the plugin with the matching constant.

Text ops fail

Text nodes need a loaded font — the plugin calls figma.loadFontAsync automatically before setting text.

Development

npm install             # workspaces: contracts, server, plugin
npm test                # 32 Vitest unit tests (schemas, codec, bridge, undo, codegen)
npm run typecheck       # tsc --noEmit (strict)
npm run build:server    # esbuild bundle → packages/server/dist/index.js (npx-runnable)
npm run build:plugin    # esbuild bundle → packages/plugin/dist/main.js
npm run start:server    # tsx dev run of the MCP server + bridge

Coding agents in this repo additionally have codebase-memory MCP, an LSP provider, and obscura browser tools connected for Spec Kit workflow runs — see docs/TOOLCHAIN.md for the wiring and reproduction. See docs/DEVELOPMENT.md for the developer guide (add a tool, build pipeline, sandbox constraints) and docs/ARCHITECTURE.md for the deep technical reference.

Repository layout

packages/
├── contracts/   # Shared, types-only: DesignContext, bridge frames, Zod tool schemas (source of truth)
├── server/      # MCP server (STDIO) + HTTP long-poll bridge host + codegen + command stack
└── plugin/      # Figma plugin: outbound long-poll client + Plugin API read/write/design-system logic
specs/001-freemcp-figma-bridge/   # Spec Kit artifacts: spec, plan, research, data-model,
                                  # contracts (protocol + tools), quickstart, tasks

Docs index

Doc

What it covers

docs/ARCHITECTURE.md

Components, request lifecycle, long-poll internals, undo, codegen pipeline, security

docs/DEVELOPMENT.md

Adding a tool, build/test workflow, Figma sandbox constraints, conventions

docs/TOOLCHAIN.md

Connected agent tooling for Spec Kit runs: codebase-memory MCP, LSP provider, obscura, routing skill — setup + verification

skills.md

Production-ready Figma design workflow for the bridge MCP: audit → tokens → components → screens, Auto Layout rules, verification gates, bridge limits

specs/001-freemcp-figma-bridge/spec.md

Feature specification (FRs, user stories, success criteria)

specs/001-freemcp-figma-bridge/contracts/protocol.md

HTTP long-poll bridge protocol contract

specs/001-freemcp-figma-bridge/contracts/tools.md

MCP tool surface contract

specs/001-freemcp-figma-bridge/quickstart.md

Manual end-to-end validation scenarios

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    A
    maintenance
    Enables AI assistants to read, analyze, and modify Figma designs, manage design tokens, and create prototype connections, all while keeping data local.
    63
    14 npm
    9
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables coding agents like Cursor to access Figma design data, fetch layout and styling information, and implement designs in any framework.
    55,619 npm
    MIT
  • A
    license
    B
    quality
    C
    maintenance
    Enables local AI agents to generate and edit Figma designs via the Plugin API through a WebSocket relay, with no rate limits and all communication remaining local.
    50
    707 npm
    MIT