@adia-ai/a2ui-mcp
v0.5.4
Published
AdiaUI A2UI MCP server. Exposes the compose engine over MCP with an engine selector for monolithic + zettel strategies.
Readme
@adia-ai/a2ui-mcp
MCP server wrapping @adia-ai/a2ui-compose. Exposes the generation
engine, component catalog, pattern library, validator, and training
feedback loop as stdio tools for Claude Desktop, Claude Code, and any
other MCP-speaking host.
Runtime only. Generation logic lives in
@adia-ai/a2ui-compose; UI atoms in@adia-ai/web-components; the A2UI protocol runtime (renderer, registry, streams, wiring) in@adia-ai/a2ui-runtime; corpus in@adia-ai/a2ui-corpus.
Install
npm install -g @adia-ai/a2ui-mcp # global — exposes the `adiaui-mcp` bin
# OR
npm install @adia-ai/a2ui-mcp # local — invoke via npxThe package ships an adiaui-mcp executable + a server.js entry point. Most MCP hosts (Claude Desktop, Claude Code) invoke the binary directly via command + args in their MCP config.
Quick start
adiaui-mcp # if globally installed
npx @adia-ai/a2ui-mcp # via npx
node packages/a2ui/mcp/server.js # from a local checkoutRegister with Claude Code (.claude/settings.json):
{
"mcpServers": {
"adia-ui": {
"command": "node",
"args": ["packages/a2ui/mcp/server.js"]
}
}
}API keys (at least one required for generate_ui):
export ANTHROPIC_API_KEY=sk-ant-…
export OPENAI_API_KEY=sk-…
export GEMINI_API_KEY=AIza…Tools
The server registers 24 tools. Argument schemas via Zod; shape is stable across the v0.3.x line.
See TOOLS.md for the full reference — tool names, descriptions, grouping, and source pointers. Quick map:
| Group | Tools |
|---|---|
| Generation | generate_ui |
| Discovery | get_component_map, lookup_component, lookup_chunk, get_traits, get_wiring_catalog |
| Retrieval | search_chunks, get_chunk, search_patterns, get_fragment, get_composition, get_graph, resolve_composition, zettel_stats |
| Intent + context | classify_intent, assemble_context |
| Validation + conversion | validate_schema, check_anti_patterns, convert_html |
| Feedback + evaluation | submit_feedback, get_quality_metrics, get_training_gaps, run_eval |
| Authoring | import_pattern |
Layout
gen-ui-mcp/
├── server.js MCP bootstrap — registers all 21 tools inline
├── scripts/ Standalone runners (smoke tests, eval diffs, visual validate)
│ ├── generate.mjs CLI: `node scripts/generate.mjs "pricing page"`
│ ├── eval-diff.mjs diff held-out run vs baseline
│ ├── eval-fix.mjs re-run failing eval intents
│ ├── dogfood-test.mjs 20-intent dogfood + avg-score gate
│ ├── multi-turn-test.mjs session iteration smoke
│ ├── smoke-engine-registry.mjs registry + reserved-name checks
│ ├── smoke-register-engine.mjs plugin engine registration
│ ├── smoke-zettel.mjs zettel-specific smoke (corpus + composer)
│ ├── smoke-synthesis.mjs fragment-synthesis path
│ ├── smoke-merged.mjs cross-engine merge check
│ ├── smoke-searchable-select.mjs known-good composition regression
│ ├── test-a2ui.mjs A2UI message validator unit tests
│ ├── test-evals.mjs evals harness wrapper
│ └── visual-validate.mjs Playwright render + Vision-LLM critique
├── tools/ (reserved; tool code currently inlined in server.js)
└── personas/ persona presets (vocabulary + style hints for adapters)CLI usage
# One-shot generation from a prompt
node packages/a2ui/mcp/scripts/generate.mjs "pricing page with 3 tiers"
# Run the held-out eval
node packages/a2ui/mcp/scripts/test-evals.mjs
# Full verification sweep (invoked by /verification-sweep slash command)
npm run smoke:engines && \
npm run smoke:register-engine && \
npm run test:a2ui && \
npm run eval:diff -- --engine zettelHow it fits together
┌─────────────┐ MCP stdio
│ Claude Code │◀─────────────────▶ server.js
└─────────────┘ │
├── @adia-ai/a2ui-compose (engines, validator, LLM bridge)
├── @adia-ai/a2ui-corpus (catalog, fragments, feedback)
└── @adia-ai/web-components (component schemas via .a2ui.json)On start, the server:
- Loads the component catalog (
@adia-ai/a2ui-corpus/catalog-a2ui_0_9.json) - Lazy-initializes the zettel corpus on first
generate_ui/zettel_*call - Resolves LLM adapter from env vars
- Registers tools + opens stdio transport
Gotchas
- Corpus load is noisy. The zettel composer prints stats to stderr on first invocation. Callers expecting silent MCP should swallow stderr.
- API keys must be set before the server starts. Changing env vars mid-session doesn't hot-reload adapters.
- Engine selector is internal. Don't pass
engine: 'mcp'— the generator picksmonolithicvszettelfrom intent + mode. Reserved names in the registry guard against accidental shadowing. - Validator score < 70 is still returned. Consumers should gate on
the
passedboolean or rawscore— the tool doesn't auto-retry. - Multi-turn state is per-process, in-memory, ephemeral. Both the
zettel
state-cache(keyed bystate_idfor refinement chains) and the zettelsession-store(keyed bysessionIdfor follow-up iteration) live in the MCP process's heap. Restarting the server drops every multi-turn chain in flight. Consumers that need durability across restarts should checkpoint the canvas to their own store between turns and passcurrentCanvason resume rather than relying onexecutionId/sessionId. A future phase may add file-backed persistence as opt-in viaA2UI_STATE_CACHE_PATH; not implemented today. session-storeandstate-cacheoverlap intentionally. Different lifecycles (MCP-call multi-turn vs engine-internal stable-id resolution), different APIs, kept separate by design — seestate-cache.jsandsession-store.jsfor the contracts.
Evals + regression floors
The server enforces the same thresholds as the rest of the pipeline:
test:a2ui— 19/19 green (+1 skipped OK)smoke:register-engine— 11/11 greeneval:diff -- --engine zettel— coverage 100%, avgScore ≥ 88- Dogfood — 20/20 intents at avg ≥ 95
See repo-root AGENTS.md for the full verification sweep.
License
MIT
