a2uicatalog

A2UI Atomic Catalog Real rendered UI in the conversation — charts, gauges, dashboards, study apps — without the model writing a single line of HTML.

Community: Submitted by a user or imported; check the owner before granting accessOnlineNo sign-inGlobalFreeCan modify data

What it can do

  • List Catalogs: List every A2UI catalog with a when-to-use, so you can pick the extension catalogs a surface needs. The base catalog (a2ui-atoms-v1) is always resolved.
  • Get Catalog: Return one catalog's atoms (type + one-line description) so you know its vocabulary.
  • Required Catalogs: Given an A2UI payload, return the resolvable catalog URIs it needs (deterministic — pure function of the atoms).

What data it sees

Do you need an account

No: the server works without sign-in

A2UI Atomic Catalog

Real rendered UI in the conversation — charts, gauges, dashboards, study apps — without the model writing a single line of HTML.

The agent names a component from a fixed vocabulary of 474 typed atoms. A renderer that already knows that component draws it. So a hallucinated atom is a parse error, not a broken screen — the failure surfaces before anything reaches the user.

No signup, no API key, no configuration. Add the URL and start.

https://a2uicatalog.ai/mcp

Try it

Using the A2UI catalog, render a stat_card with value "1,234", label "Daily users", delta "+12%".

Build me a full-screen revision app for the French Brevet — subject tabs for Maths, Français and Histoire-Géo, with flashcards and a timed drill in each.

Show a live ATC radar for Toulouse with simulated traffic and the real LFBO weather.

The second one is a single tool call: emit_runbook_surface stamps your content through a pre-authored composition, so the agent supplies content and makes zero layout decisions. The third pulls live METAR through a declared data proxy.

One payload, many surfaces

Every atom declares where it works, where it degrades, and where it genuinely cannot go — and those declarations are enforced, not documentation:

works_on renders fully
degraded_on renders with something lost — an animation frozen, an ordered list instead of a stepper
incompatible_on cannot do what it is designed to do there, and says so instead of pretending

A quiz_set you cannot answer is not a degraded quiz, it is not a quiz. The catalogue refuses rather than shipping something that looks right and isn't.

Surfaces: web · MCP Apps · Google Apps Script · Google Meet · Google Chat · PDF · email

Interactive UI, not screenshots

Implements MCP Apps (SEP-1865)ui:// resources over the standard ui/* JSON-RPC bridge. Verified rendering full-screen in both Claude and ChatGPT from an identical payload, which is the point: the vocabulary is the product, the host is a detail.

15 tools

Composelist_catalogs, get_catalog, required_catalogs, distill_document Renderrender_surface, render_ping, preview_url, make_surface_url, build_multi_page_surface Runbooksemit_runbook_surface, emit_training_runbook (pre-authored compositions; you supply content only) Shipemit_deployment, publish_url, unpublish_url Setupidentify_model (capability-matched guidance; optional, never a precondition)

Without MCP at all

The vocabulary stands alone. No client, no connector, no account:

curl -X POST https://a2uicatalog.ai/api/render \
  -H 'Content-Type: application/json' \
  -d '{"blocks":[{"type":"stat_card","value":"1,234","label":"Daily users"}]}'

npx -p @a2uicatalog/mcp a2ui render page.json --surface email

OpenAPI · spec.json · llms.txt · ARD catalog — all public, all unauthenticated.

Free

No paid tier, because there is nothing to upgrade to. MIT licensed, renderers in the public repo — anything you hit a limit on here, you can run yourself. Full limits: https://a2uicatalog.ai/pricing.md


Docs · OpenAPI · Source · MIT

Server tool list (15)

Raw names from tools/list. Only developers need these.

list_catalogsList every A2UI catalog with a when-to-use, so you can pick the extension catalogs a surface needs. The base catalog (a2ui-atoms-v1) is always resolved.
get_catalogReturn one catalog's atoms (type + one-line description) so you know its vocabulary.
required_catalogsGiven an A2UI payload, return the resolvable catalog URIs it needs (deterministic — pure function of the atoms).
build_multi_page_surfaceBuild a multi-section A2UI app from raw title+content sections — you never estimate size or decide how to split; each section becomes its own independently-encoded page (no shared hub, so per-page size never grows with page count — genuinely unlimited sections). Returns the first page's `url` plus a `pages` array ([{heading, url}]) for every section — present that list to the user yourself (e.g. numbered links); pages do not cross-link to each other. Prefer this over make_surface_url for multi-section content.
make_surface_urlRender an A2UI payload in the CALLER'S OWN environment. Pass renderer_url (your deployed renderer /exec) and get a live URL + the catalogs it declares. Omit renderer_url to get the encoded fragment + BYO guidance. We host nothing and never see your content. NEVER hand-write your own gzip/base64 encoding for the ?p= URL, in ANY language, even as a "just this once" fallback. This is the single most common cause of "could not decompress gzip" — a self-written encoder with one wrong flag (wrong wbits, standard vs. urlsafe base64, un-stripped padding) produces a broken URL at ANY size, not just large ones. Always call this tool again — never substitute your own implementation. SIZING IS AUTOMATIC — you do not need to estimate, count characters, or decide whether to split. Call this tool ONCE with your FULL, unsplit payload. If it fits, you get back `url` (and nothing else to do). If it does not fit the real size ceiling, the tool SPLITS IT FOR YOU server-side (at natural heading boundaries) and returns `auto_split: true` plus a `pages` array of independent URLs — present that list to the user (e.g. as numbered links) instead of the single `url`. Never pre-split your content before the first call; always send everything in one call and let the response tell you what happened. GRADUATE substantial surfaces with emit_deployment instead (no size limit at all) when you want a standing app rather than a shareable link. IF A RENDER CHECK REPORTS "could not decompress gzip" / "Render error" / "invalid distance too far back" on a URL this tool returned: STOP. Do NOT call this tool again with the SAME unchanged payload — re-call it with the SAME payload once to confirm, and if it still fails, use emit_deployment instead. Never fall back to a hand-written encoding script.
preview_urlQuick DEMO render on the public renderer (ephemeral, nothing stored). Limited to 2 runs per client, then deploy your own renderer and use make_surface_url. Onboarding only — not the workflow. DATA-IN-URL: keep payloads SMALL (URL < ~2000 chars); large payloads make long URLs that get truncated (→ render errors). For substantial content GRADUATE with emit_deployment instead — no size limit.
render_surfaceRender an A2UI payload INSIDE the chat as a live interactive view (MCP Apps hosts only — on other hosts this returns the payload as text). No URL, no size ceiling, nothing stored: the payload travels in the tool result and renders in the a2ui_catalog_view. Accepts the blocks dialect or a v1.0 createSurface envelope (templates + dataModel decode in the view). Prefer this over preview_url when the host supports MCP Apps.
render_pingDiagnostic: render a tiny test view in-chat (MCP Apps hosts only). Proves view mounting works independent of the full catalog renderer. Echoes back whatever payload you pass.
distill_documentCompile a training.md / roadmap markdown document into a live interactive A2UI app — DETERMINISTIC parser, no model involved. Fact sheet: input is MARKDOWN following the training-md contract (frontmatter id/domain/name/source/license + a # Steps section); the text transits to the catalog's stateless parser service for the duration of the call and is NOT stored; lint errors come back as a structured report (fix and re-call). On success the result IS the compiled surface — MCP Apps hosts paint it in the view; other hosts can pass the returned payload to preview_url for a link.
publish_urlSTORES the payload server-side and returns a SHORT shareable link. Opt-in only: requires acknowledge_storage=true — confirm with the user first that they accept operator-hosted storage (ONE WEEK retention on the public tier, revocable earlier via the returned delete_token; anyone with the link can view). target "play" (default) renders in the a2uicatalog playground by reference (no URL size ceiling); target "gas" makes the short link redirect to the public Apps Script renderer. For storage in the USER's own account use emit_deployment; for nothing-stored links use preview_url.
unpublish_urlDelete a published short link before its TTL using the delete_token returned by publish_url.
emit_deployment🎓 GRADUATE a tested surface into a dedicated, DEPLOYER-ONLY standing app in YOUR OWN Google Apps Script account. Returns a deterministic recipe (config files + clasp ops + least-privilege scopes derived from the atoms + verify) — you run it with your own clasp; nothing runs on our side, we hold no creds.
emit_training_runbookBuild a multi-lesson training/course surface as ONE properly-linked page with real in-app tab navigation between lessons — prefer this over build_multi_page_surface for training/course content specifically: that tool produces N independent pages with NO links between them (you must present the list yourself); this tool produces one page where lessons are real, clickable tabs. Zero sizing/estimation judgment required — give it your lessons, it handles composition and navigation.
emit_runbook_surfaceStamp your content through a DECLARED runbook — a pre-authored, judgment-free surface composition. You supply content only; the runbook supplies the composition (which atoms, how arranged, navigation). DISCOVERY: call with runbook_id only (no content) to get that runbook's input_contract + parsing_guide — shape your source data to the contract (parsing is your job as the consumer), then call again with `content`. Available stampable runbooks: learning_hub (curriculum/revision study app — subject tabs, slide pills, timeline/drill/flashcards/quiz/takeaways/method interactions per slide, the full rich hub UI). Prefer this over emit_training_runbook for study/curriculum content — much richer output, still zero composition decisions.
identify_modelCALL THIS FIRST, before any other a2ui-catalog tool, once per session. Declares your own model identity so this response can hand you capability-matched guidance up front — some models need simpler, judgment-free tools; skipping this just means you default to the full toolkit, including tools that require sizing/pagination judgment calls. HOW TO ANSWER — do not guess: - Copy your model name EXACTLY as stated in your own system prompt or developer context (look for phrasing like "you are powered by the model named X" or similar). Do NOT infer it from your training cutoff, your own behavior, or general capability. - Examples of valid values: "claude-haiku-4-5", "claude-sonnet-5", "claude-opus-4-8", "gemini-2.0-flash", "gpt-4o". Partial names are fine ("haiku", "sonnet"). - If your model name is genuinely not stated anywhere in your context, pass "unknown" — do NOT guess a plausible-sounding value. A wrong report is worse than no report: it can hand you tools you cannot reliably operate.