PluginWorld
Fi

figma-mcp-py

MCP

A read-only Figma MCP server that lets Claude list frames, read a frame's layout as flexbox, extract color and text styles as CSS variables, export icons as SVG, and render a PNG of the frame for visual comparison. This gives Claude everything it needs to build a matching web page from a design on Figma's free plan, with responses cached locally.

@stacksprint-io · MIT License · updated today

SECURITY

B

SCORE

60

STARS

▲ 0

PLUG IN

git clone https://github.com/stacksprint-io/figma-mcp-py.git

See the README to configure this MCP server

README

figma-mcp-py

A small Figma MCP server in Python, built with FastMCP. It gives Claude a design it can build from: the layout as flexbox, the colour and text styles as CSS variables, the icons as SVG, and a picture of the frame to compare against.

It is five read-only tools in about 280 lines of Python, so you can read all of it, change what Claude sees, and run it on Figma's free plan.

The Tallyhive landing-page mock this repo is tested against

Tallyhive is a made-up product. The mock above is drawn by the plugin in mock/, so you can draw the same file in your own Figma account and follow along.

Why write your own instead of using an existing one

  • You decide what Claude reads. Figma's file JSON is big: the one-page mock above is about 100 KB, roughly 20k tokens, and Claude Code warns when a tool returns more than 10k tokens (it cuts off at 25k unless you raise MAX_MCP_OUTPUT_TOKENS). get_layout turns the same frame into about 17 KB of what a developer needs: auto layout as flex (direction, gap, padding, justify, align), text with its font, colours as hex, sizes in px, and style names. Everything else is dropped.
  • It works on the free plan. Figma's REST rate limits put file reads and image exports in Tier 1, and their docs list View and Collab seats at up to 20 of those calls a month. This server makes at most three calls per file (the file, a PNG of the frame, the icons as SVG) and saves each response under .cache/. Every tool reads from the cache after that.
  • It's read-only. No tool writes to Figma, so there's nothing to approve call by call.

The tools

Tool What it returns
list_frames(file_url) The top-level frames in the file: page, id, name, size. Start here.
get_layout(file_url, frame_id) One frame as a compact layout tree. Icons show up as one icon node each (name, id, size), not their vector paths.
get_tokens(file_url) Colour and text styles as CSS custom properties, for example --color-brand: #3B5CF6 and --font-display: 700 56px/64px Inter.
export_icons(file_url, frame_id) Every icon in the frame (any node named Icon / ...) as inline SVG, keyed by name.
render_frame(file_url, frame_id) A PNG of the frame, returned as an MCP image so Claude can see the design.

file_url is the link you copy from Figma's address bar (figma.com/design/<file key>/...); the bare file key works too.

The picture and the tokens do different jobs. From the PNG alone, Claude gets the look right but has to guess exact values (it read our brand blue as roughly #3D5AFE); get_tokens gives it the real #3B5CF6.

How the code is laid out

figma_mcp/
  figma.py      the two Figma REST endpoints (/v1/files, /v1/images), every response cached on disk
  simplify.py   Figma JSON → the compact layout, tokens and icon list (pure functions, no network)
  server.py     the five @mcp.tool() functions; their docstrings are what Claude reads to pick a tool
mock/           a Figma development plugin that draws the Tallyhive mock
tests/          pytest, offline, against a saved copy of the mock

Setup

You need Python 3.12+, Claude Code, and Node.js (only for the Playwright MCP server, see below).

git clone https://github.com/stacksprint-io/figma-mcp-py.git
cd figma-mcp-py
python3 -m venv .venv
.venv/bin/pip install -e '.[dev]'
.venv/bin/pytest            # 21 tests, all offline

1. A design to read

Use any Figma file you can open, or draw the Tallyhive mock:

  1. Create a new design file in the Figma desktop app.
  2. Plugins → Development → Import plugin from manifest, pick mock/manifest.json, then run Tallyhive mock.
  3. Copy the file's link from the address bar.

The server works best on designs built with auto layout and named styles, because those are what turn into flex and CSS variables.

2. A Figma token

In Figma: Settings → Security → Personal access tokens → Generate new token, with read-only access to file content. Then:

cp .env.example .env        # and paste the token after FIGMA_TOKEN=

.env and .cache/ are both in .gitignore. The token is only needed the first time a file is read; once a file is cached, the server runs without it. To fetch a file again after you change the design, delete its files from .cache/.

3. Register it with Claude Code

This repo ships a project .mcp.json with two servers: this one (figma) and Microsoft's official Playwright MCP (playwright), which lets Claude open the page it built, take a screenshot and compare it with the design. Start Claude Code in the repo folder, approve the two project servers when it asks, and run /mcp to check both are connected.

To add only the Figma server, or to use it from another project:

claude mcp add figma -- /full/path/to/figma-mcp-py/.venv/bin/python -m figma_mcp.server

The Playwright server runs headless at 1440×900. Remove --headless from .mcp.json if you want to watch the browser.

Build a page from the mock

Serve an empty site/ folder (cd site && python3 -m http.server 8765), then give Claude Code one prompt:

Build the landing page in this Figma file as site/index.html: <your Figma link>. Use the figma tools to read the frames, the layout, the tokens, the icons and the picture. Plain HTML with Bootstrap 5 from the CDN and a small style block using the tokens as CSS variables; no build step. A server is already serving the site folder at http://127.0.0.1:8765/ (don't start one). When it's written, open it with the playwright tools at 1440 wide, take a screenshot, compare it with the Figma picture, fix what differs, and list what you fixed.

On the Tallyhive mock this produces one HTML file whose sections match the frame's heights to the pixel at 1440 wide (102, 518, 338, 640 and 92 px, 1690 in all).

The Figma frame next to the page Claude Code built from it, at 1440 wide

In the run recorded for the video, the compare step found and fixed two things: a negative letter-spacing Claude had added itself, which made the headline about 27 px narrower than in Figma, and a favicon.ico 404 in the console. Runs differ; an earlier run found the featured pricing card's 2 px border instead.

Limits

  • It reads one frame at a time and only solid fills. Gradients, images, effects (shadows, blur), components and variants aren't simplified yet; add them in simplify.node if your designs need them.
  • Fonts are reported by family, size, weight and line height. The page still has to load the font itself (the Tallyhive mock uses Inter).
  • Icons are found by name: a node named Icon / <something> is exported as one SVG.
  • Text nodes keep their characters and font but not their box size, so Claude picks text widths itself (it capped the Tallyhive headline at 800 px). If your design needs exact text widths, keep size for text nodes in simplify.node.
  • Claude only sees the frames you draw. With a desktop frame alone, the narrow-screen layout is its own guess; draw a mobile frame if you want that right.

License

MIT

SIMILAR PLUGINS