@hex-core/mcp

Stdio MCP server: emit_app_context, emit_figma_tokens, resolve_spec, and more.

Install

Version 0.4.2Tool / dlx invocation
bash
pnpm dlx @hex-core/mcp

What 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

ts
{
	name: "search_components",
	input: { query: string; limit?: number },
	output: { results: { slug: string; score: number; matchedOn: string[] }[] }
}

Fuzzy search across component names, descriptions, tags, and AI hints. Higher score = better match. Agents call this first when picking a primitive.

ts
// agent prompt: "find me a confirmation dialog"
// → search_components({ query: "confirmation dialog" })
// → { results: [{ slug: "dialog", score: 0.94, ... }, { slug: "alert-dialog", score: 0.91, ... }] }

get_component / get_component_schema

ts
{
	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.

ts
// agent has already added the button — only needs the schema
// → get_component_schema({ slug: "button" })

emit_app_context

ts
{
	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.

ts
// One call powers the studio's /copy page workflow:
// → emit_app_context({
//     theme: "default",
//     components: ["button", "card", "input"],
//     density: "comfortable",
//   })

emit_figma_tokens

ts
{
	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.

ts
// → emit_figma_tokens({ theme: "midnight" })
// → { content: [{ type: "text", text: '{"$schema":...}' }] }

list_recipes / get_recipe

ts
{ 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.

ts
// → list_recipes()
// → { recipes: [{ slug: "auth-form", ... }, { slug: "settings-page", ... }, ...] }

resolve_spec / verify_checklist

ts
{ 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.

ts
// → 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.

json
{
	"mcpServers": {
		"hex-ui": {
			"command": "npx",
			"args": ["@hex-core/mcp"]
		}
	}
}

Wire the server into Cursor

Cursor reads `.cursor/mcp.json` at the project root.

json
{
	"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.

tsx
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