@theme-registry/refract-mcp
v0.1.18
Published
Model Context Protocol server for refract — query + validate a project's theme from an AI agent.
Readme
@theme-registry/refract-mcp
A Model Context Protocol server for refract. It lets an AI agent (Claude Code, claude.ai, or any MCP client) query and validate your project's theme while authoring — the "middleware" that keeps an agent bound to the theme's real vocabulary instead of guessing.
It is project-scoped: it loads your theme.config.(ts|js|mjs) once at startup and serves queries
against it, so the agent asks about your theme without ever resending it. It reloads on change.
The reload watches the config's directory recursively — so a theme split across ./tokens/*.ts reloads
too, not just an edit to the config itself. Hidden paths are never watched (that includes .git,
.next, .turbo, and the hidden .mjs files a .ts config's graph-compile emits beside your sources
and unlinks again), and neither are node_modules / dist / out / coverage. Reloads never overlap.
Tools
| Tool | Answers |
| --- | --- |
| resolveToken | What does colors.brand.dark resolve to — its value, CSS varName, unit, and derivedFrom? |
| listTokens | What token paths exist (the addressable vocabulary)? |
| findToken | Which token paths start with a prefix? |
| searchTokens | Which tokens match a query on their path OR resolved value? |
| listRecipes | What recipes are defined? |
| getClass | What real class (and composed class-list) does a recipe get — with the project's configured prefix? |
| renderRecipe | What exact CSS does one recipe emit? |
| checkContrast | Do the theme's colour pairings pass WCAG-2 (+ advisory APCA)? |
| validateTheme | Is a candidate theme valid on every configured target? — returns every problem at once (collect-all), per target. |
| diffTheme | What's the blast radius of a candidate edit — which tokens moved, classes changed, pairings crossed a threshold, targets stopped building? |
| reload | Reload the project's theme config from disk (also happens automatically on change). |
diffTheme is the plan-then-apply guardrail: pass a candidate edit and it builds it against the
project's real adapters and reports the blast radius before the agent writes — the claim a token file
can't make. validateTheme surfaces refract's collect-all errors with their stable code per target, so
an agent fixes all problems in one pass and catches adapter-level rules (unknown state, naming collision)
a generic check would miss. getClass / resolveToken read the real emitted names, so the prefix matches
what ships. The query tools take no
theme argument — they read the loaded project theme.
Note: over MCP, getClass takes named arguments — { subsystem, group, variant } (a JSON object,
as the tool schema requires) — whereas the runtime theme.getClass(subsystem, group, variant) takes the
same three positionally. Same identifiers, different call shape for the two surfaces.
Architecture
Pure tools (src/tools.ts, unit-tested) operate on a built Theme the server holds; callTool
(src/server.ts) is the transport-agnostic dispatch core; the transport is the official
@modelcontextprotocol/sdk over stdio.
agent ⇄ (MCP stdio, SDK) ⇄ callTool ⇄ tools.ts ⇄ the project theme (loaded once from theme.config)Connect
Register the server with your agent. Once published:
claude mcp add refract -- npx -y @theme-registry/refract-mcpOr from a local build:
pnpm --filter @theme-registry/refract-mcp build # → dist/server.js (a runnable bin)
claude mcp add refract -- node ./packages/refract-mcp/dist/server.jsThe server auto-discovers theme.config.(ts|js|mjs) in the working directory; pass --config <path>
to point elsewhere. A .ts config needs the typescript optional peer at 5.x (same as
refract build — a bare npm i -D typescript now resolves to 7.x, which doesn't expose the compiler
API from its main entry). A .mjs or .js config never loads typescript at all.
For project scope, commit a .mcp.json:
{ "mcpServers": { "refract": { "command": "npx", "args": ["-y", "@theme-registry/refract-mcp", "--config", "theme.config.ts"] } } }Test
pnpm --filter @theme-registry/refract-mcp testNotes
- Stable — published on the npm
latesttag in lockstep with core and the adapters. - It's the refract half of a Figma → refract → AI loop: an agent reads a design, authors a theme,
and
validateThemeis the guardrail that stops it drifting.
