token-reconciler-mcp
by humano-ai
README.md
# Your design system says one thing. Your product ships another. This shows you exactly where.
```bash
npx token-reconciler ./design-tokens.json https://yourproduct.com
```
Give it any two sources — a design-tool export (Figma, Sketch, Penpot, Tokens Studio…), a live site or web-app URL, a codebase token file — and it prints a real drift report. Site URLs are **scanned live** (extraction is delegated to the open-source [Dembrandt](https://github.com/dembrandt/dembrandt) extractor), so there is nothing to set up and nothing staged: the report is your actual design system, as it exists right now.
No arguments? `npx token-reconciler` opens a guided start that walks you through it.
## The problem
A design system never lives in one place. There's the Figma file, the shipped CSS, and the codebase — three copies of the same decisions. Over time they quietly stop agreeing: a developer hardcodes Tailwind's blue instead of the brand indigo, Figma gets a new gray that never ships, a heading goes out `700` where the type scale says `600`. No single tool notices, because each tool only sees its own copy.
By 2026 the *extraction* side of this is solved — good open-source tools pull tokens out of live sites, and Figma exports Variables — all speaking the same [DTCG format](https://tr.designtokens.org/format/) (the W3C **D**esign **T**okens **C**ommunity **G**roup standard: one agreed JSON shape for design tokens, so every tool can read every other tool's output). What was missing is the step after: **comparing those files and knowing which differences matter.** That's what this tool does.
## What you get
Running a comparison produces a report with three sections:
- **Conflicts** — the same token defined differently in two sources, sorted by a 0–1 **confidence score** for how much the difference matters. Scoring is type-aware: colors are compared perceptually (OKLab), not as strings — so `#FFFFFF` vs `rgb(255,255,255)` is *not* a conflict, while two grays one shade apart is. Dimensions and durations are unit-normalized (`1rem` = `16px`, `0.3s` = `300ms`), and DTCG aliases are resolved before comparing, so `{color.base.indigo.500}` vs its raw value agree.
- **Unmatched tokens** — designed but never shipped, or shipped but never designed. Not conflicts yet; usually where the next one comes from.
- **A suggested resolution per conflict** — from a deliberately simple default resolver (`mostRecentWins`), with its reasoning stated. Smarter resolution is [pluggable](#plugging-in-your-own-resolver).
- **Accessibility analysis, current and next standard** — text-role color tokens are paired against background-role tokens and checked against **WCAG 2.2 AA** (4.5:1 — the current W3C standard, and the level EU EAA / ADA rules bind to), with AAA and an informative **APCA** reading (the WCAG 3.0 draft algorithm) per pair. The unique part: because this tool sees *multiple* sources, it can tell you when **drift changed accessibility** — the same pairing passes AA in Figma but fails on the shipped site. A generic audit can't say that; a reconciler can.
Here's a fragment of a real run (two production sites, scanned live):
```
### typography.style.text-heading-1
Confidence: 0.97 🔴 · type: typography
| Source | Value |
|---------------|----------------------------------------------------------|
| wildchild.ai | { fontFamily: Geist, fontSize: 48px, fontWeight: 400 … } |
| humano.ai | { fontFamily: Inter, fontSize: 12px, fontWeight: 700 … } |
### color.palette.palette-3
Confidence: 0.94 🔴 · type: color
| wildchild.ai | #7a7a7a |
| humano.ai | #888888 |
```
## How to use it
**Compare your design system against your product** (the main event):
1. Export your design system's tokens to DTCG JSON from whatever tool holds it — Figma (Community plugins like "Design Tokens (W3C)" or DesignBridge), Penpot (native DTCG export), Sketch, or Tokens Studio.
2. Run:
```bash
npx token-reconciler ./design-tokens.json https://yourproduct.com
```
**Compare any two sources** — every argument can be a `.json` file path, a URL to a token file, or a site URL to scan:
```bash
npx token-reconciler https://yoursite.com https://staging.yoursite.com
npx token-reconciler design-system.tokens.json codebase-scan.tokens.json
```
**Guided mode** — if you're not sure where to start:
```bash
npx token-reconciler
```
**In CI** — the exit code is the drift gate (`0` clean, `1` high-confidence conflicts, `2` input error):
```bash
npx token-reconciler reconcile figma.tokens.json site.tokens.json --threshold 0.7 --out report.md
```
Useful flags: `--json` (JSON report), `--out <file>`, `--names a,b`, `--kinds figma-variables,live-site`, `--threshold <0..1>`, `--no-fail`. See [examples/ci-usage.md](examples/ci-usage.md) for a full GitHub Actions setup and [examples/dembrandt-vs-figma.md](examples/dembrandt-vs-figma.md) for a worked walkthrough.
## Beyond marketing sites: SaaS, web apps, and mobile apps
Design systems live mostly in *products*, not public websites. Every kind of product connects — the source just differs:
**Logged-in SaaS / web apps.** They're still web — the scanner just needs your session. Grab your cookie from the browser's dev tools (Application → Cookies) and pass it through:
```bash
npx token-reconciler ./design-tokens.json https://app.yourproduct.com --cookie "session=abc123"
```
`--header "Authorization: Bearer …"` works too, for token-authenticated apps. Scan the screens that matter by pointing at their URLs directly.
**Mobile apps (iOS / Android / React Native / Flutter).** There's no URL to scan — but a mobile app's design tokens *live in its codebase*, which is even better than scanning: Android Compose/XML themes, iOS asset catalogs, React Native theme files. If you use [Style Dictionary](https://styledictionary.com/) or Tokens Studio, your source token JSON is already DTCG-compatible — feed it in directly:
```bash
npx token-reconciler ./design-tokens.json ./mobile-app/tokens/theme.tokens.json
```
That codebase-as-source path is also the most precise one for web apps, when you'd rather compare *intended* code tokens than scanned computed styles.
**All three at once.** The tool takes 2+ sources — so one run can answer "does Figma, the web app, *and* the mobile theme agree?":
```bash
npx token-reconciler design-tokens.json https://app.yourproduct.com android/tokens.json
```
## Use it from an AI agent (MCP)
```bash
claude mcp add token-reconciler -- npx -y token-reconciler-mcp
```
Three tools: `reconcile(sources)` runs a comparison and returns the scored report; `get_conflicts(runId)` retrieves a past run; `explain_conflict(runId, tokenPath)` breaks one conflict down completely — raw and resolved values per source, alias chains, and every confidence factor with its weight and reasoning. Pairs naturally with extractor MCP servers: an agent can scan a site with Dembrandt and reconcile against a Figma export in one conversation.
## Use it as a library
```ts
import { reconcileSources } from "token-reconciler";
const report = await reconcileSources([
{ name: "Design system", kind: "design-tool", document: "./design.tokens.json" },
{ name: "Live site", kind: "live-site", document: "./site.tokens.json" },
]);
for (const conflict of report.conflicts) {
console.log(conflict.path, conflict.confidence.score, conflict.confidence.factors);
}
```
`document` accepts a file path, an `http(s)` URL, or an already-parsed DTCG object. If a source carries an extraction timestamp in `$extensions` (Dembrandt does), it's picked up automatically.
### How confidence scoring works
Every conflict's score is built from three documented factors — the full breakdown ships in every report, never a black box:
| Factor | Weight | What it measures |
|---|---|---|
| `valueDelta` | 0.6 | Type-aware distance. Perceptual (OKLab) for colors, relative-numeric for dimensions/durations, field-averaged for composites. Mid-range deltas score highest — tiny ones are usually rounding noise; huge ones often mean two different tokens share a name. |
| `nameMatch` | 0.25 | The same token path exists in both sources. |
| `typeAgreement` | 0.15 | Both sources agree on the token's `$type`. |
The score tops out around 0.97 by design: it's a heuristic, and a heuristic claiming 1.00 would be lying.
### Plugging in your own resolver
Detecting conflicts is this library's job; *deciding the winner* is pluggable. One deliberately simple resolver ships (`mostRecentWins` — newest extraction wins; abstains without timestamps). Writing your own is one function:
```ts
import type { Resolver } from "token-reconciler";
const designWins: Resolver = (conflict) => {
const design = conflict.sightings.find((s) => s.sourceKind === "design-tool");
if (!design) return { decision: "unresolved", reasoning: "no design-tool source" };
return {
decision: "resolved",
winner: design.sourceName,
value: design.token.resolvedValue,
reasoning: "design file is the declared source of truth",
};
};
```
Every resolution carries a `reasoning` string, always. Provenance is the point.
## Scope — what this deliberately does not do
- **No extraction engine of its own.** Site scanning is delegated to [Dembrandt](https://github.com/dembrandt/dembrandt); Figma export belongs to Figma plugins. This tool starts where extractors stop.
- **No invented schema.** Standard DTCG in, standard DTCG concepts out.
- **No pretend judgment.** The default resolver is honest about being dumb. Real judgment — knowing *your* system's intent — is a different product.
## Works great with
- **[Dembrandt](https://github.com/dembrandt/dembrandt)** — live site → DTCG tokens; powers this tool's URL scanning.
- **[designlang](https://www.designlang.app/)** — live site → tokens + layout + a11y data ([GitHub](https://github.com/manavarya09/design-extract)).
- **[uiscanner](https://uiscanner.com/mcp)** — URL → token teardown via MCP.
- **[DesignBridge](https://www.figma.com/community/plugin/1618014379367021983/designops-tools-designbridge)** — Figma design system → structured `DESIGN.md` + tokens.
- **[W3C DTCG format](https://tr.designtokens.org/format/)** — the interchange format that makes all of this composable.
## Development
```bash
npm install
npm run build # tsc → dist/
npm test # vitest — includes an end-to-end MCP client/server test
```
## License
[Apache-2.0](LICENSE). Use it, fork it, build products on it.
---
Built by [wildchild.ai](https://wildchild.ai)
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues