← WebMCP Directory

Tool tree

bananalabs-sable.vercel.app

Media & PersonalTools verified
Website
BananaLabs DJ
Explore capabilities
    get_sessionAnswer

    Compact live snapshot: decks, mixer, arrangement, proposal pending. Use before editing.

    View tool JSON
    {
      "name": "get_session",
      "kind": "answer",
      "impl": "imperative",
      "description": "Compact live snapshot: decks, mixer, arrangement, proposal pending. Use before editing.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      }
    }
    get_trackAnswer

    Full track analysis: BPM, Camelot key, sections, energy curve, vocal regions, beat/downbeat samples, waveform peaks, lyrics preview. No mix-point suggestions — choose bars yourself.

    View tool JSON
    {
      "name": "get_track",
      "kind": "answer",
      "impl": "imperative",
      "description": "Full track analysis: BPM, Camelot key, sections, energy curve, vocal regions, beat/downbeat samples, waveform peaks, lyrics preview. No mix-point suggestions — choose bars yourself.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "track_id": {
            "type": "string"
          },
          "detail": {
            "type": "string",
            "enum": [
              "full",
              "compact"
            ]
          }
        },
        "required": [
          "track_id"
        ],
        "additionalProperties": false
      }
    }
    search_libraryAnswer

    List/filter library tracks by title/artist, BPM range, or Camelot key (e.g. 8A). Paginated: limit (default 25, max 100) + offset; response includes total and has_more — keep paging until has_more is false instead of guessing the rest.

    View tool JSON
    {
      "name": "search_library",
      "kind": "answer",
      "impl": "imperative",
      "description": "List/filter library tracks by title/artist, BPM range, or Camelot key (e.g. 8A). Paginated: limit (default 25, max 100) + offset; response includes total and has_more — keep paging until has_more is false instead of guessing the rest.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string"
          },
          "bpm_min": {
            "type": "number"
          },
          "bpm_max": {
            "type": "number"
          },
          "key": {
            "type": "string"
          },
          "limit": {
            "type": "number"
          },
          "offset": {
            "type": "number"
          }
        },
        "additionalProperties": false
      }
    }
    suggest_compatibleAnswer

    Ranks other tracks by BPM/key/energy distance to a seed. Metrics only — you choose the set.

    View tool JSON
    {
      "name": "suggest_compatible",
      "kind": "answer",
      "impl": "imperative",
      "description": "Ranks other tracks by BPM/key/energy distance to a seed. Metrics only — you choose the set.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "track_id": {
            "type": "string"
          },
          "bpm_min": {
            "type": "number"
          },
          "bpm_max": {
            "type": "number"
          }
        },
        "required": [
          "track_id"
        ],
        "additionalProperties": false
      }
    }
    get_set_qualityAnswer

    Returns numeric BPM/key/energy metrics plus craft notes from verify_set. Prefer verify_set as the gate before propose.

    View tool JSON
    {
      "name": "get_set_quality",
      "kind": "answer",
      "impl": "imperative",
      "description": "Returns numeric BPM/key/energy metrics plus craft notes from verify_set. Prefer verify_set as the gate before propose.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string",
            "enum": [
              "arrangement",
              "proposal"
            ]
          }
        },
        "additionalProperties": false
      }
    }
    get_dj_playbookAnswer

    The rulebook: chop formula first (INTRO→UP+→DROP→[DOWN]→DROP+→OUTRO), then what each recipe compiles, verify error codes, Camelot/BPM refs. Read it once before your first set.

    View tool JSON
    {
      "name": "get_dj_playbook",
      "kind": "answer",
      "impl": "imperative",
      "description": "The rulebook: chop formula first (INTRO→UP+→DROP→[DOWN]→DROP+→OUTRO), then what each recipe compiles, verify error codes, Camelot/BPM refs. Read it once before your first set.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "topic": {
            "type": "string",
            "enum": [
              "all",
              "recipes",
              "verify"
            ]
          }
        },
        "additionalProperties": false
      }
    }
    get_mix_pointsAnswer

    Phrase candidates: peak drop, 8/16 before that drop, vocal_end, safe_leave, breakdown, mix-in/out, grid. Prefer phraseBars. Leave on safe_leave, not mid-line.

    View tool JSON
    {
      "name": "get_mix_points",
      "kind": "answer",
      "impl": "imperative",
      "description": "Phrase candidates: peak drop, 8/16 before that drop, vocal_end, safe_leave, breakdown, mix-in/out, grid. Prefer phraseBars. Leave on safe_leave, not mid-line.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "track_id": {
            "type": "string"
          }
        },
        "required": [
          "track_id"
        ],
        "additionalProperties": false
      }
    }
    verify_setAction

    Craft gate — run before proposing/applying and after any rewrite. ready:true means no broken automation. Errors (must fix): double-bass on a blend, echo without FX, mid-vocal leave, key-unknown pad, overlap past the Camelot cap, |ΔBPM|>3 without a tempo lane, unknown transition type. echo_out / cut / backspin do not share a clock and do not need a tempo ramp. Warnings are observations — keep them if you meant it.

    View tool JSON
    {
      "name": "verify_set",
      "kind": "act",
      "impl": "imperative",
      "description": "Craft gate — run before proposing/applying and after any rewrite. ready:true means no broken automation. Errors (must fix): double-bass on a blend, echo without FX, mid-vocal leave, key-unknown pad, overlap past the Camelot cap, |ΔBPM|>3 without a tempo lane, unknown transition type. echo_out / cut / backspin do not share a clock and do not need a tempo ramp. Warnings are observations — keep them if you meant it.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string",
            "enum": [
              "arrangement",
              "proposal"
            ]
          }
        },
        "additionalProperties": false
      }
    }
    apply_transition_recipeAction

    Compile a join you chose on incoming entry (index≥1). tease_slam (the chop default) parks incoming at drop−bars so its build teases in filtered under the outgoing, rides the tempo lane across the window, then roll + throw and the slam on the 1. drop_swap parks incoming at drop−8 (the build), leaves after the vocal line, then peels. power_cut / backspin / air_cut park incoming on its drop. air_cut = suck-out, one bar of dead air, slam — no shared clock. echo_out = echo-throw leave (dry holds, delay fills, cut on the 1; incoming from its drop/heat, never bar 0, no tempo ramp). Never pad-blend two vocal leads; only half/double-time records still air-slam. The result echoes the parked trims and the compiled commit (commit_bars, commit_on_drop) — trust that echo over your own bar math.

    View tool JSON
    {
      "name": "apply_transition_recipe",
      "kind": "act",
      "impl": "imperative",
      "description": "Compile a join you chose on incoming entry (index≥1). tease_slam (the chop default) parks incoming at drop−bars so its build teases in filtered under the outgoing, rides the tempo lane across the window, then roll + throw and the slam on the 1. drop_swap parks incoming at drop−8 (the build), leaves after the vocal line, then peels. power_cut / backspin / air_cut park incoming on its drop. air_cut = suck-out, one bar of dead air, slam — no shared clock. echo_out = echo-throw leave (dry holds, delay fills, cut on the 1; incoming from its drop/heat, never bar 0, no tempo ramp). Never pad-blend two vocal leads; only half/double-time records still air-slam. The result echoes the parked trims and the compiled commit (commit_bars, commit_on_drop) — trust that echo over your own bar math.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "index": {
            "type": "number"
          },
          "recipe": {
            "type": "string",
            "enum": [
              "tease_slam",
              "drop_swap",
              "double_drop",
              "power_cut",
              "air_cut",
              "build_cut",
              "bass_swap",
              "eq_swap",
              "filter_sweep",
              "echo_out",
              "loop_out",
              "loop_roll",
              "backspin",
              "hook_layer",
              "half_bridge",
              "tempo_ride",
              "power_block"
            ]
          },
          "bars": {
            "type": "number"
          }
        },
        "required": [
          "index",
          "recipe"
        ],
        "additionalProperties": false
      }
    }
    get_crate_healthAnswer

    START HERE before composing a set. Cards carry MEASURED facts only: bpm, bpm_lane, key+confidence (a ? means untrusted), energy, brightness, drop/heat/hole/safe_leave, vocals, cue_before_drop_8/16. mood and genre are MusicBrainz or tag_track — never DSP. Roles are craft-only. Next step: prepare_set (chop formula by default).

    View tool JSON
    {
      "name": "get_crate_health",
      "kind": "answer",
      "impl": "imperative",
      "description": "START HERE before composing a set. Cards carry MEASURED facts only: bpm, bpm_lane, key+confidence (a ? means untrusted), energy, brightness, drop/heat/hole/safe_leave, vocals, cue_before_drop_8/16. mood and genre are MusicBrainz or tag_track — never DSP. Roles are craft-only. Next step: prepare_set (chop formula by default).",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      }
    }
    plan_set_arcAction

    Peak-first track order + mix windows + drop cues. Does not pick the join (1-bar cut placeholder). Optional apply=true stages set_propose.

    View tool JSON
    {
      "name": "plan_set_arc",
      "kind": "act",
      "impl": "imperative",
      "description": "Peak-first track order + mix windows + drop cues. Does not pick the join (1-bar cut placeholder). Optional apply=true stages set_propose.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "arc": {
            "type": "string",
            "enum": [
              "journey",
              "peak_time",
              "warm_up",
              "cool_down",
              "chill",
              "power_block"
            ]
          },
          "track_count": {
            "type": "number"
          },
          "apply": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      }
    }
    prepare_setAction

    Default action for 'make me a set'. Chop formula: INTRO→UP+→DROP→[DOWN]→DROP+→OUTRO. 16–32 bar heat/drop clips, sudden entries, never intros. Default join: tease_slam — the incoming build teases in filtered under the outgoing, the tempo lane rides the BPM gap, roll + throw, slam on the 1 (loop_roll / backspin / power_cut for variety and no-drop cases; no two identical slams in a row). Blend + echo only when intent is chill/deep/warm-up/smooth. The engine owns bar math — you never compute in_bars/out_bars. Options: intent; track_count; order; join_overrides; apply (default true); hear (default true). Rewrite any join with apply_transition_recipe, then verify_set.

    View tool JSON
    {
      "name": "prepare_set",
      "kind": "act",
      "impl": "imperative",
      "description": "Default action for 'make me a set'. Chop formula: INTRO→UP+→DROP→[DOWN]→DROP+→OUTRO. 16–32 bar heat/drop clips, sudden entries, never intros. Default join: tease_slam — the incoming build teases in filtered under the outgoing, the tempo lane rides the BPM gap, roll + throw, slam on the 1 (loop_roll / backspin / power_cut for variety and no-drop cases; no two identical slams in a row). Blend + echo only when intent is chill/deep/warm-up/smooth. The engine owns bar math — you never compute in_bars/out_bars. Options: intent; track_count; order; join_overrides; apply (default true); hear (default true). Rewrite any join with apply_transition_recipe, then verify_set.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "intent": {
            "type": "string"
          },
          "track_count": {
            "type": "number"
          },
          "order": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Explicit track_ids in play order; omit for auto arc"
          },
          "join_overrides": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "index": {
                  "type": "number"
                },
                "recipe": {
                  "type": "string",
                  "enum": [
                    "tease_slam",
                    "drop_swap",
                    "double_drop",
                    "power_cut",
                    "air_cut",
                    "build_cut",
                    "bass_swap",
                    "eq_swap",
                    "filter_sweep",
                    "echo_out",
                    "loop_out",
                    "loop_roll",
                    "backspin",
                    "hook_layer",
                    "half_bridge",
                    "tempo_ride",
                    "power_block"
                  ]
                },
                "bars": {
                  "type": "number"
                }
              },
              "required": [
                "index"
              ]
            }
          },
          "hear": {
            "type": "boolean"
          },
          "apply": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      }
    }
    preview_joinAction

    Listen-score a join (index ≥ 1) — the ear you lack. Auditions the ACTUAL overlap windows from the stored chroma (harmony.blend_ok / bass_only / clash): measured audio beats the Camelot label. echo_out is scored as a leave (incoming is not in the window). Isolator recipes are not failed for raw-file bass or a guessed key. Fails mid-vocal leave, measured-clash pad blends, and pad blends that break the cap. Returns drops/cues plus the compiled commit (commit_bars, commit_on_drop): on a drop recipe the commit must land on the incoming drop's 1, otherwise your cue math drifted.

    View tool JSON
    {
      "name": "preview_join",
      "kind": "act",
      "impl": "imperative",
      "description": "Listen-score a join (index ≥ 1) — the ear you lack. Auditions the ACTUAL overlap windows from the stored chroma (harmony.blend_ok / bass_only / clash): measured audio beats the Camelot label. echo_out is scored as a leave (incoming is not in the window). Isolator recipes are not failed for raw-file bass or a guessed key. Fails mid-vocal leave, measured-clash pad blends, and pad blends that break the cap. Returns drops/cues plus the compiled commit (commit_bars, commit_on_drop): on a drop recipe the commit must land on the incoming drop's 1, otherwise your cue math drifted.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "index": {
            "type": "number"
          },
          "hear": {
            "type": "boolean"
          }
        },
        "required": [
          "index"
        ],
        "additionalProperties": false
      }
    }
    tag_trackAction

    You are the curator of mood, genre, and role. The detector measures audio (bpm, energy, brightness, drop) but cannot know a euphoric anthem from a minor key. MusicBrainz may fill genre on import; override here (genreSource=agent). Also: role opener|builder|bridge|peak|reset|closer, energyLevel 1–10.

    View tool JSON
    {
      "name": "tag_track",
      "kind": "act",
      "impl": "imperative",
      "description": "You are the curator of mood, genre, and role. The detector measures audio (bpm, energy, brightness, drop) but cannot know a euphoric anthem from a minor key. MusicBrainz may fill genre on import; override here (genreSource=agent). Also: role opener|builder|bridge|peak|reset|closer, energyLevel 1–10.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "track_id": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "enum": [
              "opener",
              "builder",
              "bridge",
              "peak",
              "reset",
              "closer"
            ]
          },
          "energy_level": {
            "type": "number"
          },
          "mood": {
            "type": "string",
            "enum": [
              "dark",
              "bright",
              "driving",
              "warm"
            ]
          },
          "genre_hint": {
            "type": "string"
          }
        },
        "required": [
          "track_id"
        ],
        "additionalProperties": false
      }
    }
    apply_power_blockAction

    Trim each arrangement entry to the first drop/hook (~32 bars) and set every join to a 1-bar cut.

    View tool JSON
    {
      "name": "apply_power_block",
      "kind": "act",
      "impl": "imperative",
      "description": "Trim each arrangement entry to the first drop/hook (~32 bars) and set every join to a 1-bar cut.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      }
    }
    analyze_trackAction

    Re-run analysis for a track already in the library (BPM, sections, energy, waveform).

    View tool JSON
    {
      "name": "analyze_track",
      "kind": "act",
      "impl": "imperative",
      "description": "Re-run analysis for a track already in the library (BPM, sections, energy, waveform).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "track_id": {
            "type": "string"
          }
        },
        "required": [
          "track_id"
        ],
        "additionalProperties": false
      }
    }
    fetch_lyricsAnswer

    Fetch synced lyrics (LRCLIB) and store on the track. Then use find_lyric to map words → bars.

    View tool JSON
    {
      "name": "fetch_lyrics",
      "kind": "answer",
      "impl": "imperative",
      "description": "Fetch synced lyrics (LRCLIB) and store on the track. Then use find_lyric to map words → bars.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "track_id": {
            "type": "string"
          }
        },
        "required": [
          "track_id"
        ],
        "additionalProperties": false
      }
    }
    get_lyricsAnswer

    Return stored lyric words {t seconds, w}. Empty if not fetched yet.

    View tool JSON
    {
      "name": "get_lyrics",
      "kind": "answer",
      "impl": "imperative",
      "description": "Return stored lyric words {t seconds, w}. Empty if not fetched yet.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "track_id": {
            "type": "string"
          },
          "offset": {
            "type": "number"
          },
          "limit": {
            "type": "number"
          }
        },
        "required": [
          "track_id"
        ],
        "additionalProperties": false
      }
    }
    find_lyricAnswer

    Search stored lyrics for query. Returns start_bars/end_bars for seek/loop/trim. fetch_lyrics first if none.

    View tool JSON
    {
      "name": "find_lyric",
      "kind": "answer",
      "impl": "imperative",
      "description": "Search stored lyrics for query. Returns start_bars/end_bars for seek/loop/trim. fetch_lyrics first if none.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "track_id": {
            "type": "string"
          },
          "query": {
            "type": "string"
          },
          "limit": {
            "type": "number"
          }
        },
        "required": [
          "track_id",
          "query"
        ],
        "additionalProperties": false
      }
    }
    set_cueAction

    Arm channel Cue (PFL). Any armed Cue solos those channels to master (web has no separate phones out).

    View tool JSON
    {
      "name": "set_cue",
      "kind": "act",
      "impl": "imperative",
      "description": "Arm channel Cue (PFL). Any armed Cue solos those channels to master (web has no separate phones out).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "deck": {
            "type": "string",
            "enum": [
              "A",
              "B",
              "C",
              "D"
            ]
          },
          "enabled": {
            "type": "boolean"
          }
        },
        "required": [
          "deck",
          "enabled"
        ],
        "additionalProperties": false
      }
    }
    set_insert_trackAction

    Insert a track into the working arrangement at index. Prefer cue parking over raw bars: cue = auto | drop | mix_in | <bars>. 'auto' parks from the join compiler (incoming N bars before its drop for swap recipes, on the drop for cuts, drop/heat for echo) and 'drop'/'mix_in' pick that cue explicitly. Raw in_bars/out_bars still work but are NOT phrase-snapped — verify_set will flag off-grid bars. transition accepts types (cut, drop_swap, …) or recipe names (power_cut, bass_swap, half_bridge, power_block). Result echoes the parked entry and, for index ≥ 1, where the compiled xfader commit lands (commit_on_drop).

    View tool JSON
    {
      "name": "set_insert_track",
      "kind": "act",
      "impl": "imperative",
      "description": "Insert a track into the working arrangement at index. Prefer cue parking over raw bars: cue = auto | drop | mix_in | <bars>. 'auto' parks from the join compiler (incoming N bars before its drop for swap recipes, on the drop for cuts, drop/heat for echo) and 'drop'/'mix_in' pick that cue explicitly. Raw in_bars/out_bars still work but are NOT phrase-snapped — verify_set will flag off-grid bars. transition accepts types (cut, drop_swap, …) or recipe names (power_cut, bass_swap, half_bridge, power_block). Result echoes the parked entry and, for index ≥ 1, where the compiled xfader commit lands (commit_on_drop).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "index": {
            "type": "number"
          },
          "track_id": {
            "type": "string"
          },
          "cue": {
            "type": [
              "string",
              "number"
            ],
            "description": "auto | drop | mix_in | bars — parking handled by the compiler"
          },
          "in_bars": {
            "type": "number"
          },
          "out_bars": {
            "type": "number"
          },
          "transition": {
            "type": "string",
            "enum": [
              "cut",
              "blend",
              "eq_swap",
              "filter_sweep",
              "echo_out",
              "loop_out",
              "build_cut",
              "drop_swap",
              "double_drop",
              "loop_roll",
              "backspin",
              "hook_layer",
              "air_cut",
              "tempo_ride",
              "tease_slam",
              "tease_slam",
              "drop_swap",
              "double_drop",
              "power_cut",
              "air_cut",
              "build_cut",
              "bass_swap",
              "eq_swap",
              "filter_sweep",
              "echo_out",
              "loop_out",
              "loop_roll",
              "backspin",
              "hook_layer",
              "half_bridge",
              "tempo_ride",
              "power_block"
            ]
          },
          "bars": {
            "type": "number"
          }
        },
        "required": [
          "index",
          "track_id"
        ],
        "additionalProperties": false
      }
    }
    set_remove_trackAction

    Remove arrangement entry at index.

    View tool JSON
    {
      "name": "set_remove_track",
      "kind": "act",
      "impl": "imperative",
      "description": "Remove arrangement entry at index.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "index": {
            "type": "number"
          }
        },
        "required": [
          "index"
        ],
        "additionalProperties": false
      }
    }
    set_move_trackAction

    Reorder arrangement entry from_index → to_index.

    View tool JSON
    {
      "name": "set_move_track",
      "kind": "act",
      "impl": "imperative",
      "description": "Reorder arrangement entry from_index → to_index.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "from_index": {
            "type": "number"
          },
          "to_index": {
            "type": "number"
          }
        },
        "required": [
          "from_index",
          "to_index"
        ],
        "additionalProperties": false
      }
    }
    set_set_trimAction

    Set in_bars/out_bars for an arrangement entry. Bars within ±1 of the 8-bar phrase grid are auto-snapped to it (a 71 becomes 72) — off-phrase commits are the #1 'beats don't match' complaint. Values further off-grid pass through untouched and verify_set will flag them.

    View tool JSON
    {
      "name": "set_set_trim",
      "kind": "act",
      "impl": "imperative",
      "description": "Set in_bars/out_bars for an arrangement entry. Bars within ±1 of the 8-bar phrase grid are auto-snapped to it (a 71 becomes 72) — off-phrase commits are the #1 'beats don't match' complaint. Values further off-grid pass through untouched and verify_set will flag them.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "index": {
            "type": "number"
          },
          "in_bars": {
            "type": "number"
          },
          "out_bars": {
            "type": "number"
          }
        },
        "required": [
          "index",
          "in_bars",
          "out_bars"
        ],
        "additionalProperties": false
      }
    }
    set_set_transitionAction

    Set the join INTO the entry at index (index ≥ 1). Accepts transition types (cut, blend, drop_swap, echo_out, …) or recipe names (power_cut, bass_swap, half_bridge, power_block — resolved to their types). Prefer apply_transition_recipe for recipes: it also parks the cue bars. Result echoes the compiled commit (commit_bars on the set clock, commit_on_drop) — if commit_on_drop is false on a drop recipe, your cue math drifted from the recipe shape.

    View tool JSON
    {
      "name": "set_set_transition",
      "kind": "act",
      "impl": "imperative",
      "description": "Set the join INTO the entry at index (index ≥ 1). Accepts transition types (cut, blend, drop_swap, echo_out, …) or recipe names (power_cut, bass_swap, half_bridge, power_block — resolved to their types). Prefer apply_transition_recipe for recipes: it also parks the cue bars. Result echoes the compiled commit (commit_bars on the set clock, commit_on_drop) — if commit_on_drop is false on a drop recipe, your cue math drifted from the recipe shape.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "index": {
            "type": "number"
          },
          "type": {
            "type": "string",
            "enum": [
              "cut",
              "blend",
              "eq_swap",
              "filter_sweep",
              "echo_out",
              "loop_out",
              "build_cut",
              "drop_swap",
              "double_drop",
              "loop_roll",
              "backspin",
              "hook_layer",
              "air_cut",
              "tempo_ride",
              "tease_slam",
              "tease_slam",
              "drop_swap",
              "double_drop",
              "power_cut",
              "air_cut",
              "build_cut",
              "bass_swap",
              "eq_swap",
              "filter_sweep",
              "echo_out",
              "loop_out",
              "loop_roll",
              "backspin",
              "hook_layer",
              "half_bridge",
              "tempo_ride",
              "power_block"
            ]
          },
          "bars": {
            "type": "number"
          }
        },
        "required": [
          "index",
          "type"
        ],
        "additionalProperties": false
      }
    }
    set_clearAction

    Clear the working arrangement (not the library).

    View tool JSON
    {
      "name": "set_clear",
      "kind": "act",
      "impl": "imperative",
      "description": "Clear the working arrangement (not the library).",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      }
    }
    set_proposeAction

    Stage an arrangement for human Accept/Reject. You author tracks and joins. Do not invent tracks. verify_set ready:true means no broken automation.

    View tool JSON
    {
      "name": "set_propose",
      "kind": "act",
      "impl": "imperative",
      "description": "Stage an arrangement for human Accept/Reject. You author tracks and joins. Do not invent tracks. verify_set ready:true means no broken automation.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "entries": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "track_id": {
                  "type": "string"
                },
                "in_bars": {
                  "type": "number"
                },
                "out_bars": {
                  "type": "number"
                },
                "transition": {
                  "type": "string",
                  "enum": [
                    "cut",
                    "blend",
                    "eq_swap",
                    "filter_sweep",
                    "echo_out",
                    "loop_out",
                    "build_cut",
                    "drop_swap",
                    "double_drop",
                    "loop_roll",
                    "backspin",
                    "hook_layer",
                    "air_cut",
                    "tempo_ride",
                    "tease_slam",
                    "tease_slam",
                    "drop_swap",
                    "double_drop",
                    "power_cut",
                    "air_cut",
                    "build_cut",
                    "bass_swap",
                    "eq_swap",
                    "filter_sweep",
                    "echo_out",
                    "loop_out",
                    "loop_roll",
                    "backspin",
                    "hook_layer",
                    "half_bridge",
                    "tempo_ride",
                    "power_block"
                  ]
                },
                "recipe": {
                  "type": "string",
                  "enum": [
                    "tease_slam",
                    "drop_swap",
                    "double_drop",
                    "power_cut",
                    "air_cut",
                    "build_cut",
                    "bass_swap",
                    "eq_swap",
                    "filter_sweep",
                    "echo_out",
                    "loop_out",
                    "loop_roll",
                    "backspin",
                    "hook_layer",
                    "half_bridge",
                    "tempo_ride",
                    "power_block"
                  ]
                },
                "bars": {
                  "type": "number"
                }
              },
              "required": [
                "track_id",
                "in_bars",
                "out_bars"
              ]
            }
          },
          "automation": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "param": {
                  "type": "string",
                  "enum": [
                    "tempo",
                    "xfader",
                    "filter_a",
                    "filter_b",
                    "eq_low_a",
                    "eq_mid_a",
                    "eq_high_a",
                    "eq_low_b",
                    "eq_mid_b",
                    "eq_high_b",
                    "fader_a",
                    "fader_b",
                    "gain_a",
                    "gain_b",
                    "fx_wet",
                    "fx_arm"
                  ]
                },
                "start_bars": {
                  "type": "number"
                },
                "end_bars": {
                  "type": "number"
                },
                "start_value": {
                  "type": "number"
                },
                "end_value": {
                  "type": "number"
                },
                "curve": {
                  "type": "string",
                  "enum": [
                    "linear",
                    "exponential",
                    "ease_in",
                    "ease_out"
                  ]
                }
              },
              "required": [
                "param",
                "start_bars",
                "end_bars",
                "start_value",
                "end_value"
              ]
            }
          },
          "reason": {
            "type": "string"
          }
        },
        "required": [
          "entries"
        ],
        "additionalProperties": false
      }
    }
    set_apply_proposalAction

    Apply the pending proposal to the arrangement.

    View tool JSON
    {
      "name": "set_apply_proposal",
      "kind": "act",
      "impl": "imperative",
      "description": "Apply the pending proposal to the arrangement.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      }
    }
    set_reject_proposalAction

    Discard the pending proposal.

    View tool JSON
    {
      "name": "set_reject_proposal",
      "kind": "act",
      "impl": "imperative",
      "description": "Discard the pending proposal.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      }
    }
    get_set_timelineAnswer

    Flattened set timeline with deck assignment, overlaps from transitions, duration, and automation lanes. Use before adding tempo/mixer automations (bars are absolute from set start).

    View tool JSON
    {
      "name": "get_set_timeline",
      "kind": "answer",
      "impl": "imperative",
      "description": "Flattened set timeline with deck assignment, overlaps from transitions, duration, and automation lanes. Use before adding tempo/mixer automations (bars are absolute from set start).",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      }
    }
    set_set_tempoAction

    Set master set tempo in BPM (null clears → first track BPM). Tempo automation overrides while active.

    View tool JSON
    {
      "name": "set_set_tempo",
      "kind": "act",
      "impl": "imperative",
      "description": "Set master set tempo in BPM (null clears → first track BPM). Tempo automation overrides while active.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "bpm": {
            "type": [
              "number",
              "null"
            ]
          }
        },
        "required": [
          "bpm"
        ],
        "additionalProperties": false
      }
    }
    set_add_automationAction

    Add a set-timeline automation lane (absolute bars). param=tempo for BPM ramps (e.g. 124→128 over 16 bars). Also xfader, filter_a/b, eq_*_a/b, fader_a/b, gain_a/b. curve: linear|exponential|ease_in|ease_out. Play performs these with transitions.

    View tool JSON
    {
      "name": "set_add_automation",
      "kind": "act",
      "impl": "imperative",
      "description": "Add a set-timeline automation lane (absolute bars). param=tempo for BPM ramps (e.g. 124→128 over 16 bars). Also xfader, filter_a/b, eq_*_a/b, fader_a/b, gain_a/b. curve: linear|exponential|ease_in|ease_out. Play performs these with transitions.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "param": {
            "type": "string",
            "enum": [
              "tempo",
              "xfader",
              "filter_a",
              "filter_b",
              "eq_low_a",
              "eq_mid_a",
              "eq_high_a",
              "eq_low_b",
              "eq_mid_b",
              "eq_high_b",
              "fader_a",
              "fader_b",
              "gain_a",
              "gain_b",
              "fx_wet",
              "fx_arm"
            ]
          },
          "start_bars": {
            "type": "number"
          },
          "end_bars": {
            "type": "number"
          },
          "start_value": {
            "type": "number"
          },
          "end_value": {
            "type": "number"
          },
          "curve": {
            "type": "string",
            "enum": [
              "linear",
              "exponential",
              "ease_in",
              "ease_out"
            ]
          }
        },
        "required": [
          "param",
          "start_bars",
          "end_bars",
          "start_value",
          "end_value"
        ],
        "additionalProperties": false
      }
    }
    set_remove_automationAction

    Remove an automation lane by id (from get_session / get_set_timeline).

    View tool JSON
    {
      "name": "set_remove_automation",
      "kind": "act",
      "impl": "imperative",
      "description": "Remove an automation lane by id (from get_session / get_set_timeline).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          }
        },
        "required": [
          "id"
        ],
        "additionalProperties": false
      }
    }
    set_clear_automationAction

    Clear all explicit automation lanes (compiled transition automations remain).

    View tool JSON
    {
      "name": "set_clear_automation",
      "kind": "act",
      "impl": "imperative",
      "description": "Clear all explicit automation lanes (compiled transition automations remain).",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      }
    }
    download_setAction

    Offline-bounce the arrangement (transitions + automation) to a WAV file and download it. Same as TopBar Download. Does not use the live Rec bus.

    View tool JSON
    {
      "name": "download_set",
      "kind": "act",
      "impl": "imperative",
      "description": "Offline-bounce the arrangement (transitions + automation) to a WAV file and download it. Same as TopBar Download. Does not use the live Rec bus.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "filename": {
            "type": "string",
            "description": "Optional base filename without extension"
          }
        },
        "additionalProperties": false
      }
    }
    review_setAction

    Bounce the arrangement offline and MEASURE each join from the rendered audio: dead air at the commit, level jump across the 1, bass stacking during the tease, whether the tease rises, whether the drop's FIRST hit lands open (first_hit < 0.7 = the slam ramps through the 1), whether the slam lifts. Trust these numbers over imagination — what fails here fails in the room. Loop rolls and tempo rides render like live. Run after prepare_set / apply_transition_recipe. With fix:true, writes gainstage lanes that level every entry's solo loudness to the set mean (kills hot/sagging slams) — then re-run to confirm. Pass index to focus one join.

    View tool JSON
    {
      "name": "review_set",
      "kind": "act",
      "impl": "imperative",
      "description": "Bounce the arrangement offline and MEASURE each join from the rendered audio: dead air at the commit, level jump across the 1, bass stacking during the tease, whether the tease rises, whether the drop's FIRST hit lands open (first_hit < 0.7 = the slam ramps through the 1), whether the slam lifts. Trust these numbers over imagination — what fails here fails in the room. Loop rolls and tempo rides render like live. Run after prepare_set / apply_transition_recipe. With fix:true, writes gainstage lanes that level every entry's solo loudness to the set mean (kills hot/sagging slams) — then re-run to confirm. Pass index to focus one join.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "index": {
            "type": "number",
            "description": "Optional join index (≥1) to focus"
          },
          "fix": {
            "type": "boolean",
            "description": "Write gain-staging lanes from the measurements"
          }
        },
        "additionalProperties": false
      }
    }
    set_playAction

    Perform the arrangement: loads A/B alternating, applies transition types and automation (tempo/EQ/filter/xfader). Optional start_bars seeks first.

    View tool JSON
    {
      "name": "set_play",
      "kind": "act",
      "impl": "imperative",
      "description": "Perform the arrangement: loads A/B alternating, applies transition types and automation (tempo/EQ/filter/xfader). Optional start_bars seeks first.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "start_bars": {
            "type": "number"
          }
        },
        "additionalProperties": false
      }
    }
    set_pauseAction

    Pause set performance.

    View tool JSON
    {
      "name": "set_pause",
      "kind": "act",
      "impl": "imperative",
      "description": "Pause set performance.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      }
    }
    set_seekAction

    Seek set playhead to absolute bars (also works while paused).

    View tool JSON
    {
      "name": "set_seek",
      "kind": "act",
      "impl": "imperative",
      "description": "Seek set playhead to absolute bars (also works while paused).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "bars": {
            "type": "number"
          }
        },
        "required": [
          "bars"
        ],
        "additionalProperties": false
      }
    }
    fx_setAction

    Master FX unit: type off|delay|reverb|echo, wet 0–1, time_beats, feedback.

    View tool JSON
    {
      "name": "fx_set",
      "kind": "act",
      "impl": "imperative",
      "description": "Master FX unit: type off|delay|reverb|echo, wet 0–1, time_beats, feedback.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "off",
              "delay",
              "reverb",
              "echo"
            ]
          },
          "wet": {
            "type": "number"
          },
          "time_beats": {
            "type": "number"
          },
          "feedback": {
            "type": "number"
          }
        },
        "additionalProperties": false
      }
    }
    historyAnswer

    Undo or redo the last SetDoc mutation.

    View tool JSON
    {
      "name": "history",
      "kind": "answer",
      "impl": "imperative",
      "description": "Undo or redo the last SetDoc mutation.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "action": {
            "type": "string",
            "enum": [
              "undo",
              "redo"
            ]
          }
        },
        "required": [
          "action"
        ],
        "additionalProperties": false
      }
    }