Skip to main content
Glama
humano-ai

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)