@hex-core/mcp
Stdio MCP server: emit_app_context, emit_figma_tokens, resolve_spec, and more.
Install
0.6.0Tool / dlx invocationpnpm dlx @hex-core/mcpWhat it does
`@hex-core/mcp` is the stdio MCP (Model Context Protocol) server. It exposes the registry, themes, recipes, and the canonical LLM payload as structured tool calls for AI agents.
Wire it into Claude Code, Cursor, Continue, Zed, ChatGPT Desktop, or any MCP-aware client and your agent gains tools like `search_components`, `get_component`, `list_recipes`, `emit_app_context`, and `emit_figma_tokens`. Every tool's I/O is schema-validated; agents can't pass unknown fields.
As of `@hex-core/mcp@0.4.0`, the server is a thin transport shell over `@hex-core/payload`. The pure-function builders live in `payload`; this package wraps them in `@modelcontextprotocol/sdk`'s server primitives. If you want the same outputs without the stdio handshake, depend on `@hex-core/payload` directly.
Public API
search_components
{
name: "search_components",
input: {
// All three filters are optional — omit all to enumerate the catalog.
query?: string;
tags?: string[];
// 0.4.4: `category` filter accepts the new "artifact" value alongside the
// existing primitive | component | block | example | hook | lib | ai
// categories — narrows search to the 23 diagram primitives shipped in
// @hex-core/components@1.8.0 (Arc, Chord, Cloze, …, Venn).
category?: "primitive" | "component" | "block" | "example" | "hook" | "lib" | "ai" | "artifact";
},
// MCP standard envelope; the embedded text is a JSON-stringified array.
output: {
content: [{
type: "text";
text: string; // Array<{ name, displayName, description, category, subcategory?, tags, tokenBudget? }>
}];
};
}Search the registry by free-text query, tags, or category. Returns the slim catalog metadata for each match (name, displayName, description, category, subcategory, tags, tokenBudget) wrapped in MCP's standard text envelope. The `category` filter (0.4.4+) lets agents scope to a single surface — e.g., `category: "artifact"` for the diagram primitives, `category: "ai"` for the chat/multimodal cluster.
// All three inputs are optional — pass query, tags, category, or any combo.
// → search_components({ query: "confirmation dialog" })
// → {
// content: [{
// type: "text",
// text: '[{"name":"dialog","displayName":"Dialog","description":"...","category":"component","tags":["overlay","modal"],"tokenBudget":...}, ...]'
// }]
// }get_component / get_component_schema
{
name: "get_component",
input: { slug: string },
output: RegistryItem
}
{
name: "get_component_schema",
input: { slug: string },
output: { props: PropDef[]; variants: VariantDef[]; ai: AIHints }
}`get_component` returns the full registry item — props, variants, examples, AI hints, source. `get_component_schema` returns the schema slice only, for agents reasoning about a component they've already installed.
// agent has already added the button — only needs the schema
// → get_component_schema({ slug: "button" })emit_app_context
{
name: "emit_app_context",
input: {
theme: string; // theme name
components: string[]; // slugs
recipes?: string[];
overrides?: Record<string, string>;
density?: "compact" | "comfortable" | "spacious";
},
output: { content: [{ type: "text", text: /* markdown */ }] }
}Returns the full canonical context markdown — install commands, `globals.css`, `tailwind.config.ts`, components, recipes, and the LLM context prompt. Same artifact `@hex-core/payload`'s `buildAppContext` produces.
// One call powers the studio's /copy page workflow:
// → emit_app_context({
// theme: "default",
// components: ["button", "card", "input"],
// density: "comfortable",
// })emit_figma_tokens
{
name: "emit_figma_tokens",
input: { theme: string },
output: { content: [{ type: "text", text: /* JSON */ }] }
}Emit a Figma Variables JSON document for the named theme. Same shape `@hex-core/payload`'s `buildFigmaTokens` returns — paste into the Figma plugin's import slot.
// → emit_figma_tokens({ theme: "midnight" })
// → { content: [{ type: "text", text: '{"$schema":...}' }] }list_recipes / get_recipe
{ name: "list_recipes", input: {}, output: { recipes: { slug: string; description: string }[] } }
{ name: "get_recipe", input: { slug: string }, output: Recipe }Enumerate the recipe catalog (auth-form, settings-page, command-palette, …) or fetch one in full with its ordered install steps and post-install checklist.
// → list_recipes()
// → { recipes: [{ slug: "auth-form", ... }, { slug: "settings-page", ... }, ...] }resolve_spec / verify_checklist
{ name: "resolve_spec", input: { brief: string }, output: { components: string[]; recipes: string[]; rationale: string } }
{ name: "verify_checklist", input: { installed: string[] }, output: { missingPeers: string[]; ok: boolean } }`resolve_spec` turns a natural-language brief into a ranked component shortlist. `verify_checklist` cross-checks the agent's installed list against the registry's internal-dependency graph.
// → resolve_spec({ brief: "settings page with profile, billing, notifications" })
// → { components: ["tabs", "card", "input", ...], recipes: ["settings-page"], rationale: "..." }Workflows
Wire the server into Claude Code
Drop the snippet into `.claude/settings.json` (project) or `~/.claude/settings.json` (global). The next Claude session picks up the tools.
{
"mcpServers": {
"hex-ui": {
"command": "npx",
"args": ["@hex-core/mcp"]
}
}
}Wire the server into Cursor
Cursor reads `.cursor/mcp.json` at the project root.
{
"mcpServers": {
"hex-ui": {
"command": "npx",
"args": ["@hex-core/mcp"]
}
}
}Skip the transport — call buildAppContext directly
If you're inside a Server Component or a generator script and don't need the tool-call overhead, depend on `@hex-core/payload` instead. Same output, no stdio handshake.
import { buildAppContext, loadRegistryItem } from "@hex-core/payload";
import { defaultTheme } from "@hex-core/tokens";
const components = ["button", "card"].map((slug) => ({
slug,
item: loadRegistryItem(slug),
}));
const markdown = buildAppContext({
theme: { requested: "default", resolved: defaultTheme },
components,
});Compatibility
- Requires Node.js 20.9+ on the client side (whatever spawns the server). The bundled registry travels with the tarball, so the server boots without network access.
- Bin name: `hex-ui-mcp`. Most MCP clients invoke via `npx @hex-core/mcp` rather than the bin directly.
- All tool I/O is Zod-validated with `additionalProperties: false`. Invalid input throws structured errors back to the client.
- Depends on `@modelcontextprotocol/sdk@^1.12.0`, `@hex-core/payload@^0.2.0`, `@hex-core/registry@^0.2.1`.
See also
Verified against @hex-core/components@1.12.0 · @hex-core/tokens@1.3.6 · @hex-core/themes@0.2.2 · @hex-core/registry@0.5.1 · @hex-core/payload@0.3.0