# compositions_save_draft

Canonical HTML page: https://bitterclip.com/docs/assistants/tools/compositions_save_draft

Surface: app-only

Product release: 1dce717408a55fac1047e7d779177fa3ef8ede51
Public contract commit: 1ce47f7857ae3d9b6933fe83d5c33de3ae5efc64
Public contract SHA-256: 241d47d25e4b4c1dae9d2263793874d06fc4ba7bc3c78d4cf2bc63fbb32ed7dc
Descriptor SHA-256: 885d46f3ca3939dec2ace0cd6e93611c8b3f741f2d8f7a82e0adfe1452cc9a9e
Captured: 2026-09-24T16:39:30.100Z
Source: https://app.bitterclip.com/api/v1/mcp_descriptors.json

Durably persist an Episode or Clip's overlays, settings (aspect ratio, captions) and copy (title, description, chapters), each under the optional draft-revision guard. A segment graph is accepted only to promote a Recording draft into its first Episode: pass recording_id and segments while that Recording's working draft has no Program yet. An existing Episode or Clip changes arrangement only through occurrence operations (episode_edit, or episode_edit_full in the editor); a segment graph addressed to one, by composition_id or through its Recording, refuses with program_occurrence_operation_required and changes nothing.

The JSON blocks below are the exact MCP descriptor projections served by Rails for the named profiles at capture time. Security schemes and resource URIs may vary by connected host.

## App descriptor

```json
{
  "name": "compositions_save_draft",
  "title": "Save the composition edit document",
  "description": "Durably persist an Episode or Clip's overlays, settings (aspect ratio, captions) and copy (title, description, chapters), each under the optional draft-revision guard. A segment graph is accepted only to promote a Recording draft into its first Episode: pass recording_id and segments while that Recording's working draft has no Program yet. An existing Episode or Clip changes arrangement only through occurrence operations (episode_edit, or episode_edit_full in the editor); a segment graph addressed to one, by composition_id or through its Recording, refuses with program_occurrence_operation_required and changes nothing.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "recording_id": {
        "type": "string",
        "description": "Recording the draft was opened from (its per-recording working draft). Omit if passing composition_id."
      },
      "composition_id": {
        "type": "string",
        "description": "Existing draft to update. Omit to find-or-create the working draft for recording_id."
      },
      "title": {
        "type": "string"
      },
      "description": {
        "type": "string",
        "description": "Episode description. Defaults to the recording's generated map; an empty string clears it."
      },
      "chapters": {
        "type": "array",
        "maxItems": 250,
        "description": "Optional user-authored Episode-time chapters. Omit to preserve the current field; pass [] to clear it.",
        "items": {
          "type": "object",
          "properties": {
            "start_seconds": {
              "type": "number",
              "minimum": 0,
              "description": "Chapter start on the playable Episode clock."
            },
            "title": {
              "type": "string"
            }
          },
          "required": [
            "start_seconds",
            "title"
          ]
        }
      },
      "aspect_ratio": {
        "type": "string",
        "enum": [
          "9:16",
          "16:9",
          "1:1"
        ],
        "description": "Defaults to 16:9 landscape on a new draft."
      },
      "captions_enabled": {
        "type": "boolean"
      },
      "expected_revision": {
        "type": "string",
        "description": "Optional draft revision token from compositions_get_draft/save responses. When present, stale saves are rejected instead of overwriting newer server edits."
      },
      "segments": {
        "type": "array",
        "description": "Recording-draft promotion only: the ordered first Program (same shape as episode.create) for recording_id's working draft. Omit it, or pass [], for an overlay, settings or copy save; a non-empty graph for an existing Episode or Clip refuses.",
        "items": {
          "type": "object",
          "properties": {
            "recording_id": {
              "type": "string"
            },
            "occurrence_id": {
              "type": "string",
              "description": "Omit for a first Program; every promoted row mints its own stable occurrence identity."
            },
            "part_id": {
              "type": "string",
              "description": "Legacy segment UUID alias retained for compatible editors during the occurrence-identity cutover."
            },
            "start_seconds": {
              "type": "number"
            },
            "end_seconds": {
              "type": "number"
            },
            "crop_strategy": {
              "type": "string",
              "enum": [
                "center_crop",
                "fit_pad"
              ]
            },
            "audio_policy": {
              "type": "string",
              "enum": [
                "source",
                "mute"
              ]
            },
            "caption_mode": {
              "type": "string",
              "enum": [
                "inherit",
                "off",
                "on"
              ]
            },
            "transition_policy": {
              "type": "string",
              "description": "Existing occurrence transition policy. Preserve it unless intentionally changing it."
            },
            "transition_duration_seconds": {
              "type": "number",
              "description": "Existing occurrence transition duration in seconds."
            },
            "metadata": {
              "type": "object",
              "description": "Occurrence-local typed-object, provenance, span, and seam metadata returned by compositions_get_draft."
            }
          },
          "required": [
            "recording_id",
            "start_seconds",
            "end_seconds"
          ]
        }
      },
      "overlays": {
        "type": "array",
        "description": "Overlay track (text/image/pip), replaced whole. Omit it to leave the track untouched; [] clears it. Persisted now; rendered in a later pass.",
        "items": {
          "type": "object"
        }
      }
    },
    "required": [],
    "additionalProperties": false
  },
  "annotations": {
    "readOnlyHint": false,
    "destructiveHint": false,
    "idempotentHint": true,
    "openWorldHint": false
  },
  "securitySchemes": [
    {
      "type": "noauth"
    }
  ],
  "_meta": {
    "securitySchemes": [
      {
        "type": "noauth"
      }
    ],
    "ui": {
      "visibility": [
        "app"
      ]
    },
    "openai/widgetAccessible": true,
    "openai/visibility": "private"
  },
  "outputSchema": {
    "type": "object",
    "properties": {
      "draft": {
        "type": "boolean"
      },
      "composition_id": {
        "type": "string"
      },
      "revision": {
        "type": "string",
        "description": "Opaque draft CAS token."
      },
      "structural_revision": {
        "type": "integer",
        "description": "Monotonic Episode structure revision."
      },
      "status": {
        "type": "string"
      },
      "title": {
        "type": "string"
      },
      "description": {
        "type": "string"
      },
      "chapters": {
        "type": "array"
      },
      "chapter_timebase": {
        "type": "string",
        "enum": [
          "episode"
        ]
      },
      "aspect_ratio": {
        "type": "string"
      },
      "captions_enabled": {
        "type": "boolean"
      },
      "segments": {
        "type": "array"
      },
      "overlays": {
        "type": "array"
      },
      "editor_document": {
        "type": "object",
        "description": "Versioned application document consumed by the shared editor."
      }
    },
    "required": [],
    "additionalProperties": false
  }
}
```

## Errors

```json
[
  "recording_not_found",
  "composition_not_found",
  "invalid_time_range",
  "episode_changed_during_read",
  "invalid_input",
  "stale_composition_revision",
  "program_occurrence_operation_required"
]
```

## Examples

```json
[]
```
