ux
Blog · Technical · 2026-05-28

MCP server for design intelligence — 14 tools any agent can call.

A slash command is shaped like a prompt template. A skill is shaped like a manifest the host model reads. Neither is composable with other agents. The Model Context Protocol is — and ux-skill v2.1 ships an MCP server that exposes the recommender, the 51-rule linter, and every queryable manifest as 14 tools any MCP-aware host can call. Claude Desktop, Cursor, Windsurf, Cline, Continue — same engine, same Pydantic schemas, same 1,182 entries.

Why MCP, not another skill

Claude Code skills are valuable: low-friction install, single-file manifests, model-friendly markdown. The ceiling is also low: a skill runs inside one host (Claude Code), it can't be invoked by another agent on the same machine, and it can't return structured data — only prose the model has to reparse.

MCP solves the ceiling. Once ux-skill speaks MCP:

The asymmetric move against ui-ux-pro-max-skill (84,000 stars, Claude-Code-only skill) is not "another skill." It's the same engine, distributed via a protocol they don't yet speak.

The 14 tools, verbatim

Pulled from the TOOLS registry in engine/mcp/server.py. Every tool has a Pydantic input model, a typed handler, and a one-line description that renders in the host's tool picker.

Tool What it does Returns
ux_recommendRun the 5-parallel-search recommender against a brief.System object — style, palette, type, motion, components, brand.
ux_lintRun the 51-rule regex linter over a path.List of findings (id, severity, file, line, why, fix).
ux_stylesQuery the 84-style manifest.Style entries with tokens, voice, intent labels.
ux_palettesQuery the 176-palette manifest.Palettes with hex tokens, intent, contrast ratios.
ux_type_pairsQuery the 70 typeface pairings.Display + body + mono pairs with weights and reasoning.
ux_componentsQuery the 148-component catalog.Component entries with anatomy, states, and motion bindings.
ux_industriesQuery the 184 industry rule packs.Per-industry tone, motion, and color biases.
ux_motion_presetsQuery the 57 motion presets.Presets with Framer Motion, GSAP, and CSS snippets.
ux_anti_patternsRead the 51 lint rules as data, not as a runner.Rule definitions with regex, scope, why, fix.
ux_brandsRead one of the 73 brand DESIGN.md specs.Full brand spec — tokens, ramps, motion, surfaces.
ux_landing_patternsQuery landing-page layout patterns.Pattern entries with sections, IA rhythm, and CTAs.
ux_persist_savePersist a recommendation to .ux/master.json.Path written, hash, timestamp.
ux_persist_loadLoad a previously persisted system.The previously-saved system object.
ux_statsHealth check + catalog counts.Version, entry counts per manifest, build hash.

Wiring into Claude Desktop

Claude Desktop reads its MCP server list from ~/Library/Application Support/Claude/claude_desktop_config.json on macOS (and the equivalent on Windows/Linux). Add ux-skill as a stdio server pointing at the installed CLI:

// ~/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "uxskill": {
      "command": "uxskill",
      "args": ["mcp"],
      "env": {
        "UX_DATA_DIR": "~/.ux-skill/data"
      }
    }
  }
}

Restart Claude Desktop. Open the tools pane — ux-skill's 14 tools appear under uxskill, each with its Pydantic-derived input schema. The agent picks them when relevant, calls them with structured arguments, receives structured responses.

Wiring into Cursor

Cursor honors the same protocol. Edit ~/.cursor/mcp.json (or the project-local .cursor/mcp.json):

// .cursor/mcp.json
{
  "mcpServers": {
    "uxskill": {
      "command": "uxskill",
      "args": ["mcp"]
    }
  }
}

Restart Cursor. The agent panel now lists all 14 tools as MCP-provided. The full Cursor walkthrough covers the rest of the install paths.

Wiring into Windsurf

Windsurf's Cascade reads its MCP server registry from ~/.windsurf/mcp_config.json:

// ~/.windsurf/mcp_config.json
{
  "mcpServers": {
    "uxskill": {
      "command": "uxskill",
      "args": ["mcp"],
      "disabled": false,
      "autoApprove": [
        "ux_stats",
        "ux_styles",
        "ux_palettes",
        "ux_type_pairs",
        "ux_anti_patterns"
      ]
    }
  }
}

The autoApprove list whitelists read-only tools so the agent doesn't prompt for confirmation on every catalog query. Writes (ux_persist_save) still require explicit approval. The full Windsurf walkthrough.

An end-to-end agent call

Here's the actual JSON-RPC exchange the agent and the ux-skill server have when the user asks "recommend a design system for a freight TMS targeting fleet ops." The agent infers the brief, calls ux_recommend, gets a system back, and continues.

// → request: tool call
{
  "jsonrpc": "2.0",
  "id": 8,
  "method": "tools/call",
  "params": {
    "name": "ux_recommend",
    "arguments": {
      "brief": {
        "project_type": "b2b logistics dashboard",
        "industry": "freight / TMS / supply chain",
        "audience": ["fleet operators", "dispatch managers"],
        "tone": ["operational", "trustworthy", "dense"],
        "must_have": ["data density", "keyboard-first"],
        "forbidden": ["playful palette", "hero animations"]
      }
    }
  }
}

// ← response: typed system object
{
  "jsonrpc": "2.0",
  "id": 8,
  "result": {
    "content": [{
      "type": "text",
      "text": "{...full system JSON...}"
    }],
    "structuredContent": {
      "style": { "id": "operational-density", "name": "Operational Density" },
      "palette": { "id": "dispatch-slate", "tokens": { "...": "..." } },
      "type_pair": { "id": "ibm-plex-sans-mono" },
      "motion": { "presets": ["state-flip", "row-highlight"] },
      "components": ["table-dense", "command-palette", "status-pill", "..."]
    }
  }
}

The response is structured. The agent doesn't have to re-parse a prose recommendation; it gets a typed system object and continues to the next step (often ux_lint after generating a surface from that system).

A composed call — recommend then lint

Where MCP earns its keep is composition. Here's a two-step the agent runs without re-prompting the user:

// 1. Compose a system for the brief.
const system = await mcp.call("ux_recommend", { brief });

// 2. Generate surface code using that system (model call).
const html = await model.generate({ system, surface: "hero" });
await fs.write("src/Hero.tsx", html);

// 3. Lint the generated file against the 51 rules.
const findings = await mcp.call("ux_lint", {
  paths: ["src/Hero.tsx"],
  threshold: "high"
});

// 4. If anything fired, ask the model to fix and re-lint.
if (findings.length > 0) {
  const fixed = await model.fix({ html, findings });
  await fs.write("src/Hero.tsx", fixed);
}

Four steps, two MCP calls, no manual handoff. More on the linter loop.

What's inside the server

The server module (engine/mcp/server.py) is roughly 500 lines. Three things matter about its shape:

The tool catalog is a dict, not a decorator forest. Every tool is registered in a single TOOLS: Dict[str, ToolEntry] map. ToolEntry is a triple of (handler function, Pydantic input model, description string). The MCP framework wrapper iterates the dict at startup and registers each entry. This means tests can call handlers directly without importing the mcp library.

The transport is optional. import mcp.server is wrapped in a try/except. If the mcp pip package isn't installed, the module still imports cleanly — the error only fires when you try to run_server(). This keeps uxskill recommend and uxskill lint usable as standalone CLI commands even without MCP installed.

Logging goes to stderr. stdout is reserved for the MCP JSON-RPC protocol stream — anything written there breaks the transport. The logger configuration enforces stderr-only at module import.

The skill manifest is a contract with one host. The MCP server is a contract with every host that speaks the protocol.

Discovering tools the agent doesn't know about

MCP hosts call tools/list on startup to enumerate what each server provides. The ux-skill server returns all 14 with their JSON Schema input definitions. The agent picks at runtime — the user doesn't have to remember a slash command, and the host doesn't have to ship a custom integration. That's the protocol working.

For agents that want to plan ahead — "what categories of design data does this server expose?" — call ux_stats first. It returns version, build hash, and entry counts per manifest:

$ mcp call uxskill ux_stats
{
  "version": "2.1.0-alpha.3",
  "build_hash": "a4c1f7e",
  "manifests": {
    "styles": 84,
    "palettes": 176,
    "type_pairs": 70,
    "components": 148,
    "industries": 184,
    "motion_presets": 57,
    "anti_patterns": 51,
    "brands": 73,
    "chart_types": 35,
    "tech_stacks": 25,
    "ux_guidelines": 112
  },
  "total_entries": 1015
}
Honesty card

MCP is young. The protocol moves.

The Model Context Protocol shipped late 2024 and is still version-pinning aggressively. Anthropic's Python SDK is the canonical implementation; the spec stabilized into 1.0 in early 2025. Our server tracks the SDK closely but if you're running an older Claude Desktop build (anything before December 2024) the tool list may not appear — upgrade the host first.

The 14 tools are also still alpha-tier. Names are stable; argument shapes may grow new optional fields. We don't break the contract on existing arguments.

The asymmetric move

ui-ux-pro-max-skill is the most-installed UX skill on GitHub (83,958 stars on 2026-05-28). Its distribution is single-host: Claude Code, via the marketplace, as a manifest. If a Cursor user wants the same recommender, there isn't one.

ux-skill's MCP server side-steps the popularity contest. We don't have to win Claude Code's UX-skill category — we can be present in every MCP-aware host simultaneously. Full side-by-side comparison with ui-ux-pro-max.

Related reading

Wire it into your host

One server. 14 tools. Every MCP host.

Same Python engine that powers the CLI, the skill, and the recommender — exposed over MCP for Claude Desktop, Cursor, Windsurf, and every other host that speaks the protocol. MIT, no telemetry, no account.

$ /plugin marketplace add Laith0003/ux-skill
$ /plugin install ux@ux-skill
— or —
$ pip install uxskill[mcp]
— or —
$ npx uxskill@alpha mcp