Add enriched design-token MCP server for AI coding assistants (proposal) - #684
Add enriched design-token MCP server for AI coding assistants (proposal)#684ronnyhummitzsch wants to merge 35 commits into
Conversation
Phase 1 design for extending sage-tokens-mcp with light/dark values, $description context and resolved alias/layer chains, sourced from data/tokens via a new enriched style-dictionary build output. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Task-by-task TDD plan: new custom/json-enriched format, per-mode build output, light/dark postbuild merge, rewritten mcp/server.js, and the .claude.json re-point. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… dist/mcp/tokens.json Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…i-word search Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ption, comment) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Four test classes (data integrity vs dist/css, adversarial input, end-to-end over MCP protocol, agent scenarios), a report generator, and mcp/README.md. All hardening runs in npm test; npm run mcp:report produces a Markdown snapshot for PR artefacts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…hardening class Phase-1 spec is reframed away from "extension of an existing MCP" — the MCP in mcp/ is a standalone component in this repo, replacing an earlier external wrapper prototype. Tool table no longer compares to prior state. Hardening spec gains test class 5: repository self-containment. Asserts no host-absolute paths, no legacy wrapper references in versioned code, presence of mcp/README.md with required sections, root README mentions the MCP, and dist/mcp/tokens.json is reproducible without secrets. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Project policy: all committed artefacts (specs, plans, code comments, documentation, reports) are written in English regardless of conversation language. German remains the working-conversation language only. Translates 2026-05-27 enriched MCP spec (143 lines) and implementation plan (~750 lines), plus three lingering German inline comments inside the plan's code samples. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Ten tasks: five hardening test classes (data integrity, adversarial input, agent scenarios, MCP wire-protocol E2E, repository self-containment), mcp/README.md with the consumer flow, a root README pointer, an npm-run-mcp:report Markdown snapshot, a fresh-clone verification helper, and final acceptance verification against the user's criteria (executable, executed, traceable, robust, ready for daily use). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…sation
Adds the data integrity hardening test class (schema invariants,
refChain termination, completeness vs dist/css, value consistency
for resolved layers).
The CSS-vs-MCP value consistency check exposed a real build bug:
postbuild.ts:fixShadowValues normalises bare numeric components in
shadow shorthand to px for CSS/SCSS outputs only. The MCP merged
output kept the source's unitless numerics ("0 0 1 1"), diverging
from what Sage ships in CSS ("0 0 1px 1px").
Fix applies the same normalisation to shadow tokens during the
light/dark merge in scripts/utils/merge-mcp-tokens.ts, so MCP values
match the CSS contract for the 7 affected global-depth tokens.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The self-containment test reads tracked files via git ls-files and scans for /Users/ paths and legacy wrapper references. After the test file itself became tracked, the scan matched its own search patterns (the test names and the literal it searches for). Test files legitimately contain such strings as fixtures and patterns and are not production code, so we exclude them from the scope alongside docs/superpowers/. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Under @tsconfig/strictest, bins[key]++ failed because indexed access yields number | undefined. Switched to bins[key] = (bins[key] ?? 0) + 1 mirroring the countBy pattern in the same file. Behaviour unchanged.
E2E error-contract test no longer tautological — it explicitly asserts "throw OR isError:true" rather than collapsing both outcomes into a trivially-true expression. Mode-reduction E2E test now picks a genuinely mode-divergent token via list-then-filter and verifies the reduced value equals the requested mode's side. Data-integrity refChain termination checks both light AND dark branches' termini for mode-divergent chains (previously only dark was existence-checked). mcp/tools.js: getToken null/undefined guard is now explicit (was relying on data coincidence). searchTokens and listTokensByCategory clamp negative limit to 0 to keep results.length and truncated internally consistent. verify-fresh-clone.sh removes the stale dist/mcp/tokens.json before the build so the post-build existence check cannot pass against a prior run's artefact. Removes the unused kebabToDotted helper from data-integrity. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A single-file, edge-to-edge slide presentation about the Sage Design Tokens MCP. Uses the real Sage UI font weights (base64-embedded), the authentic Sage token palette, and the live numbers from dist/mcp/tokens.json. Ten editorial slides cover the motivation, the architecture, the enriched token anatomy, the four MCP tools, the live snapshot, the hardening, the quickstart, the roadmap, and a colophon. Editorial / refined-minimalist aesthetic: Sage UI dominant, signature green used as a marker rather than a fill, dot-grid background evokes a design-system spec sheet, numbers ARE the design on the snapshot slide. Light and dark themes both via real Sage tokens; press T to toggle live. Navigation: ←/→ to navigate, Space toggles the index grid, Esc closes, T toggles theme, R restarts, Home/End jump to extremes. Build artefacts: - scripts/build-mcp-demo.ts — generator: reads fonts + dist/mcp/tokens.json + git metadata, templates the HTML. - package.json — npm run build:demo runs the generator. - docs/mcp-demo.html — generated single-file output, ~157 KB, no external requests (inline favicon, base64 fonts, inline CSS/JS). Verified at 1440×900 and 768×1024 via playwright. All ten slides render correctly in both light and dark themes; index overlay grid works; the self-containment story holds (no network calls, no external assets). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…reen
Acts on user feedback:
- Cover and end slides now use a 2/3 + 1/3 editorial grid. The right
column carries an aside with edition copy and a live-stat readout,
letting the title breathe and wrap naturally instead of crammed
against the left rule.
- Italics removed from every headline accent. Sage brand has no
italic, so emphasised words now use signature green at weight 700
without any font-style:italic. Body em still upright + weight 500.
- Slide counter moved from the top-left (where it collided with the
per-slide chapter eyebrow) into a new bottom-right navbar that pairs
it with a discrete keyboard hint ("← → navigate · Space index ·
F full"). The hint fades out when the index overlay is open.
- Fullscreen via the F key OR a Full icon button next to the theme
toggle. The button label flips between "Full" / "Exit" via the
fullscreenchange listener.
- Topbar no longer contains the counter — only theme + fullscreen
controls live there.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…slide The five test classes already make the hardening story; advertising the specific bugs that were caught during development isn't what the deck should foreground. Title softened to "Five test classes. End to end." and the .caught CSS removed since it's no longer used. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The slide-head parent already caps at 92ch, so the extra 60ch limit on .lede only forced senseless line breaks where space was available — the Anatomy slide's "A real entry from dist/mcp/tokens.json — button-typical-primary-bg-default." wrapped before the token name fit. Adds text-wrap: pretty so longer paragraphs (Why slide) still wrap gracefully without an arbitrary character cap. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
scripts/build-mcp-bundle.ts assembles a self-contained MCP bundle under ../mcp-bundle/ for sharing with the team ahead of any upstream release. Bundles: server.js (path-rewritten to read ./tokens.json), tools.js, the live dist/mcp/tokens.json, REPORT.md, the standalone demo.html and a README.md walking through setup. Run via `npm run build:bundle` and ship the directory or an `npm pack`ed tarball. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
@ronnyhummitzsch - we're wanting to develop an MCP server also for a different reason. What progress have you made towards getting this formally approved as my understanding is only MCP servers listed in our Sage registry are approved for use? We'll follow whatever worked for you 👍
|
|
@adrianbruntonsagecom ... not at all - I use it locally for my own purposes, and since it works quite well, I considered upstreaming - after a quick chat with the repo owners, we said they will have a look and see if that is somewhat useful. This is where we stand - once usefulness is agreed, I am happy to go for the approval process. What do you mean by MCP for a different reason? |
Our purpose would be entirely outside the scope of this repo. We have a developer interested in creating an MCP server for our component library, to allow consuming apps have copilot be more aware of the schema of the components available. |
Proposal — for review, not yet merge-ready (Draft)
This branch proposes adding a Model Context Protocol (MCP) server to
@sage/design-tokensso AI coding assistants can query the design tokensdirectly — with both light and dark values, the source
$descriptioncontext, and the fully resolved alias/layer chain. Opened as a Draft so it
can be evaluated at your leisure; happy to split, reshape, or drop parts based
on feedback.
Try it in 30 seconds (no install)
Download
docs/mcp-demo.htmland open it in a browser.It is fully self-contained (assets base64-embedded, no server, no network) —
GitHub won't render it inline, so grab the raw file. It walks through what the
MCP exposes and why.
What it does
A self-contained component under
mcp/. The style-dictionary build emits anenriched artefact (
dist/mcp/tokens.json, light/dark merged); the server loadsit and serves four tools over stdio:
get_token(name, mode?)refChain, description.modereduces mode-dependent fields to one mode's value.search_tokens(query, category?, layer?, limit?)category/layerfilters.list_categories()list_tokens_by_category(category, limit?)descriptionwhere available.What makes it more than a flat dump (current snapshot — see
mcp/REPORT.md): 1532 tokens, 1009 mode-divergent(carry
{light, dark}), 425 (27.7%) with a sourcedescription, and everyalias resolved into an explicit
refChain(depth up to 4+).Run the MCP server
Point an MCP client at
mcp/server.js. Full wiring (incl. the Claude CodemcpServersentry) and the data shape are inmcp/README.md.What's in this branch (the rigor)
docs/superpowers/— thereasoning behind the enriched build format and the hardening pass.
tests/hardening/: data integrity (schema + every alias terminates at aliteral + values match
dist/css), adversarial input, realistic agentscenarios, a real MCP wire-protocol E2E (server spawned as subprocess, driven
via the SDK
Client), and self-containment (no host-absolute paths, etc.).implementation → hardening → review feedback) rather than squashed.
Test plan
npm install && npm run buildproducesdist/mcp/tokens.jsonnpm test→ 81 passing(cd mcp && npm install), wiremcp/server.jsinto a client, calllist_categories→ returnscore,global,mode+ every component categorydocs/mcp-demo.htmland sanity-check the walkthroughscripts/verify-fresh-clone.shfor a hands-off fresh-clone checkOpen questions for review
consumes the build artefact? (Phase 2 idea below.)
dist/mcp/tokens.jsonthe right contract, orshould the enriched format be published with the npm package?
assistants actually query tokens?
docs/mcp-demo.htmluseful to keep in-repo, or better as anout-of-repo artefact?
Scope / roadmap
Phase 2 (tracked separately): contribute the enriched build format upstream so
the MCP can ship with the package and downstream consumers use it without
cloning the repo.