Content
# Figma MCP Bridge
[](https://www.npmjs.com/package/mcp-figma-bridge)
[](https://www.npmjs.com/package/mcp-figma-bridge)
[](https://github.com/sonht113/mcp-figma-bridge/releases)
[](./LICENSE)
[](https://www.npmjs.com/package/mcp-figma-bridge)
Connect any MCP client (**Grok**, **Claude**, **Codex**, **OpenCode**, **Cursor**, …) to **Figma Desktop** in realtime via a local plugin — no Figma REST API key required.
| | |
|--|--|
| **npm** | [`mcp-figma-bridge`](https://www.npmjs.com/package/mcp-figma-bridge) |
| **GitHub** | [`sonht113/mcp-figma-bridge`](https://github.com/sonht113/mcp-figma-bridge) |
| **Releases** | [GitHub Releases](https://github.com/sonht113/mcp-figma-bridge/releases) (tags `v*` ↔ npm versions) |
| **Changelog** | [CHANGELOG.md](./CHANGELOG.md) |
| **CLI** | `mcp-figma-bridge` / `npx -y mcp-figma-bridge` |
```
MCP client (Grok / Claude / Codex / OpenCode / …)
│ stdio JSON-RPC
▼
npx mcp-figma-bridge → mcp-server/index.js
│ (auto-starts bridge if needed)
│ HTTP POST /cmd
▼
mcp-server/bridge.js (:3765)
│ long-poll GET /poll
▼
figma-plugin/ui.html ↔ code.js ↔ Figma Plugin API
```
### Check installed / latest version
```bash
npm view mcp-figma-bridge version # latest on npm
npm list -g mcp-figma-bridge # global install (if any)
npx -y mcp-figma-bridge help # runs package; see npm for version
```
GitHub tag **vX.Y.Z** matches npm **X.Y.Z** (semver without the leading `v` on npm).
---
## Prerequisites
- **Node.js ≥ 18** (`node --version`)
- **[Figma Desktop](https://www.figma.com/downloads/)** (the web app cannot run this local plugin)
- An MCP-capable client (see [Configure MCP clients](#configure-mcp-clients))
---
## Quick start (recommended)
### 1. Import the Figma plugin (once)
```bash
npx -y mcp-figma-bridge plugin-path
```
Copy the printed absolute path, then:
1. Open **Figma Desktop**
2. **Plugins → Development → Import plugin from manifest…**
3. Select that `manifest.json`
4. Open a design file → **Plugins → Development → MCP Bridge**
5. Port `3765` → **Start** (badge **Connected** = OK)
> Figma does not load plugins from npm by itself. `plugin-path` only tells you where the installed package put `manifest.json`.
### 2. Configure your MCP client
Use **`npx`** so you do not need a clone path:
| Field | Value |
|-------|--------|
| Command | `npx` |
| Args | `-y`, `mcp-figma-bridge` |
| Env (optional) | `BRIDGE_PORT=3765`, `BRIDGE_HOST=127.0.0.1` |
The MCP process **auto-starts** the HTTP bridge on port `3765` if it is not already running. Set `BRIDGE_AUTO_START=0` to disable that.
Restart the client after saving config.
### 3. Health check
```bash
curl -s http://127.0.0.1:3765/health
```
---
## CLI
```bash
npx -y mcp-figma-bridge # MCP stdio (default; auto-starts bridge)
npx -y mcp-figma-bridge mcp # same
npx -y mcp-figma-bridge bridge # HTTP bridge only
npx -y mcp-figma-bridge plugin-path # absolute path to figma-plugin/manifest.json
npx -y mcp-figma-bridge help
```
| Variable | Default | Meaning |
|----------|---------|---------|
| `BRIDGE_PORT` | `3765` | HTTP port |
| `BRIDGE_HOST` | `127.0.0.1` | Bind / connect address |
| `BRIDGE_AUTO_START` | `1` | Set `0` / `false` to skip auto-start |
| `CMD_TIMEOUT_MS` | `35000` | MCP → bridge command timeout |
---
## Configure MCP clients
Shared settings for all examples below:
| Field | Value |
|-------|--------|
| Command | `npx` |
| Args | `-y`, `mcp-figma-bridge` |
| Env | `BRIDGE_PORT=3765`, `BRIDGE_HOST=127.0.0.1` (optional) |
From a **git clone**, you can still use absolute paths:
```text
command: node
args: /ABSOLUTE/PATH/TO/figma-mcp-bridge/mcp-server/index.js
```
---
### Grok (xAI / Grok CLI · TUI)
**Config file:** `~/.grok/config.toml`
**Or project:** `<repo>/.grok/config.toml`
```toml
[mcp_servers.figma-bridge]
command = "npx"
args = ["-y", "mcp-figma-bridge"]
env = { BRIDGE_PORT = "3765", BRIDGE_HOST = "127.0.0.1" }
enabled = true
startup_timeout_sec = 30
tool_timeout_sec = 60
# Optional: larger tool results (page trees) before client-side truncation
[mcp]
max_output_bytes = 100000
```
**CLI alternative:**
```bash
grok mcp add figma-bridge \
-e BRIDGE_PORT=3765 \
-e BRIDGE_HOST=127.0.0.1 \
-- npx -y mcp-figma-bridge
```
**Verify:**
```bash
grok mcp list
grok mcp doctor figma-bridge
```
In a session: `/mcps` → refresh `r` if you edited config while running.
Tools appear as `figma-bridge__list_page_frames`, `figma-bridge__get_node_tree`, etc.
---
### Claude Desktop
**Config file:**
| OS | Path |
|----|------|
| macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` |
| Windows | `%APPDATA%\Claude\claude_desktop_config.json` |
| Linux | `~/.config/Claude/claude_desktop_config.json` |
```json
{
"mcpServers": {
"figma-bridge": {
"command": "npx",
"args": ["-y", "mcp-figma-bridge"],
"env": {
"BRIDGE_PORT": "3765",
"BRIDGE_HOST": "127.0.0.1"
}
}
}
}
```
Also see `claude_desktop_config.example.json` in this repo.
Restart **Claude Desktop** after saving. Check **Settings → Developer** (or MCP logs) if tools do not appear.
---
### Claude Code (CLI)
**Project** (recommended): `.mcp.json` in the project root.
```bash
claude mcp add figma-bridge -- npx -y mcp-figma-bridge
```
**`.mcp.json` (project):**
```json
{
"mcpServers": {
"figma-bridge": {
"command": "npx",
"args": ["-y", "mcp-figma-bridge"],
"env": {
"BRIDGE_PORT": "3765",
"BRIDGE_HOST": "127.0.0.1"
}
}
}
}
```
Restart the Claude Code session after changing MCP config.
---
### OpenAI Codex (CLI / IDE)
**Config file:** `~/.codex/config.toml`
**Or project:** `.codex/config.toml` (trusted project)
> Top-level key is **`mcp_servers`** (underscore), not `mcpServers`.
```toml
[mcp_servers.figma-bridge]
command = "npx"
args = ["-y", "mcp-figma-bridge"]
startup_timeout_sec = 30
[mcp_servers.figma-bridge.env]
BRIDGE_PORT = "3765"
BRIDGE_HOST = "127.0.0.1"
```
Restart Codex / open a new thread. Use `/mcp` (or equivalent) to confirm tools.
---
### OpenCode
**Config file:** `~/.config/opencode/opencode.json` or `opencode.jsonc`
**Or project:** `opencode.json` in the repo
```json
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"figma-bridge": {
"type": "local",
"enabled": true,
"command": ["npx", "-y", "mcp-figma-bridge"],
"environment": {
"BRIDGE_PORT": "3765",
"BRIDGE_HOST": "127.0.0.1"
}
}
}
}
```
Restart OpenCode after saving.
---
### Cursor
**Project:** `.cursor/mcp.json`
**Or global:** `~/.cursor/mcp.json`
```json
{
"mcpServers": {
"figma-bridge": {
"command": "npx",
"args": ["-y", "mcp-figma-bridge"],
"env": {
"BRIDGE_PORT": "3765",
"BRIDGE_HOST": "127.0.0.1"
}
}
}
}
```
Reload Cursor window / MCP servers from settings after editing.
---
### Windsurf / other “Claude-compatible” editors
Most use the same shape as Claude Desktop:
```json
{
"mcpServers": {
"figma-bridge": {
"command": "npx",
"args": ["-y", "mcp-figma-bridge"],
"env": {
"BRIDGE_PORT": "3765",
"BRIDGE_HOST": "127.0.0.1"
}
}
}
}
```
---
### Generic MCP (`.mcp.json`)
```json
{
"mcpServers": {
"figma-bridge": {
"command": "npx",
"args": ["-y", "mcp-figma-bridge"],
"env": {
"BRIDGE_PORT": "3765",
"BRIDGE_HOST": "127.0.0.1"
}
}
}
}
```
---
### Windows notes
- If `npx` is missing from the client’s PATH, use the full path, e.g.
`C:\\Program Files\\nodejs\\npx.cmd`
- Or install once: `npm i -g mcp-figma-bridge` and set
`command` = `mcp-figma-bridge` (or full path under `%AppData%\\npm\\`).
- Prefer forward slashes in JSON paths when using a local clone.
---
## MCP tools (12)
| Tool | Description |
|------|-------------|
| `get_bridge_status` | **Preflight** — bridge up? plugin Connected? next steps (no Figma selection needed) |
| `list_page_frames` | **Start here for pages** — top-level screens/frames outline |
| `get_file_info` | File name, pages; `nodeCount` only if `includeNodeCount=true` |
| `get_pages` | All pages |
| `get_node_tree` | Tree for a **frame** `nodeId` (page without id → outline only) |
| `get_selection` | Current selection (large page-scale → summary + warning) |
| `get_components` | Components & component sets |
| `get_colors` | Solid fills by usage |
| `get_fonts` | Font family + style list |
| `export_node` | PNG @2x (MCP **image** + meta) or SVG; `includeBase64` / `includeDataUri` optional |
| `export_icons` | Batch SVG icons (parallel, `concurrency` default 4) |
| `check_design_quality` | Auto-names, hidden layers, tiny text, spacing grid |
### Timeout chain
| Layer | Default | Role |
|-------|---------|------|
| Plugin UI sandbox | ~28s | Per command inside Figma |
| Bridge `POST /cmd` | ~30s | Wait for plugin `/result` |
| MCP `CMD_TIMEOUT_MS` | 35s | Client → bridge HTTP |
| Grok `tool_timeout_sec` | 60 (recommended) | Client aborts the tool call |
For large `export_node` / `export_icons`, keep client tool timeout ≥ 60s, prefer `scale=1` on large frames, and avoid `includeDataUri` / `includeBase64` unless needed.
Tool results are **compact JSON** (no indentation). Truncated trees include `meta.continueWith` for follow-up `get_node_tree` calls. `list_page_frames` is cached ~15s (`forceRefresh=true` to bust).
Tool names in the client are usually prefixed with the server name, e.g.
`figma-bridge__list_page_frames`.
---
## Page vs component accuracy
Selecting a **single component/frame** is typically very accurate. Dumping an **entire page** in one call is not: depth limits + MCP output size truncate the tree, so the model misses layers.
**Recommended workflow (page-level):**
1. `list_page_frames` → pick a screen (`likelyScreen: true` or by name)
2. `get_node_tree` with `nodeId=<frameId>`, `maxDepth=8`, `detail=standard`
3. If a section is incomplete → `get_node_tree` again with that section’s `nodeId`
4. Optional: `export_node` PNG of the frame for visual check
Avoid: one `get_node_tree` on the whole page with high `maxDepth`.
---
## Daily checklist
```text
[ ] Figma → MCP Bridge → Start (Connected)
[ ] MCP client running with figma-bridge config (npx auto-starts bridge)
[ ] Open the correct Figma file / page
[ ] Optional: call get_bridge_status (ready=true) before heavy tools
```
---
## Project layout
```text
figma-mcp-bridge/
├── bin/
│ └── mcp-figma-bridge.js # npx / bin entry
├── figma-plugin/
│ ├── manifest.json
│ ├── code.js # Figma sandbox — API + tools
│ └── ui.html # Long-poll UI
├── mcp-server/
│ ├── bridge.js # HTTP long-poll bridge
│ └── index.js # MCP stdio server (+ auto-start bridge)
├── package.json
├── claude_desktop_config.example.json
├── LICENSE
└── README.md
```
---
## Develop from a clone
```bash
git clone https://github.com/sonht113/mcp-figma-bridge.git
cd mcp-figma-bridge
node bin/mcp-figma-bridge.js plugin-path # import this manifest in Figma
node bin/mcp-figma-bridge.js bridge # optional if not using MCP auto-start
# MCP client args: node /ABS/PATH/mcp-server/index.js
```
---
## Versions & releases
| Source | Where to look |
|--------|----------------|
| Latest npm | https://www.npmjs.com/package/mcp-figma-bridge |
| Git tags / Releases | https://github.com/sonht113/mcp-figma-bridge/releases |
| Full history | [CHANGELOG.md](./CHANGELOG.md) |
Convention: GitHub tag `vX.Y.Z` == npm version `X.Y.Z`.
---
## Publish (maintainers)
### Recommended: tag → GitHub Release → npm (CI)
1. Bump version and changelog on `main`:
```bash
# edit package.json version + CHANGELOG.md
git add package.json CHANGELOG.md
git commit -m "chore: release v1.0.3"
git push origin main
```
2. Create annotated tag and push (triggers [Release workflow](.github/workflows/release.yml)):
```bash
git tag -a v1.0.3 -m "v1.0.3"
git push origin v1.0.3
```
3. CI will:
- Create a **GitHub Release** for the tag
- **`npm publish`** when repo secret `NPM_TOKEN` is set
Set secret: GitHub → **Settings → Secrets and variables → Actions →** `NPM_TOKEN`
(npm classic or granular token with publish rights).
### Manual publish (fallback)
```bash
npm pack --dry-run
npm publish --access public
git tag -a v$(node -p "require('./package.json').version") -m "v$(node -p "require('./package.json').version")"
git push origin --tags
```
---
## Troubleshooting
| Symptom | Fix |
|---------|-----|
| Client has no Figma tools | `npx -y mcp-figma-bridge`; restart client; verify config key (`mcp_servers` vs `mcpServers` vs `mcp`) |
| Plugin timeout 30s | Call `get_bridge_status`; click **Start** in plugin; `curl` `/health`; ensure auto-start or run `… bridge` |
| Badge stays Disconnected / Error | Bridge not running or wrong port; check `localhost:3765` |
| Network error in plugin | Re-import `manifest.json` (`devAllowedDomains` for localhost) |
| Port in use | `BRIDGE_PORT=3766` in MCP env **and** plugin UI |
| Page dump inaccurate | Use `list_page_frames` → per-frame `get_node_tree` |
| Grok truncates large trees | `[mcp] max_output_bytes = 100000` in `~/.grok/config.toml` |
| Codex ignores config | Confirm section is `[mcp_servers.…]` (underscore) |
| OpenCode no tools | `type: "local"`, `command` as **array**, `environment` for env vars |
| `npx` not found in client | Full path to `npx.cmd` / `npm i -g mcp-figma-bridge` |
**MCP stderr logs (Grok):** `~/.grok/logs/mcp/figma-bridge.stderr.log`
**Bridge debug:** `GET http://127.0.0.1:3765/health`
---
## License
MIT
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available