# MCP tool reference, the a2ui server's tool surface

**Schema SoT is `packages/gen-ui/mcp/TOOLS.md` (the `gen-ui` section, 31 tools),
generated alongside `server.js`, read it for input/output shapes; never
restate schemas here (they drift).** Tools register in
`packages/gen-ui/mcp/gen-ui/server.js` +
`packages/gen-ui/mcp/gen-ui/tools/{corpus,discovery,feedback,refine,synthesis,
validation,zettel}.js`. Any tool change updates TOOLS.md in the same commit.

## Stability rule (load-bearing)

Changing an existing tool's input/output contract is a breaking change for
every external MCP client. The full producer-side rule, dry-run schema diff,
explicit operator proceed, `@adia-ai/mcp` version bump, factory pin
update, and the consumer-load-bearing subset whose contracts are
frozen-unless-versioned, lives in
[../../../references/contracts/a2ui-mcp-surface.md](../../../references/contracts/a2ui-mcp-surface.md).
Adding tools is additive and safe; removing or renaming is breaking.

## Tool map by job

| Group | Tools | Registered in |
| --- | --- | --- |
| Generation | `generate_ui`, `refine_ui` (monolithic repair) | `synthesis.js`, `refine.js` |
| Chunk synthesis + multi-turn | `compose_from_chunks`, `refine_composition`, `get_state`, `report_issue` | `synthesis.js` |
| Chunk retrieval | `search_chunks`, `get_chunk`, `lookup_chunk` | `corpus.js` |
| Catalog inspection | `lookup_component`, `get_component_map`, `get_traits`, `get_wiring_catalog`, `server_status` | `discovery.js` |
| Composition/zettel inspection | `search_patterns`, `get_fragment`, `get_composition`, `get_graph`, `resolve_composition`, `zettel_stats` | `zettel.js` |
| Intent + context | `classify_intent`, `assemble_context` | `discovery.js` |
| Validation + conversion | `validate_schema`, `check_anti_patterns`, `convert_html` | `validation.js` |
| Feedback + evaluation | `submit_feedback`, `get_quality_metrics`, `get_training_gaps`, `run_eval` | `feedback.js` |
| Authoring (write path) | `import_pattern` | `zettel.js` |

Selection heuristics:

- **Fresh creation from a known page-shape** → `compose_from_chunks`
  (retrieval-first); generic/novel intent → `generate_ui`.
- **Modifying an existing surface** ("change", "add to", "remove") →
  `refine_composition` with the prior `state_id`, never re-generate.
- **Catalog literacy** → `lookup_component` / `get_component_map`; the MCP is
  the live catalog, don't memorize component names.
- **Trust gate on any LLM-emitted A2UI** → `validate_schema` then
  `check_anti_patterns` on the rendered HTML.

## Local wrappers (all verified in `scripts/`)

- `scripts/mcp-pipeline.cjs "<intent>"`, full pipeline one-shot with a
  combined report.
- `scripts/mcp-call.cjs <tool> '<json-args>'`, single-tool call for stepping
  through / inspecting intermediates.
- `scripts/a2ui-to-html.cjs [file|stdin]`, renders A2UI message arrays to
  HTML between `validate_schema` and `check_anti_patterns`.

## When adding a tool

1. Register in the matching `mcp/tools/<group>.js` file (zod input schema +
   description that names its trigger phrases and its non-goals).
2. Update `TOOLS.md` in the same commit (generated with the server build, `npm run build:mcp-server`).
3. Verify: `npm run mcp:smoke`, then a real-client round-trip.
