> ## Documentation Index
> Fetch the complete documentation index at: https://docs.videngineer.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Cuts

> MCP tools for the cut menu, one-cut reads, cut briefs, building cuts, cross-library cut search, and scene timelines.

Cut and scene tools for one analysis you own (plus library-wide cut search). Parent: [Connector API](/agents/connector-api).

**Cut identity.** Every cut-accepting tool takes either:

* **`cut_number`** — stable 1-based index matching The Cuts grid (cut 3 is cut 3)
* **`technique_id`** — stored id such as `cut-003`

Pass either as `cut`. Unknown references return the valid set.

If cuts are not built yet, cut tools return `cuts_built: false` and name `build_cuts` as recovery.

***

## `list_cuts`

List the compact cut index for one analysis you own. Free, read-only menu: stable cut numbers, titles, durations, brief readiness. Image URLs and descriptions stay in `get_cut()`.

**Charges:** read-only, 0 credits. **Scope:** `mcp:read`.

### Parameters

| Name     | Type   | Allowed / notes | Default  |
| -------- | ------ | --------------- | -------- |
| `job_id` | string | Analysis id     | required |

### Example call

```text theme={null}
list_cuts("EXAMPLE_JOB_ID")
```

### Example response (menu shape)

```json theme={null}
{
  "job_id": "EXAMPLE_JOB_ID",
  "cuts_built": true,
  "count": 31,
  "cuts": [
    {
      "cut_number": 1,
      "technique_id": "cut-001",
      "title": "Cold Open On Hands, No Face",
      "duration_s": 2.4,
      "brief_ready": false
    },
    {
      "cut_number": 3,
      "technique_id": "cut-003",
      "title": "Intimate Static Two-Shot Bonding Frame",
      "duration_s": 3.8,
      "brief_ready": true
    }
  ],
  "note": "Call get_cut(job_id, cut_number) to inspect one cut."
}
```

`brief_ready` means a build spec already exists and `get_cut_brief` re-opens free.

***

## `get_cut`

Read **one** cut from an analysis you own, for free. Returns the cut's `clip_url` (presigned, short-lived \~15 minutes: fetch promptly, never store; null if no clip), up to 8 keyframes, timing, on-screen text, camera/motion signals, scene classes. Never returns or reconstructs a recreation brief — call `get_cut_brief()` when you are ready to remake the cut.

**Charges:** read-only, 0 credits. **Scope:** `mcp:read`.

**Byte budget:** \~**2,983 B wire / \~2.6 KB compact** (measured on cut 4 of a real job).

### Parameters

| Name     | Type          | Allowed / notes                                          | Default  |
| -------- | ------------- | -------------------------------------------------------- | -------- |
| `job_id` | string        | Analysis id                                              | required |
| `cut`    | int or string | Cut number (`4` / `"4"`) or `technique_id` (`"cut-004"`) | required |

### Example call

```text theme={null}
get_cut("4c93985356cf", 4)
```

### Example response (trimmed — real excerpt; presigned URLs omitted)

```json theme={null}
{
  "cut_number": 4,
  "technique_id": "cut-004",
  "title": "Moving-Vehicle POV with Data Overlay",
  "desc": "Driving through San Francisco streets with $1,000,000 AI Bill overlay text",
  "timing": { "duration_s": 2.59, "start_s": 9.55, "end_s": 12.14 },
  "on_screen_text": ["$1,000,000 AI Bill we have this huge bill with Anthropic,"],
  "motion_camera": ["POV · moderate"],
  "scene_classes": ["establishing"],
  "style": {
    "palette": ["#c9a84c", "#7a8a9a", "#4a6a8a"],
    "look": "mixed",
    "composition": "Reflection in side mirror creates layer…"
  }
}
```

Also present on the full payload: `job_id`, `clip_url`, `frames` (up to 8), `next_step` pointing at `get_cut_brief`.

***

## `get_cut_brief`

Generate or re-open the recreation build-spec for **one** cut you own. A new brief costs **2 credits** by default (or **0** when `free_taste` is true), and a brief that already exists for that cut re-opens for **0 additional credits**.

**Charges:** as above. Response reports `charged` and plain-language `credit_status` — do not guess. **Scope:** `mcp:cut_brief`. Annotation title: *Cut Blueprint — 2 credits (re-open free)*. Idempotent re-open.

Server dedupe is on analysis + cut + engine version. Retries cannot double-charge a ready brief.

### Parameters

| Name     | Type          | Allowed / notes              | Default  |
| -------- | ------------- | ---------------------------- | -------- |
| `job_id` | string        | Analysis id                  | required |
| `cut`    | int or string | Cut number or `technique_id` | required |

### Example call

```text theme={null}
get_cut_brief("EXAMPLE_JOB_ID", 3)
```

### Example response (while generating)

```json theme={null}
{
  "job_id": "EXAMPLE_JOB_ID",
  "cut_number": 3,
  "technique_id": "cut-003",
  "status": "running",
  "free_taste": false,
  "will_charge": 2,
  "credit_status": "generation started — will charge 2 credits when ready",
  "message": "Building the Cut Blueprint…",
  "note": "Re-call get_cut_brief with the same cut to retrieve the saved brief."
}
```

### Example response (ready, new)

```json theme={null}
{
  "job_id": "EXAMPLE_JOB_ID",
  "cut_number": 3,
  "technique_id": "cut-003",
  "title": "Intimate Static Two-Shot Bonding Frame",
  "cached": false,
  "charged": 2,
  "credit_status": "generated, 2 credits charged",
  "clip_url": "<signed clip URL, short-lived>",
  "build_spec": {
    "group_prompt": "Locked-off medium two-shot…",
    "frames": [
      {
        "frame_number": 1,
        "timestamp": "0:11",
        "image_prompt": "Medium two-shot of [YOUR SUBJECT]…",
        "video_prompt": "Camera static. Motion: micro only…",
        "camera_motion": "locked off, eye level"
      }
    ],
    "direction": {
      "how_they_did_it": "…",
      "build_steps": "…",
      "difficulty": "moderate"
    }
  },
  "reference_note": "Study the mechanism, then shoot it with your own subjects and footage."
}
```

Re-open same cut: `cached: true`, `charged: 0`, `credit_status` like `brief ready — 0 credits charged on this request`.

***

## `build_cuts`

Build the cut grid for one analysis you own — the recovery step when `list_cuts` / `get_cut` report `cuts_built: false`. Privileged, plan-gated: needs `mcp:build_cuts` **and** a paid plan (Pro+; free plans get `upgrade_required`).

**Charges:** **0 CREDITS FROM YOUR BALANCE** — a wallet statement, not a platform-cost claim: included plan compute runs ffmpeg clipping plus a title-model pass. Annotation title: *Build the cut grid — 0 wallet credits (Pro+)*.

Async: poll `list_cuts(job_id)` until `cuts_built: true` (usually 1–2 minutes). Safe to re-call — a built analysis returns its cuts unchanged. Repeated failures trip a per-job circuit breaker (`build_unavailable`).

### Parameters

| Name     | Type   | Allowed / notes | Default  |
| -------- | ------ | --------------- | -------- |
| `job_id` | string | Analysis id     | required |

### Example call

```text theme={null}
build_cuts("EXAMPLE_JOB_ID")
```

### Example response (build started)

```json theme={null}
{
  "job_id": "EXAMPLE_JOB_ID",
  "status": "running",
  "cuts_built": false,
  "charged": 0,
  "note": "Build started — 0 credits from your balance (included plan compute runs it). Poll list_cuts(job_id) until cuts_built:true."
}
```

Already built: `cuts_built: true`, `charged: 0`, note to call `list_cuts`.

***

## `find_cuts`

Find cuts **across** your library. Free lean index — no media URLs, no analysis bodies.

**Charges:** read-only, 0 credits. **Scope:** `mcp:read`.

**Honest empty:** returns empty until the cut-index **backfill** runs (Mark-gated). The tool and route are live; production data is not filled yet.

### Parameters

| Name                 | Type         | Allowed / notes                                                  | Default |
| -------------------- | ------------ | ---------------------------------------------------------------- | ------- |
| `query`              | string       | Free-text match; max 120 chars                                   | `""`    |
| `cut_scene_type`     | string       | Scene-type filter for the cut                                    | `""`    |
| `has_on_screen_text` | bool or null | When set, only cuts with/without on-screen text                  | `null`  |
| `min_duration`       | number       | Minimum cut duration (seconds)                                   | `0`     |
| `max_duration`       | number       | Maximum; `0` = no upper bound. Must be ≥ `min_duration` when set | `0`     |
| `hook_type`          | string       | Parent analysis hook type                                        | `""`    |
| `limit`              | int          | Max **25**                                                       | `25`    |
| `offset`             | int          | ≥ 0                                                              | `0`     |

### Example call

```text theme={null}
find_cuts(cut_scene_type="talking_head", has_on_screen_text=true, max_duration=4)
```

### Example response (shape when indexed; often empty today)

```json theme={null}
{
  "cuts": [],
  "total": 0,
  "limit": 25,
  "offset": 0,
  "has_more": false,
  "next_offset": null
}
```

When backfill has data, rows are a lean index (job id, cut number / technique id, title, duration, scene type, brief readiness) — still no media.

***

## `list_scenes`

List the scene timeline of one analysis you own — free, read-only, paged. Each row is one scene: index, timestamp, type, subject/on-screen text when present. Scenes are the analyzed timeline; cuts are the signature shots built from them.

**Charges:** read-only, 0 credits. **Scope:** `mcp:read`.

### Parameters

| Name     | Type   | Allowed / notes        | Default  |
| -------- | ------ | ---------------------- | -------- |
| `job_id` | string | Analysis id            | required |
| `limit`  | int    | Default 25, max **60** | `25`     |
| `offset` | int    | ≥ 0                    | `0`      |

### Example call

```text theme={null}
list_scenes("EXAMPLE_JOB_ID", limit=25, offset=0)
```

### Example response (shape)

```json theme={null}
{
  "job_id": "EXAMPLE_JOB_ID",
  "scenes": [
    {
      "scene": 1,
      "ts": "0:00",
      "type": "cold_open",
      "duration_s": 2.4,
      "subject": "Hands counting cash",
      "text": "Break the cycle"
    }
  ],
  "count": 25,
  "total": 48,
  "limit": 25,
  "offset": 0,
  "has_more": true,
  "next_offset": 25
}
```
