# MCP actions — full catalog

The live catalog is always one MCP call away, and the codebase is the source of truth. This section explains how to navigate it, not enumerate every entry (the registry sits at ~130 actions today and adds / renames are continuous — recent additions include `dsp.compile` for FX-shape validation in the `.dsp` editor and `builder.kind.describe` now surfaces per-kind `imports` for the libfaust-wasm bundled libs).

## The discovery dance

The pattern every MCP client uses (including the in-app Assistant) to find what it needs — say, to add reverb:

```
1. palette.list     { search: "reverb" }                     → candidate actions
2. palette.describe { action_ids: ["master.fx.slot.add"] }   → input_schema + examples
3. palette.run      { action_id: "master.fx.slot.add", input: { … } }
```

For a quick *"what categories exist"*:

```
palette.list {}                              ← returns category summaries
```

For everything:

```
palette.list { all: true }                   ← full catalog
```

## Categories (today)

Actions cluster by category. The current set:

| Category | Roughly |
|---|---|
| **DSP** | Builder graph ops (~24 actions, hard-required `module_id`) + Faust DSP ops (`dsp.run`, `DSP.param.*`) |
| **TRANSPORT** | `transport.play / stop / bpm.set` |
| **MIDI** | Sequencer (~30 actions: tracks, slots, scenes, steps, key, progressions) + Keyboard (`keyboard.note.on/off`, `.channel.set`, `.octave.set`, `.hold.set`, `.notes.clear`, `.state`) + `midi.note.play` / `midi.sequence.play` / `midi.sequence.stop` + ports & diagnostics (`midi.ports.list`, `midi.monitor.get`) + **`midi.panic`** |
| **AUDIO** | Master volume / softclip / clip clear, audio device select, Master FX slots, Recorder + recordings, MixerTracks (`mixer.tracks.*` — set / create / delete / rename / reorder / attach_source / fx.add·remove·set) + legacy per-module strip params (`mixer.set` / `mixer.clear`) |
| **ROUTING** | Connection CRUD (`routing.list / connect / disconnect / set`), Source / Sink listing |
| **MODULATION** | LFO sources, mod-edge connect/disconnect, `modulation.base.set` |
| **HUB** | Search, install, publish, version upload, fork, star, item update / delete, account.delete (safety-railed) |
| **KB** | Search, doc.get, section list / get, scope set / clear, pack uninstall, reindex |
| **PROJECT** | List, current, switch, close, export, import, list project files (`project.files`), rename a project file (`project.file.rename`), delete a project file (`project.file.delete`) |
| **FILE** | Samples (`samples.import / list / get / remove`), lib mount / list, library list, editor source set / get / save |
| **VIEW** | Toggle rail / master / minimap panel |
| **APPEARANCE** | Theme set (Dark / Light / Cyberpunk / Auto) |
| **SYSTEM** | `system.state` snapshot (master / mixer / mixer_tracks / transport / chat / kb / auth / routing / midi-consumers / hub) |
| **DEBUG** | `logs.get`, `activity.recent` |

For a current count + breakdown:

```yaml
actions:
  - action_id: palette.list
    input: {}
    save_as: cats
    label: "▶ Get the per-category counts"
```

## Hot-path tools vs `palette.run`

The MCP transport publishes a curated subset (~22) of the highest-frequency actions as **hot-path tools** — they appear in the MCP client's tool list with their full schemas. The other ~108 actions live behind the `palette.run` meta-action.

The split exists because of the **MCP 128-tool soft cap** — Anthropic's API rejects more than 128 published tools in a single context. Current publishing decision: ~22 hot-path tools + `palette.run` + `palette.list` + `palette.describe` = 25 published, well under the cap.

Which actions are hot-path varies by build; the canonical list is the one the MCP client sees on connect.

## Hard-required `module_id` rule

Every DSP-Builder action requires `module_id` as a first-class input. No fallback to "the active Builder." See **FaustWave — AI Assistant** § 3 *Hard-required `module_id` on DSP-Builder actions* for the rationale and the TOCTOU race it closes.

The sequencer has a documented exception — `instance_id` is optional with active-fallback. Grandfathered as a lower-frequency surface.

## Dual-path vs mcpRun-only

Some actions have a `run` handler (the human-callable / Command-Palette path) plus an `mcpRun` handler (the AI-callable / MCP path). Some are **mcpRun-only** — the registry doesn't surface them in the Palette because they only make sense from the AI side.

Examples:

- **Dual-path**: `transport.play` (UI button + MCP), `recorder.toggle` (Topbar Widget + MCP), most user-facing toggles.
- **mcpRun-only**: `builder.graph.get` (no UI surface for "show me the graph as JSON" — that's the canvas), `kb.search` (the assistant's grounding tool, not a user gesture).

## Friendly error strings

Most actions return strings (success or error) rather than throwing. The Activity log shows the string in the `result` field for both — handler-returned error strings still count as `outcome: completed`. Real exceptions are `outcome: failed` with the message in `error`.

This is the "AI-friendly errors" convention — the model can read the string back, self-correct, retry. Examples:

- `"Module id is required. Available Builders: builder-abc, builder-xyz"`
- `"dsp.polyphonic.set needs a non-negative integer voices count, got string: 'eight'"`
- `"Theme set to cyberpunk."`

## Where the real catalog lives

For a precise + current listing, query the registry directly:

```
palette.list { all: true }
```

It returns id + title + category + description for every registered action. Pipe through `palette.describe { action_ids: [...] }` for the input schemas.

The codebase organisation mirrors the categories — actions live in `packages/<extension>/src/commands/*.ts` or `lib/commands.ts`. Each `buildXxxCommands(api)` returns the `ActionDef[]` for that extension. The shell aggregates them at extension activation.

## Where to go from here

- **FaustWave — AI Assistant** § 2 — the Command Palette (human surface to the same registry).
- **FaustWave — AI Assistant** § 1 — the in-app AI surface.
- **FaustWave — AI Assistant** § 3 — the external-client (MCP) surface.
