Figma Local Bridge
Local MCP bridge that drives the real Figma Desktop plugin API, letting agents read and edit the open Figma file, take screenshots, export/import assets, inspect variables and design-system components, search libraries, and run arbitrary Plugin API snippets under scope protection — no Dev/Full seat required.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Figma Local Bridgescreenshot the current selection and export it as a PNG"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Figma Local Bridge
Unofficial local MCP bridge for Figma Desktop. Drives the real plugin API from any MCP client (OpenCode, Claude Code, Cursor, …) over a single local daemon — read and edit the open file, take screenshots, export assets, inspect variables, search the design system. No Dev/Full seat required.
Русская версия с подробными инженерными заметками: README.ru.md. Not affiliated with Figma, Inc.
Why this exists
Figma's official MCP server (Dev Mode, 127.0.0.1:3845) requires a Dev/Full seat on Professional+. This project ships its own Figma plugin instead: the manifest uses editorType: ["figma", "figjam"] rather than devid, so it runs in an ordinary editor window. Everything stays local — a WebSocket on 127.0.0.1, no cloud, no API keys, no telemetry.
Related MCP server: figma-meta-mcp
Architecture
Figma Desktop ──WebSocket──▶ daemon (port 8787, one per machine)
▲
│ WebSocket client
┌─────────────────────┼─────────────────────┐
MCP process MCP process MCP process
(workspace A) (workspace B) (workspace C)
▲
│ stdio
OpenCode / Claude / CursorThe daemon exists for three concrete reasons:
the Figma plugin pairs with exactly one socket;
Figma's manifest CSP can only allowlist fixed origins, so the port cannot be ephemeral;
MCP clients spawn one server process per workspace — on a fixed port, they would collide.
One daemon = one socket = one port = one token = one plugin import.
Repo layout
Path | What |
| stdio MCP server, daemon (WebSocket hub), link state, tool implementations |
| Figma plugin: |
| unit tests ( |
| the first prototype, kept for history |
Quick start
Requirements: Node.js 20+ (developed on v25) and the Figma Desktop app. Developed on macOS; the Node side is cross-platform.
git clone git@github.com:Miart/figma-local-bridge.git
cd figma-local-bridge
npm install
npm run build
npm run daemon # keep it running; log: /tmp/figma-bridge-daemon.logImport the plugin (once): in Figma → Plugins → Development → Import plugin from manifest… →
<repo>/plugin/manifest.json. (npm run buildmust have run first —plugin/code.jsis generated and not committed.)Run the plugin: Plugins → Development → Figma Local Bridge.
The panel asks for the daemon token — copy it from
~/.local/share/opencode/figma-bridge-daemon.jsonand paste it once. It is kept infigma.clientStorage, and the plugin reconnects by itself on every launch. The port is fixed byplugin/manifest.json(networkAccess.devAllowedDomains) — the panel cannot change it.Point your MCP client at
server/dist/index.js(stdio). Example (opencode):
"figmaBridge": {
"type": "local",
"command": ["node", "/path/to/figma-local-bridge/server/dist/index.js"],
"environment": {
"FIGMA_BRIDGE_PORT": "8787",
"FIGMA_BRIDGE_WRITE": "1",
"FIGMA_BRIDGE_DESTRUCTIVE": "0"
}
}Without the plugin running, the MCP server still starts and every tool answers FIGMA_BRIDGE_OFFLINE — fast, with a precise reason, instead of hanging for 30–115 seconds.
Configuration
Variable | Default | Meaning |
| from | Daemon port |
|
| Interfaces to listen on |
|
| State file: pid, port, |
|
| Persistent plugin token ( |
|
|
|
|
|
|
Don't run a second bridge instance: the plugin pairs with one socket, and a second daemon evicts the first (4409 already paired).
What the plugin panel shows
Row | Meaning |
status |
|
| what is open and selected right now — pushed by the plugin, so it stays live even without a connection |
| how many MCP sessions are attached (0 = no client is bound) |
| the last call error (full text in the tooltip) |
counter (top right) | how many calls went through; turns red after an error |
Tools
17 tools mirroring Figma's official server, plus 4 local ones — 21 in total.
Parity with the official Figma MCP server:
Tool | What it does |
| User, open file, pages, viewport |
| Sparse XML skeleton of a node — cheap, use it to find ids |
| Full design description of a node for implementing it in code |
| PNG / JPG / SVG of a node (the caption carries |
| Variables used in a subtree |
| Variable collections available from libraries |
| Search components, styles, variables |
| FigJam board: stickies, shapes, connectors, sections |
| Local Code Connect mappings |
| Export / import assets |
| Switch the active page |
| Select nodes and pan the viewport to them — the only way to move the user's cursor |
| Fonts actually used by the file, with per-text-node counts |
| Inventory of every component in the file |
| Arbitrary Plugin API snippet under scope protection; the answer carries |
Local additions:
Tool | What it does |
| Health check: verifies the plugin is paired, reports the active page |
| Current selection, answered from memory — the plugin pushes selection changes, so this costs no round trip |
| Compact structure + semantic fingerprint; |
| Replaces repeated identical nodes with instances of one master component, in a single transactional call. Refuses unless every target is provably equivalent; try |
Not available through a plugin (cloud-only in the official server): create_new_file, generate_figma_design, generate_diagram, export_video, shaders, Weave, cloud Code Connect sync.
Safety model
The bridge edits real design files with an agent at the wheel, so most of the engineering went into making failure modes visible instead of silent:
Idempotent retries.
opIdis minted once per logical call and reused by every attempt (server/src/figma.ts). The plugin keeps a boundedopId → resultcache and, on a repeat, replays the recorded answer (replayed: true) without touching the document. A repeat arriving while the first attempt is still running joins it instead of running the snippet twice.Serialized mutations. Figma's undo barrier is global — two mutations in flight roll each other back. Mutating methods are chained one at a time (
plugin/dispatch.ts); reads stay parallel.revbumps on success and failure.Honest disconnects. An error distinguishes
disconnected before <method> was sent(safe to retry) frommay or may not have been applied(retried under the sameopId, so a replay cannot apply code twice).Fast-fail offline. A call waits one 2-second grace period (
LINK_GRACE_MS) for a reconnecting plugin, then fails with a precise reason. A request that was never sent is not retried at all.Scope guard + fingerprint diff.
figma_useruns against a scoped, fingerprint-checked node set and is rolled back if the document drifts outside the scope. Switching pages inside a call is refused (currentpagechange): one call per page, orfigma_set_pagefirst.Timeouts don't roll back. A
Promise.racestops waiting, but the snippet keeps running and may still write — the message says exactly that instead of pretending "(rolled back)".Stale screenshots are detectable. Figma caches exports.
revtravels in the caption, so identical bytes with a higherrevmeans the render is stale, not that the edit did nothing.Gated writes.
FIGMA_BRIDGE_WRITE=0makes the bridge read-only;figma_useadditionally needsFIGMA_BRIDGE_DESTRUCTIVE=1and an explicit scope.
The full journal of failure modes met in practice (symptom → cause → fix) lives in the Russian notes: README.ru.md.
Development
npm run build # plugin (esbuild) + server (tsc)
npm run typecheck # server + plugin (with @figma/plugin-typings)
npm test # rebuilds artifacts, then unit + e2e with --test-concurrency=1npm test rebuilds server/dist and plugin/*.mjs first because the tests import the built modules — a test running against a stale artifact passes on code Figma will never execute. The suites run serially (--test-concurrency=1): e2e tests spin up real daemons on real ports and share one token file, and parallel runs make them flaky by construction.
Current suites: 143 unit checks (commands, fingerprint, scope, retry, offline, dispatch, daemoninfo, use-figma.gate, use-figma.safety) and 47 e2e checks (daemon, link-state, mcp, tools).
Troubleshooting
Symptom | Cause |
| The plugin is not running in Figma, or the daemon is down |
| The plugin is not paired |
The daemon won't start | Port 8787 is busy — |
| A second bridge instance; kill the extra process |
| The daemon restarted with a new |
| The token in the plugin doesn't match |
Liveness check: lsof -nP -iTCP:8787 | grep -i figma — empty output means the plugin is not paired.
Limitations
indexTreewalks the whole page per call. On very large pages, split the work — the cache cannot be incremental because the user edits the file in parallel.Figma caches screenshot exports;
revmakes stale renders visible, but there is no way to force a redraw from the Plugin API.figma_usehands you the full plugin API: it is a notice-and-rollback guard, not a sandbox. Code that runs after the call returns (fire-and-forget promises) escapes the diff; a timeout therefore does not roll back and says so.Figma unloads the plugin UI when the app is backgrounded. In-flight calls are cancelled immediately (instead of hanging until their timeout), and the bridge reconnects on its own when you return.
License
MIT — see LICENSE. Unofficial project, not affiliated with Figma, Inc.
This server cannot be deployed
Maintenance
Related MCP Connectors
The Figma MCP server brings Figma design context directly into your AI workflow.
MCP connector that lets ChatGPT list, search, and run your Apple Shortcuts via a local Mac agent
MCP connector for iMessage & Contacts via a local Mac agent + Vercel relay
Remote MCP server exposing your Node Command fleet (files, shell, processes, browser) to AI hosts.
Related MCP Servers
- AlicenseBqualityCmaintenanceLocal MCP server connecting AI clients to the Figma desktop app for inspecting and editing Figma documents via the Plugin API.1616 npm1MIT
- AlicenseAqualityCmaintenanceFigma MCP server that lets agents execute arbitrary JavaScript inside a running Figma desktop app via a local development plugin, enabling real-time document inspection and manipulation while avoiding REST API rate limits.3MIT
- AlicenseNot gradedqualityBmaintenanceLocal-first MCP bridge for live Figma documents, enabling design inspection, editing, asset export, component authoring, and variable management through a plugin and WebSocket server without consuming Figma REST API requests.1MIT
- AlicenseAqualityBmaintenanceThe Figma desktop app as an MCP server. Gives AI agents the full Figma Plugin API on your open file: read, write, tokens, components, exports, undo. Runs locally with no cloud API, no token and no quota.1040 npm1MIT