refract v0.1 · beta
Agent-native / MCP server

MCP server

A Model Context Protocol server that exposes your project's theme as live tools an agent calls directly — so it answers "what class do I use here?" against the real compiled theme, and validates its own work as it goes. It's the one capability a plain token file can't offer.

Project-scoped. The server loads your theme.config.(ts|js|mjs) once at startup (auto-discovered in the cwd, or via --config) and holds it — so the query tools take no theme argument; the agent asks about the loaded theme without resending it. It reloads on change, and runs on the official @modelcontextprotocol/sdk over stdio. Published on the npm latest tag, versioned in lockstep with core and the adapters. A .ts config needs the typescript optional peer at 5.x (same as refract build — see Installation).

The tools

Eleven read/validate tools over the loaded theme:

ToolArgumentsAnswers
resolveToken{ path }a token path's value + its CSS varName, unit, and derivedFrom
listTokens{ }every token path — the addressable vocabulary
findToken{ prefix }token paths that start with a prefix (discover names)
searchTokens{ query }tokens matching a query on their path OR resolved value
listRecipes{ }every recipe as { subsystem, group, variant }
getClass{ subsystem, group, variant }the real class + composed class-list for a recipe (configured prefix)
renderRecipe{ subsystem, group, variant }the exact CSS one recipe emits
checkContrast{ minWcag? }WCAG-2 contrast audit of the theme's pairings (+ advisory APCA)
validateTheme{ theme? }validate a candidate edit against every target — every problem at once (collect-all), per target
diffTheme{ theme }the blast radius of a candidate vs the loaded theme — tokens moved, classes changed, pairings crossed, targets failing
reload{ }reload the project's theme config from disk
The server also exposes two MCP resourcesrefract://llms.txt (prose) and refract://manifest.json (a machine index, schema 1, with real class names + DTCG tokens) — the same self-documenting guide refract build --guide emits, rendered live from the loaded theme. Query tools take no theme argument (they read the loaded project); validateTheme / diffTheme take a candidate.
diffTheme has a CLI + CI twin. The same blast-radius diff runs without an MCP server — refract diff <candidate> — and gates a PR on how much a change moves. It's a headline capability with its own page: Blast radius — refract diff.

Connect

Register the server with your agent — any MCP client works the same way over stdio. Once published:

Terminal
claude mcp add refract -- npx -y @theme-registry/refract-mcp

…or from a local build (it auto-discovers theme.config.* in the cwd; pass --config to point elsewhere):

Terminal
pnpm --filter @theme-registry/refract-mcp build          # → dist/server.js
claude mcp add refract -- node ./packages/refract-mcp/dist/server.js

For project scope, commit a .mcp.json — anyone who opens the repo gets an agent wired to that theme:

.mcp.json
{ "mcpServers": { "refract": {
    "command": "npx",
    "args": ["-y", "@theme-registry/refract-mcp", "--config", "theme.config.ts"] } } }

Examples

Ask for a class. The agent calls getClass — no theme in the call, it's the loaded one — and gets the exact class-list to put on an element:

tools/call · getClass
// → request
{ "method": "tools/call", "params": { "name": "getClass",
    "arguments": { "subsystem": "components", "group": "buttons", "variant": "primary" } } }

// ← result (inside the MCP content block)
{ "className": "dt-components-buttons-primary",
  "classList": ["dt-colors-solid-brand", "dt-components-buttons-primary"] }

Validate before writing. validateTheme returns every problem in one pass with a stable code — the agent fixes them all, then proceeds:

tools/call · validateTheme
// → validate a theme with a bad colour
{ "name": "validateTheme",
  "arguments": { "theme": { "colors": { "x": { "base": "nope" } } } } }

// ← result
{ "ok": false, "code": "REFRACT_E_COLOR_INPUT",
  "errors": ["Invalid colour \"nope\". Author a colour as a hex string (\"#4dabf7\"), …"] }

Resolve a value. When an agent needs a literal (a chart colour, an inline style), resolveToken hands back exactly what the CSS variable holds:

tools/call · resolveToken
// → { path: "colors.brand.dark" }
// ← result
{ "path": "colors.brand.dark", "value": "rgb(51, 77, 210)" }
Why it matters. An agent bound to getClass + validateTheme can't drift: it reads real names and its work is checked against the real compiler at every step. Pair it with DTCG import — pull a design's tokens from a Figma (or Style Dictionary) export, author a theme from them, and let the server keep the agent honest — for a design-to-code loop that can't invent values. See Agent-native for the whole story.
Technical documentation for @theme-registry/refract · all output is compiled client-side by the real library (CSS adapter). The chrome is theme-aware; the render panes carry each preset's own world. · MIT licensed.