npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

figma-ui-mcp

v1.9.1

Published

Bidirectional Figma MCP — draw UI with Claude, read design back to code

Readme

figma-ui-mcp

Bidirectional Figma MCP — use Claude (or any MCP client) to draw UI directly in Figma, and read existing designs back as structured data or code.

Requires Figma Desktop — the plugin communicates with the MCP server over localhost HTTP polling. Figma's web app does not allow localhost network access, so Figma Desktop is required.

Claude ──figma_write──▶ MCP Server ──HTTP (localhost:38451)──▶ Figma Plugin ──▶ Figma Document
Claude ◀─figma_read──── MCP Server ◀──HTTP (localhost:38451)── Figma Plugin ◀── Figma Document

How the localhost bridge works

The MCP server starts a small HTTP server bound to localhost:38451. The Figma plugin (running inside Figma Desktop) polls this server every 500 ms to pick up queued operations and post results back. All traffic stays on your machine — nothing is sent to any external server.

This approach is necessary because Figma plugins run in a sandboxed iframe and cannot use stdio or WebSocket to talk to a local process directly. HTTP polling over localhost is the only supported method for a Figma plugin to communicate with a local tool.


Features

| Direction | Tool | What it does | |-----------|------|-------------| | Write | figma_write | Draw frames, shapes, text on any page via JS code | | Read | figma_read | Extract node trees, colors, typography, screenshots | | Info | figma_status| Check plugin connection status | | Docs | figma_docs | Get full API reference + examples |


Quick Start

Step 1 — Add the MCP server to your AI client

Choose your platform:

# Project scope (default)
claude mcp add figma-ui-mcp -- npx figma-ui-mcp

# Global scope (all projects)
claude mcp add --scope user figma-ui-mcp -- npx figma-ui-mcp

Edit config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "figma": {
      "command": "npx",
      "args": ["-y", "figma-ui-mcp"]
    }
  }
}

Edit .cursor/mcp.json (project) or ~/.cursor/mcp.json (global):

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

Edit .vscode/mcp.json (project) or add to settings.json (global):

{
  "mcp": {
    "servers": {
      "figma": {
        "command": "npx",
        "args": ["-y", "figma-ui-mcp"]
      }
    }
  }
}

Edit ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "figma": {
      "command": "npx",
      "args": ["-y", "figma-ui-mcp"]
    }
  }
}
  1. Open "..." dropdown at the top of the agent panel
  2. Click "Manage MCP Servers""View raw config"
  3. Add to mcp_config.json:
{
  "mcpServers": {
    "figma": {
      "command": "npx",
      "args": ["-y", "figma-ui-mcp"]
    }
  }
}
git clone https://github.com/TranHoaiHung/figma-ui-mcp
cd figma-ui-mcp
npm install
# Then point your MCP client to: node /path/to/figma-ui-mcp/server/index.js

⚠️ IMPORTANT: After adding the MCP server, you MUST restart your IDE / AI client (quit and reopen). The MCP server only loads on startup — simply saving the config file is not enough. This applies to Claude Code, Cursor, VS Code, Windsurf, and Antigravity.

Step 2 — Run the Figma plugin

  1. Open Figma Desktop (required — web app cannot access localhost)
  2. Go to Plugins → Development → Import plugin from manifest...
  3. Select plugin/manifest.json from this repo
  4. Run Plugins → Development → Figma UI MCP Bridge

The plugin UI shows a green dot when the MCP server is connected.

Step 3 — Start designing with AI

The MCP tools are automatically available in your AI client:

figma_status     — check connection
figma_write      — draw / modify UI
figma_read       — extract design data
figma_docs       — API reference

Usage Examples

Draw a screen

Ask Claude: "Draw a dark dashboard with a sidebar, header, and 4 KPI cards"

Claude calls figma_write with code like:

await figma.createPage({ name: "Dashboard" });
await figma.setPage({ name: "Dashboard" });

const root = await figma.create({
  type: "FRAME", name: "Dashboard",
  x: 0, y: 0, width: 1440, height: 900,
  fill: "#0f172a",
});

const sidebar = await figma.create({
  type: "FRAME", name: "Sidebar",
  parentId: root.id,
  x: 0, y: 0, width: 240, height: 900,
  fill: "#1e293b", stroke: "#334155", strokeWeight: 1,
});

await figma.create({
  type: "TEXT", name: "App Name",
  parentId: sidebar.id,
  x: 20, y: 24, content: "My App",
  fontSize: 16, fontWeight: "SemiBold", fill: "#f8fafc",
});
// ... continue

Read a design

Ask Claude: "Read my selected frame and convert it to Tailwind CSS"

Claude calls figma_read with operation: "get_selection", receives the full node tree, then generates corresponding code.

Screenshot a frame

figma_read  →  operation: "screenshot"  →  nodeId: "123:456"

Returns a base64 PNG Claude can analyze and describe.


Architecture

figma-ui-mcp/
├── server/
│   ├── index.js            MCP server (stdio transport)
│   ├── bridge-server.js    HTTP bridge on localhost:38451
│   ├── code-executor.js    VM sandbox — safe JS execution
│   ├── tool-definitions.js MCP tool schemas
│   └── api-docs.js         API reference text
└── plugin/
    ├── manifest.json       Figma plugin manifest
    ├── code.js             Plugin main — operation handlers
    └── ui.html             Plugin UI — HTTP polling + status

Security

| Layer | Protection | |-------|-----------| | VM sandbox | vm.runInContext() — blocks require, process, fs, fetch | | Localhost only | Bridge binds 127.0.0.1:38451, never exposed to network | | Operation allowlist | Only 20 predefined operations accepted | | Timeout | 10s VM execution + 10s per plugin operation | | Body size limit | 500 KB max per request |


Available Write Operations (figma_write)

Core CRUD

| Operation | Description | |-----------|-------------| | figma.create({ type, ... }) | Create FRAME / RECTANGLE / ELLIPSE / LINE / TEXT / SVG / IMAGE | | figma.modify({ id, ... }) | Update node properties (fill, size, text, layout, etc.) | | figma.delete({ id }) | Remove a node | | figma.query({ type?, name?, id? }) | Find nodes by type, name, or ID | | figma.append({ parentId, childId }) | Move node into parent |

Page Management

| Operation | Description | |-----------|-------------| | figma.status() | Current Figma context info | | figma.listPages() | List all pages | | figma.setPage({ name }) | Switch active page | | figma.createPage({ name }) | Add a new page |

Node Operations

| Operation | Description | |-----------|-------------| | figma.clone({ id, x?, y?, parentId? }) | Duplicate a node with optional repositioning | | figma.group({ nodeIds, name? }) | Group multiple nodes | | figma.ungroup({ id }) | Ungroup a GROUP/FRAME | | figma.flatten({ id }) | Flatten/merge vectors into single path | | figma.resize({ id, width, height }) | Resize any node | | figma.set_selection({ ids }) | Programmatically select nodes | | figma.set_viewport({ nodeId?, x?, y?, zoom? }) | Navigate viewport | | figma.batch({ operations }) | Execute up to 50 ops in one call (10-25x faster) |

Components

| Operation | Description | |-----------|-------------| | figma.listComponents() | List all components in document | | figma.instantiate({ componentId }) | Create component instance | | figma.createComponent({ nodeId, name? }) | Convert FRAME/GROUP → reusable Component |

Design Tokens & Styles

| Operation | Description | |-----------|-------------| | figma.createVariableCollection({ name }) | Create variable collection ("Colors", "Spacing") | | figma.createVariable({ name, collectionId, value }) | Create COLOR/FLOAT/STRING/BOOLEAN variable | | figma.applyVariable({ nodeId, field, variableName }) | Bind variable to node fill/stroke/opacity | | figma.createPaintStyle({ name, color }) | Create reusable paint style | | figma.createTextStyle({ name, fontFamily, fontSize, ... }) | Create reusable text style | | figma.modifyVariable({ variableName, value }) | Change variable value — all bound nodes update instantly | | figma.setupDesignTokens({ colors, numbers }) | Bootstrap complete token system in one call (idempotent) | | figma.ensure_library() | Create/get Design Library frame | | figma.get_library_tokens() | Read library color + text tokens |

Image & Icon Helpers (server-side)

| Operation | Description | |-----------|-------------| | figma.loadImage(url, opts) | Download image → place on canvas | | figma.loadIcon(name, opts) | Fetch SVG icon (auto fallback: Fluent → Bootstrap → Phosphor → Lucide) | | figma.loadIconIn(name, opts) | Icon inside centered circle background |

Available Read Operations (figma_read)

| Operation | Description | |-----------|-------------| | get_selection | Full design tree of selected node(s) + design tokens | | get_design | Full node tree for a frame/page (depth param: default 10, or "full") | | get_page_nodes | Top-level frames on the current page | | screenshot | Export node as PNG — displays inline in Claude Code | | export_svg | Export node as SVG markup | | export_image | Export node as base64 PNG/JPG — for saving to disk (format, scale params) | | get_node_detail | CSS-like properties for single node (no tree traversal) | | get_styles | All local paint, text, effect, grid styles | | get_local_components | Component listing with descriptions + variant properties | | get_viewport | Current viewport position, zoom, bounds | | get_variables | Local variables (Design Tokens) — collections, modes, values |


Star History

If figma-ui-mcp helps you, please give it a star — it helps others discover the project!

GitHub stars

Star History Chart


License

License: MIT

MIT © TranHoaiHung — free to use, modify, and distribute. See LICENSE for details.