Design system MCP

The in-repo MCP server that lets coding agents look up, audit, and author the Reva design system.

What it is

@reva/design-system-mcp is an in-repo MCP (Model Context Protocol) server — a CLI for the design language that coding agents speak directly. It gives an agent working inside this monorepo precise, token-cheap answers about the design system, lints code against the system's rules, and (for tokens) authors the DTCG source for you.

It's organised as three independent pillars:

PillarWhat it doesMode
TokensResolve, search, and author design tokens; map raw colours to rolesread + write
ComponentsLook up the @reva/ui component API and audit code against component rulesread
ExamplesReturn copy-pasteable usage examples pulled from the component docsread

Each pillar loads independently and fails open — if one isn't available, the others keep working.

It's already on

The server is registered for the whole monorepo — there's nothing to install. Each editor reads a different config file:

EditorConfig file
Claude Code.mcp.json (repo root)
Cursor.cursor/mcp.json

Both files carry the same server entry:

{
  "mcpServers": {
    "design-system": {
      "command": "bun",
      "args": ["packages/design-system-mcp/src/index.ts"]
    }
  }
}

In Claude Code, run /mcp to see the design-system server and its tools listed (they appear to the model as mcp__design-system__*). In Cursor, open Settings → MCP — you should see design-system under Workspace MCP Servers. Toggle it off and on (or restart Cursor) if it doesn't connect on first open.

Build prerequisites

The server reads from the same build artifacts the rest of the system produces. Run these once (and after the relevant sources change):

ToolsNeedsBuild it with
get_token, find_tokens, resolve_color, audit/usage_report (token rules), all authoring writesBuilt @reva/design-tokens artifactsbun run tokens:build
get_component, find_components, get_component_examples, audit/usage_report (component rules)The build-time caches dist/components.json + dist/examples.json (gitignored)bun run build --filter=@reva/design-system-mcp

If a tool replies with an actionable "cache not built" message, that's the cue to run the matching command above — it never errors out, it tells you exactly what to build.

audit / usage_report ride with the token pillar

The three pillars fail open independently, but audit and usage_report are registered inside the token pillar (they need the built @reva/design-tokens artifacts for their token-vocabulary index). So if the token artifacts aren't built, the whole token pillar — audit, usage_report, find_tokens, resolve_color, and the four authoring writes — degrades to a single get_token explainer, even though the component rules alone could run. The component and examples pillars keep working. The fix is bun run tokens:build. (A missing component cache, by contrast, only no-ops the component audit rules — audit still runs the token rules.)

New/changed components surface without a rebuild

The component/examples caches are build-time snapshots, but the server self-heals: when a @reva/ui source (or docs <Preview>) file is newer than the cache, the read tools re-extract from source in-process on the next call — a component added, or a prop changed, since the last build surfaces with no rebuild and no restart. If it genuinely can't refresh, it serves the last data flagged cacheStale: true with a rebuild hint, so you're never silently served stale data. The on-disk cache is just a cold-start seed and the CI/test artifact.

The tools

The server exposes twelve tools, grouped by pillar.

Tokens — read

ToolWhat it answers
get_tokenResolve one token by any identifier (path, alias, CSS var). On a miss it suggests near matches — but a raw colour literal (hex/rgb/hsl/oklch) gets a pointer to resolve_color instead, since that's where raw colours are resolved.
find_tokensList or search tokens by category or free text.
resolve_colorMap a raw colour to its foundation token and the semantic role(s) that use it.

Audit — read + compute

ToolWhat it answers
auditLint a snippet, file, or glob against the token and component rules.
usage_reportAggregate token usage and surface off-system hotspots across a glob.

audit and usage_report run the token rules (color-literal, raw-tailwind-scale, raw-stop-vs-role, arbitrary-value) alongside the eight component rules (layout-primitive, typography-tag, icon-import, row-as-item, bespoke-vs-primitive, variant-conformance, uppercase-eyebrow, cardcontent-padding).

The audit also gates CI + pre-commit

The audit engine runs outside the MCP as a CLI too, so adherence is enforced deterministically — no agent required:

bun run audit:design                    # audit the default consumer surfaces (apps, prototypes)
bun run audit:design apps/foo/Bar.tsx   # audit specific files (e.g. a changed-files list)

CI runs it over the .tsx a PR changes and blocks on error-severity findings (off-palette colours, hex literals, non-Phosphor icons); the husky pre-commit audits staged UI files best-effort. Warnings — e.g. uppercase-eyebrow, cardcontent-padding — print but don't block. The MCP audit tool is the interactive path; the CLI is the gate; both share one rule set.

Tokens — author (write)

ToolWhat it does
set_tokenCreate or update a leaf token (upsert). A semantic color.* role writes to both light.json and dark.json (parity-locked); pass value_dark / description_dark for per-mode divergence.
set_groupCreate or update group-level metadata ($type / $description / $extends).
rename_nodeRename a leaf or subtree and rewrite every in-source {reference}. Reports code consumers (file:line) — never auto-rewrites them.
remove_nodeDelete a leaf or subtree. Blocked when referrers exist unless cascade; deprecate: true soft-deprecates instead.

Components — read

ToolWhat it answers
get_componentFull component API: import path, props, cva variant axes + defaults, sub-components, and the rules distilled from the ## Per-component rules section of packages/ui/COMPONENT-RULES.md (including the typography primitives Text / Heading).
find_componentsList or search components by name or purpose (e.g. rowItem).

Examples — read

ToolWhat it answers
get_component_examplesCopy-pasteable usage examples extracted from the docs <Preview> blocks, each paired with the exact imports it needs.

Getting the best out of it

The win is asking the system instead of guessing a class name or hand-editing JSON. Talk to your agent in plain language — it picks the right tool. A few patterns:

Ask your agent……and it reaches for
"What token should I use for a muted card surface?"find_tokens / get_token
"Is #1f1f1f already a token? What role owns it?"resolve_color
"Audit this file for off-system colours and raw layout tags before I commit."audit
"Where are we using raw hex or flex divs across apps/client-portal?"usage_report
"How do I use StatusBadge? Show me the variants and a working example."get_component + get_component_examples
"Which primitive is the under-used general-purpose row?"find_components (purpose search → Item)
"Add a color.surface.faintest role, lighter in dark mode."set_token
"Rename color.brand.accent to color.brand.highlight and tell me what consumes it."rename_node

Audit before you commit — CI already does. The CI gate and husky pre-commit run these rules automatically (blocking on errors), but pointing audit at your diff interactively surfaces off-system colours, raw <div className="flex …">, raw <p>/<h*> typography, non-Phosphor icon imports, all-caps eyebrows, CardContent padding, and invalid cva variant values earlier — before CI flags them.

Prefer the tools over manual edits. Reach for set_token instead of hand-editing token JSON, and get_component_examples instead of guessing an API — the tools carry the invariants you'd otherwise have to remember.

Guarantees & caveats

The authoring (write) tools are deliberately conservative:

  • Validated against the real lint gate. Every write is checked by the actual @reva/design-tokens lint gate, run on a temporary copy of the token tree. On any failure the write aborts untouched and returns the gate's own messages — with the temp-copy paths re-rooted back to the real packages/design-tokens/src/… source so you know which file to fix.
  • Minimal, hook-stable diffs. The committed token sources are kept in the writer's canonical format (which Biome leaves byte-identical), so a one-token set_token adds just that token's lines instead of reformatting the whole file — and the pre-commit biome check is a no-op on the change.
  • Path-validated. A malformed dot-path (traversal like color.x/../evil, empty or whitespace segments) is rejected before anything is touched.
  • Atomic. Writes are tmp-then-rename — no half-written files.
  • Never auto-commits. The tools mutate the source on disk; git stays yours. Review the diff and commit when you're ready.
  • Light/dark parity is preserved, and the palette-generator-owned src/core/foundation/colors.json is off-limits — a write targeting it is rejected with a pointer to scripts/gen-palettes.ts.
  • rename_node / remove_node report code consumers but never rewrite app code — you stay in control of the call sites.

How it relates to the rules

The design system already ships conventions for agents — the AGENTS.md baseline, the per-package rules, and the reva-design-system-adherence skill. Those describe what on-brand looks like. The MCP server is how an agent checks and authors it: the same rules, made executable and queryable. Use the rules to set the defaults, and the server to look things up, lint against them, and write tokens without leaving the conversation.

On this page