Skip to main content
Glama

caption_style

DestructiveIdempotent

Read or update the project's stored caption look. Apply presets like clean, karaoke, reveal, or boxed; override colors, position, and timing, and validate changes with plan before writing.

Instructions

Read or change the caption look this project keeps.

The style is project state and the captions are derived from it, so a restyle survives every later cut: regenerating re-reads this. Call it with no arguments to read the current look and learn the field names; any argument sets that field and leaves the others alone. reset drops every override first — reset plus preset starts clean from a preset.

preset is the base look ("clean", "karaoke" for per-word highlight, "reveal" for words landing mid-frame and fading in as spoken, or "boxed"); everything else overrides one of its fields, and only the overrides are stored. reveal ("fade", "blur" or "none") is how each word arrives.

Colours take "#rrggbb", "#rrggbbaa", a name ("yellow", "white", "red", …) or an ASS "&H…" value. text is the word's colour and highlight what it turns as it is spoken, which only shows with karaoke on. position is named: "bottom", "top", "top-right", and so on. Both come back resolved, because ASS quotes colours backwards and alpha-inverted.

plan validates and resolves without writing. Use caption_view to see the result on the actual timeline.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
boxNoDraw an opaque box behind the words. It buys legibility over light footage — white captions over the film's own light cards measure 1.10:1 without one — and costs clean edges, since libass draws one box per override block.
boldNoDraw bold.
fontNoFamily name to draw with. Whether it actually draws is a different question from whether it is installed — `fonts` measures a render, and libass substitutes silently at exit 0.
holdNoHow long a cue lingers after its last word, in seconds.
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.
sizeNoType size, against the project's canvas as the reference frame.
textNoThe word's own colour: `#rrggbb`, `#rrggbbaa`, a name, or an ASS `&H…` value. It comes back resolved, because ASS quotes colours backwards and alpha-inverted.
resetNoDrop every override first. `reset` together with `preset` starts clean from that preset.
marginNoDistance from the frame edge, in canvas pixels.
presetNoThe base look: `clean`, `karaoke` (per-word highlight), `reveal` (words land mid-frame, fading in as spoken) or `boxed`. Everything else overrides one of its fields, and only the overrides are stored.
revealNoHow each word arrives as it is spoken: `fade`, `blur` (blurs and fades in; the outline returns at the end), or `none`. The line is laid out whole from the start, so nothing moves.
shadowNoDrop-shadow distance.
karaokeNoFill each word as it is spoken. The fill is left-to-right within a line rather than a per-word step, which is what the grouping fields below shape.
max_gapNoStart a new cue when the silence between two words exceeds this many seconds.
positionNoWhere captions sit, named: `bottom`, `top`, `top-right` and so on.
highlightNoWhat a word turns as it is spoken. It only shows with `karaoke` on.
max_wordsNoMost words in one caption cue. Grouping is part of the look, which is why it is stored with it.
reveal_msNoHow long a word's reveal takes, in milliseconds. Default 150. Needs a reveal.
box_colourNoColour of the box behind the type, when `box` is on.
reveal_blurNoHow blurred a word starts under `reveal=blur` (ASS `\blur`; a gaussian of 0.85 x this in canvas pixels). Default 6.
max_durationNoLongest a single cue stays on screen, in seconds.
outline_widthNoOutline thickness. With no box this is what holds the words apart from the picture.
outline_colourNoColour of the outline around the type.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed4 schema fields changedv0.43.0
    • changedInput schema / properties / preset / description
      Previous value: -"The base look: `clean`, `karaoke` (per-word highlight) or `boxed`. Everything else overrides one of its fields, and only the overrides are stored."New value: +"The base look: `clean`, `karaoke` (per-word highlight), `reveal` (words land mid-frame, fading in as spoken) or `boxed`. Everything else overrides one of its fields, and only the overrides are stored."
    • addedInput schema / properties / reveal
      Added value: +{
      +  "default": null,
      +  "description": "How each word arrives as it is spoken: `fade`, `blur` (blurs and fades in; the outline returns at the end), or `none`. The line is laid out whole from the start, so nothing moves.",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedInput schema / properties / reveal_blur
      Added value: +{
      +  "default": null,
      +  "description": "How blurred a word starts under `reveal=blur` (ASS `\\blur`; a gaussian of 0.85 x this in canvas pixels). Default 6.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedInput schema / properties / reveal_ms
      Added value: +{
      +  "default": null,
      +  "description": "How long a word's reveal takes, in milliseconds. Default 150. Needs a reveal.",
      +  "type": [
      +    "integer",
      +    "null"
      +  ]
      +}
  2. Changed81 schema fields changedv0.25.0
    • removedInput schema / properties / bold / anyOf
      Removed value: -[
      -  {
      -    "type": "boolean"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / bold / description
      Added value: +"Draw bold."
    • removedInput schema / properties / bold / title
      Removed value: -"Bold"
    • addedInput schema / properties / bold / type
      Added value: +[
      +  "boolean",
      +  "null"
      +]
    • removedInput schema / properties / box / anyOf
      Removed value: -[
      -  {
      -    "type": "boolean"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / box / description
      Added value: +"Draw an opaque box behind the words. It buys legibility over light footage — white captions over the film's own light cards measure 1.10:1 without one — and costs clean edges, since libass draws one box per override block."
    • removedInput schema / properties / box / title
      Removed value: -"Box"
    • addedInput schema / properties / box / type
      Added value: +[
      +  "boolean",
      +  "null"
      +]
    • removedInput schema / properties / box_colour / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / box_colour / description
      Added value: +"Colour of the box behind the type, when `box` is on."
    • removedInput schema / properties / box_colour / title
      Removed value: -"Box Colour"
    • addedInput schema / properties / box_colour / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedInput schema / properties / font / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / font / description
      Added value: +"Family name to draw with. Whether it actually draws is a different question from whether it is installed — `fonts` measures a render, and libass substitutes silently at exit 0."
    • removedInput schema / properties / font / title
      Removed value: -"Font"
    • addedInput schema / properties / font / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedInput schema / properties / highlight / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / highlight / description
      Added value: +"What a word turns as it is spoken. It only shows with `karaoke` on."
    • removedInput schema / properties / highlight / title
      Removed value: -"Highlight"
    • addedInput schema / properties / highlight / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedInput schema / properties / hold / anyOf
      Removed value: -[
      -  {
      -    "type": "number"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / hold / description
      Added value: +"How long a cue lingers after its last word, in seconds."
    • removedInput schema / properties / hold / title
      Removed value: -"Hold"
    • addedInput schema / properties / hold / type
      Added value: +[
      +  "number",
      +  "null"
      +]
    • removedInput schema / properties / karaoke / anyOf
      Removed value: -[
      -  {
      -    "type": "boolean"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / karaoke / description
      Added value: +"Fill each word as it is spoken. The fill is left-to-right within a line rather than a per-word step, which is what the grouping fields below shape."
    • removedInput schema / properties / karaoke / title
      Removed value: -"Karaoke"
    • addedInput schema / properties / karaoke / type
      Added value: +[
      +  "boolean",
      +  "null"
      +]
    • removedInput schema / properties / margin / anyOf
      Removed value: -[
      -  {
      -    "type": "integer"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / margin / description
      Added value: +"Distance from the frame edge, in canvas pixels."
    • removedInput schema / properties / margin / title
      Removed value: -"Margin"
    • addedInput schema / properties / margin / type
      Added value: +[
      +  "integer",
      +  "null"
      +]
    • removedInput schema / properties / max_duration / anyOf
      Removed value: -[
      -  {
      -    "type": "number"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / max_duration / description
      Added value: +"Longest a single cue stays on screen, in seconds."
    • removedInput schema / properties / max_duration / title
      Removed value: -"Max Duration"
    • addedInput schema / properties / max_duration / type
      Added value: +[
      +  "number",
      +  "null"
      +]
    • removedInput schema / properties / max_gap / anyOf
      Removed value: -[
      -  {
      -    "type": "number"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / max_gap / description
      Added value: +"Start a new cue when the silence between two words exceeds this many seconds."
    • removedInput schema / properties / max_gap / title
      Removed value: -"Max Gap"
    • addedInput schema / properties / max_gap / type
      Added value: +[
      +  "number",
      +  "null"
      +]
    • removedInput schema / properties / max_words / anyOf
      Removed value: -[
      -  {
      -    "type": "integer"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / max_words / description
      Added value: +"Most words in one caption cue. Grouping is part of the look, which is why it is stored with it."
    • removedInput schema / properties / max_words / title
      Removed value: -"Max Words"
    • addedInput schema / properties / max_words / type
      Added value: +[
      +  "integer",
      +  "null"
      +]
    • removedInput schema / properties / outline_colour / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / outline_colour / description
      Added value: +"Colour of the outline around the type."
    • removedInput schema / properties / outline_colour / title
      Removed value: -"Outline Colour"
    • addedInput schema / properties / outline_colour / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedInput schema / properties / outline_width / anyOf
      Removed value: -[
      -  {
      -    "type": "number"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / outline_width / description
      Added value: +"Outline thickness. With no box this is what holds the words apart from the picture."
    • removedInput schema / properties / outline_width / title
      Removed value: -"Outline Width"
    • addedInput schema / properties / outline_width / type
      Added value: +[
      +  "number",
      +  "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"
      +]
    • 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"
    • removedInput schema / properties / position / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / position / description
      Added value: +"Where captions sit, named: `bottom`, `top`, `top-right` and so on."
    • removedInput schema / properties / position / title
      Removed value: -"Position"
    • addedInput schema / properties / position / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedInput schema / properties / preset / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / preset / description
      Added value: +"The base look: `clean`, `karaoke` (per-word highlight) or `boxed`. Everything else overrides one of its fields, and only the overrides are stored."
    • removedInput schema / properties / preset / title
      Removed value: -"Preset"
    • addedInput schema / properties / preset / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • addedInput schema / properties / reset / description
      Added value: +"Drop every override first. `reset` together with `preset` starts clean from that preset."
    • removedInput schema / properties / reset / title
      Removed value: -"Reset"
    • removedInput schema / properties / shadow / anyOf
      Removed value: -[
      -  {
      -    "type": "number"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / shadow / description
      Added value: +"Drop-shadow distance."
    • removedInput schema / properties / shadow / title
      Removed value: -"Shadow"
    • addedInput schema / properties / shadow / type
      Added value: +[
      +  "number",
      +  "null"
      +]
    • removedInput schema / properties / size / anyOf
      Removed value: -[
      -  {
      -    "type": "integer"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / size / description
      Added value: +"Type size, against the project's canvas as the reference frame."
    • removedInput schema / properties / size / title
      Removed value: -"Size"
    • addedInput schema / properties / size / type
      Added value: +[
      +  "integer",
      +  "null"
      +]
    • removedInput schema / properties / text / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / text / description
      Added value: +"The word's own colour: `#rrggbb`, `#rrggbbaa`, a name, or an ASS `&H…` value. It comes back resolved, because ASS quotes colours backwards and alpha-inverted."
    • removedInput schema / properties / text / title
      Removed value: -"Text"
    • addedInput schema / properties / text / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedInput schema / title
      Removed value: -"caption_styleArguments"
  3. First observedv0.24.0

TDQS

A4.3/5.0
Behavior4/5

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

Annotations mark destructiveHint=true and readOnlyHint=false, and the description adds meaningful context: `reset` drops overrides, the style persists across cuts, and colors come back resolved due to ASS quirks. It also highlights the non-destructive `plan` path. This goes beyond the annotations without contradicting them.

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 highly structured: it leads with the core purpose, then explains argument semantics, presets, colors, and validation/viewing alternatives. Every paragraph serves a clear function and no sentence is redundant. It is efficiently organized for a tool with 24 parameters.

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

Completeness4/5

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

Given the tool's complexity (24 params) and that an output schema exists, the description covers the essential concepts: read vs. set, reset behavior, preset override model, color resolution, and how to validate/view. It doesn't enumerate every parameter, but the schema already does. The description supplies the conceptual glue an agent needs to use the tool correctly.

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 the baseline is 3. The description enhances understanding by explaining the preset system (e.g., only overrides stored), how `reset` interacts with presets, and the meaning of color formats and position names. It ties parameters together conceptually (e.g., `reveal` needs a reveal_ms, `highlight` shows only with karaoke), adding value beyond the schema.

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+resource pair: 'Read or change the caption look this project keeps.' It clearly distinguishes itself from sibling tools like caption_view (which shows the result), caption_style_save/load (persistence), and caption_style_library (storage). An agent can immediately understand the tool's role.

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?

Provides explicit invocation patterns: call with no arguments to read, with arguments to set fields, and describes reset behavior. It also names `plan` for validation without writing and points to caption_view for visual confirmation. However, it does not explicitly exclude use cases for the persistence-related siblings, so it's not a full 5.

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

Deploy Server

Other Tools