{
  "schema_version": "1.0",
  "version": "0.1.0",
  "status": "pre-alpha",
  "name": "Zing MCP Tool Manifest",
  "description": "Static tool inventory. Input schemas are derived from Python type annotations and defaults, not runtime SDK output.",
  "source": "ryanbiddy/zing@d308dc3f9c2b42e305afd4d7d61e4bfa2f276bc4:src/myzing/mcp_server.py",
  "source_ref": "origin/main",
  "schema_source": "python-ast",
  "tool_count": 36,
  "stdio_tool_count": 36,
  "tools": [
    {
      "name": "zing_explain",
      "description": "Explain a local video or uoink:<id> as card.json, card.md, card.png and StyleRecipe. Optional against compares a draft. Returns paths and a short summary, never media bytes. Models stay local. URLs require explicit download consent via offline=false; default offline=true.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string"
          },
          "out_dir": {
            "type": "string"
          },
          "transitions": {
            "type": "boolean",
            "default": true
          },
          "offline": {
            "type": "boolean",
            "default": true
          },
          "against": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          }
        },
        "required": [
          "source",
          "out_dir"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "zing_studio",
      "description": "Start here. Stateless guided creative session: pass path a-f and answers so far; returns the next question with recommendation/reason/evidence, or a plan to confirm. Local probes and a bounded offline reference preview; saved-reference search only with a configured reachable peer. No production or downloads.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "path": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "answers": {
            "anyOf": [
              {
                "type": "object",
                "additionalProperties": {}
              },
              {
                "type": "null"
              }
            ],
            "default": null
          }
        },
        "required": []
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "zing_studio_run",
      "description": "Start a confirmed studio plan for b (no-reference edit), d (style breakdown) or f (re-delivery). Returns a job project; poll with project, optionally cancel=true. For a/c/e reuse match_start, still_concepts/still_render and music_check. Local models only; paths and metadata out.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "answers": {
            "anyOf": [
              {
                "type": "object",
                "additionalProperties": {}
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "confirmed": {
            "type": "boolean",
            "default": false
          },
          "project": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "cancel": {
            "type": "boolean",
            "default": false
          }
        },
        "required": []
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "brief_questions",
      "description": "Get six creative-brief topics with optional answer fields, defaults, and JSON examples. No model calls.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "required": []
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "brief_save",
      "description": "Validate and atomically save answers to brief.json in an existing local project folder. Replaces the whole brief; omitted fields use brief_questions defaults. Returns answers, path, and a recommendation grounded in inventory and any attached reference breakdown. No media bytes, downloads, or model calls.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "project": {
            "type": "string"
          },
          "answers": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "required": [
          "project",
          "answers"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "study_video",
      "description": "Start studying a video (URL or local file path). Returns a slug immediately and measures in the background (typically 1–5 minutes): shot boundaries, word-timed transcript, caption OCR, audio layout. Poll zing_status() for phase, then get_breakdown(slug). Optional kept_media: path to a locally kept copy of the URL's media (e.g. a uoink keep_media file) — studies from it with zero network fetch when it checks out; falls back to fetching with the reason named in warnings.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "url_or_path": {
            "type": "string"
          },
          "kept_media": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          }
        },
        "required": [
          "url_or_path"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "study_uoink_item",
      "description": "Study a uoink corpus item by its stable reference (uoink://item/<id>). Resolves the item's kept media through uoink's token-gated handoff endpoint (INTEGRATION-CONTRACT v1): a usable kept file is studied with zero network fetch and integrity-verified provenance; otherwise zing refetches from the item's source URL and the provenance names why. Needs UOINK_URL/UOINK_TOKEN configured; references only — this tool never accepts a file path.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "item_ref": {
            "type": "string"
          }
        },
        "required": [
          "item_ref"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "import_shot_list",
      "description": "Import a Writer shot-list export (the user-chosen .md file) against a studied breakdown. Validates the writer.shot-list v1 format exactly, stores a content-addressed copy, and returns the path-free zing.shot-list.import receipt (document sha256 + writer://script ref + zing://breakdown target). Re-importing the same file for the same slug is idempotent. The imported plan is editorial context — zing's measured direction stays the authority for keeper spans.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "path": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          }
        },
        "required": [
          "path",
          "slug"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "get_breakdown",
      "description": "Fetch a studied video's Breakdown JSON by slug. Every response carries a `state` field: running | done | failed | absent. The job status is checked FIRST: while a (re-)study runs you get ready=false with the current phase — never superseded measurements (`stale_breakdown_exists` flags that an older snapshot is on disk). If the latest re-study failed but an earlier study succeeded, the last successful breakdown is served with state='failed' plus `restudy_error`, so you decide whether to judge it. A `running` job whose runner process died is reported as failed with recovery instructions. detail='summary' returns meta + pacing + counts without the per-word/per-caption arrays (use it for long videos).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string"
          },
          "detail": {
            "type": "string",
            "default": "full"
          }
        },
        "required": [
          "slug"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "list_breakdowns",
      "description": "List all studied videos in the workspace: slug, platform, title, duration, measurement counts, judgment sections.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "required": []
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "generate_thumbnails",
      "description": "For a studied video slug, extract 3-5 source-resolution thumbnail candidate frames and attach them with three distinct YouTube image-model prompts (emotion, object/result tease, story contrast). Deterministic selectors exclude burned-caption times and cut-adjacent frames, deduplicate near-matches, and ground every prompt promise in the first-30s transcript. Requires stored media and ffmpeg.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string"
          }
        },
        "required": [
          "slug"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "save_judgment",
      "description": "Write your judgment of a breakdown back to Zing (hook type, structure beats, caption style, why it works — the shape is defined by get_prompt('study')). Each top-level section is replaced wholesale; pass model=<your model name> for provenance.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string"
          },
          "judgment": {
            "type": "object",
            "additionalProperties": {}
          },
          "section": {
            "type": "string",
            "default": "study"
          },
          "model": {
            "type": "string",
            "default": ""
          }
        },
        "required": [
          "slug",
          "judgment"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "zing_status",
      "description": "Zing's health and state: tool availability (ffmpeg, yt-dlp, whisper, OCR), workspace stats, running/failed study jobs, available prompts. Cheap — call freely.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "required": []
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "push_to_uoink",
      "description": "Optional: push a studied video's breakdown.md into the user's uoink corpus as a note (only works when the uoink helper is running locally — zing_status shows it under environment). Zing is fully standalone without it.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string"
          }
        },
        "required": [
          "slug"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "list_presets",
      "description": "List installed taste preset packs (curated reference sets with genre and why-picked notes). Empty is honest: personal tastes via setup_taste(links=...) work without any packs.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "required": []
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "setup_taste",
      "description": "Onboard a named taste: from a preset pack OR your own reference links. Idempotent — starts missing studies in the background, builds the StyleProfile when all references are studied; call again with the same arguments to advance. Multiple named tastes are first-class.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "links": {
            "anyOf": [
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "pack": {
            "type": "string",
            "default": ""
          },
          "genre": {
            "type": "string",
            "default": ""
          },
          "platform": {
            "type": "string",
            "default": ""
          }
        },
        "required": [
          "name"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "render_edl",
      "description": "Render EDL v1 or Composition v2 JSON to a video with ffmpeg (cuts, positioned ASS word captions, voiceover/music mix). V2 checks asset/font SHA-256, supported features and layout safety before dispatch. Returns a render_id immediately; rendering runs in the background (seconds to a few minutes) — poll get_render(render_id). Renders without voiceover when no TTS is available (stated).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "edl_path": {
            "type": "string"
          },
          "output_path": {
            "type": "string",
            "default": ""
          }
        },
        "required": [
          "edl_path"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "get_render",
      "description": "A render job's honest state: running / done (with the output path) / failed (with the error and next step).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "render_id": {
            "type": "string"
          }
        },
        "required": [
          "render_id"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "export_otio",
      "description": "Export an EDL json as an OpenTimelineIO (.otio) timeline that opens in real NLEs. Fast and synchronous.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "edl_path": {
            "type": "string"
          },
          "output_path": {
            "type": "string",
            "default": ""
          }
        },
        "required": [
          "edl_path"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "build_profile",
      "description": "Aggregate N studied+judged reference videos into a StyleProfile: robust stats (median/p25/p75) of pacing, hook timing, captions, audio, plus collected judgments. Honest about coverage (n per stat, unjudged sources named). Fast. genre = a docs/taste rubric key (e.g. 'talking-head').",
      "inputSchema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "slugs": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "genre": {
            "type": "string",
            "default": ""
          },
          "platform": {
            "type": "string",
            "default": ""
          }
        },
        "required": [
          "name",
          "slugs"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "get_profile",
      "description": "Fetch a StyleProfile by name: the measured aggregates and collected judgments to compare new videos against (see the 'compare' prompt).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          }
        },
        "required": [
          "name"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "list_profiles",
      "description": "List stored StyleProfiles: name, genre, platform, source counts, unjudged-source count, warnings.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "required": []
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "get_frames",
      "description": "SEE the video: extract labeled still frames at the given timestamps (seconds) from a studied video's stored media. Up to 8 per call (6 recommended). Sample at shot boundaries (shots[].start), hook window 0-3s first, and judge frames together with the transcript — frames alone under-perform. Frames are 1024px longest-edge JPEGs extracted on demand; nothing is cached.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string"
          },
          "timestamps": {
            "type": "array",
            "items": {
              "type": "number"
            }
          }
        },
        "required": [
          "slug",
          "timestamps"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "get_prompt",
      "description": "Fetch a Zing prompt-pack file by name (e.g. 'study': how to judge a Breakdown and write it back). Use this if your client doesn't surface MCP prompts as commands.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "default": "study"
          }
        },
        "required": []
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "still_concepts",
      "description": "Create 1-8 distinct meme concepts from a local photo folder and topic. Requires myzing[memes]. No model calls, network, or media uploads. Supply a new/empty out folder. Optional lines is a local JSON file of AI/user-written ideas; all text is validated. aspect: 1:1, 4:5, 9:16, 16:9. layout: auto, classic, caption, labels. Uses local YuNet when installed/cached; otherwise reports a center heuristic. Optional protect is a list of normalized [x,y,width,height] boxes text must avoid, besides faces and a model-free subject estimate. Returns index_path, contact_sheet path, writer prompt, concept IDs, scores, alt text and warnings, never media bytes.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "photos": {
            "type": "string"
          },
          "topic": {
            "type": "string"
          },
          "out": {
            "type": "string"
          },
          "n": {
            "type": "integer",
            "default": 6
          },
          "aspect": {
            "type": "string",
            "default": "1:1"
          },
          "layout": {
            "type": "string",
            "default": "auto"
          },
          "lines": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "protect": {
            "anyOf": [
              {
                "type": "array",
                "items": {
                  "type": "array",
                  "items": {
                    "type": "number"
                  }
                }
              },
              {
                "type": "null"
              }
            ],
            "default": null
          }
        },
        "required": [
          "photos",
          "topic",
          "out"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "still_render",
      "description": "Re-render a concept from still_concepts: supply its out_folder and concept_id. Verifies the source photo hash, writes a full-size PNG, and records the selection and alt text in index.json. video=true also exports a five-second MP4; gif=true adds MP4 and a bounded GIF (requires FFmpeg). No network. Returns file paths and metadata, never media bytes.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "out_folder": {
            "type": "string"
          },
          "concept_id": {
            "type": "string"
          },
          "video": {
            "type": "boolean",
            "default": false
          },
          "gif": {
            "type": "boolean",
            "default": false
          }
        },
        "required": [
          "out_folder",
          "concept_id"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "meme_templates",
      "description": "Search the offline classic meme catalog: ids, names, box counts, and normalized regions. No images are downloaded.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "search": {
            "type": "string",
            "default": ""
          }
        },
        "required": []
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "meme_ideas",
      "description": "Generate 1-8 deterministic formula ideas for a topic and optional template. No model or network. Use get_prompt('meme-writer') for your own writing judgment.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "topic": {
            "type": "string"
          },
          "template": {
            "type": "string",
            "default": ""
          },
          "n": {
            "type": "integer",
            "default": 6
          },
          "tone": {
            "type": "string",
            "default": "dry"
          },
          "audience": {
            "type": "string",
            "default": ""
          }
        },
        "required": [
          "topic"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "meme_check",
      "description": "Check on-image texts: 70 characters per box, 110 total, beat count, banned filler. Returns valid and structured problems. Empty strings preserve template slots; box_count supports custom regions.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "texts": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "template": {
            "type": "string",
            "default": ""
          },
          "box_count": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          }
        },
        "required": [
          "texts"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "meme_render",
      "description": "Render a finished PNG/JPEG/WebP from exactly one local image path or template id. Requires myzing[memes]. Explicit template requests download a blank from api.memegen.link on cache miss; offline=true forbids downloads. Local photos stay offline. An existing out file is refused unless overwrite=true. Returns a file path and layout metadata, never image bytes. Layouts: classic, caption, labels; regions are normalized [x,y,width,height] in source-image coordinates. Font accepts anton, sans, a system font name, or file path. Optional protect is a list of normalized [x,y,width,height] source boxes text must avoid; faces and a confident model-free subject estimate are also protected (protection reports the estimate and its uncalibrated confidence).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "texts": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "image": {
            "type": "string",
            "default": ""
          },
          "template": {
            "type": "string",
            "default": ""
          },
          "layout": {
            "type": "string",
            "default": ""
          },
          "aspect": {
            "type": "string",
            "default": "1:1"
          },
          "out": {
            "type": "string",
            "default": ""
          },
          "fit": {
            "type": "string",
            "default": ""
          },
          "font": {
            "type": "string",
            "default": ""
          },
          "regions": {
            "anyOf": [
              {
                "type": "array",
                "items": {
                  "type": "array",
                  "items": {
                    "type": "number"
                  }
                }
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "plate": {
            "type": "boolean",
            "default": false
          },
          "shadow": {
            "type": "boolean",
            "default": false
          },
          "rotation": {
            "type": "number",
            "default": 0
          },
          "offline": {
            "type": "boolean",
            "default": false
          },
          "overwrite": {
            "type": "boolean",
            "default": false
          },
          "protect": {
            "anyOf": [
              {
                "type": "array",
                "items": {
                  "type": "array",
                  "items": {
                    "type": "number"
                  }
                }
              },
              {
                "type": "null"
              }
            ],
            "default": null
          }
        },
        "required": [
          "texts"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "meme_render_video",
      "description": "Render a local video/GIF or still image/cached template to H.264 MP4 (AAC when source has audio), optionally a companion GIF. Requires myzing[memes], FFmpeg and ffprobe. No network. Maximum selected duration 30s; trim with source start/end. Still duration defaults to 5s; zoom is 0..0.25. Layouts and text caps match meme_render. at/until arrays give one inclusive output-time window per text, relative to the trimmed clip. GIF limits: 8s, 10fps, 640px wide; parameters may lower these. Existing outputs require overwrite=true. Returns paths, dimensions, durations, byte sizes and text boxes, never media bytes.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "texts": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "video": {
            "type": "string",
            "default": ""
          },
          "image": {
            "type": "string",
            "default": ""
          },
          "template": {
            "type": "string",
            "default": ""
          },
          "layout": {
            "type": "string",
            "default": ""
          },
          "aspect": {
            "type": "string",
            "default": "1:1"
          },
          "out": {
            "type": "string",
            "default": ""
          },
          "fit": {
            "type": "string",
            "default": ""
          },
          "font": {
            "type": "string",
            "default": ""
          },
          "regions": {
            "anyOf": [
              {
                "type": "array",
                "items": {
                  "type": "array",
                  "items": {
                    "type": "number"
                  }
                }
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "plate": {
            "type": "boolean",
            "default": false
          },
          "shadow": {
            "type": "boolean",
            "default": false
          },
          "rotation": {
            "type": "number",
            "default": 0
          },
          "start": {
            "type": "number",
            "default": 0
          },
          "end": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "max_duration": {
            "type": "number",
            "default": 30
          },
          "duration": {
            "type": "number",
            "default": 5
          },
          "zoom": {
            "type": "number",
            "default": 0
          },
          "fps": {
            "type": "integer",
            "default": 30
          },
          "width": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "gif": {
            "type": "boolean",
            "default": false
          },
          "gif_fps": {
            "type": "integer",
            "default": 10
          },
          "gif_width": {
            "type": "integer",
            "default": 640
          },
          "gif_duration": {
            "type": "number",
            "default": 8
          },
          "at": {
            "anyOf": [
              {
                "type": "array",
                "items": {
                  "type": "number"
                }
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "until": {
            "anyOf": [
              {
                "type": "array",
                "items": {
                  "type": "number"
                }
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "overwrite": {
            "type": "boolean",
            "default": false
          }
        },
        "required": [
          "texts"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "inspect_timeline",
      "description": "Create one local PNG showing a filmstrip, aligned waveform, planned cuts and timed transcript. Supply video and out paths; with edl, video must be the rendered edit. Times are output seconds. Use start/end OR around; an EDL without a range centers one row on each cut. breakdown is a stored slug; otherwise EDL captions supply words. Requires myzing[memes] and FFmpeg; no network or ASR. Capped at 60 frames, 12 rows, 12 megapixels, 120 seconds per row and a 50-second decoder budget. Returns PNG path, source/output mappings and pixel metadata, never image bytes. Existing output is refused unless overwrite=true.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "video": {
            "type": "string"
          },
          "out": {
            "type": "string"
          },
          "start": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "end": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "around": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "edl": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "breakdown": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "frames": {
            "type": "integer",
            "default": 5
          },
          "width": {
            "type": "integer",
            "default": 1600
          },
          "radius": {
            "type": "number",
            "default": 1.0
          },
          "overwrite": {
            "type": "boolean",
            "default": false
          }
        },
        "required": [
          "video",
          "out"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "music_check",
      "description": "Rate local music candidates for a brief or v2 plan: good, usable or bad, with measured reasons. Optional length seconds, pace seconds per cut and speech context. Requires myzing[audio] and FFmpeg. No downloads, uploads or song identification. Licensing stays unknown unless the user records a claim; Zing does not verify it.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "tracks": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "brief": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "plan": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "length": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "pace": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "speech": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "license_record": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          }
        },
        "required": [
          "tracks"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "plan_drafts",
      "description": "Plan three distinct Composition v2 edits from a project folder, StyleRecipe JSON path, and saved brief.json. Reads local clip studies from project/breakdowns and ZING_HOME. Writes plan-A/B/C.json, comparison.json, and v1 EDL derivatives when representable. No study, render, model download or network. Returns paths, planned match deviations and named shortages; status=shortage means no trio was written. Seed defaults to 0.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "project": {
            "type": "string"
          },
          "recipe": {
            "type": "string"
          },
          "out": {
            "type": "string"
          },
          "seed": {
            "type": "integer",
            "default": 0
          }
        },
        "required": [
          "project",
          "recipe",
          "out"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "match_start",
      "description": "Start a resumable background reference-to-drafts job. Supply a local file, uoink:<id>, or URL; URL acquisition requires explicit allow_download=true. Supply local clips/out folders and brief path or answers. Uses cached models only. Writes three distinct v2 plans, rendered MP4s, recipe, timeline PNGs and rendered-output match reports. Missing footage yields director shortages. Poll match_status; ready counts require full decode and report.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "reference": {
            "type": "string"
          },
          "clips": {
            "type": "string"
          },
          "out": {
            "type": "string"
          },
          "brief": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "answers": {
            "anyOf": [
              {
                "type": "object",
                "additionalProperties": {}
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "drafts": {
            "type": "integer",
            "default": 3
          },
          "seed": {
            "type": "integer",
            "default": 0
          },
          "resume": {
            "type": "boolean",
            "default": false
          },
          "allow_download": {
            "type": "boolean",
            "default": false
          },
          "studio_options": {
            "anyOf": [
              {
                "type": "object",
                "additionalProperties": {}
              },
              {
                "type": "null"
              }
            ],
            "default": null
          }
        },
        "required": [
          "reference",
          "clips",
          "out"
        ]
      },
      "transports": [
        "stdio"
      ]
    },
    {
      "name": "match_status",
      "description": "Read match job progress, failures/log paths, final comparison and actual ready count. cancel=true stops this server's owned worker tree and preserves checkpoints for resume.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "project": {
            "type": "string"
          },
          "cancel": {
            "type": "boolean",
            "default": false
          }
        },
        "required": [
          "project"
        ]
      },
      "transports": [
        "stdio"
      ]
    }
  ]
}
