Skip to main content
Glama

vo_synth

Destructive

Rank multiple zero-shot voice-clone renders of a line, pick the most speaker-like non-flat take, and splice it into the timeline after a chosen word.

Instructions

Say text in a cloned voice — render several seeds, rank them, read the winner back.

Zero-shot Qwen3-TTS from a ≈19s reference clip (voice); there is no built-in voice. Seeds seed .. seed+candidates-1 render in one process, each with sim (speaker-embedding likeness to the reference — a real take ≈0.99, a 3-semitone shift ≈0.96) and spread (voiced pitch movement). chosen is the best sim less a flatness penalty, since likeness alone keeps the flattest read. A render that hit max_seconds is capped and never wins while an uncapped one exists.

The winner is read back through whisper and heard/wer reported — a clone that sounds right and says the wrong words is the failure nothing else sees. A report, never a gate.

Renders are cached under cache/synth/, so a repeat spends no GPU. The splice is not cached: with clip_id + word_index the winner is registered and spliced in after that word through vo_extend's mechanism (melt routing, restore refusing across the seam, a covered_by report), and calling again splices a second time — check the timeline or undo rather than re-calling. plan=True reports the ranking and splice preview from cached renders only, and says rendered: False rather than spending the GPU.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
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.
seedNoFirst seed of the range; seeds `seed .. seed+candidates-1` render in one process. A new range renders only what the cache lacks.
textYesWhat the voice says. It is respelled first through the project's `lexicon.json` `say` folds, if one exists — the fix for a mispronounced name.
voiceNoA directory holding `ref.wav` + `ref.txt`, the ≈19s reference the clone is zero-shot from. Unset, `$PROOFCUT_TTS_VOICE`. There is no built-in voice, and none ships in the repo: a voice is somebody's recorded speech.
clip_idNoWith `word_index`, the track to splice the winner into. Omitted, nothing is spliced and the renders are just ranked.
lexiconNoA `{"say": {…}, "hear": {…}}` file: `say` respells what the model is given, `hear` folds whisper's spelling back to the script's before the WER is scored. Defaults to the project's own `lexicon.json` if it has one.
readbackNoTranscribe the winner with whisper and report `heard`/`wer`. On by default: a clone that sounds right and says the wrong words is the failure nothing else sees. The numbers are a report, never a gate.
candidatesNoHow many seeds to render and rank. Seed moves a render more than the reference does, which is why this ranks rather than renders once.
flat_floorNoBelow this much voiced pitch movement (semitones) a render starts paying the flatness penalty. Likeness alone keeps the flattest read, because sims in one pool differ by thousandths while spread differs by semitones.
word_indexNoThe word to splice the winner in right after, through `vo_extend`'s own mechanism — so the same one-way consequences follow (melt routing, `restore` refusing across the seam).
flat_weightNoHow much likeness to subtract per semitone of flatness under the floor. 0 restores likeness-only ranking.
max_secondsNoLength cap per render. One that hits it is reported `capped` and never wins while an uncapped one exists — a 21s reference once ran every render to 655s.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed37 schema fields changedv0.25.0
    • addedInput schema / properties / candidates / description
      Added value: +"How many seeds to render and rank. Seed moves a render more than the reference does, which is why this ranks rather than renders once."
    • removedInput schema / properties / candidates / title
      Removed value: -"Candidates"
    • removedInput schema / properties / clip_id / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / clip_id / description
      Added value: +"With `word_index`, the track to splice the winner into. Omitted, nothing is spliced and the renders are just ranked."
    • removedInput schema / properties / clip_id / title
      Removed value: -"Clip Id"
    • addedInput schema / properties / clip_id / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • addedInput schema / properties / flat_floor / description
      Added value: +"Below this much voiced pitch movement (semitones) a render starts paying the flatness penalty. Likeness alone keeps the flattest read, because sims in one pool differ by thousandths while spread differs by semitones."
    • removedInput schema / properties / flat_floor / title
      Removed value: -"Flat Floor"
    • addedInput schema / properties / flat_weight / description
      Added value: +"How much likeness to subtract per semitone of flatness under the floor. 0 restores likeness-only ranking."
    • removedInput schema / properties / flat_weight / title
      Removed value: -"Flat Weight"
    • removedInput schema / properties / lexicon / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / lexicon / description
      Added value: +"A `{\"say\": {…}, \"hear\": {…}}` file: `say` respells what the model is given, `hear` folds whisper's spelling back to the script's before the WER is scored. Defaults to the project's own `lexicon.json` if it has one."
    • removedInput schema / properties / lexicon / title
      Removed value: -"Lexicon"
    • addedInput schema / properties / lexicon / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • addedInput schema / properties / max_seconds / description
      Added value: +"Length cap per render. One that hits it is reported `capped` and never wins while an uncapped one exists — a 21s reference once ran every render to 655s."
    • removedInput schema / properties / max_seconds / title
      Removed value: -"Max Seconds"
    • 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"
      +]
    • 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 / readback / description
      Added value: +"Transcribe the winner with whisper and report `heard`/`wer`. On by default: a clone that sounds right and says the wrong words is the failure nothing else sees. The numbers are a report, never a gate."
    • removedInput schema / properties / readback / title
      Removed value: -"Readback"
    • addedInput schema / properties / seed / description
      Added value: +"First seed of the range; seeds `seed .. seed+candidates-1` render in one process. A new range renders only what the cache lacks."
    • removedInput schema / properties / seed / title
      Removed value: -"Seed"
    • addedInput schema / properties / text / description
      Added value: +"What the voice says. It is respelled first through the project's `lexicon.json` `say` folds, if one exists — the fix for a mispronounced name."
    • removedInput schema / properties / text / title
      Removed value: -"Text"
    • removedInput schema / properties / voice / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / voice / description
      Added value: +"A directory holding `ref.wav` + `ref.txt`, the ≈19s reference the clone is zero-shot from. Unset, `$PROOFCUT_TTS_VOICE`. There is no built-in voice, and none ships in the repo: a voice is somebody's recorded speech."
    • removedInput schema / properties / voice / title
      Removed value: -"Voice"
    • addedInput schema / properties / voice / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedInput schema / properties / word_index / anyOf
      Removed value: -[
      -  {
      -    "type": "integer"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / word_index / description
      Added value: +"The word to splice the winner in right after, through `vo_extend`'s own mechanism — so the same one-way consequences follow (melt routing, `restore` refusing across the seam)."
    • removedInput schema / properties / word_index / title
      Removed value: -"Word Index"
    • addedInput schema / properties / word_index / type
      Added value: +[
      +  "integer",
      +  "null"
      +]
    • removedInput schema / title
      Removed value: -"vo_synthArguments"
  2. First observedv0.24.0

TDQS

A4.5/5.0
Behavior5/5

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

Annotations already declare destructiveHint=true, and the description richly confirms and extends this: it discloses the non-cached splice with double-splice risk, the caching under `cache/synth/` that avoids GPU on repeat, the ranking rule ('best `sim` less a flatness penalty'), the `capped`-never-wins rule, and the readback as 'a report, never a gate.' It even explains the failure mode a clone that sounds right but says the wrong words. This is far beyond what annotations provide and contradicts nothing.

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

Conciseness3/5

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

The description is front-loaded with the core purpose in the first sentence and organized into logical paragraphs (ranking logic, readback, caching/splice warning, plan behavior). However, it is quite long and dense for a description, requiring sustained reading. For a 13-parameter tool much of the length is earned, but it could be tightened without losing essential behavioral disclosure.

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?

An output schema exists, so return values need not be explained. For a destructive, 13-parameter tool with splicing side effects, the description covers everything an agent needs: caching, splice non-idempotency, ranking rules, capped renders, readback semantics, and the `plan` path. The one reliance on `vo_extend`'s documented mechanism is a reasonable pointer rather than a gap. Complete for the tool's complexity.

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?

Schema coverage is 100%, so baseline is 3. The description goes well beyond the schema by explaining the meaning of core outputs and ranking terms (`sim`, `spread`, `chosen`, `capped`) and the rationale behind `flat_floor`/`flat_weight` ('likeness alone keeps the flattest read, because sims in one pool differ by thousandths while spread differs by semitones'). It also clarifies `max_seconds` with a concrete anecdote. This adds real value over the schema's per-parameter descriptions.

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 first sentence is a specific verb+resource: 'Say `text` in a cloned voice — render several seeds, rank them, read the winner back.' This states exactly what the tool does and clearly separates it from its sibling `vo_extend` (splicing/extension) and `transcribe`/`hear` (readback-only). An agent can tell what this tool is for immediately.

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 strong workflow guidance: it explains when to use `plan=True` (report from cached renders, spend no GPU), and explicitly warns against re-calling the splice ('calling again splices a second time — check the timeline or `undo` rather than re-calling'). It references `vo_extend`'s mechanism as an alternative pathway for splicing. It lacks an explicit when-not-to-use statement versus a specific sibling, but the workflow context is clear.

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