All MCP tools

compositions_save_draft

Save the composition edit document

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.

Surface: App-only

Product release 1dce717408a55fac1047e7d779177fa3ef8ede51
Public contract commit 1ce47f7857ae3d9b6933fe83d5c33de3ae5efc64
Public contract SHA-256 241d47d25e4b4c1dae9d2263793874d06fc4ba7bc3c78d4cf2bc63fbb32ed7dc
Captured 2026-09-24T16:39:30.100Z. Review or improve this contract on GitHub.

These blocks show the complete MCP descriptors captured from serving Rails. Security schemes and resource URIs can differ by connected host.

App descriptor

{
  "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

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

Examples

[]