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-mcp-rs

v0.1.0

Published

A zero-cost, unlimited Figma/FigJam MCP server in Rust — no API key, no rate limits

Readme

figma-mcp-rs

Figma/FigJam MCP server in Rust — free, no rate limits. Rust port of vkhanhqui/figma-mcp-go with a rewritten SolidJS plugin and FigJam support.

Open-source MCP server with full read/write access to Figma and FigJam via plugin — no REST API, no rate limits. Turn text into designs and designs into real code. Works with Claude, Cursor, GitHub Copilot, and any MCP-compatible AI tool.

npm license

Highlights

  • No Figma API token required
  • No rate limits — free plan friendly
  • Read and Write live Figma/FigJam data via plugin bridge — 87 tools total (73 from the Go reference, plus get_status, execute_code, eight FigJam tools, the use_figma escape hatch, and four design-system tools: update_style, update_variable, set_variable_mode, bind_variable_to_style)
  • Full design automation — styles, variables (values, aliases, scopes, modes), components, prototypes, and content
  • Colors accepted anywhere as hex, rgb(), hsl(), or oklch(); get_styles and export_tokens emit any of them via colorFormat
  • Design strategies included — 12 MCP prompts built in
  • Native binary, fast startup, low memory
  • Plugin bundled in the binary — the server self-installs it on first run, no download step
  • Built on rmcp 3.2; negotiates MCP protocol revision with each client

Why this exists

The official Figma MCP servers go through the REST API, which is rate limited per plan:

| Figma plan | REST budget | |------------|-------------| | Starter | 6 calls/month | | Professional | 200 calls/day | | Enterprise | 600 calls/day |

This server never calls the REST API. It talks to a plugin running inside Figma Desktop over a local WebSocket, so every read and write is unlimited and free — and unlike REST, the plugin can write to the open file.

Performance

Measured on Apple M4 Pro: ~6 MB RSS idle, ~7 MB with a plugin connected during tool round trips; startup < 10 ms. The Go reference runs ~15–25 MB.

Installation & Setup

1. Configure your AI tool

Claude Code CLI

claude mcp add -s project figma-mcp-rs -- npx -y figma-mcp-rs@latest

Or build from source:

make build   # cargo build --release + plugin build
claude mcp add -s project figma-mcp-rs -- /path/to/figma-mcp-rs/target/release/figma-mcp-rs

Codex CLI

codex mcp add figma-mcp-rs -- npx -y figma-mcp-rs@latest

Claude Code plugin marketplace (also installs the 15 skills)

/plugin marketplace add <this-repo>
/plugin install figma-mcp-rs@figma-mcp-rs

.mcp.json (Claude and other MCP-compatible tools)

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

.vscode/mcp.json (Cursor / VS Code / GitHub Copilot)

{
  "servers": {
    "figma-mcp-rs": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "figma-mcp-rs"]
    }
  }
}

Docker

docker build -t figma-mcp-rs .
docker run -i --rm -p 1998:1998 figma-mcp-rs

.mcp.json with Docker:

{
  "mcpServers": {
    "figma-mcp-rs": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "-p", "1998:1998", "figma-mcp-rs"]
    }
  }
}

The image listens on 0.0.0.0:1998 (baked into the default CMD), so the Figma plugin connects to ws://127.0.0.1:1998 as usual through the port mapping — keep the host port at 1998 or update the host in the plugin UI. Run one container per plugin connection; for multiple simultaneous MCP clients on one machine prefer the native binary, whose leader election shares a single plugin connection. The self-installed plugin path inside the container is not host-accessible — import the plugin from this repo's plugin/ directory or the release plugin.zip instead.

Server flags: --ip (default 127.0.0.1), --port (default 1998).

2. Install the Figma plugin

The plugin is bundled inside the server binary — no download or build step.

  1. Start the server once (any method above). On startup it writes manifest.json, dist/code.js, and dist/index.html to ~/.figma-mcp-rs/plugin/ (Windows: %USERPROFILE%\.figma-mcp-rs\plugin\) and logs the path.
  2. In Figma Desktop: Plugins → Development → Import plugin from manifest → select ~/.figma-mcp-rs/plugin/manifest.json
  3. Run the plugin inside any Figma or FigJam file — it connects to the server over ws://127.0.0.1:1998 (host/port configurable in the plugin UI)

If a tool fails with plugin not connected, call get_status — it diagnoses the bridge and returns setup instructions.

Multiple server instances are safe: the first to bind the port becomes leader and owns the plugin connection; others become followers that proxy tool calls and take over automatically if the leader dies.

FigJam & Slides support

The plugin loads in every editor (editorType: ["figma", "figjam", "slides", "dev"]):

  • Reads work in both: get_document/get_design_context serialize FigJam node types (STICKER, CONNECTOR, MARKER, WIDGET, EMBED, MEDIA…)
  • FigJam writes are eight named tools: create_sticky, create_stickies, create_connector, create_shape_with_text, create_table, create_code_block, auto_arrange, get_board_contents
  • Figma-only tools (styles, variables, components, prototype reactions, auto-layout) return a clear error in FigJam files
  • Remaining gaps — Slides, team-library variables/styles (figma.teamLibrary.*, importVariableByKeyAsync), and anything else unwrapped: use use_figma

Available Tools

Status

| Tool | Description | |------|-------------| | get_status | Check whether the plugin bridge is connected; returns setup instructions when it is not. Call this first if any tool fails with plugin not connected. |

Escape hatch

| Tool | Description | |------|-------------| | use_figma | Run Plugin API JavaScript inside the file. The code is the body of async () => { … }: top-level await works and only the return value comes back (console.log is discarded; the value must be JSON-serializable, so return IDs/counts/names, not node objects). Covers what the named tools don't wrap: Slides, component variants and properties, vector networks, styled text ranges, variable scopes, bulk edits in one round-trip. | | execute_code | Run arbitrary Plugin API code in the same sandbox — the code runs as an async function body, with an optional timeoutMs (1–25000 ms, default 5000) for long-running operations. Runs in the user's open file and is undoable with Cmd/Ctrl+Z. Use only for operations the dedicated tools don't cover; prefer the specific tool when one exists. |

Write — Create

| Tool | Description | |------|-------------| | create_frame | Create a frame with optional auto-layout, fill, and parent | | create_rectangle | Create a rectangle with optional fill and corner radius | | create_ellipse | Create an ellipse or circle | | create_text | Create a text node (font loaded automatically) | | import_image | Decode base64 image and place it as a rectangle fill | | create_component | Convert an existing FRAME node into a reusable component | | create_section | Create a Figma Section node to organise frames on a page |

Write — Modify

| Tool | Description | |------|-------------| | set_text | Update text content of an existing TEXT or STICKER node | | set_fills | Set solid fill color (hex) on a node | | set_strokes | Set solid stroke color and weight on a node | | set_opacity | Set opacity of one or more nodes (0 = transparent, 1 = opaque) | | set_corner_radius | Set corner radius — uniform or per-corner | | set_auto_layout | Set auto-layout properties on one or more nodes — direction, padding, gap, alignment, wrap, HUG/FILL sizing, absolute positioning (Figma only) | | set_visible | Show or hide one or more nodes | | lock_nodes / unlock_nodes | Lock/unlock one or more nodes | | rotate_nodes | Set absolute rotation in degrees on one or more nodes | | reorder_nodes | Change z-order: bringToFront, sendToBack, bringForward, sendBackward | | set_blend_mode | Set blend mode (MULTIPLY, SCREEN, OVERLAY, …) | | set_constraints | Set responsive constraints on one or more nodes | | move_nodes | Move nodes to an absolute x/y position | | resize_nodes | Resize nodes by width and/or height | | rename_node | Rename a node | | clone_node | Clone a node, optionally repositioning or reparenting | | reparent_nodes | Move nodes to a different parent frame, group, or section | | group_nodes / ungroup_nodes | Group nodes into a GROUP / dissolve groups | | batch_rename_nodes | Bulk rename via find/replace, regex, or prefix/suffix | | find_replace_text | Find and replace text across TEXT nodes in a subtree or page; supports regex | | delete_nodes | Delete one or more nodes permanently |

Write — Prototype (Figma only)

| Tool | Description | |------|-------------| | set_reactions | Set prototype reactions (triggers + actions); mode replace or append | | remove_reactions | Remove all or specific reactions by index |

Write — Styles (Figma only)

| Tool | Description | |------|-------------| | set_effects | Apply drop shadow / blur effects directly on a node | | create_paint_style / create_text_style / create_effect_style / create_grid_style | Create named local styles | | update_style | Update any style in place — paint color, text font/size/spacing, effects, grid — plus name and description | | bind_variable_to_style | Bind a variable to a style so the style itself is token-driven | | apply_style_to_node | Apply an existing local style to a node | | delete_style | Delete any style by ID |

Write — Variables (Figma only)

| Tool | Description | |------|-------------| | create_variable_collection | Create a new local variable collection with an optional initial mode | | add_variable_mode | Add a new mode to an existing collection (e.g. Light/Dark) | | create_variable | Create a variable (COLOR/FLOAT/STRING/BOOLEAN) in a collection | | set_variable_value | Set a variable's value for a mode — a literal or an alias to another variable | | update_variable | Rename a variable or collection; set description, scopes, Dev Mode code syntax; rename a mode | | set_variable_mode | Apply or clear a collection's mode override on a node or the current page | | bind_variable_to_node | Bind a variable to a node property (fills, strokes, size, spacing, …); omit variableId to unbind | | delete_variable | Delete a variable, an entire collection, or a single mode |

Write — Pages

| Tool | Description | |------|-------------| | add_page | Add a new page (optional name and index) | | delete_page | Delete a page by ID or name | | rename_page | Rename a page by ID or current name |

Write — Components & Navigation

| Tool | Description | |------|-------------| | navigate_to_page | Switch the active page by ID or name | | swap_component | Swap the main component of an INSTANCE node | | detach_instance | Detach component instances to plain frames |

Read — Document & Selection

| Tool | Description | |------|-------------| | get_document | Full current page tree | | get_metadata | File name, pages, current page | | get_pages | All pages (IDs + names) — lightweight | | get_selection | Currently selected nodes | | get_node / get_nodes_info | One node / multiple nodes by ID | | get_design_context | Depth-limited tree with detail level (minimal/compact/full) | | search_nodes | Find nodes by name substring and/or type | | scan_text_nodes | All text nodes in a subtree | | scan_nodes_by_types | Nodes matching a type list | | get_viewport | Current viewport center, zoom, visible bounds | | get_reactions | Prototype reactions on a node | | get_fonts | Fonts used on the current page, sorted by frequency |

Read — Styles & Variables

| Tool | Description | |------|-------------| | get_styles | Paint, text, effect, and grid styles — with descriptions, publish state, bound variables, and colorFormat | | get_variable_defs | Variable collections, modes, values, aliases, scopes, and code syntax | | get_local_components | All components + component sets | | get_annotations | Dev-mode annotations | | export_tokens | Design tokens (variables + paint styles) as JSON or CSS, with alias var() references and colorFormat |

Export

| Tool | Description | |------|-------------| | get_screenshot | Base64 image export of any node | | save_screenshots | Export images to disk (server-side write) | | export_frames_to_pdf | Multiple frames as one multi-page PDF (server-side merge) |

FigJam

| Tool | Description | |------|-------------| | create_sticky | Create a sticky note with text (FigJam only) | | create_stickies | Create multiple sticky notes at once, with optional grid auto-layout (FigJam only) | | create_connector | Create a connector, optionally between two nodes (FigJam only) | | create_shape_with_text | Create a shape with text — rectangles, circles, diamonds, … (FigJam only) | | create_table | Create a table with optional cell text content (FigJam only) | | create_code_block | Create a code block with syntax highlighting (FigJam only) | | auto_arrange | Auto-arrange objects in grid, row, or column layout (FigJam only) | | get_board_contents | All objects and connectors on the current FigJam page, with text content and connection data |

MCP Prompts (12)

read_design_strategy, design_strategy, text_replacement_strategy, annotation_conversion_strategy, swap_overrides_instances, reaction_to_connector_strategy, style_audit_strategy, bulk_rename_strategy, design_token_generation_strategy, generate_color_palette, generate_type_scale, generate_component_variants

Claude Skills (15)

skills/ ships the 12 prompts as Claude Code skills plus bridge-troubleshooting (connection diagnostics), figjam-boards (FigJam stickies, shapes, tables, connectors, auto-arrange), and editor-compatibility (Figma/FigJam/Slides tool matrix). Installed automatically via the plugin marketplace; otherwise copy skills/ into your project's .claude/skills/.

Development

make test      # cargo test + plugin bun test
make build     # release binary + plugin dist
  • CI: fmt + clippy + tests (linux amd64/arm64, windows, macos) + plugin typecheck/test/build on every PR.

  • Releases: conventional commits (feat:, fix:) on main → release-please opens a version-bump PR (Cargo.toml, Cargo.lock, npm/package.json, CHANGELOG); merging it tags vX.Y.Z and the same workflow builds the five binaries + plugin.zip, publishes npm, and pushes the multi-arch image to ghcr.io/jirayusueb/figma-mcp-rs. Re-run a release build for an existing tag with gh workflow run "Release please" -f tag=vX.Y.Z.

  • Server: Rust (tokio, axum, rmcp). Plugin: TypeScript + SolidJS, built with Vite (UI inlined to dist/index.html, core IIFE dist/code.js).

  • Toolchain: Bun 1.4.2, TypeScript 7.

  • The wire protocol (bridge WebSocket frames, follower /rpc) is kept compatible with the Go reference, so this server also works with the original figma-mcp-go plugin.

Credits

Fork of the architecture and tool design of figma-mcp-go by vkhanhqui — ported to Rust with a SolidJS plugin and FigJam support.

Related Projects

License

MIT