Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

MPDS

БесплатноНе проверен

A multi-project design system MCP server that manages design tokens, component specs, and validation with parent-child inheritance, accessible via REST API and

GitHubEmbed

Описание

A multi-project design system MCP server that manages design tokens, component specs, and validation with parent-child inheritance, accessible via REST API and JSON-RPC.

README

Multi-Project Design System MCP Server — an HTTP server that exposes design tokens, component specs, and validation utilities via a JSON REST API and an MCP JSON-RPC endpoint. Multiple design-system projects can coexist, each with parent-child inheritance for token resolution.

Architecture

modules/
  mcp-server/   # Express HTTP server (this binary, port MCP_PORT)
  registry/     # Project CRUD (SQLite-backed)
  tokens/       # Token storage, overrides, semantic resolution
  components/   # Component spec storage and overrides
  patterns/     # Pattern library: patterns, variants, composition rules, layout guidelines
  validate/     # Color-pair + snippet validation
  preview/      # HTML showcase generator (generate_showcase MCP tool)
  db/           # Shared SQLite connection + migrations

Inheritance model

Every project carries a nullable parentId (registry):

  • A project with parentId = null is a base design system.
  • A project with a parentId is a child that inherits from its base and may override individual tokens, component-spec fields, and patterns.
  • Inheritance is two levels deep only — creating a child of a child is rejected with MAX_INHERITANCE_DEPTH (no grandchildren).
  • A base cannot be deleted while it still has children (BASE_HAS_CHILDREN), and a project cannot be deleted while it still owns tokens (PROJECT_HAS_TOKENS).
graph TD
    Base["<b>Base design system</b><br/>parentId = null"]
    ChildA["<b>Child: Brand A</b><br/>parentId = Base"]
    ChildB["<b>Child: Brand B</b><br/>parentId = Base"]
    GC(["Grandchild<br/>❌ MAX_INHERITANCE_DEPTH"])

    Base --> ChildA
    Base --> ChildB
    ChildA -. rejected .-> GC

    classDef base fill:#1f4e5f,stroke:#0d2b36,color:#fff;
    classDef child fill:#2d6a4f,stroke:#1b4332,color:#fff;
    classDef bad fill:#7f1d1d,stroke:#450a0a,color:#fff,stroke-dasharray: 4 3;
    class Base base;
    class ChildA,ChildB child;
    class GC bad;

How values resolve

resolveTokens (and the equivalent component/pattern resolvers) merge the base layer with the child's own layer. For a base project every value is tagged source: "base"; for a child the base values are inherited and any keys the child defines win, tagged source: "override":

flowchart LR
    subgraph BASE["Base project (parent)"]
        BA["color.primary = #1f4e5f"]
        BB["color.surface = #ffffff"]
        BC["radius.md = 8px"]
    end

    subgraph CHILD["Child project (own layer)"]
        OA["color.primary = #2d6a4f"]
    end

    BASE -->|"inherited (source: base)"| R
    CHILD -->|"overrides (source: override)"| R

    subgraph R["resolveTokens(child) → resolved set"]
        RA["color.primary = #2d6a4f  (override)"]
        RB["color.surface = #ffffff  (base)"]
        RC["radius.md = 8px  (base)"]
    end

Resolution order is: start from the parent's values, then apply the child's own values by key — so a child key of the same name replaces the inherited one while every un-overridden base key flows through unchanged.

Running locally

Prerequisites

  • Node.js 20+ and npm
  • A writable directory for the SQLite DB (or use :memory: for a transient session)

Start (development)

npm ci
MCP_SECRET=dev DB_PATH=/tmp/mpds-dev.db MCP_PORT=3100 \
  npm --prefix modules/mcp-server run dev

Health check:

curl http://localhost:3100/health
# → {"status":"ok"}

Start (production build)

npm ci
npm --prefix modules/mcp-server run build
MCP_SECRET=<secret> DB_PATH=/home/mpds/data/mpds.db MPDS_ENV=production \
  npm --prefix modules/mcp-server start

Environment variables

Variable Required Default Description
MCP_SECRET Yes (production) "" (no auth) Bearer token — every /api/* request must carry it
DB_PATH Yes SQLite file path or :memory: (transient)
MCP_PORT No random port TCP port the server listens on
MPDS_ENV No Set to production to enforce MCP_SECRET check
HOME No (set by OS/Docker) Used for allowed DB path prefix validation

API endpoints

All endpoints (except /health) require Authorization: Bearer <MCP_SECRET>.

Error envelope: { "error": { "code": "...", "message": "..." } }

Health

GET /health

Projects

GET    /api/projects
POST   /api/projects           body: { id, name, parentId? }
GET    /api/projects/:id
DELETE /api/projects/:id

Tokens

GET    /api/projects/:projectId/tokens
PUT    /api/projects/:projectId/tokens/:key     body: { value, description? }
DELETE /api/projects/:projectId/tokens/:key/override

Components

GET    /api/projects/:projectId/components
GET    /api/projects/:projectId/components/:componentId
PUT    /api/projects/:projectId/components/:componentId/override
DELETE /api/projects/:projectId/components/:componentId/override

Validation

POST   /api/validate/color-pair     body: { foreground, background }

Patterns

GET    /api/projects/:projectId/patterns
POST   /api/projects/:projectId/patterns                       body: { id, name, category, description?, tags?, guidanceUrl? }
GET    /api/projects/:projectId/patterns/:patternId
PATCH  /api/projects/:projectId/patterns/:patternId            body: { name?, description?, tags?, guidanceUrl? }
DELETE /api/projects/:projectId/patterns/:patternId

Pattern variants

GET    /api/projects/:projectId/patterns/:patternId/variants
POST   /api/projects/:projectId/patterns/:patternId/variants   body: { name, appliesAt, description? }
GET    /api/projects/:projectId/patterns/:patternId/variants/:variantId
PATCH  /api/projects/:projectId/patterns/:patternId/variants/:variantId
DELETE /api/projects/:projectId/patterns/:patternId/variants/:variantId

Composition rules

GET    /api/projects/:projectId/composition-rules
POST   /api/projects/:projectId/composition-rules              body: { patternAId, patternBId, relation, guidance? }
DELETE /api/projects/:projectId/composition-rules/:ruleId

relation enum: NESTING_ALLOWED | NESTING_FORBIDDEN | OVERRIDE_CAUTION | SIBLING_ONLY | EXCLUSIVE

Layout guidelines

GET    /api/projects/:projectId/layout-guidelines
POST   /api/projects/:projectId/layout-guidelines              body: { type, name, description?, data }
GET    /api/projects/:projectId/layout-guidelines/:guidelineId
PATCH  /api/projects/:projectId/layout-guidelines/:guidelineId
DELETE /api/projects/:projectId/layout-guidelines/:guidelineId

type enum: breakpoints | spacing | grid | alignment | typography | animation

See contracts/P1/ and contracts/P2/ for the full frozen OpenAPI specs.

MCP configuration

The server exposes a JSON-RPC 2.0 endpoint at POST /mcp (requires the same Authorization: Bearer <MCP_SECRET> header as the REST API). Configure it in your MCP client as an HTTP server.

Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json)

{
  "mcpServers": {
    "mpds": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "http://localhost:3100/mcp"],
      "env": {
        "MCP_REMOTE_HEADER_AUTHORIZATION": "Bearer <MCP_SECRET>"
      }
    }
  }
}

Claude Code (.claude/settings.json in your project)

{
  "mcpServers": {
    "mpds": {
      "type": "http",
      "url": "http://localhost:3100/mcp",
      "headers": {
        "Authorization": "Bearer <MCP_SECRET>"
      }
    }
  }
}

GitHub Copilot (.vscode/mcp.json in your workspace)

{
  "inputs": [
    {
      "type": "promptString",
      "id": "mpds_secret",
      "description": "MPDS MCP bearer token",
      "password": true
    }
  ],
  "servers": {
    "mpds": {
      "type": "http",
      "url": "http://localhost:3100/mcp",
      "headers": {
        "Authorization": "Bearer ${input:mpds_secret}"
      }
    }
  }
}

The input block causes VS Code to prompt for the secret once per session and store it in the system keychain. To skip the prompt, replace ${input:mpds_secret} with the token literal (not recommended for shared workspaces).

OpenCode (opencode.json in your project root, or ~/.config/opencode/opencode.json globally)

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "mpds": {
      "type": "remote",
      "url": "http://localhost:3100/mcp",
      "enabled": true,
      "headers": {
        "Authorization": "Bearer <MCP_SECRET>"
      }
    }
  }
}

To avoid hard-coding the secret, reference an environment variable using OpenCode's {env:VAR} interpolation:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "mpds": {
      "type": "remote",
      "url": "http://localhost:3100/mcp",
      "enabled": true,
      "headers": {
        "Authorization": "Bearer {env:MCP_SECRET}"
      }
    }
  }
}

Available MCP methods

Read & validate

Method Description Required params
list_projects List all design-system projects
get_tokens Resolve tokens for a project (with inheritance) projectId, category?
get_design_system Full token map + component specs projectId
get_component_spec Single component spec projectId, componentId
validate_color_pair WCAG contrast ratio fg, bg, context (normal|large|ui)
validate_token_pair Contrast check using token keys projectId, fgKey, bgKey, context
validate_snippet Lint HTML/JSX for a11y issues content, contentType? (html|jsx)
create_guideline Create a design guideline id, title, body?, tags?
search_guidelines Full-text search guidelines query
propose_token_override Propose a token value change for review projectId, tokenKey, proposedValue, rationale?, agentId?
list_proposals List pending token proposals projectId

Write — projects & tokens

Method Description Required params
create_project Create a project id, name, parentId?
update_project Rename a project projectId, name
delete_project Delete a project projectId
list_tokens List all tokens for a project projectId, category?
get_token Get a single token projectId, key
create_token Create a token projectId, key, category, value, isSemantic?, semanticRef?
update_token Update a token value (OCC) projectId, key, version, value?, semanticRef?
set_token Set/override a token value projectId, key, value, version
delete_token Delete a token (OCC) projectId, key, version
delete_token_override Remove a child project override projectId, key

Write — components

Method Description Required params
create_component Create a component spec projectId, id, name, description?, props?, variants?, states?, …
update_component Update a component spec (OCC) projectId, componentId, version, name?, description?, …
delete_component Delete a component spec projectId, componentId

Write — pattern library

Method Description Required params
create_pattern Create a pattern projectId, id, name, category, description?, tags?
update_pattern Update a pattern projectId, patternId, name?, description?, tags?
delete_pattern Delete a pattern projectId, patternId
create_variant Add a variant to a pattern projectId, patternId, name, appliesAt, description?
update_variant Update a variant projectId, patternId, variantId, name?, appliesAt?
delete_variant Delete a variant projectId, patternId, variantId
create_composition_rule Define a pattern relationship projectId, patternAId, patternBId, relation, guidance?
delete_composition_rule Remove a composition rule projectId, ruleId
create_layout_guideline Create a layout guideline projectId, type, name, description?, data
update_layout_guideline Update a layout guideline projectId, guidelineId, name?, description?, data?
delete_layout_guideline Delete a layout guideline projectId, guidelineId

Showcase

Method Description Required params
generate_showcase Generate a self-contained HTML design system preview (color palette, component gallery, pattern library) projectId, title?
# Save and open the showcase locally
curl -s http://localhost:3100/mcp \
  -H "Authorization: Bearer <MCP_SECRET>" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"generate_showcase","params":{"projectId":"my-ds"}}' \
  | jq -r '.result.html' > /tmp/showcase.html && open /tmp/showcase.html

All requests follow JSON-RPC 2.0:

curl -s http://localhost:3100/mcp \
  -H "Authorization: Bearer <MCP_SECRET>" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"list_projects","params":{}}' | jq

Running tests

Tests use an in-memory SQLite database and require no external services:

DB_PATH=:memory: MCP_SECRET=test npm test

Docker

docker build -t mpds-mcp .
docker run -p 3100:3100 \
  -e MCP_SECRET=<secret> \
  -e DB_PATH=/home/mpds/data/mpds.db \
  -v $(pwd)/data:/home/mpds/data \
  mpds-mcp

See INSTALL.md for full setup and docker-compose instructions.

from github.com/nouhouari/mods-mcp

Установка MPDS

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/nouhouari/mods-mcp

FAQ

MPDS MCP бесплатный?

Да, MPDS MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для MPDS?

Нет, MPDS работает без API-ключей и переменных окружения.

MPDS — hosted или self-hosted?

Доступен hosted-вариант: Unyly запускает сервер в облаке, локальная установка не обязательна.

Как установить MPDS в Claude Desktop, Claude Code или Cursor?

Открой MPDS на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare MPDS with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории design