5 min read1,088 words

Design System MCP

Overview

As Usul's engineers adopted AI coding agents, a gap opened. Agents could ship interface code fast, but nothing checked that the result actually matched the design. I built a design-system MCP workflow that gives agents direct access to our Figma source of truth (design context, component metadata, and design tokens) and a repeatable skill that audits code against it.

Why

Design systems in Figma go stale. The file gets updated, but nothing forces the code to catch up, and the two drift further apart the longer nobody reconciles them. The most up-to-date a design system can be is in the codebase itself, since that's what's actually shipping, but that's only true if someone is actively maintaining its health. Left alone, code drifts too, just in its own direction instead of Figma's.

  1. It's faster to ship straight from a prompt than to update Figma first, so Figma stops being where the truth lives.
  2. With no single place to check, every team ends up rebuilding the same pattern its own way.
  3. The drift stays invisible until someone runs an actual audit and counts it.

Design review was the bottleneck in an agent-speed workflow. Developers "vibe coding" against a deadline would ship screens that drifted from the system (near-miss colors, off-scale spacing, overridden component variants), and catching that manually meant a designer eyeballing every PR. The system knew the right values; the workflow just couldn't reach them.

One audit made the scale of the drift concrete. A "Create/Edit View" panel had grown past 1,700 lines and 15-plus filter categories while still built as a slide-out sheet, a container meant for quick, contextual tasks, not a page's worth of configuration. Filters told the same story sideways. Eight different feature areas had each built their own filter UI, with at least three incompatible approaches to state management and no shared component between any of them.

Building the Pipeline

My first attempt connected Cursor to Figma over MCP and asked it to read the codebase and rebuild the design details there. The output was rough, Cursor missed details as basic as button corner radius, and getting it right meant burning through tokens on repeated rebuilds.

When Figma shipped its own official MCP server, I reconnected the same workflow through Claude instead (via a community plugin, claude-talk-to-figma-mcp), and the difference was immediate. The output was far more accurate on the first pass, though rebuilding a component from scratch still burns through a lot of tokens, so I stayed selective about what actually needed a redo versus a smaller fix.

The first full extraction was accurate but thin: colors, type, spacing, and border radius, pulled straight from the codebase, with none of the usage guidance a designer would need to actually pick it up. That gap, knowing what a token is versus knowing when to reach for it, is what the rules library below was built to close. That pipeline, Claude reading the live codebase and writing the design system straight into Figma, became the foundation the audit skill was later built on.

How It Works

The workflow connects the coding agent to Figma over MCP and runs a structured design check. It pulls the design's screenshot, reference implementation, and token definitions, reads the developer's actual code, then compares across six areas (colors, typography, spacing, shape, layout, and overall visual feel). The agent reports mismatches in plain language ("the blue is too light", "padding is 12px, design says 16px"), always paired with the minimal fix, and can apply the fixes directly and show the diff.

Visual diffing is only half of it. Alongside the Figma check, I built a 15-category rules library, accessibility, naming conventions, styling, component API design, testing, performance, error handling, state management, and more, that the same agent checks code against, the kind of standard a design system usually only enforces through a human code reviewer.

The skill is defensive by design. It guides developers to the right Figma node when links are ambiguous, adapts when components are unnamed, falls back to raw values when tokens are sparse, and, when the code uses the design system, checks that the right component variant is used rather than raw styles overriding the system.

What It Changed

This was a solo project, and it's now used across the whole team, five developers and one designer, not because anyone had to opt in, but because the skill is checked into the codebase itself and loads automatically into every engineer's Claude Code session. Adoption isn't something people remember to turn on. It's just there by default.

On the design side, I use the same workflow myself, for pattern checking and component creation, not only as a check on developers' code. It's a tool in my own design system work, not just a gate on someone else's.

That changed the nature of my own oversight more than I expected. Before this, getting pulled into a PR over a color or spacing mismatch meant I was functioning as another engineer, enforcing a spec line by line instead of doing design work. Once the agent could catch and fix that layer of drift on its own, being pulled in stopped meaning a nitpick. It gave me back the room to ask the harder question, not whether the padding was right, but whether a given feature was worth building at all.

It also made the design system itself more valuable. A token or a named component used to be a reference a developer could choose to consult. Once an agent could check code against those definitions automatically, every token and named component became something that could be enforced, not just something available to look up.

The system keeps expanding as it runs. A full scan across the frontend measured what memory alone had let slip through.

1,494

rule violations already sitting in the codebase, across 22 mistake types the system can detect.

42%

of frontend component files carried at least one violation, 348 of 827, before anything checked.

The single biggest category was hardcoded colors, 1,248 of the 1,494, each one a place a theme change or dark mode silently wouldn't apply. The old debt got quarantined into a baseline file rather than treated as blame. The system only flags new violations, so the alarm always means something, and the baseline shrinks toward zero as legacy files get touched. Every path into the codebase, editor save, CI, pull request, gets checked now, closing exactly the gap this project started with.