An MCP server that lets Claude render interactive A2UI v0.9 UIs in a browser. Claude generates structured JSON via the send_a2ui tool, the server validates it against the A2UI schema, and pushes it to a React renderer over SSE. User interactions flow back to Claude through MCP channels, enabling real-time bidirectional UI conversations.
Claude Code / Claude Desktop
|
| stdio (JSON-RPC)
v
MCP Server (@a2ui-claude/mcp-server)
|
|-- POST /action <---- React Client (@a2ui-claude/react-client)
|-- GET /events ----> (SSE stream of A2UI messages)
|
v
Channel notification back to Claude
MCP Server exposes a send_a2ui tool and A2UI schema resources. It validates messages with ajv, tracks surface state, and bridges between Claude (stdio) and the renderer (HTTP/SSE).
React Client renders A2UI surfaces using @a2ui/react and @a2ui/web_core. Built with Rsbuild, started automatically by the MCP server as a dev server.
- Node.js >= 24
- pnpm >= 10
# Clone and install
git clone https://github.com/PupilTong/a2ui-claude.git
cd a2ui-claude
pnpm install
# Build
pnpm build
# Add to Claude Code
claude mcp add --transport stdio a2ui-server -- \
node --enable-source-maps packages/mcp-server/dist/server.js
# Start Claude Code with channel support (required for user interactions)
claude --dangerously-load-development-channels server:a2ui-serverThe --dangerously-load-development-channels flag enables the MCP channel that delivers user actions (button clicks, input changes) back to Claude. Without it, Claude can render UIs but won't receive interactions.
Then ask Claude to create a UI:
"Show me a weather dashboard for Austin, TX"
Claude will call send_a2ui and the UI will render at http://localhost:5173.
a2ui-claude/
packages/
mcp-server/ # MCP server with A2UI tool, schema validation, SSE bridge
src/
server.ts # Main server: MCP tools, resources, HTTP endpoints
dev-server.ts # Programmatic Rsbuild dev server for the React client
validator.ts # ajv-based A2UI schema validation with error denoising
schema-loader.ts # Loads JSON schemas and examples
surface-state.ts # Tracks per-surface component and data model state
sse-bridge.ts # SSE client management and message broadcasting
bootstrap.ts # MCPB first-launch dependency installer
diagnose.ts # Diagnostic entry point for debugging
schemas/ # A2UI v0.9 JSON schemas and examples
manifest.json # MCPB packaging manifest
react-client/ # React-based A2UI renderer
src/
App.tsx # SSE connection, action handler, surface rendering
main.tsx # Entry point
# Watch mode (rebuild on change)
pnpm --filter @a2ui-claude/mcp-server dev
# Type check all packages
pnpm typecheck
# Pack as MCPB bundle (for Claude Desktop)
pnpm --filter @a2ui-claude/mcp-server pack:mcpbAdd to your project's .mcp.json:
{
"mcpServers": {
"a2ui-server": {
"command": "node",
"args": ["--enable-source-maps", "./packages/mcp-server/dist/server.js"],
"cwd": "/absolute/path/to/a2ui-claude"
}
}
}Or use the CLI:
claude mcp add --transport stdio a2ui-server -- \
node --enable-source-maps /absolute/path/to/a2ui-claude/packages/mcp-server/dist/server.jsImportant: Always launch Claude Code with channels enabled:
claude --dangerously-load-development-channels server:a2ui-server| Variable | Default | Description |
|---|---|---|
A2UI_HOST |
127.0.0.1 |
HTTP bridge bind address |
A2UI_PORT |
8789 |
HTTP bridge port |
The React client dev server runs on port 5173.
- Claude generates A2UI JSON via the
send_a2uitool -- an array of messages (createSurface, updateComponents, updateDataModel, deleteSurface) - Server validates the JSON against A2UI v0.9 schemas using ajv, fixing common LLM errors (trailing commas, markdown fences)
- Server pushes validated messages to the React client over SSE (
GET /events) - React client renders the UI using
@a2ui/reactcomponents - User actions (button clicks, input changes) are POSTed back to the server (
POST /action) - Server forwards actions to Claude as MCP channel notifications
- Claude responds by calling
send_a2uiagain to update the UI
The server can be packaged as a lightweight .mcpb bundle (~30KB) for distribution:
pnpm --filter @a2ui-claude/mcp-server pack:mcpb
# Output: packages/mcp-server/a2ui-server.mcpbThe bundle contains source code and package manifests but no node_modules. On first launch, the bootstrap script automatically installs dependencies via npm install.