Skip to main content
Glama

music

DestructiveIdempotent

Read or update the background bed under an edit's voiceover. Set its start/end by transcript words or phrases, choose assets, fades, ducking, and rotation, or preview using plan.

Instructions

Read or change the A2 music bed this project mixes under its edit.

Call with no arguments to read what is in force. The bed stores word indices and an asset, never a length: it starts where word_index_start of clip_id (the VO transcript) lands on the timeline and runs to where word_index_end ends — or to the end of the edit — so a cut before either boundary moves both. Duration is derived at build time.

The first set needs asset, clip_id and a start (word_index_start or phrase_start) together; after that each field updates on its own. A field set by phrase stores the phrase beside the index it resolved to, so cue_reresolve can re-derive it; set by plain index, the stored phrase is cleared. Both boundaries are echoed with their resolved words and neighbours — check them.

Beyond one asset from its head: passages (more pieces, each from its own word), rotate (assets in turn), crossfade, src_in; under levels the bed below the voice, duck dips it while the voice speaks, keyed off the edit's own audio at export. export's music field says what the render carried. clear_* and reset undo each; plan validates without writing.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
duckNoPull the bed this many dB down while the voice is speaking and let it back up in the pauses. It is keyed off the timeline's own audio at export rather than the transcript's word timings, which were measured against a bed recovered from a real render and beaten: 2.72 dB off for the audio gate against a word-span duck's 3.39.
pathNoThe project directory to act on. Omit it — the usual case — when this server is bound to a project (started as `proofcut -C DIR mcp`, or inside a project; `ping` says which): it then resolves to that one bound project, a relative path resolves against it, and a path outside it is refused by name. Unbound, `path` is the whole address and omitting it refuses rather than guessing.
planNoResolve the whole call and report what it would do, writing nothing. Prefer it over doing the thing and undoing it.
afterNoA forward cursor over the matches of `phrase_start`/`phrase_end`: any match at or before this word index is skipped. -1, the default, means from the start.
assetNoThe bed's own music, as a registered clip id — never `card:name`, since a held frame has no sound. It plays from its own head; shorter than its span pads with real silence, longer is trimmed.
resetNoDrop the bed entirely.
underNoLevel the whole bed this many LU below the voice, measured. It is a fixed offset; `duck` is the moving one.
rotateNoFurther assets to play in turn as each one runs out, overlapping by `crossfade`. `[]` clears them.
src_inNoWhere inside the bed's own asset it starts, in seconds.
clip_idNoThe transcript the bed's word indices address — the VO, not the music.
fade_inNoSeconds of fade at the bed's start. The fades ride the bed's own entry, so a fade-out ends where the music audibly ends.
fade_outNoSeconds of fade at the bed's end. A fade pair the bed cannot hold refuses at build time rather than being clamped.
passagesNoReplace the list of passages after the bed's own asset: each `{asset, word_index_start | phrase_start, src_in?, crossfade?, rotate?}`. `[]` clears them.
clear_endNoDrop the end word, returning the bed to running to the end of the edit.
crossfadeNoSeconds two pieces overlap by. A crossfade edge is equal-power rather than the straight dB line an ordinary fade draws — two straight fades crossing sum to a hole.
clear_duckNoReturn the bed to one level, with no ducking.
occurrenceNoDisambiguate `phrase_start`/`phrase_end` by count, **1-based**. Unset, an ambiguous phrase is refused rather than guessed at.
phrase_endNoSet the out-point by wording instead; it binds the phrase's last word. Each boundary is independent — one can be a phrase and the other an index.
clear_underNoReturn every asset to its own level.
phrase_startNoSet the in-point by wording instead; it binds the phrase's first word. The resolved phrase is stored beside the index, so `cue_reresolve` can re-derive it after a re-record.
word_index_endNoWhere the bed goes out. Unset means *to the end of the edit*, so a tail holds over silence.
word_index_startNoWhere the bed comes in, as a word of `clip_id`. The bed stores words and never a length, so a cut before either boundary moves it automatically.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed75 schema fields changedv0.25.0
    • addedInput schema / properties / after / description
      Added value: +"A forward cursor over the matches of `phrase_start`/`phrase_end`: any match at or before this word index is skipped. -1, the default, means from the start."
    • removedInput schema / properties / after / title
      Removed value: -"After"
    • removedInput schema / properties / asset / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / asset / description
      Added value: +"The bed's own music, as a registered clip id — never `card:name`, since a held frame has no sound. It plays from its own head; shorter than its span pads with real silence, longer is trimmed."
    • removedInput schema / properties / asset / title
      Removed value: -"Asset"
    • addedInput schema / properties / asset / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • addedInput schema / properties / clear_duck
      Added value: +{
      +  "default": false,
      +  "description": "Return the bed to one level, with no ducking.",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / clear_end / description
      Added value: +"Drop the end word, returning the bed to running to the end of the edit."
    • removedInput schema / properties / clear_end / title
      Removed value: -"Clear End"
    • addedInput schema / properties / clear_under / description
      Added value: +"Return every asset to its own level."
    • removedInput schema / properties / clear_under / title
      Removed value: -"Clear Under"
    • removedInput schema / properties / clip_id / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / clip_id / description
      Added value: +"The transcript the bed's word indices address — the VO, not the music."
    • removedInput schema / properties / clip_id / title
      Removed value: -"Clip Id"
    • addedInput schema / properties / clip_id / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedInput schema / properties / crossfade / anyOf
      Removed value: -[
      -  {
      -    "type": "number"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / crossfade / description
      Added value: +"Seconds two pieces overlap by. A crossfade edge is equal-power rather than the straight dB line an ordinary fade draws — two straight fades crossing sum to a hole."
    • removedInput schema / properties / crossfade / title
      Removed value: -"Crossfade"
    • addedInput schema / properties / crossfade / type
      Added value: +[
      +  "number",
      +  "null"
      +]
    • addedInput schema / properties / duck
      Added value: +{
      +  "default": null,
      +  "description": "Pull the bed this many dB down while the voice is speaking and let it back up in the pauses. It is keyed off the timeline's own audio at export rather than the transcript's word timings, which were measured against a bed recovered from a real render and beaten: 2.72 dB off for the audio gate against a word-span duck's 3.39.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • removedInput schema / properties / fade_in / anyOf
      Removed value: -[
      -  {
      -    "type": "number"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / fade_in / description
      Added value: +"Seconds of fade at the bed's start. The fades ride the bed's own entry, so a fade-out ends where the music audibly ends."
    • removedInput schema / properties / fade_in / title
      Removed value: -"Fade In"
    • addedInput schema / properties / fade_in / type
      Added value: +[
      +  "number",
      +  "null"
      +]
    • removedInput schema / properties / fade_out / anyOf
      Removed value: -[
      -  {
      -    "type": "number"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / fade_out / description
      Added value: +"Seconds of fade at the bed's end. A fade pair the bed cannot hold refuses at build time rather than being clamped."
    • removedInput schema / properties / fade_out / title
      Removed value: -"Fade Out"
    • addedInput schema / properties / fade_out / type
      Added value: +[
      +  "number",
      +  "null"
      +]
    • removedInput schema / properties / occurrence / anyOf
      Removed value: -[
      -  {
      -    "type": "integer"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / occurrence / description
      Added value: +"Disambiguate `phrase_start`/`phrase_end` by count, **1-based**. Unset, an ambiguous phrase is refused rather than guessed at."
    • removedInput schema / properties / occurrence / title
      Removed value: -"Occurrence"
    • addedInput schema / properties / occurrence / type
      Added value: +[
      +  "integer",
      +  "null"
      +]
    • removedInput schema / properties / passages / anyOf
      Removed value: -[
      -  {
      -    "items": {
      -      "additionalProperties": true,
      -      "type": "object"
      -    },
      -    "type": "array"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / passages / description
      Added value: +"Replace the list of passages after the bed's own asset: each `{asset, word_index_start | phrase_start, src_in?, crossfade?, rotate?}`. `[]` clears them."
    • addedInput schema / properties / passages / items
      Added value: +{
      +  "additionalProperties": true,
      +  "type": "object"
      +}
    • removedInput schema / properties / passages / title
      Removed value: -"Passages"
    • addedInput schema / properties / passages / type
      Added value: +[
      +  "array",
      +  "null"
      +]
    • removedInput schema / properties / path / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / path / description
      Added value: +"The project directory to act on. Omit it — the usual case — when this server is bound to a project (started as `proofcut -C DIR mcp`, or inside a project; `ping` says which): it then resolves to that one bound project, a relative path resolves against it, and a path outside it is refused by name. Unbound, `path` is the whole address and omitting it refuses rather than guessing."
    • removedInput schema / properties / path / title
      Removed value: -"Path"
    • addedInput schema / properties / path / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedInput schema / properties / phrase_end / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / phrase_end / description
      Added value: +"Set the out-point by wording instead; it binds the phrase's last word. Each boundary is independent — one can be a phrase and the other an index."
    • removedInput schema / properties / phrase_end / title
      Removed value: -"Phrase End"
    • addedInput schema / properties / phrase_end / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedInput schema / properties / phrase_start / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / phrase_start / description
      Added value: +"Set the in-point by wording instead; it binds the phrase's first word. The resolved phrase is stored beside the index, so `cue_reresolve` can re-derive it after a re-record."
    • removedInput schema / properties / phrase_start / title
      Removed value: -"Phrase Start"
    • addedInput schema / properties / phrase_start / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • addedInput schema / properties / plan / description
      Added value: +"Resolve the whole call and report what it would do, writing nothing. Prefer it over doing the thing and undoing it."
    • removedInput schema / properties / plan / title
      Removed value: -"Plan"
    • addedInput schema / properties / reset / description
      Added value: +"Drop the bed entirely."
    • removedInput schema / properties / reset / title
      Removed value: -"Reset"
    • removedInput schema / properties / rotate / anyOf
      Removed value: -[
      -  {
      -    "items": {
      -      "type": "string"
      -    },
      -    "type": "array"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / rotate / description
      Added value: +"Further assets to play in turn as each one runs out, overlapping by `crossfade`. `[]` clears them."
    • addedInput schema / properties / rotate / items
      Added value: +{
      +  "type": "string"
      +}
    • removedInput schema / properties / rotate / title
      Removed value: -"Rotate"
    • addedInput schema / properties / rotate / type
      Added value: +[
      +  "array",
      +  "null"
      +]
    • removedInput schema / properties / src_in / anyOf
      Removed value: -[
      -  {
      -    "type": "number"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / src_in / description
      Added value: +"Where inside the bed's own asset it starts, in seconds."
    • removedInput schema / properties / src_in / title
      Removed value: -"Src In"
    • addedInput schema / properties / src_in / type
      Added value: +[
      +  "number",
      +  "null"
      +]
    • removedInput schema / properties / under / anyOf
      Removed value: -[
      -  {
      -    "type": "number"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / under / description
      Added value: +"Level the whole bed this many LU below the voice, measured. It is a fixed offset; `duck` is the moving one."
    • removedInput schema / properties / under / title
      Removed value: -"Under"
    • addedInput schema / properties / under / type
      Added value: +[
      +  "number",
      +  "null"
      +]
    • removedInput schema / properties / word_index_end / anyOf
      Removed value: -[
      -  {
      -    "type": "integer"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / word_index_end / description
      Added value: +"Where the bed goes out. Unset means *to the end of the edit*, so a tail holds over silence."
    • removedInput schema / properties / word_index_end / title
      Removed value: -"Word Index End"
    • addedInput schema / properties / word_index_end / type
      Added value: +[
      +  "integer",
      +  "null"
      +]
    • removedInput schema / properties / word_index_start / anyOf
      Removed value: -[
      -  {
      -    "type": "integer"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / word_index_start / description
      Added value: +"Where the bed comes in, as a word of `clip_id`. The bed stores words and never a length, so a cut before either boundary moves it automatically."
    • removedInput schema / properties / word_index_start / title
      Removed value: -"Word Index Start"
    • addedInput schema / properties / word_index_start / type
      Added value: +[
      +  "integer",
      +  "null"
      +]
    • removedInput schema / title
      Removed value: -"musicArguments"
  2. First observedv0.24.0

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already carry destructiveHint and idempotentHint, and the description substantially adds behavioral details: the bed stores word indices rather than a length, duration is derived at build time, phrase-based entries store the phrase while index-based ones clear it, and `plan` validates without writing. It also discloses that `clear_*` and `reset` undo each respective action, giving the agent a reliable mental model of side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long, but it is front-loaded with the core read/change distinction and organized into clear thematic sections covering boundaries, phrase storage, and auxiliary features. Each sentence contributes a model fact or usage constraint, leaving little waste. It is denser than strictly necessary, but for a 22-parameter tool this level of detail is reasonable and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a 22-parameter schema with 100% coverage, annotations, and an output schema, the description completes the picture by explaining how the bed span is derived, the initial-bundle requirement, and the interaction mechanics of phrase resolution, ducking, under, and plan. It covers all major branches—read, set, clear, reset, plan, passages, and rotate—so an agent is unlikely to need external context before calling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has 100% coverage and many parameter descriptions already contain rich detail (e.g., `asset` never takes `card:name`, `clip_id` must be the VO transcript). The description adds cross-parameter semantics that are not in the schema: the first set must bundle `asset`, `clip_id`, and one start, and boundaries can mix phrase and index forms independently. These interactions materially clarify how to call the tool correctly.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a precise verb pair—'Read or change'—and a concrete resource, 'the A2 music bed this project mixes under its edit,' so the tool's function is immediately unambiguous. It also exposes two fundamental modes (no-arg read vs. arg mutation), which helps distinguish it from related audio tools like `hear` or `vo_extend`.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit usage guidance for the read mode ('Call with no arguments to read what is in force') and states the key first-set requirement for writes: `asset`, `clip_id`, and one start together, after which fields update independently. It does not name any sibling tool as an explicit alternative, so there is no when-not-to-use contrast, but the context is otherwise clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.