



I built a tool that connects Figma to Claude Code, without the Figma MCP
Hi! I'm Denys, a design engineer and product designer with 15+ years of experience. These days I spend a lot of my time figuring out how interface designers can adapt to the new AI reality. I build pipelines, tools, and full products that can do design in code. This is the story of one of my tools, Figmosha2.
A bit of context so it's clear why any of this exists. My main workflow hasn't lived in Figma for a while now — it lives in a repository: research, wireframes, tokens, components, documentation, all of it is code driven by Claude Code. But the teams I work with live in Figma. Design systems sit in Figma, reviews happen there, handoff often goes through Figma too. So I needed a reliable bridge: one where the agent could not just look at a mockup, but systematically read from and write to a file. Read the structure of hundreds of components, bind tokens, draw mockups using library components. That's the need Figmosha2 was born from.
The origin story is banal: I was doing a design system audit with Claude Code and the official Figma MCP. Anyone who's tried this knows how huge that kind of work is in scope and especially in time. So using AI should have helped a lot. But after a couple of hours of working in Claude Code through the Figma MCP, the monthly request limit on Figma's side ran out. I'm on a Figma Pro plan. The audit was maybe ten percent done.
That's how I learned that the official bridge between an AI agent and Figma is designed for one-off requests like "give me the spec of this button," not for systematic work with a file. And systematic work was exactly what I needed: go through the entire library, read the structure of every component, verify token bindings. One component is one or two requests, but when you have two hundred components and each one needs to be read first, then fixed, then re-read and verified, the request counter melts before your eyes. The monthly limit gets eaten in a single working morning, and then you sit and wait for next month.
Next I'll tell you how I arrived at my own solution through two failed iterations, and why it ended up fitting into 500 lines of Python.
Iteration zero: I just copy-pasted code
The first working pipeline looked like this. My Figma plugin reads a component's structure into YAML. Claude Code reads the YAML, picks semantic tokens, and generates an apply script. And then me, by hand: open the Scripter plugin in Figma, paste the generated code, hit Run.
Why the Plugin API and not the Figma REST API, you might ask. Because the REST API is nearly useless for this task. It's great at reading a file as JSON and exporting images, but it basically can't write to a design: create a frame, bind a token to a fill, fix an auto layout — none of that works through REST. And working with Variables through REST is only available on the Enterprise plan. So for actually manipulating a design there's only one path: the Plugin API from inside Figma itself. The only question was how to give the agent access to it.
This is how I migrated a library from primitives through styles to semantic variables — the repo with that pipeline is on my GitHub. But I still did a lot by hand. Claude Code generates a script in seconds, then waits while I copy, paste, and run it. For every component. For every fix iteration. Ugh, it drove me nuts!
Iteration one: Playwright
The logical next step: remove myself from the loop. The first version of Figmosha did this with Playwright: it opened Figma in a browser, found Scripter, pasted the code into the editor, clicked Run, waited for the result. It was very slow, though at least not manual. Browser automation kind of does everything like a human: waits for renders, hunts for elements in the DOM, fights window focus. A single operation took tens of seconds, with frequent glitches. When the agent needs 2-3 fix cycles on a complex layout, the session stretched into minutes of waiting where the actual work takes seconds. At that point it was easier to just do it by hand...
And that's a separate lesson I took from that iteration. Browser automation in agent pipelines is almost always a last resort. It imitates a human where no human is needed at all. If a system has a programmatic interface, go straight to it, even if it means writing a bit of your own infrastructure. A DOM click on a button is the most fragile link you can possibly build into an automated loop.
Iteration two: throw out the browser
And here a simple thought appeared. Scripter is just a plugin that executes TypeScript via the Figma Plugin API. The Plugin API is Figma's most stable and most powerful interface — thousands of plugins run on it. The only problem is that it's locked inside Figma's UI. So why not build my own plugin that holds an open WebSocket to a local server? The agent sends code over HTTP, the server passes it to the plugin, the plugin executes it via the Plugin API and returns the result.
That's how Figmosha 2.0 came to be. The whole system: one Python server file at 200 lines, one CLI at 300 lines, a plugin at 250 lines. No npm, no frameworks. The plugin is imported in dev mode via manifest — nothing needs to be published. Claude Code and I built it in a couple of days.
Now Claude Code writes a script and executes it in Figma via curl or the CLI. Reading a node takes milliseconds. Compared to the Playwright version, operations came out 150 to 950 times faster depending on the type of task. The plugin even works when Figma is minimized!
A word about security, because "arbitrary code execution" sounds scary. The whole system is local: the server listens only on localhost, the code runs in your own open Figma on your own machine, nothing goes out to the internet. No access tokens, no cloud middlemen, no third-party servers between the agent and your file. It's the same trust level as running a script in Scripter by hand — just without the hands.
Helpers: experience instead of boilerplate
The raw Plugin API has its own share of footguns. The fills array is frozen and can't be mutated directly. You can't write text until you've loaded the font. The synchronous getVariableById is deprecated. Anyone who's written Figma scripts through Scripter has probably hit all of this.
So the plugin runtime has 15 helpers baked in. h.setText loads fonts itself before writing text. h.bF correctly binds a Variable to a fill through an array copy. h.cloneNext clones a node and places it next to the original with an offset. A typical script with helpers is 60-70 percent shorter.
I didn't build them because I felt like it, but based on errors from real tasks. I ran Figmosha2 on working cases: drawing mockups from library components, auto layouts, token binding. Every repeated chunk of code and every footgun became a helper. So the helpers aren't an abstract convenience library — they're literally condensed error experience. If the agent tripped over the same rake three times, that rake turns into a function, and the next session never sees it.
Hints: the agent heals itself
The second important detail: when a script fails with a known error, the response includes a hint field with a suggestion. Say the script died on an unloaded font — the response says: use h.setText, it loads fonts itself.
This isn't made for me, it's made for Claude Code. The agent reads the hint, rewrites its script, and runs it again — without my involvement. In practice it looks like this: I type "create a button component," the agent draws it from library components with correct states and tokens, then reads back the result itself and checks: did the constraints break, are the auto layout settings right. If the layout is complex and came out crooked on the first try, the agent goes through 2-3 fix cycles on its own. And this is already a working scheme!
In general, the helpers-plus-hints combo is a small example of a broader principle I apply in all my agent pipelines: don't try to write the perfect instructions upfront — make the system feed knowledge back to the agent at the moment of failure. A five-page instruction gets lost in context; a hint in the response to a failed request works every time, because it arrives exactly when it's needed.
But what about existing solutions
An honest question I asked myself: why build my own when there's figma-console-mcp with 1.7k stars and 103 tools, plus the official Figma MCP. The official MCP was out because of the limits — that's where this whole story started.
figma-console-mcp is architecturally very similar to Figmosha: it also has a plugin bridge over WebSocket and also supports arbitrary code execution. But it's a product: Node.js, the MCP protocol, client configs, a Figma personal access token, four connection modes, 103 tools. Figmosha doesn't even need a token, because it never touches the Figma REST API at all: everything executes locally via the Plugin API.
And it's those 103 tools that bother me the most. Every tool is a description in the agent's context — a constant tax on every session. My approach is the opposite: one exec operation plus 15 helpers. An agent that can write code doesn't need a hundred wrappers over an API — it needs direct access and the shortest path to execution. Plus, 500 lines of code can be debugged and extended in an evening. A new helper goes into one file and works on the next request.
This is actually a bigger conversation than one plugin. The industry is mass-producing MCP servers on the logic of "the more tools the better," when in fact, for a strong model, every extra tool is noise. Code was and remains the most compact interface between an agent and a system. Give the agent exec and a one-page doc, and it will do more than with a hundred wrappers. That's the harness not just design engineers but the whole agentic development industry is moving toward.
What's not great
The plugin is tied to the open file: switch files, and you have to restart the plugin. Only one instance runs at a time. The agent still draws large pages slowly, and complex things in Figma are still faster to do by hand. Figmosha removes the grunt work, but it doesn't replace the designer.
What's next
Figmosha became the bridge I'm building my next tools on. The token migration pipeline now runs through it without manual Scripter. More than a hundred designers are already using it in their work. And for me it's also a proving ground: every new working task, from a library audit to mockup generation, stress-tests the tool and adds another helper or two.
The code is open under MIT — install it, test it, and send feedback: github.com/denysosadchyi/figmosha2