{
  "name": "a2uicatalog",
  "displayName": "A2UI Atomic Catalog",
  "description": "474 typed UI atoms an agent composes into real rendered interfaces — charts, gauges, steppers, dashboards — across web, Google Meet, Apps Script, Google Chat and MCP Apps hosts. The agent names a component from a fixed vocabulary; a renderer that already knows it draws it, so no HTML is generated by the model.",
  "version": "1.0.0",
  "serverUrl": "https://a2uicatalog.ai/mcp",
  "transport": "streamable-http",
  "authentication": {
    "type": "none",
    "required": false
  },
  "icon": "https://a2uicatalog.ai/avatar/a2ui-chat-app.png",
  "documentation": "https://a2uicatalog.ai/llms.txt",
  "tools": [
    {
      "name": "list_catalogs",
      "description": "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."
    },
    {
      "name": "get_catalog",
      "description": "Return one catalog's atoms (type + one-line description) so you know its vocabulary."
    },
    {
      "name": "get_atom_schema",
      "description": "Return the PROP SHAPE (field names + what each field takes) for named atoms. get_catalog tells you an atom EXISTS; this tells you how to fill it. Call this before authoring any atom you have not used before — guessing prop names is the single most common cause of an atom rendering empty or wrong. Accepts several types at once, so a…"
    },
    {
      "name": "required_catalogs",
      "description": "Given an A2UI payload, return the resolvable catalog URIs it needs (deterministic — pure function of the atoms)."
    },
    {
      "name": "build_multi_page_surface",
      "description": "Build 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…"
    },
    {
      "name": "make_surface_url",
      "description": "Render 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.\n\nNEVER hand-write your own gzip/base64 encoding for the ?p= URL, in ANY language…"
    },
    {
      "name": "preview_url",
      "description": "Quick 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…"
    },
    {
      "name": "render_surface",
      "description": "Render 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…"
    },
    {
      "name": "render_ping",
      "description": "Diagnostic: 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."
    },
    {
      "name": "distill_document",
      "description": "Compile 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…"
    },
    {
      "name": "publish_url",
      "description": "STORES 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…"
    },
    {
      "name": "unpublish_url",
      "description": "Delete a published short link before its TTL using the delete_token returned by publish_url."
    },
    {
      "name": "emit_deployment",
      "description": "🎓 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."
    },
    {
      "name": "emit_training_runbook",
      "description": "Build 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…"
    },
    {
      "name": "emit_runbook_surface",
      "description": "Stamp 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…"
    },
    {
      "name": "describe_playbook",
      "description": "Explain a playbook to a HUMAN as a rendered surface: the frame it reads against, the lenses available, and the questions it will ask them. Compiled from the runbook declaration, so it costs nothing and cannot drift from what the stamper enforces. This is NOT emit_runbook_surface discovery — that returns a contract addressed to YOU. Use…"
    },
    {
      "name": "open_workspace",
      "description": "Open the A2UI Workspace — a rendered surface that IS the demo: each tool is introduced by the scenario it answers, then wired to run, then shows what it saved. This tool RENDERS ITSELF: its result carries the view, so call it alone and show the result — do NOT pass it on to render_surface, and do not describe the payload in prose. Call…"
    },
    {
      "name": "get_profile",
      "description": "Read the signed-in reader's saved profile and recent history. Call this BEFORE asking a runbook's `elicit` questions: if a domain or default lens is already saved, CONFIRM it (\"reading as: a2ui, generative ui — change?\") instead of asking from scratch. Returns available:false on the public endpoint, where there is no one to have a…"
    },
    {
      "name": "save_profile",
      "description": "Update the signed-in reader's profile. Only the keys you pass change; pass null to clear one. Save what the reader TOLD you, never what you inferred from one article — a profile that drifts on every reading is worse than no profile, because they stop being able to predict what it will do."
    },
    {
      "name": "save_reading",
      "description": "Record a stamped surface in the reader's history so it can be compared and reopened later. Call it AFTER emit_runbook_surface, and PASS ITS `payload` — that stores the reading itself rather than a link to it. Silently no-ops when nobody is signed in."
    },
    {
      "name": "export_reading",
      "description": "Export a kept reading as something that outlives this connector. format \"html\" returns ONE self-contained file — styles inlined, no network, opens in any browser years from now with nothing installed. \"url\" rebuilds a link against any renderer (yours by preference). \"surface\" returns the payload for repainting in place. \"json\" returns…"
    },
    {
      "name": "render_reading_to_slack",
      "description": "Post a kept reading into Slack as real, native Block Kit — the continuity proof: generate here, save it, and the SAME content reopens in Slack, not a link back to a renderer. Requires the caller's Slack account to already be linked (`/a2ui link` in Slack) and only works on an authenticated connection — it posts to a real workspace using…"
    },
    {
      "name": "list_readings",
      "description": "The reader's recent stamped surfaces, newest first — what makes \"compare this to my last three teardowns\" answerable at all. Optionally filter to one runbook. Returns available:false when nobody is signed in."
    },
    {
      "name": "delete_reading",
      "description": "Permanently remove one or more of the reader's saved readings from their History. Takes an array so the Workspace's multi-select can delete a batch in one call rather than one round trip per row. Ids that don't exist (or belong to someone else's history) are silently skipped — the response's `deleted` count says how many rows actually…"
    },
    {
      "name": "unlink_slack_account",
      "description": "Revoke one or more Slack accounts' link to this reader's store, from the Workspace side (the reverse of the Slack-side `/a2ui unlink` command — see slack-compiler/DESIGN-identity.md, \"many Slack -> one sub\"). Removes that account's ability to post via render_reading_to_slack or resolve to this reader; everything else about the reader's…"
    },
    {
      "name": "wall_calc",
      "description": "Compute a coursed block/brick wall specification — course and unit counts, weight, cost, mortar bags, a build-time curve across 1-6 builders, and load-bearing/height advisories. Pure arithmetic, no model call: a native-catalogue rebuild of the Gemini Enterprise \"Wall Builder\" demo, kept byte-for-byte correct against that original's…"
    },
    {
      "name": "whoami",
      "description": "Report who this connection is authenticated as. Answers two SEPARATE questions that are easy to conflate: which APPLICATION is connected (the OAuth client), and which HUMAN authorised it (the signed-in account, when the endpoint is one that can know). The public endpoint is anonymous by design and will say so — that is not an error, it…"
    },
    {
      "name": "identify_model",
      "description": "CALL 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…"
    }
  ],
  "toolAvailabilityNotes": "All 28 tools listed are served to most callers. Callers that declare their model via identify_model as 'haiku' are instead served a curated 8-of-28 subset (judgment-heavy tools like sizing/pagination removed) — currently excluded for that tier: delete_reading, describe_playbook, distill_document, emit_deployment, export_reading, get_atom_schema, get_profile, list_readings, make_surface_url, open_workspace, preview_url, publish_url, render_ping, render_reading_to_slack, save_profile, save_reading, unlink_slack_account, unpublish_url, wall_calc, whoami. Call identify_model first to get the tool set your model can reliably use."
}
