Skip to main content
Glama
Edwson

eds-mcp-server

by Edwson
README.md
# eds-mcp — the Edwson Design System over MCP + HTTP

[![CI](https://github.com/Edwson/eds-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/Edwson/eds-mcp/actions/workflows/ci.yml)
![Node](https://img.shields.io/badge/node-%E2%89%A518-3c873a)
![MCP](https://img.shields.io/badge/MCP-server-6e56cf)
![HTTP API](https://img.shields.io/badge/HTTP-REST%20%2B%20OpenAPI-22d3ee)
![Library](https://img.shields.io/badge/library-zero%20deps-3c873a)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./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

B3.2/5.0

Scored across 29 tools

Disambiguation5/5

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.

Naming Consistency5/5

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.

Tool Count3/5

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).

Completeness5/5

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.

Maintenance

ActivityMaintained
ResponsivenessNo issues