
Design System MCP
io.github.dgestevesv0.1.1更新於 Oct 7, 2026
Ground truth about your React design system for coding agents, plus a UI linter they can run.
概覽
為編碼代理提供 React 設計系統的元件、屬性、變體與權杖的真實資訊,並提供可對其自身輸出執行的 UI 檢查器。
- 功能
- 此伺服器會靜態分析 React 專案的元件檔案、權杖樣式表與文件,並透過 MCP 提供這些資訊。工具包括 list_components、get_component、search_components 與 get_tokens,可回傳匯入路徑、屬性、cva 變體值、解析後的權杖值及深色模式值。check_ui 可檢查程式碼片段或檔案,回傳含規則 id、位置、訊息與具體修正建議的診斷,涵蓋硬編碼顏色、間距與圓角、原生元素、未知元件、屬性與變體,以及沒有無障礙名稱的圖示按鈕。另提供 ds://components/{name} 與 ds://tokens 資源,以及 build-with-design-system 提示。
- 適用情境
- 當代理在已有元件庫與設計權杖的 React 專案中撰寫介面,而你希望產生的程式碼使用真實元件、有效變體與語意權杖,而非任意 Tailwind 值時適用。也適合在 CI 中以命令列執行同一套規則。
- 執行需求
- 透過 npm 套件 @dgesteves/design-system-mcp 以 stdio 在本機執行,通常使用 npx。需要 Node.js 22.18 或更新版本。需要包含元件檔案的 React 專案,非預設版面可選用 design-system-mcp.config.json;專案根目錄來自 --root、設定檔或客戶端回報的工作區根目錄。未宣告帳戶、API 金鑰或環境變數。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 Design System MCP,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
design-system-mcp
An MCP server that gives coding agents ground truth about your React design system, and a linter they can run on their own UI.
The problem
Coding agents write UI from their training data, not from your design system. Ask for a settings card in a shadcn/ui project and you get bg-[#ef4444], p-[13px], a native <button> with hand-rolled classes, variant="danger" on a Button that only knows destructive, <Card.Header> in a system that exports CardHeader, and an icon button nobody can name with a screen reader.
The agent cannot see your Storybook or docs site, and TypeScript only catches part of it after the fact. On the demo draft above, tsc reports 3 of the 11 problems (the invalid variant, the unknown prop and the missing member) and has no opinion on hex colors, off-scale spacing, native elements or accessible names.
design-system-mcp reads your components, tokens and docs, and serves them to the agent over MCP: what exists, which props and variant values are valid, which token to use. It also gives the agent check_ui, a linter it calls on its own output. Every finding has a rule id, a location and a concrete fix, so the agent can correct itself before you review anything.
Quickstart
In a shadcn/ui-style project (components/ui/*.tsx, app/globals.css) no config is needed. Give your agent the tools, check what was extracted, and run the same rules from the terminal:
Other layouts take a config file. Requires Node.js 22.18 or later.
Setup
The server speaks MCP over stdio. It finds the project from --root, a config file in the working directory, or the workspace roots the client reports.
Claude Code
To share it with your team, add --scope project, which writes .mcp.json at the repository root:
Cursor
.cursor/mcp.json:
VS Code (Copilot agent mode)
.vscode/mcp.json:
Any other MCP client: run npx -y @dgesteves/design-system-mcp --root /path/to/app as a stdio server. On native Windows, wrap it as cmd /c npx ....
The server sends usage instructions during the MCP handshake. Clients that ignore them benefit from one line in CLAUDE.md, AGENTS.md or .cursor/rules: "Before writing UI, use the design-system tools. Run check_ui on every file you change and fix all errors."
Tools
All tools are read-only, have zod-validated input schemas with size limits (up to 1,000,000 characters of code for check_ui), and return compact Markdown for the model plus JSON structuredContent (with an output schema) for programs.
Resources: ds://components/{name} (Markdown, with name completion) and ds://tokens (JSON). Prompt: build-with-design-system, which takes a task and walks the agent through search, contract, tokens and check_ui. Claude Code exposes it as /mcp__design-system__build-with-design-system.
What the agent sees, from the demo:
Rules
Color matches under ΔE 0.02 count as the same color; under 0.1 the fix is offered; beyond that the message names the nearest token but leaves the choice to the agent. Likewise, a spacing or radius step that is off by more than half the value (and more than 4px) is suggested but not auto-fixed. Rules that need tokens are skipped when the design system defines none of that category; a stylesheet that imports tailwindcss brings Tailwind's default spacing unit and radius scale, unless the theme resets that namespace (--spacing-*: initial, --radius-*: initial), in which case only the project's own steps are suggested. Syntax errors are reported as syntax.
Configuration
design-system-mcp.config.json (or .ts, .mjs, .js) in the project root. Every field is optional; the JSON Schema gives editor completion.
Paths and globs are relative to the root and use forward slashes. Windows-style backslashes (components\ui\**\*.tsx, .\tsconfig.app.json) are read as separators, except in a pattern that already uses /, where \ escapes glob syntax (app/\(marketing\)/**). A tsconfig that does not exist is a config error rather than a silent fallback.
Tokens can be W3C DTCG JSON ($type inheritance, aliases, object color and dimension values, $deprecated, modes under $extensions.modes) or CSS custom properties: :root values, .dark / [data-theme] / prefers-color-scheme / @variant dark modes, and Tailwind v4 @theme mappings, with calc() evaluated. Token stylesheets are read as one theme, so .dark can live in its own file; without a :root block the light mode is the base, and a dark mode never is. A DTCG file and the CSS generated from it are merged by custom property.
elements maps a native element to the component that replaces it ({ "a": "Link" }, or a key such as input[type=checkbox] for a non-text input type); a mapped component is treated as a drop-in, so the rename is auto-fixed.
Docs are Markdown or MDX, one file per component, matched by component: frontmatter, the first heading or the file name. Fenced tsx/jsx blocks become examples (title="..." in the fence names them); JSDoc @example tags work too.
CLI flags override the file: --root, --config, --components, --tokens, --docs (repeatable), --no-cache, --no-watch. Run design-system-mcp --help for the rest.
CI
check runs the same rules as check_ui and exits 1 on errors (or on more than --max-warnings warnings):
--format github prints workflow commands, so findings show up as annotations on the pull request. --format json prints the raw results.
How it works
- Components. One TypeScript program over the component files, with the project's
tsconfig(so path aliases and dependency types resolve). For each exported PascalCase function,forwardRef,memoor class component, and each alias of a library component (const Dialog = DialogPrimitive.Root), the checker gives the props type. Props declared in the project, or by packages such as Radix, are listed with types, required flags, defaults (from destructuring,@defaultordefaultVariants) and JSDoc. React's DOM attributes are summarised as "…plus 290 props fromReact.ComponentProps<"button">" but kept in full for linting. When dependency types are missing, extraction falls back to what resolves and marks the props as open, so the linter does not guess. - Variants.
cva()andtv()calls are read from the AST: values in declaration order, defaults, per-value classes and compound variants. They are linked to a component throughVariantProps<typeof x>or a call in its body. - Composition. Flat parts (
CardHeadernext toCardincard.tsx), static members (Card.Header = CardHeader) andObject.assign(Root, { List })become parent/part relationships. The wrapped native element comes fromComponentProps<"button">,ButtonHTMLAttributes<HTMLButtonElement>, theforwardRefelement type, or the rendered JSX (includingconst Comp = asChild ? Slot : "button"). - Model. Components, tokens and docs form one JSON model, cached in
node_modules/.cache/design-system-mcpand keyed on the sizes and mtimes of the component, token and docs files, the project files the components import and the tsconfig chain, plus the lockfile, the config and the package version. The server answers the MCP handshake immediately and loads in the background; requests wait for the load. File changes trigger a rebuild that reuses the previous TypeScript program, an edited config file is read again, and clients are notified that resources changed. - Lint.
check_uiparses the snippet on its own (no type-checking), resolves each JSX tag through its imports (named, default, namespace, relative, and barrels such as@/components/uior../components/ui) to a design-system component, and runs the rules against the model. Fixes are text edits with offsets, so an agent or a tool can apply them mechanically.
Design decisions
Static analysis, not another model. The agent is already the LLM; what it lacks is ground truth. Everything here is deterministic, takes milliseconds, runs offline, needs no API key, and can be unit-tested rule by rule. The cost: it cannot judge intent, such as whether a Dialog was the right call. That stays with the agent and the reviewer.
The TypeScript checker over react-docgen-typescript. react-docgen-typescript wraps the same API but hides the AST, and cva() parsing, composition and element inference all need it. One program serves all four. The runtime dependency is TypeScript 6, the last release with the JavaScript compiler API; TypeScript 7 (the Go port) does not expose a stable one yet.
Syntactic linting. Agents check fragments they have not saved, often without imports. Type-checking those would need the whole program and would fail on the fragment's missing context. check_ui complements tsc: it catches what types cannot express (tokens, native elements, accessible names) and says what to write instead.
BM25, not embeddings. A design system is tens to a few hundred documents whose vocabulary already lives in names, docs and variant values. Field-weighted BM25 with Porter stemming and a small synonym map ("modal" → Dialog, "delete" → destructive) ranks them well, deterministically, with no model download or API key. It does not understand paraphrases the synonym map does not cover.
OKLCH for nearest colors. Distance in OKLCH (ΔE in OKLab) tracks perceived difference, so the suggested token is the one that looks closest, not the one with the closest hex digits. It also matches how Tailwind v4 and shadcn/ui define colors.
Markdown for the model, JSON for programs. Tool results put compact Markdown in content, which costs fewer tokens than JSON and reads well to a model, and the full JSON in structuredContent for clients and scripts.
Limits
- React only. Fix suggestions are Tailwind classes when the tokens come from a Tailwind theme, otherwise
var(--token). - Linting is per file and syntactic. Class names built at runtime (
`bg-${color}-500`) are not checked, and spread props are trusted. no-unknown-propis skipped for components whose props type does not fully resolve (dependencies not installed).- Composition is inferred from naming and static members; other patterns need explicit exports.
- While the server runs, it rebuilds on changes in the component, token and docs folders, the config file, the tsconfig and the tsconfigs it extends. An edit to another file the components import (a shared
lib/types.ts) is picked up on the next start. - No typography or shadow rules yet, and stdio is the only transport.
Roadmap
- Angular and Web Components extraction: signal and decorator inputs, and the Custom Elements Manifest.
- Storybook import: stories as examples,
argTypesas prop docs, CSF as a docs source. - Figma variables: import variables and modes as tokens, through the REST API or a DTCG export.
- Typography and shadow rules, an ESLint plugin that wraps the same rules, and a Streamable HTTP transport for remote agents.
Development
Releases use Changesets: add one with pnpm changeset.
License
MIT © Diogo Esteves
來源:README.md,提交 5f9045b
工具
0版本歷史
1- v0.1.1最新Oct 7, 2026


