eds-mcp-server
# eds-mcp — the Edwson Design System over MCP + HTTP
[](https://github.com/Edwson/eds-mcp/actions/workflows/ci.yml)




[](./LICENSE)
Your design-system **token + component contract**, served three ways from one engine — to **AI agents**
(Model Context Protocol), to **any app** (a zero-dependency HTTP REST API with an OpenAPI spec), and to
**Node code** (import the pure library). Not just to *read*, but to **scaffold correct code, lint a
proposed usage, discover components by the regulation they serve, and export the theme** — one source of
truth, auto-synced across the org, with your **AI-token bill going down instead of up**.
This is the runnable backbone behind the "AI-Native Development" section of the
[design system showcase](https://edwson.com/design-system-showcase.html).
```
MCP: 29 tools · 5 resources · 3 prompts HTTP: 29 REST endpoints · OpenAPI 3.1 Library: createCore()
65 institutional contracts across 14 domains **+ the Consumer Design System pack: 118 B2C categories across 11 domains** · reads + code-generation + linting + accessibility & compliance audits + flow composition + theme export + a machine-carried agent protocol
```
> **👉 Fastest way to see what this is _for_: `npm run example`.** One plain-English requirement
> → a shipped, compliant, tested feature, in one command — eds-mcp drives the design-system spine
> of the whole intake → planning → PRD → R&D → QA → launch lifecycle and writes real artifacts at
> every stage. Walkthrough + a committed sample run: [`examples/lifecycle/`](./examples/lifecycle/).
---
## Use it in one line
**① As an MCP server — for AI agents (Claude Desktop / Code, Cursor, Codex).** No install, no clone:
```json
{ "mcpServers": { "eds": { "command": "npx", "args": ["-y", "github:Edwson/eds-mcp"] } } }
```
Drop that into your MCP client config and the agent gains all 29 tools. (Once it's on npm:
`"args": ["-y", "eds-mcp-server"]`.)
**② As an HTTP REST API — for any language, any tool, curl, a browser.** Runs with **zero dependencies**:
```bash
npx -y --package=github:Edwson/eds-mcp eds-mcp-http # or: git clone … && node http.js (no npm install needed)
curl localhost:8787/v1/theme/css # the dual-theme token CSS
curl localhost:8787/v1/regulation/FINRA%202111 # components that satisfy a rule
curl -X POST localhost:8787/v1/scaffold -d '{"component":"OrderTicket"}' # a method-compliant skeleton
```
`GET /` lists every endpoint; `GET /openapi.json` is a full OpenAPI 3.1 spec you can load into Swagger or
Postman. Deploy it anywhere — or `docker build -t eds-mcp . && docker run -p 8787:8787 eds-mcp`.
**③ As a library — in Node code.** The pure engine, importable directly:
```js
import { createCore } from 'eds-mcp-server'; // server, http, library: all the same core.js
```
---
## Why an enterprise adopts this (and doesn't leave)
**1 · It cuts your AI-token spend.** The expensive way teams use AI for UI today: paste a 6–15 KB
CSS/theme file plus a screenshot into the agent *every turn*, let it regenerate full hex/CSS, and
correct it 2–3 times. This server serves **targeted, reference-based, cache-friendly slices** — and
goes further by *generating* the structure so the agent never invents it:
| Mechanism | Effect on tokens |
|---|---|
| **Targeted retrieval** — `get_tokens(color, dark)` returns only what's asked | a colour slice is **~78% smaller** than the full token file |
| **Reference output** — agent emits `--accent2` / `OrderTicket`, not regenerated CSS | output tokens drop sharply |
| **Generation** — `scaffold_component` returns a method-compliant skeleton | the agent completes, it doesn't architect from scratch |
| **Contract correctness** — `whenToUse` / `whenNot` / `dataContract` / `regulatory` | correction loops (the real cost driver) collapse toward 1 |
**2 · It auto-syncs across the org.** `build-manifest.js` hashes every contract file into
`manifest.json` (version + per-file SHA-256). Consumers compare their cached manifest and pull **only
the changed files** (`diff_since`). A token change propagates everywhere — apps, Storybook, agents —
without a rebuild, because everything references tokens, never literals.
**3 · It enforces consistency + compliance.** One signed manifest = one source of truth; checksums
prevent drift; SemVer gates breaking changes. Regulated components carry their rule in the contract;
`lint_usage` rejects hardcoded colours and non-canonical states before they ship; `find_by_regulation`
makes "which component satisfies FINRA 2111?" a one-call question.
---
## Tools (29)
Every tool returns a text block **and** `structuredContent` (the same object, machine-parseable);
failures set `isError: true` instead of masquerading as data.
**Tokens & theme**
| Tool | Returns |
|---|---|
| `list_token_groups` | group names only (cheapest orientation) |
| `get_tokens {group, theme?}` | only the requested token group |
| `get_token {name, theme?}` | resolve one token by name + its canonical CSS var (theme-aware) |
| `export_theme {format}` | the whole token set as **css · json · scss · tailwind** (dual-theme) |
**Component discovery**
| Tool | Returns |
|---|---|
| `list_components {domain?}` | every id + purpose + domain + regulatory flags |
| `get_component {id}` | one component's full contract |
| `get_data_contract {id}` | data shape + required render states |
| `get_decision_register {id}` | the four-cell register (when / when-not / a11y / regulatory) |
| `search_components {query}` | **ranked** keyword search (id > domain/regulatory > purpose) |
| `find_by_regulation {rule}` | every component that serves a rule, e.g. `"FINRA 2111"`, `"NACHA"` |
| `recommend_component {useCase, limit?}` | NL use case → ranked picks, each with its `whenNot` warning |
| `bundle_components {ids[]}` | resolve `requires` transitively → dependency-ordered set + token union |
**Generation & checks**
| Tool | Returns |
|---|---|
| `scaffold_component {id}` | a paste-ready skeleton: `ds-section` HTML + scoped **tokens-only** CSS + delegated reduced-motion-safe JS + the four-cell register |
| `lint_usage {tokens?, states?, css?}` | issues by severity: unknown tokens, non-canonical states, hardcoded colours, inline styles |
| `scaffold_test {id}` | a dependency-free, runnable **conformance test** (tokens resolve · states canonical · anchors intact · a11y passes · CSS tokens-only) |
**Accessibility, compliance & composition**
| Tool | Returns |
|---|---|
| `audit_accessibility {id}` | static a11y audit against the contract (a11y text, error state, dual-theme lock-step, reduced-motion, anchor) + per-token contrast in both themes |
| `contrast_report {theme?}` | the WCAG 2.1 contrast ladder for the token set, both themes, with AA / AA-large / AAA + a failures list |
| `compliance_check {jurisdiction?, feature?}` | a jurisdiction (`us·eu·uk·au·sg·jp·global`) → the regulatory anchors + guardrail components present here (a coverage map, not legal advice) |
| `compose_flow {ids[], name?}` | a dependency-resolved multi-component flow with a per-step decision register + the union of tokens + anchors |
**Meta**
| Tool | Returns |
|---|---|
| `get_manifest` | version + per-file checksums |
| `diff_since {version}` | changed files since a version (auto-sync delta) |
| `get_method` | the nine non-negotiables + verification gates — the Ed-agent operating contract |
| `get_stats` | version, component + domain counts, regulatory coverage, token count |
**Consumer Design System pack (the second system, same engine)**
The server also carries a bundled snapshot of the author's [Consumer Design System](https://edwson.com/consumer-design-system.html)
— 118 B2C component categories across 11 domains (commerce, social, media, onboarding, growth, trust & safety, and a
22-entry AI & Agents domain), each anchored to a public platform guideline (Apple HIG, Material 3, WCAG 2.2,
App Store / Play policy, GDPR, COPPA, FTC). The live contracts at `edwson.com/cds/` are canonical; the snapshot makes
them deterministic offline.
| Tool | Returns |
|---|---|
| `list_consumer_components {domain?}` | the B2C catalogue — id, name, domain, anchor, canonical URL |
| `get_consumer_component {id}` | one entry **with its bundle obligations attached** (paywall arrives owing a cancellation flow) |
| `search_consumer_components {query}` | keyword search across names, summaries, domains, anchors |
| `find_consumer_by_anchor {rule}` | regulation-first discovery: "COPPA" → the entries + hard rules that answer to it |
| `get_consumer_bundles {id?}` | bundled-by-contract pairs — dependencies as data, not tribal knowledge |
| `get_agent_protocol` | the machine-carried reading logic: seven-step read path + blockable hard rules |
### Resources (5, whole-file)
`eds://tokens` · `eds://components` · `eds://manifest` · `eds://method` · `eds://regulatory`
(the last maps every regulation to the components that serve it).
### Prompts (3, contract-grounded)
`build-regulated-component {id}` · `compliance-review {regulation}` · `accessibility-audit {id}` —
reusable workflows that wire the tools together the right way.
---
## Integrations · The Agency (agency-agents)
eds-mcp ships a **drop-in specialist** for
[The Agency](https://github.com/msitarzewski/agency-agents) — Matt Sitarzewski's open-source
(MIT) collection of AI agent personas. The Agency gives an agent a personality and a workflow;
eds-mcp gives it the design-system backend to build regulated UI **and prove it**. See
[`integrations/agency-agents/`](./integrations/agency-agents/) for the
`Regulated-Finance Design-System Engineer` persona (authored in The Agency's open format) plus an
example MCP config. This is interoperability with attribution — no upstream files are copied or
redistributed; please support the upstream project.
---
## HTTP REST API (for everyone who isn't an MCP client)
The same engine, over plain HTTP + JSON, **zero dependencies** (Node built-ins only — runs straight from
a clone with no `npm install`). CORS is open; every bad input returns `{ error }` with a `4xx`.
| Method & path | Equivalent of |
|---|---|
| `GET /health` · `GET /v1/stats` · `GET /v1/method` | liveness · counts · the operating contract |
| `GET /v1/tokens` · `GET /v1/tokens/{group}?theme=` · `GET /v1/token/{name}` | token groups · a group · one token |
| `GET /v1/theme/{css\|json\|scss\|tailwind}` | `export_theme` |
| `GET /v1/components?domain=` · `GET /v1/components/{id}` | `list_components` · `get_component` |
| `GET /v1/components/{id}/contract` · `/register` | `get_data_contract` · `get_decision_register` |
| `GET /v1/search?q=` · `GET /v1/regulation/{rule}` | `search_components` · `find_by_regulation` |
| `POST /v1/recommend` · `POST /v1/bundle` | `recommend_component` · `bundle_components` |
| `POST /v1/scaffold` · `POST /v1/lint` | `scaffold_component` · `lint_usage` |
| `GET /` · `GET /openapi.json` | self-describing index · OpenAPI 3.1 spec |
```bash
node http.js # serve on $PORT (default 8787) — no install required
npm run serve # same, via the package script
curl localhost:8787/v1/components?domain=payments
curl -s -X POST localhost:8787/v1/lint -d '{"tokens":["accent","nope"],"css":"a{color:#fff}"}'
```
---
## The killer move: `scaffold_component`
Ask for a component and get correct structure back, not a guess:
```jsonc
// scaffold_component { "id": "OrderTicket" } →
{
"prefix": "ot", "sectionId": "sec-order-ticket",
"tokensUsed": ["accent2","green","red","radius.md","space.4"],
"files": {
"html": "<section class=\"ds-section\" id=\"sec-order-ticket\">…four-cell register…</section>",
"css": ".ot-wrap{font-family:var(--type-font);color:var(--text1)} …tokens only, dual-theme…",
"js": "(function(){ var root=document.getElementById('ot-root'); … delegated, render-once … })();"
}
}
```
The CSS it emits is **guaranteed tokens-only** (the test asserts zero hardcoded hex), the HTML carries
the four-cell decision register, and the JS is a delegated, render-once, reduced-motion-safe stub —
the [Edwson method](https://edwson.com/) baked into the output.
---
## Use it as a library (not only as an MCP server)
The logic lives in a pure, dependency-free `core.js`. Import it directly:
```js
import { createCore } from 'eds-mcp-server'; // or './core.js'
import tokens from './tokens.json' assert { type: 'json' };
import components from './components.json' assert { type: 'json' };
const eds = createCore({ tokens, components });
eds.exportTheme('tailwind'); // → tailwind.config theme.extend
eds.scaffoldComponent('SuitabilityGate'); // → { files: { html, css, js } }
eds.lintUsage({ css: '.x{color:#f00}' }); // → { ok:false, issues:[{code:'hardcoded-color'…}] }
eds.findByRegulation('SEC 17a-4'); // → components with WORM-retention anchors
```
`server.js` is a thin MCP adapter over the same `core.js`, so the MCP tools and the library API can
never drift apart.
## Run from source
```bash
git clone https://github.com/Edwson/eds-mcp && cd eds-mcp
node http.js # HTTP REST API on :8787 — runs with NO npm install (zero deps)
npm install # only the MCP server (the SDK/zod) + the test suites need this
npm start # MCP server over stdio
npm run serve # HTTP API (same as node http.js)
npm run build:manifest # regenerate manifest.json after any token/component change
```
Register the local MCP server with a client (`mcp.json`):
```json
{ "mcpServers": { "eds": { "command": "node", "args": ["server.js"], "cwd": "./eds-mcp" } } }
```
Requires Node 18+. The contract lives in `tokens.json` + `components.json`; edit those, re-run
`build:manifest`, and every consumer picks up the delta.
65 component contracts span fourteen domains — `trading`, `compliance`, `payments`, `lending`, `wealth`, `identity`, `ai`, `ml`,
`ai-cost`, `data-eng`, `ai-infra`, `b2b`, `a11y`, `platform`.
## Quality & CI
Every push runs CI on **Node 18 / 20 / 22**: syntax check, ESLint, a **manifest-drift check**
(`build-manifest` must produce no diff), and **three test suites** — the dependency-free contract test
(`npm test`), the **end-to-end MCP integration test** that boots the real server over stdio and exercises
tools / resources / prompts through the SDK client (`npm run test:mcp`), and the **HTTP API integration
test** that boots the real REST server and hits every endpoint (`npm run test:http`).
```bash
npm run validate # everything CI runs, locally: build:manifest + lint + test + test:mcp + test:http
```
Typed (`core.d.ts`), MIT-licensed, SemVer-versioned ([CHANGELOG](./CHANGELOG.md)). See
[CONTRIBUTING](./CONTRIBUTING.md), [SECURITY](./SECURITY.md), and runnable [`examples/`](./examples).
## Files
```
core.js pure engine — all logic, dependency-free, importable as a library + test-covered
core.d.ts TypeScript declarations for the library API
loadCore.js builds a ready core from the bundled JSON (shared by server, http, tests)
server.js thin MCP adapter — 29 tools + 5 resources + 3 prompts over stdio
http.js zero-dependency HTTP REST API — 29 endpoints + OpenAPI 3.1 (node http.js)
build-manifest.js auto-sync engine — hashes contracts -> manifest.json
tokens.json token contract (color light/dark, space, radius, type, density)
components.json component contracts (purpose, when-to-use/not, props, a11y, regulatory, dataContract)
consumer.json the Consumer Design System pack — 118 B2C entries + agentProtocol + bundles + hardRules
test.js dependency-free test — contract shape + manifest sync + full engine behaviour
test-mcp.js end-to-end integration test — boots the real MCP server, exercises it via the SDK client
test-http.js end-to-end integration test — boots the real HTTP API, hits every endpoint
manifest.json generated — version + SHA-256 per file
Dockerfile zero-dependency image for the HTTP API
.github/ CI workflow (Node 18/20/22), issue + PR templates, dependabot
examples/ library usage + an MCP client config
```
TDQS
Scored across 29 tools
Each tool targets a distinct resource or action: tokens, components, consumers, compliance, accessibility, scaffolding, etc. Even similar tools like 'search_components' and 'recommend_component' serve different query methods (keyword vs. natural language), eliminating ambiguity.
All 29 tools follow a consistent verb_noun pattern in snake_case (e.g., list_token_groups, get_component, bundle_components, scaffold_component). There are no deviations or mixed conventions.
29 tools is above the typical well-scoped range (3-15) and falls into the 'heavy' category (16-25+). While each tool serves a specific purpose, the count is borderline and could benefit from consolidation in some areas (e.g., multiple search/find tools).
The tool surface covers the full design system lifecycle: discovery (list, search, recommend), retrieval (get, find), validation (lint, audit, contrast), scaffolding, compliance, and versioning. No obvious gaps for an agent working with the system.