Last May, I had the experience of launching an e-commerce service at my company in just 2-3 months of actual development time. In that process, we actively used Figma MCP to rapidly produce designs.
The results were not good. Layouts were severely broken, and alignments were off. Fonts were applied differently to each node. Even when requesting the same screen again, the results varied each time; sometimes, a few nodes were missing, and other times, font sizes were incorrect. Changing the model didn't help either. Ultimately, we concluded that Figma MCP was an unreliable method and stopped using it. At the time, we didn't fully understand what the problem was.
Recently, as we launched and refined our service, we began building a design system and adding new designs. Our team is working closely with the design team to create an environment where Figma can be properly utilized with LLMs.
In this process, I'd like to summarize what I've investigated regarding how to use Figma.
What Figma Provides
Figma provides various tools and prompts to read/write Figma through MCP, along with extensive content such as skills, plugins, and guide documents for correctly using these tools. Among these, I focused my investigation on what is necessary for development.
1. MCP
These are the Figma MCP tools that LLMs can use to retrieve Figma contexts. The full list is available in Tools and prompts.
Tools for retrieving designs
get_design_context: Returns selected nodes as structured code context (React+Tailwind format)get_metadata: Returns an XML tree. Used for understanding the overall structure and breaking down large frames into child nodes.get_screenshot: Visual reference. A baseline for comparison and verification after implementation.get_variable_defs: Variables/tokens (color, spacing, typography) used in the selection.download_assets: Exports original images, icons, and SVGs.get_motion_context: Keyframe animation data (for motion implementation).
If the selected context is too large, the get_design_context response will be truncated. Therefore, you first use get_metadata to grasp the overall structure and then delve into child nodes.
Code Connect tools (Code Connect integration)
get_code_connect_map: Retrieves Figma instance ↔ code component mappings.get_code_connect_suggestions: Detects unmapped components.get_context_for_code_connect: Defines properties for mapping creation (TEXT / BOOLEAN / VARIANT / INSTANCE_SWAP / SLOT).add_code_connect_map,send_code_connect_mappings: Registers and confirms mappings.
Design System Lookup
search_design_system: Searches for components, variables, and styles in libraries.get_libraries: Libraries linked to/linkable from a file.
Prompts
create_design_system_rules: A reference prompt that explains how to structure Figma rule files.
2. Plugins
claude plugin install figma@claude-plugins-official
Figma provides plugins to correctly use the tools described above. Installation instructions are available in Claude Code and Figma: Set up the MCP server, and the full list of skills is summarized in Figma skills for MCP.
The plugin provides various skills demonstrating when and how to use these tools.
Skills
figma-implement-design: Design → Production code. Enforces a 7-step sequence.figma-design-to-code: Read-direction implementation guide.figma-implement-motion: Motion/animation implementation.figma-code-connect-components: Entry point for discovering, approving, and attaching mapping targets. 4 steps.figma-code-connect:.figma.tstemplate creation and verification. 6 steps.create-design-system-rules: Skill version of the above prompt.figma-swiftui: iOS-specific.
What we need to focus on is the implementation flow enforced by the figma-implement-design skill.
The 7 steps fixed by the skill, and which tools are called at each step, are as follows.
Easily missed points per step
- Step 2: If the response is truncated, narrow the scope. If the design is complex or has many nested layers, it gets truncated. In such cases, use
get_metadatato get a map and request only the necessary nodes again. - Step 3: Screenshots are for verification. Keep them accessible throughout implementation, but do not read the structure from them.
get_design_contextprovides the structure. - Step 4: Assets are the fourth step. If localhost sources are provided, use them as is; do not install new icon packages or create placeholders. The necessary assets are already within the response.
- Step 5: The React + Tailwind provided by MCP is not the final code. The agent is trained on web-based data, so it provides it in a familiar format to facilitate translation, making it closer to an intermediate representation than an output format. It's our responsibility to translate it into our framework and tokens.
- Step 7: Before completion, verify with a checklist: layout, typography, colors, interaction states, responsive behavior, asset rendering, accessibility.
The last line of the skill's Prerequisites states that having an established design system or component library in the project is desirable. Step 5 instructs to replace with project tokens, Step 6 to avoid hardcoded values, and Implementation Rules to extend existing components rather than creating new ones if a suitable component exists. Without a design system, these rules are impossible to follow from the outset.
How Should a Figma File Be Structured?
No matter how accurately development follows the flow above, what enters that flow is determined by the Figma file. The official documentation Structure your Figma file for better code recommends seven practices.
- Component Usage: Everything repetitive, like buttons, cards, inputs, and navigation items, should be components. Otherwise, they come as layer groups, and the agent determines reusability.
- Code Connect Integration: The most reliable way to achieve consistent component reuse. Otherwise, the model guesses.
- Define Tokens as Variables: Apply variables to spacing, color, radius, and typography. Otherwise, raw values are provided, and the agent determines which token it is.
- Meaningful Layer Names: Use CardContainer, ProductImage, CTA_Button instead of Frame1268, Group5. Otherwise, the agent has to guess how to connect what we've described with the frames on the screen.
- Auto Layout: Avoid absolute positioning and convey layout intent. Otherwise, coordinates are provided, and the layout intent must be reverse-engineered.
- Annotation: Convey behaviors, alignments, and responsive methods that are difficult to capture with visual information alone.
- Dev resources: Development resource links attached to layers in Dev Mode.
Among these, the need for meaningful layer names was particularly striking. It is important to be able to correctly infer the screen structure by just looking at the get_metadata response through meaningful layer names.
| Principle | Bad Example | Good Example |
|---|---|---|
| Role, not appearance | Gray Box, Left Area, Rectangle 3 | ProductInfo, OrderSummary |
| Match name if corresponding to code | Card1 | ProductCard (same as code component name) |
| Layout containers include role and type | Frame 428 | CheckoutSummarySection |
| State as variant, not name | Button_disabled separate frame | Button component variant |
| Decorative elements named but distinct | Group 12 | DecorativeDivider |
Names based on appearance become false information the moment the design changes. If it's no longer gray, a name like 'Gray Box' is worse than useless.
Where Inference Accumulates
If Figma is correctly configured, the Figma file is the answer key. Then, the development task is to translate that answer key into our code's representation and reconstruct it. The content explained above ultimately aims to eliminate as many inference steps by the agent as possible.
Here, a distinction arises: what can be translated directly without inference and what requires inference. The former refers to values and components defined in Figma, while the latter is the process of translating the output provided by MCP into our conventions.
Data That Doesn't Require Inference
Design System Components (Code Connect)
When Code Connect is applied, the get_design_context response includes code information. With the node ID as the key, the component name, file path, import statement, and usage snippet are returned together.
{
"1:2345": {
"codeConnectName": "Button",
"codeConnectSrc": "src/components/ui/Button.tsx"
}
}
Mapped nodes are wrapped like this within the response. While the surrounding layout still comes in Tailwind, our component, along with its import statement, is present in place of a raw div.
import { Button } from "@/components/ui/Button";
<div className="flex gap-[12px] items-center justify-center px-[var(--unit/10,10px)]">
<CodeConnectSnippet data-name="Button" data-snippet-language="tsx">
<Button variant="primary" size="md">확인</Button>
</CodeConnectSnippet>
</div>
Without mapping, the agent looks at the node and creates something similar, differently each time. With mapping, src/components/ui/Button.tsx is written in the response. It becomes a target to call, not a target to create.
Rule documents handle the same instruction as sentences, while Code Connect handles it as data. Sentences induce action, while data eliminates choices.
Tokens
Colors, spacing, radii, and typography already have names attached to their values. Moving a named value is closer to a transfer than a translation.
Using a tool like Tokens Studio places token definitions in an external source rather than within Figma. Figma receives that source and reflects it as variables, and development also receives the same source to create CSS variables and types.
If one place is changed, both sides move together. There is little room for inference in this section.
Components
Components are trickier than tokens. Nevertheless, for design system components, the fact that they are data not requiring an inference step remains the same. Although the conversion process may not be simple, tools that attempted a static approach already existed in an open-source project called DirectedEdges/specs. They are provided as a Figma plugin and CLI(@directededges/specs-cli), with a separate shared schema (@directededges/specs-schema). It explains that evaluation and difference calculation based on Figma styles and layers start from the premise that they are mechanical and predictable, so extraction is done by script, and only truly inference-requiring aspects like behavior, accessibility, and motion are passed downstream.
| Agent Extraction | Static Extraction | |
|---|---|---|
| Speed | 5-10 minutes per component | Seconds |
| Cost | 25-100K tokens per component | 0 |
| Consistency | Inference errors, omissions, overconfidence | Deterministic, repeatable |
Based solely on the description, it was identical to what I aimed to solve.
Imported Form vs. Extracted Form
When a single button is imported with MCP, it comes in this form.
<div className="bg-[var(--color/surface/state/default,#131518)] flex gap-[12px]
items-center justify-center px-[var(--unit/10,10px)] rounded-[var(--8,8px)]">
It's readable, and sufficient for creating a single screen. However, this response alone cannot create a component, as it lacks information on which properties are defined or what changes in different combinations.
When the same component is extracted with this tool, it comes out organized as static CSS values.
.button {
display: flex;
justify-content: space-between;
background: var(--color.surface.state.default);
border-radius: var(--8);
height: 40px;
padding: 0 var(--unit.10);
}
The names called by this CSS are the tokens managed from a single source earlier. Tokens and components will refer to the same source.
While converting it to a CSS library suitable for the team would require another conversion process, it certainly seemed like an achievable area.
What Requires Inference
Even after addressing all the above, there's still a remaining section. The rules apply in the final stage: translating the received code into our conventions. If the input arriving at that stage is already a static result, the amount of inference the rules need to perform will decrease proportionally. Therefore, what's needed are essentially guidelines on how to translate it to fit our code conventions.
The skeleton of the rule file can be examined through the create_design_system_rules prompt guide provided by Figma MCP. It consists of five sections, largely overlapping with what has been discussed earlier in this post.
| Rule File Skeleton | Areas Already Eliminated Above | What Remains for Rules |
|---|---|---|
| Figma MCP Integration Rules | The skill enforces 7 steps | — |
| Asset Handling Rules | Step 4 explicitly states to use localhost sources as is | — |
| Styling Rules | Both tokens and primitives are within the design system. No need to choose values or define forms | — |
| General Component Rules | Code Connect points to what's in the design system | Where to place newly created components in the codebase, how to name them, and how to export them |
| Project-Specific Conventions | — | Everything |
By the time the LLM needs to infer, much of the data is already static. For General Component Rules, this includes where to place files in the folder, how to set up imports, how to distinguish between domain components and shared components, and where to put tests. These are all things Figma cannot and has no reason to answer, so they would need to be additionally specified.
Conclusion
Ultimately, a good Figma file is one where the agent has nothing to infer. Tokens, Code Connect, and layer names might seem like distinct features, but they all serve to eliminate one inference step at a time.
This is also why it didn't work in May. While the code side had primitives and tokens, the Figma side lacked components and variables. Since mapping partners existed only on one side, Code Connect couldn't even start. Without auto layout, coordinates were provided, and without layer names, even interpreting those coordinates required guesswork. The screens that came out differently each time were the result of guesswork piled upon guesswork. No matter how many rule documents were added, they only reached the final stage.
Recently, based on these rules, we've been configuring the Claude plugin and working with the design team to build design system components and improve their quality. Once it's somewhat complete, I'll write another retrospective post about that process.
