figma-mcp-poor
by whoistus
README.md
# figma-mcp-poor
[](https://www.npmjs.com/package/figma-mcp-poor)
[](https://opensource.org/licenses/MIT)
A Figma MCP (Model Context Protocol) bridge that lets AI assistants read design context from Figma. Uses the **Figma Plugin API** (local, no network) instead of the REST API — no API keys, no rate limits, no blown context windows.
```
AI IDE ←—MCP stdio—→ MCP Server (Node.js) ←—WebSocket—→ Figma Plugin (figma.* API)
```
## Quick Start
### 1. Set up your MCP client
Add the server to your MCP client config (see [Client Configuration](#mcp-client-configuration) below).
### 2. Install the Figma plugin
**Option A — Download pre-built (recommended):**
1. Go to [Releases](https://github.com/whoistus/figma-mcp-poor/releases/latest) and download `figma-plugin-vX.Y.Z.zip`
2. Unzip somewhere stable on your disk
3. In Figma: open any design file → **Plugins → Development → Import plugin from manifest...** → select `manifest.json` from the unzipped folder
**Option B — Build from source:**
```bash
git clone https://github.com/whoistus/figma-mcp-poor
cd figma-mcp-poor
npm install
npm run build:plugin
```
Then in Figma: **Plugins → Development → Import plugin from manifest...** → select `figma-plugin/manifest.json`.
Run the plugin — it will connect to the MCP server via WebSocket on `localhost:3055`.
### 3. Start designing with AI
Select elements in Figma and use your AI assistant to inspect them. The recommended first call is `get_dev_summary` — it returns structure, text content, colors, components, and a screenshot in one request.
## MCP Client Configuration
### Claude Code
In your project's `.mcp.json` or global `~/.claude.json`:
```json
{
"mcpServers": {
"figma": {
"command": "npx",
"args": ["-y", "figma-mcp-poor"]
}
}
}
```
### Cursor
In `.cursor/mcp.json`:
```json
{
"mcpServers": {
"figma": {
"command": "npx",
"args": ["-y", "figma-mcp-poor"]
}
}
}
```
### VS Code (Copilot)
In `.vscode/mcp.json`:
```json
{
"servers": {
"figma": {
"type": "stdio",
"command": "npx",
"args": ["-y", "figma-mcp-poor"]
}
}
}
```
### Windsurf
In `~/.codeium/windsurf/mcp_config.json`:
```json
{
"mcpServers": {
"figma": {
"command": "npx",
"args": ["-y", "figma-mcp-poor"]
}
}
}
```
### Custom port
Set the `FIGMA_MCP_PORT` environment variable to change the WebSocket port (default: `3055`):
```json
{
"mcpServers": {
"figma": {
"command": "npx",
"args": ["-y", "figma-mcp-poor"],
"env": {
"FIGMA_MCP_PORT": "4000"
}
}
}
}
```
> **Note:** If you change the port, you also need to update the Figma plugin's `manifest.json` → `networkAccess.devAllowedDomains` to match.
## Available Tools
| Tool | Description | Token Cost |
| ------------------------- | ---------------------------------------------------------------------------------- | ---------- |
| `get_dev_summary` | **Start here.** Complete summary: structure, texts, colors, components, screenshot | Medium |
| `get_document_info` | File name, pages, current page | Low |
| `get_selection` | Selected nodes with CSS properties, optional text flattening and screenshot | Low–Medium |
| `get_node_by_id` | Inspect a specific node by ID with CSS properties. Paginates large children lists | Low–Medium |
| `get_styles` | Local paint/text/effect/grid styles as CSS values | Low |
| `get_variables` | Design tokens/variables (colors, numbers, strings, booleans) | Low |
| `get_components` | Local components with property definitions | Low–Medium |
| `get_design_context` | Design brief (markdown) or detailed context (JSON) for a node | Medium |
| `get_flows` | Prototype flows: starting points, interactions, navigation connections | Low–Medium |
| `get_screenshot` | Export a node as PNG, JPG, or SVG | Medium |
| `get_user_flow_context` | Structured FlowGraph JSON: nodes, edges, BFS paths, explicit no-flow signal | Low–Medium |
## How It Works
1. The **MCP server** starts a WebSocket server on `localhost:3055`
2. The **Figma plugin** connects to this WebSocket from inside Figma
3. When an AI tool is called, the server sends a request through WebSocket to the plugin
4. The plugin reads data using the Figma Plugin API (`figma.*`) and sends it back
5. The server formats raw Figma data into developer-friendly CSS-like output and returns it to the AI
Key design decisions:
- **Default depth=1** for node traversal prevents context explosion. Use `get_node_by_id` to drill deeper.
- **Formatting is server-side** — the plugin sends raw data, the server transforms it. Formatting changes don't require reloading the plugin.
- **Smart truncation** — responses exceeding the token budget are truncated with hints guiding the AI to drill deeper.
- **Multi-instance safe** — the first MCP process to start becomes the primary (owns port 3055 + proxy port 3056). Subsequent processes (e.g. Codex starting alongside Claude Code) automatically become secondaries and forward requests through the primary. Only one Figma plugin connection is ever active.
## Development
```bash
# Install dependencies
npm install
# Build everything
npm run build
# Dev mode (MCP server with auto-reload)
npm run dev:server
# Watch mode (Figma plugin)
npm run watch -w figma-plugin
```
## Troubleshooting
**Plugin won't connect**
- Make sure the MCP server is running before starting the plugin
- Check that port 3055 (or your custom port) isn't in use: `lsof -i :3055`
- The plugin only connects to `localhost` — no remote connections
**"No selection" responses**
- Select at least one element in Figma before calling selection-based tools
- Make sure the plugin UI is open (the WebSocket client runs in the plugin UI)
**WebSocket errors**
- Only one Figma file can connect at a time (single-connection design)
- If you switch files, restart the plugin in the new file
**Multiple AI tools conflict / port already in use**
- Starting in v0.4.0, multiple MCP instances co-exist automatically. The first instance owns port 3055; subsequent ones proxy through it on port 3056.
- If you see `EADDRINUSE` errors, an old server process may still be running: `lsof -i :3055 -i :3056` to find and kill it.
**Large designs timing out**
- Use `get_node_by_id` with specific node IDs instead of scanning entire pages
- Reduce `depth` parameter (default is 1, max is 5)
- Screenshots are capped at 800px width by default — use `max_width` to adjust
## Changelog
### 0.4.0 (2026-05-05)
- **New tool: `get_user_flow_context`** — structured FlowGraph JSON for deterministic AI navigation analysis
- Returns `nodes`, `edges`, `paths` (BFS from prototype starting points), and `metadata.hasFlow`
- Explicit no-flow signal (`hasFlow: false`, empty edges/paths) when no prototype connections exist — no hallucination
- Optional `includeInference: true` adds heuristic-inferred edges (action-keyword buttons, list→detail patterns) when no real flow exists, clearly separated from real edges
- `maxDepth` param (default 10, max 20) controls BFS traversal depth; paths capped at 200 to protect token budget
- **Multi-instance support** — run Claude Code + Codex (or any two MCP clients) simultaneously without port conflicts
- First process becomes primary: owns Figma plugin WS on port 3055 + proxy listener on port 3056
- Subsequent processes become secondaries: connect to proxy port, forward all tool calls through the primary
- No changes to existing tool behaviour; no manual configuration required
### 0.3.0 (2026-04-15)
Fixes for fetching large design areas with minimal data loss.
- **Pagination on `get_node_by_id`** — new `childrenOffset` and `childrenLimit` params let AI fetch children in chunks for large frames. Response includes `pagination: { offset, limit, total, hasMore }`.
- **Raised children cap** — `MAX_CHILDREN` bumped from **100 → 200** per node. Fewer silent truncations on real-world designs.
- **Fixed `componentName` bug** — `get_dev_summary` previously reported the instance's node name as the component name. Now correctly resolves the master component name via `getMainComponentAsync()`. Renamed instances now group properly: `PrimaryButton x5: "Save", "Cancel", ...`.
- **Colors inside instances** — `get_dev_summary.colors` now walks into instances for fill colors (previously missed custom fill overrides).
- **Configurable `depth` on `get_dev_summary`** — was hardcoded to 2, now accepts `depth` param (default 2, max 5) for deeply nested screens.
- **Cap on `flatten_text`** — 500-entry default cap prevents token budget blow-ups on text-heavy pages.
- **Cap on `get_flows`** — new `limit` param (default 200, max 1000) with clear truncation hint in output.
- **`get_design_context` brief truncation signal** — 16000-char cap now includes an explicit hint instead of silently cutting mid-content.
### 0.2.0 (2026-04-15)
- **New tool: `get_flows`** — prototype flow support
- Returns flow starting points (`page.flowStartingPoints`)
- Collects all prototype connections from node trees
- Supports all trigger types (click, hover, press, drag, mouse enter/leave, timeout)
- Supports all action types (navigate, swap overlay, open URL, back, close, set variable)
- Includes transition animations (dissolve, smart animate, slide, push, etc.) with duration and easing
- **Node-level reactions** — every serialized node now includes `reactions[]` when it has prototype interactions, visible in `get_node_by_id`, `get_selection`, and other node tools
- Compact arrow format for interactions: `Button --click--> Login Screen (smart-animate 300ms)`
### 0.1.0 (2026-04-15)
- Initial public release
- 9 MCP tools: `get_dev_summary`, `get_document_info`, `get_selection`, `get_node_by_id`, `get_styles`, `get_variables`, `get_components`, `get_design_context`, `get_screenshot`
- CSS-like formatting for colors, typography, layout (flexbox), spacing
- Smart truncation with drill-deeper hints
- Depth-controlled serialization with auto depth bonus for COMPONENT_SET (+2) and INSTANCE (+1)
- Screenshot export with configurable max width
- Text flattening and color collection utilities
## License
MIT
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues