Design intelligence over Model Context Protocol.
ux-skill ships a Model Context Protocol server. Any MCP-capable host — Claude Desktop, Cursor, Windsurf, generic agents — can call the recommender, the linter, and all eleven data manifests over stdio. No plugin install, no IDE lock-in, just a long-running daemon and 14 tools.
Reaching design intelligence used to mean installing a plugin into the specific tool the plugin was written for. Claude Code plugins stay in Claude Code. Cursor rules stay in Cursor. The same recommender, the same linter, the same brand specs had to be re-wired for every host. The MCP server collapses that. One process. One protocol. Every host that speaks MCP gets the engine, identically. The recommender is deterministic, the linter is regex-grounded, and both come straight out of the same Python package as the slash commands — so an agent in a fresh repo can ask for the same Stripe-grade landing or fintech-dashboard system that a Claude Code session can.
None of the top eight ship one. We do.
The competition is locked inside Claude Code's plugin runtime. The MCP server makes ux-skill reachable from any agent — even agents that have never heard of a Claude Code plugin.
| Plugin | MCP server | Effective reach |
|---|---|---|
| ux-skill | yes ux-mcp over stdio |
Claude Desktop, Cursor, Windsurf, any MCP host, generic agents |
| ui-ux-pro-max-skill | no | Claude Code only |
| open-design | no | Claude Code only |
| taste-skill | no | Claude Code only |
| huashu-design | no | Claude Code only |
| stitch-skills | no | Claude Code only |
| nothing-design-skill | no | Claude Code only |
| hallmark | no | Claude Code only |
| material-3-skill | no | Claude Code only |
One server. Every host. That's the move.
Fourteen tools, one engine.
Each tool is a pure dict -> dict Python handler. Same code path the slash commands use; same data manifests; same deterministic recommender. The MCP layer is a thin stdio wrapper.
| Tool | What it does |
|---|---|
ux_recommend | Run the 5-parallel-search recommender over a brief. Returns style, palette, type pair, motion presets, components, brand exemplars, anti-pattern guardrails, and a rationale line per lane. |
ux_lint | Run the 120-rule anti-AI-slop regex linter over file paths. Returns findings with rule id, severity, file, line, excerpt, and fix. |
ux_styles | Return all 84+ entries from data/styles.json — design philosophies with tokens. |
ux_palettes | Return 176+ entries from data/palettes.json. Optional mode filter (light / dark). |
ux_type_pairs | Return 70+ entries from data/type-pairs.json — display + body + mono pairings. |
ux_components | Return 148+ entries from data/components.json. Optional category filter. |
ux_industries | Return 184+ entries from data/industries.json with style/palette/type biases per domain. |
ux_motion_presets | Return 57+ entries from data/motion-presets.json with easing, duration, stagger tokens. |
ux_anti_patterns | Return 35+ entries from data/anti-patterns.json (the regex rules that drive the linter). Optional severity filter. |
ux_brands | Return 131 brand specs from data/brands/*.json (Apple, Stripe, Linear, Tesla, Notion, etc.). Optional category filter. |
ux_landing_patterns | Return 24+ entries from data/landing-patterns.json — proven landing-page section patterns. |
ux_persist_save | Write a recommendation as .ux/design-system/MASTER.md in the given project root. Idempotent — same input writes byte-identical bytes. |
ux_persist_load | Load .ux/design-system/MASTER.md back into a structured dict, or report not-found. |
ux_stats | Return the engine version and per-manifest entry counts. Useful as a health probe. |
What it actually does.
ux_recommend — get a complete system from a brief
// Input { "brief": { "project_type": "landing", "industry": "fintech-neobank", "tone": ["warm", "editorial", "precise"], "must_have": ["dark-mode", "a11y-AA"], "forbidden": ["brutalism", "purple-gradients"], "stack": "nextjs-15-app-router", "region": "mena" } } // Output (abridged) { "style": { "id": "monochrome-precise", "name": "Monochrome Precise", ... }, "palette": { "id": "dark-editorial-cinema", "mode": "dark", ... }, "type_pair": { "id": "bricolage-inter-jetbrains", ... }, "motion": [ ... /* top 5 presets compatible with style */ ], "components": [ ... /* top 12 compatible components */ ], "brand_exemplars": [ ... /* top 5 brands to study */ ], "guardrails": [ ... /* all 120 anti-pattern rules — always-on */ ], "rationale": [ "Industry: Fintech Neobank", "Style: Monochrome Precise", "Palette: Dark Editorial Cinema", ... ] }
ux_lint — anti-slop regex sweep across paths
// Input { "paths": ["./app", "./components"], "threshold": "high" } // Output (abridged) { "files_scanned": 142, "rules_loaded": 35, "exit_code": 1, "findings": [ { "rule_id": "generic-placeholder-copy", "severity": "high", "file": "./app/page.tsx", "line": 42, "excerpt": "<p>Your headline goes here.</p>", "fix": "Write real copy that names the user value." }, ... ], "summary": { "critical": 0, "high": 4, "medium": 7, "low": 12, "total": 23 } }
ux_stats — engine health probe
// Input: {} ; Output: { "version": "2.0.0-alpha.1", "counts": { "styles": 84, "palettes": 176, "type-pairs": 70, "components": 148, "industries": 184, "chart-types": 35, "tech-stacks": 25, "ux-guidelines": 112, "motion-presets": 57, "anti-patterns": 35, "brands": 72 } }
Connect any MCP host in three lines.
The server is one binary: ux-mcp. Once installed, every MCP host points to it the same way.
Claude Desktop
~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"ux-skill": {
"command": "ux-mcp",
"args": [],
"env": {}
}
}
}
Cursor (project + global)
.cursor/mcp.json or ~/.cursor/mcp.json
{
"mcpServers": {
"ux-skill": {
"command": "ux-mcp"
}
}
}
Then in .cursorrules: "When designing UI, call ux-skill MCP tools first: ux_recommend for the system, ux_lint to catch slop."
Windsurf
~/.codeium/windsurf/mcp_config.json
{
"mcpServers": {
"ux-skill": {
"command": "ux-mcp"
}
}
}
Generic stdio client
any JSON-RPC over stdio host
# Spawn ux-mcp as a subprocess. # Write JSON-RPC frames to stdin. # Read responses from stdout. # Logs are on stderr only. $ ux-mcp # or, equivalently: $ python3 -m engine.mcp.server
Transport separated from handlers.
The 14 tools are pure dict -> dict Python functions in engine.mcp.server. The MCP stdio transport is an optional dependency that lazy-imports inside run_server(). Three consequences fall out:
- The
engine.mcpmodule imports cleanly whether or not themcpPython package is installed. - Tests exercise the handlers directly — no async event loop, no subprocess plumbing in the test suite.
ux-mcpfails fast with a clearpip installhint if the transport library is missing.
One source of truth, one entry point, every host.
Three lines to design intelligence in any agent.
MIT licensed. No telemetry. No account. The MCP transport is opt-in so the base install stays slim.
ux-mcp —