Skip to content

cuttingfloor

io.github.Mvp2o-ai/cuttingfloorMvp2o-aistreamable-httpv0.27.3Scanned

Hosted video editing for AI agents: cut, caption, mix and export real video. Sign in with OAuth.

71 tools: 8 can delete or cancel things, 1 do something that can't be undone, 51 change things and 11 only read.

Tools: 8 delete, 1 irreversible, 51 write, 11 read.
  • Reads private data · 4
  • Reads text others write · 6
  • Can send data out · 3
  • 14 findings

Tools listed without sign-in. Remote posture

Anlyon alternative

60 of these tools change something. Run those as governed actions.

Declare what an action changes, and Anlyon puts it under a shared limit, binds every approval to the exact request, and grades the outcome. It works on any HTTPS API you can describe as an action.

Anlyon does not run, proxy or govern this MCP server. A tool your own code calls directly is not routed through Anlyon and is not governed by it.

Import an OpenAPI spec →

Tools

Grouped by what each tool does, most consequential first. Open one for its reasons and full description; descriptions are the publisher's own words.

71 tools

Deletes or cancels 8Claude Code: deny
  • clip.removeRemove a clip and the clips linked to it; ripple closes the gap.1 finding

    Why it is in this group

    • The name "clip.remove" says "remove": a word for removing or ending something.
    • The server marks it not destructive (destructiveHint: false), but an annotation never lowers a class.

    Findings

    • Warn

      The server marks "clip.remove" not destructive (destructiveHint: false), and its own name, description or input give the class "destructive".

      Matched text

      annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "clip.remove" says "remove": a word for removing or ending something.

      What this check looks for
    Description, as the server wrote it
    Remove a clip and the clips linked to it; ripple closes the gap. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Remove clip
  • filter.removeTake an effect off.1 finding

    Why it is in this group

    • The name "filter.remove" says "remove": a word for removing or ending something.
    • The server marks it not destructive (destructiveHint: false), but an annotation never lowers a class.

    Findings

    • Warn

      The server marks "filter.remove" not destructive (destructiveHint: false), and its own name, description or input give the class "destructive".

      Matched text

      annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "filter.remove" says "remove": a word for removing or ending something.

      What this check looks for
    Description, as the server wrote it
    Take an effect off. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Remove effect
  • job.cancelStop a running job.1 finding

    Why it is in this group

    • The name "job.cancel" says "cancel": a word for removing or ending something.
    • The server marks it not destructive (destructiveHint: false), but an annotation never lowers a class.

    Findings

    • Warn

      The server marks "job.cancel" not destructive (destructiveHint: false), and its own name, description or input give the class "destructive".

      Matched text

      annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "job.cancel" says "cancel": a word for removing or ending something.

      What this check looks for
    Description, as the server wrote it
    Stop a running job. Finished jobs are left as they are.

    Annotations the server declares

    • title: Cancel job
    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • media.deleteDelete a media for good, so an old or wrong version stops turning up: its file here, proxy, mezzanine and media.analyze results go, and its room comes back to the storage cap.No findings

    Why it is in this group

    • The name "media.delete" says "delete": a word for removing or ending something.
    • The server marks it destructive (destructiveHint: true).
    Description, as the server wrote it
    Delete a media for good, so an old or wrong version stops turning up: its file here, proxy, mezzanine and media.analyze results go, and its room comes back to the storage cap. A path import leaves the original in its folder; exports made from it stay. Timelines that use it keep their ids and edits but no longer render (media_offline names it, as for expired media): replace those clips with clip.replace. Importing the same file again makes a new media_id.

    Annotations the server declares

    • title: Delete media
    • readOnlyHint: false
    • destructiveHint: true
    • idempotentHint: true
    • openWorldHint: false
  • range.extractRemove everything in a frame range on the given tracks (default all unlocked) and close the gap.1 finding

    Why it is in this group

    • The description's first verb is "remove": a word for removing or ending something.
    • The server marks it not destructive (destructiveHint: false), but an annotation never lowers a class.

    Findings

    • Warn

      The server marks "range.extract" not destructive (destructiveHint: false), and its own name, description or input give the class "destructive".

      Matched text

      annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The description's first verb is "remove": a word for removing or ending something.

      What this check looks for
    Description, as the server wrote it
    Remove everything in a frame range on the given tracks (default all unlocked) and close the gap. For cutting out silences, filler words or mistakes across all tracks at once. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Extract range
  • range.liftRemove everything in a frame range on the given tracks (default all unlocked), leaving a gap.1 finding

    Why it is in this group

    • The description's first verb is "remove": a word for removing or ending something.
    • The server marks it not destructive (destructiveHint: false), but an annotation never lowers a class.

    Findings

    • Warn

      The server marks "range.lift" not destructive (destructiveHint: false), and its own name, description or input give the class "destructive".

      Matched text

      annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The description's first verb is "remove": a word for removing or ending something.

      What this check looks for
    Description, as the server wrote it
    Remove everything in a frame range on the given tracks (default all unlocked), leaving a gap. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Lift range
  • track.removeRemove a track and its clips.1 finding

    Why it is in this group

    • The name "track.remove" says "remove": a word for removing or ending something.
    • The server marks it not destructive (destructiveHint: false), but an annotation never lowers a class.

    Findings

    • Warn

      The server marks "track.remove" not destructive (destructiveHint: false), and its own name, description or input give the class "destructive".

      Matched text

      annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "track.remove" says "remove": a word for removing or ending something.

      What this check looks for
    Description, as the server wrote it
    Remove a track and its clips. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Remove track
  • transition.removeRemove a transition; the cut becomes a hard cut.1 finding

    Why it is in this group

    • The name "transition.remove" says "remove": a word for removing or ending something.
    • The server marks it not destructive (destructiveHint: false), but an annotation never lowers a class.

    Findings

    • Warn

      The server marks "transition.remove" not destructive (destructiveHint: false), and its own name, description or input give the class "destructive".

      Matched text

      annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "transition.remove" says "remove": a word for removing or ending something.

      What this check looks for
    Description, as the server wrote it
    Remove a transition; the cut becomes a hard cut. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Remove transition
Can't be undone 1Claude Code: ask
  • create.matteA solid or gradient picture (PNG, any length on a timeline): backgrounds, slugs, colour washes with clip.set_blend.Can send data outNo findings

    Why it is in this group

    • The name "create.matte" says "create": a word for a change.
    • The input addresses people (input.gradient.to): what it sends cannot be taken back.

    What it can reach

    • outboundThe input takes a destination (input.gradient.to): what the tool writes goes there.
    Description, as the server wrote it
    A solid or gradient picture (PNG, any length on a timeline): backgrounds, slugs, colour washes with clip.set_blend. Gradients work like CSS: angle 180 runs top to bottom; radial reaches the corners; colours may carry alpha (#RRGGBBAA). Long-running like every create.* tool, but quick.

    Annotations the server declares

    • title: Create a matte
    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
Changes things 51Claude Code: ask
  • adjustment.addAn empty clip on a video track whose effects (filter.add with its clip_id) change everything below it while it runs: a colour grade or blur over a stretch of the edit.No findings

    Why it is in this group

    • The name "adjustment.add" says "add": a word for a change.
    Description, as the server wrote it
    An empty clip on a video track whose effects (filter.add with its clip_id) change everything below it while it runs: a colour grade or blur over a stretch of the edit. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Add adjustment clip
  • audio.fadeFade a clip's sound in from its start and out to its end.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    Description, as the server wrote it
    Fade a clip's sound in from its start and out to its end. null removes a fade. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Fade audio
  • audio.set_gainVolume of an audio clip (or a video clip's linked audio) in dB; keyframes ride it up and down.No findings

    Why it is in this group

    • The name "audio.set_gain" says "set": a word for a change.
    Description, as the server wrote it
    Volume of an audio clip (or a video clip's linked audio) in dB; keyframes ride it up and down. The preview is a waveform of the clip with the measured loudness. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Set gain
  • audio.set_masterGain (dB) and limiter ceiling on the whole mix.No findings

    Why it is in this group

    • The name "audio.set_master" says "set": a word for a change.
    Description, as the server wrote it
    Gain (dB) and limiter ceiling on the whole mix. The ceiling caps sample peaks (dBFS); the true peak between samples can land above it, most on dense, bright sound, and qa.check measures it (dBTP). Audio edits preview with the measured loudness. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Set master
  • audio.set_panPlace a clip's sound left (-1) to right (1).No findings

    Why it is in this group

    • The name "audio.set_pan" says "set": a word for a change.
    Description, as the server wrote it
    Place a clip's sound left (-1) to right (1). Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Set pan
  • caption.addCaptions on a video track from segments (with optional word timings for highlights), from SRT/VTT text, or in_clip: segments timed in seconds of a clip's media, such as transcript …No findings

    Why it is in this group

    • The name "caption.add" says "add": a word for a change.
    Description, as the server wrote it
    Captions on a video track from segments (with optional word timings for highlights), from SRT/VTT text, or in_clip: segments timed in seconds of a clip's media, such as transcript word times, placed where they play. One clip per caption; returns their clip_ids. A style field you leave out takes the published default (video://catalog/text: bold white Inter at 6% of the frame height, near the bottom, with a black outline); timeline.get shows the full style. Burned in when exported. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Add captions
  • clip.addPlace media on the timeline.No findings

    Why it is in this group

    • The name "clip.add" says "add": a word for a change.
    Description, as the server wrote it
    Place media on the timeline. A/V media lands as a linked pair on a video and an audio track. Default: the whole media, after the last clip, overwriting. A picture is scaled to fit the frame (a small logo fills it edge to edge); clip.set_transform {fit: "none"} keeps its own pixel size. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Add clip
  • clip.freezeHold the frame at at_frame for duration_frames: the clip splits there, a freeze frame goes in, and later clips on its tracks move later.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    Description, as the server wrote it
    Hold the frame at at_frame for duration_frames: the clip splits there, a freeze frame goes in, and later clips on its tracks move later. Freezing a clip's last frame holds it after the clip, with silence under the hold. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Freeze frame
  • clip.moveMove a clip (and its linked clips) to a frame and optionally another track.No findings

    Why it is in this group

    • The name "clip.move" says "move": a word for a change.
    Description, as the server wrote it
    Move a clip (and its linked clips) to a frame and optionally another track. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Move clip
  • clip.replaceSwap the media in a clip, keeping its place, length, speed and look.No findings

    Why it is in this group

    • The name "clip.replace" says "replace": a word for a change.
    Description, as the server wrote it
    Swap the media in a clip, keeping its place, length, speed and look. Starts at source_in (default 0). Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Replace media
  • clip.rollMove the cut between a clip and the clip right after it: one gets longer, the other shorter, nothing else moves.No findings

    Why it is in this group

    • The description's first verb is "move": a word for a change.
    Description, as the server wrote it
    Move the cut between a clip and the clip right after it: one gets longer, the other shorter, nothing else moves. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Roll edit
  • clip.set_animationEntrance, exit and loop presets layered over the clip transform (video://catalog/animations): e.g.No findings

    Why it is in this group

    • The name "clip.set_animation" says "set": a word for a change.
    Description, as the server wrote it
    Entrance, exit and loop presets layered over the clip transform (video://catalog/animations): e.g. in {name: "pop", duration_frames: 12}, loop {name: "float"}. null removes one. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Set animation
  • clip.set_blendHow a video clip mixes with the tracks below: normal, multiply, screen, overlay and more (video://catalog/blend_modes).No findings

    Why it is in this group

    • The name "clip.set_blend" says "set": a word for a change.
    Description, as the server wrote it
    How a video clip mixes with the tracks below: normal, multiply, screen, overlay and more (video://catalog/blend_modes). Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Set blend mode
  • clip.set_enabledA disabled clip stays on the timeline but renders as a gap.No findings

    Why it is in this group

    • The name "clip.set_enabled" says "set": a word for a change.
    Description, as the server wrote it
    A disabled clip stays on the timeline but renders as a gap. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Enable/disable clip
  • clip.set_maskShow only part of a video clip: rectangle (rounded), ellipse, linear, mirror, heart, star or polygon, with feather and invert.No findings

    Why it is in this group

    • The name "clip.set_mask" says "set": a word for a change.
    Description, as the server wrote it
    Show only part of a video clip: rectangle (rounded), ellipse, linear, mirror, heart, star or polygon, with feather and invert. Position, size, rotation and feather animate like transform values. null removes the mask. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Set mask
  • clip.set_speedSpeed up, slow down, ramp or reverse a clip and its linked clips.No findings

    Why it is in this group

    • The name "clip.set_speed" says "set": a word for a change.
    Description, as the server wrote it
    Speed up, slow down, ramp or reverse a clip and its linked clips. rate is constant; curve is a speed ramp over the clip. The clip keeps its source and its length changes; ripple (default) moves later clips. Pitch is kept unless preserve_pitch is false. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Set speed
  • clip.set_transformPosition, scale, rotate, fade, flip, crop or fit a video clip over the tracks below (picture-in-picture, overlays, punch-ins).No findings

    Why it is in this group

    • The name "clip.set_transform" says "set": a word for a change.
    Description, as the server wrote it
    Position, scale, rotate, fade, flip, crop or fit a video clip over the tracks below (picture-in-picture, overlays, punch-ins). fit none shows a graphic at its own pixel size, so scale 1 is its real size; the default contain scales it to touch the frame edges. Any number takes a constant or {keyframes: [{frame, value, ease}]} with frames from the clip start; eases are listed at video://catalog/eases. Omitted fields keep their value; null resets one. To pin an overlay to a moving subject, use media.analyze track boxes as keyframes: for each box, frame = timeline frame of the box time (where the tracked clip plays that media second) minus this clip's start, x = box x + w/2 and y = box y + h/2 (add your offset). That holds when the tracked clip fills the frame as is; if it is scaled, moved or cropped, map the box through its transform first. Skip boxes with found false. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Set transform
  • clip.slideMove a clip between its neighbours: the clip before it and the clip after it change length so nothing else moves.No findings

    Why it is in this group

    • The description's first verb is "move": a word for a change.
    Description, as the server wrote it
    Move a clip between its neighbours: the clip before it and the clip after it change length so nothing else moves. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Slide edit
  • clip.slipShow earlier or later source in a clip without moving or resizing it.1 finding

    Why it is in this group

    • The description's first verb is "show": a word for reading.
    • The server marks it as not read-only (readOnlyHint: false).

    Findings

    • Warn

      The server marks "clip.slip" as not read-only (readOnlyHint: false), and its words say it reads.

      Matched text

      annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The description's first verb is "show": a word for reading.

      What this check looks for
    Description, as the server wrote it
    Show earlier or later source in a clip without moving or resizing it. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Slip edit
  • clip.splitCut a clip (and its linked clips) in two at a frame.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    Description, as the server wrote it
    Cut a clip (and its linked clips) in two at a frame. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Split clip
  • clip.trimMove the start or end edge of a clip.No findings

    Why it is in this group

    • The description's first verb is "move": a word for a change.
    Description, as the server wrote it
    Move the start or end edge of a clip. side: video or audio trims one half of a link group (J/L cuts). Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Trim clip
  • create.cutoutA subject without its background, local: ProRes 4444 with alpha and the sound, or a PNG, to lay over a new background.No findings

    Why it is in this group

    • The name "create.cutout" says "create": a word for a change.
    Description, as the server wrote it
    A subject without its background, local: ProRes 4444 with alpha and the sound, or a PNG, to lay over a new background. subject any (BiRefNet) cuts out products, animals or objects; people (MODNet) is fast enough for long video. Long-running: a task, or {job_id, media_id} for job.get.

    Annotations the server declares

    • title: Cut out a subject
    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • create.lipsyncMake a person on camera say different words: their mouth is redrawn to match the speech you give (a re-recorded line, a create.voiceover, a word taken from elsewhere in the take).Reads text others writeNo findings

    Why it is in this group

    • The name "create.lipsync" says "create": a word for a change.

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
    Description, as the server wrote it
    Make a person on camera say different words: their mouth is redrawn to match the speech you give (a re-recorded line, a create.voiceover, a word taken from elsewhere in the take). Runs at the user's lip-sync provider on their own key (sync. labs), and the provider bills them for each second sent. To replace a line or swap a word, give range, the span of the video where it is said, and audio (with audio_range) holding just the new words. The result is that span alone, re-synced and carrying the new speech, as long as the speech with sync_mode remap; place it over the original span (clip.add on a track above, or clip.replace) and mute the old words. Send only the span: it costs less and finishes sooner. Lip sync is for when the face stays on screen while the words change. When the speaker is off screen at that moment, or a cutaway (b-roll, the screen being talked about, a reaction) can cover the splice, the cutaway hides the edit without it. Takes minutes. Long-running: a task, or {job_id, media_id} for job.get. The same recipe returns the same media. Provider limits (plan length, credits, file size) come back as limit_exceeded with the provider's error_code.

    Annotations the server declares

    • title: Lip-sync a video to new speech
    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: true
  • create.motionRender animated HTML to a video with alpha, frame-exactly: lower thirds, animated titles, callouts, logo stings, kinetic type, generated graphics.No findings

    Why it is in this group

    • The name "create.motion" says "create": a word for a change.
    Description, as the server wrote it
    Render animated HTML to a video with alpha, frame-exactly: lower thirds, animated titles, callouts, logo stings, kinetic type, generated graphics. Place the media_id with clip.add on a track above the video. Up to 60 s, and width × height × fps × seconds up to 30 s of 1080p30. Runs in the sandbox: no network (inline everything, load libraries from lib/; assets are for imported files the page must show as they are, like the user's logo or a font), fixed memory and time limits. To match a reference you were shown, rebuild it in HTML/SVG; it does not need importing. Long-running: returns a task, or {job_id, media_id} for job.get. The same recipe returns the same media.

    Annotations the server declares

    • title: Create a motion graphic
    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • create.stabilizedA steadied copy of shaky video, local (vid.stab): one pass measures the camera shake over the whole media, a second moves each frame against a smoothed camera path.No findings

    Why it is in this group

    • The name "create.stabilized" says "create": a word for a change.
    Description, as the server wrote it
    A steadied copy of shaky video, local (vid.stab): one pass measures the camera shake over the whole media, a second moves each frame against a smoothed camera path. New media, ProRes with the sound, to put on the timeline in place of the shaky clip (clip.replace keeps its place and timing). Long-running: a task, or {job_id, media_id} for job.get.

    Annotations the server declares

    • title: Steady shaky video
    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • create.stemsThe sound of a video or audio file pulled apart into stems, each new audio media for clip.add: vocals (voices, spoken or sung), drums, bass, other (everything else: guitars, keys, …No findings

    Why it is in this group

    • The name "create.stems" says "create": a word for a change.
    Description, as the server wrote it
    The sound of a video or audio file pulled apart into stems, each new audio media for clip.add: vocals (voices, spoken or sung), drums, bass, other (everything else: guitars, keys, effects, room noise) and no_vocals (all but the voice, in one file). Laid together at the same time, the four stems make the original sound again. Use it to keep only the voice (lose the music under an interview: vocals), keep only the music (take the voice out of a clip: no_vocals), turn the music down under speech (vocals and no_vocals on their own tracks, with their own gain), or take a beat or a bass line on its own. Demucs v4 (htdemucs), local, on the CPU: about a fifth of the media's length on 8 cores (a minute of sound in about 15 s). Built for music; on speech with background noise, vocals keeps the voice and other takes most of the noise. Media up to 3 hours. Each stem is a 32-bit float WAV, 44.1 kHz stereo, as long as the original; the same media and stems give the same media again while they last. Long-running: a task, or a job_id for job.get.

    Annotations the server declares

    • title: Separate voice and music
    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • create.stillRender an HTML page to a PNG: title and end cards, thumbnails, overlays, designed text.No findings

    Why it is in this group

    • The name "create.still" says "create": a word for a change.
    Description, as the server wrote it
    Render an HTML page to a PNG: title and end cards, thumbnails, overlays, designed text. Transparent where nothing is painted. Capture waits for fonts, and for window.__ready if the page sets it to a promise (up to 10 s). Runs in the sandbox: no network (inline everything, load libraries from lib/; assets are for imported files the page must show as they are, like the user's logo or a font), fixed memory and time limits. To match a reference you were shown, rebuild it in HTML/SVG; it does not need importing. Long-running: returns a task, or {job_id, media_id} for job.get.

    Annotations the server declares

    • title: Create a still
    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • create.voiceoverEnglish text spoken by a natural voice (Kokoro, local; the model downloads once) as WAV media.No findings

    Why it is in this group

    • The name "create.voiceover" says "create": a word for a change.
    Description, as the server wrote it
    English text spoken by a natural voice (Kokoro, local; the model downloads once) as WAV media. words (default) times each word into the media transcript (media.get include transcript). Long-running: a task, or {job_id, media_id} for job.get.

    Annotations the server declares

    • title: Create a voiceover
    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • edit.batchApply many edits as one change: one new timeline_id, one preview.No findings

    Why it is in this group

    • The name "edit.batch" says "edit": a word for a change.
    Description, as the server wrote it
    Apply many edits as one change: one new timeline_id, one preview. All apply or none do. Use {"$ref":"ops[N].clip_id"} (or track_id, clip_ids[M]) to use an id an earlier op made. Returns the edit result plus results: [{tool, clip_id?, clip_ids?, track_id?}] per op.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Batch edit
  • export.timelineWrite the edit for another editor: fcpxml (Final Cut Pro, DaVinci Resolve), otio (Premiere, Resolve, OpenTimelineIO apps), edl (CMX 3600, one video track), or srt/vtt (the captions…No findings

    Why it is in this group

    • The description's first verb is "write": a word for a change.
    Description, as the server wrote it
    Write the edit for another editor: fcpxml (Final Cut Pro, DaVinci Resolve), otio (Premiere, Resolve, OpenTimelineIO apps), edl (CMX 3600, one video track), or srt/vtt (the captions). Best effort: warnings lists what the format could not carry (masks, blend modes, effects, animated transforms, ramps, text styling). timeline.get is the lossless copy. media collect makes a .zip with the media files next to the timeline file. Long-running: a task, or {job_id} for job.get; the result has a signed download URL.

    Annotations the server declares

    • title: Export timeline
    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • export.videoRender the timeline to a file.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    Description, as the server wrote it
    Render the timeline to a file. Presets: web_1080p_h264 (MP4, fits 1920x1080), master_prores_422hq (MOV, sequence size), social_9x16_h264 (9:16 sequences, 1080x1920), web_1080p_av1 (MP4, AV1/Opus), gif (640 px, 15 fps), review_h264 (MP4, fits 854x854 with sound: small and quick, to watch a cut), audio_wav_48k, audio_mp3. overrides changes size, fps, bitrate or crf (video://catalog/presets). Long-running: returns a task, or {job_id} for job.get. The result links the file (a resource_link to video://jobs/{job_id}/output, which reads as the file, or its signed URL when large), has a signed download URL and a page_url that plays it in any browser (the link to give a person to watch or share), both working for 24 h (job.get gives fresh ones) . The server keeps the file 7 days: to keep it longer, save it from the url, and media.import it to use it again. qa.check measures a render (gaps, frames, loudness) before you export.

    Annotations the server declares

    • title: Export video
    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • filter.addApply an effect from video://catalog/effects (colour, LUT, blur, vignette, chroma key, glitch; EQ, compressor, denoise, pitch and more) to a clip, every clip on a track, or the who…No findings

    Why it is in this group

    • The name "filter.add" says "add": a word for a change.
    Description, as the server wrote it
    Apply an effect from video://catalog/effects (colour, LUT, blur, vignette, chroma key, glitch; EQ, compressor, denoise, pitch and more) to a clip, every clip on a track, or the whole timeline. Number params take keyframes. Returns its id as clip_id. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Add effect
  • filter.setChange an effect's params (merged) or turn it off and on.No findings

    Why it is in this group

    • The name "filter.set" says "set": a word for a change.
    Description, as the server wrote it
    Change an effect's params (merged) or turn it off and on. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Set effect
  • judge.askAsk TypeSafe Jev, a fast judgment model (preview), your questions about a state you give, and get typed answers back in about a second.Reads text others write1 finding

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.

    Findings

    • Info

      The description is 2,634 characters long, over the 2,000 this check looks for.

      Matched text

      description ends: "...estions: https://docs.typesafe.ai/primitives and https://docs.typesafe.ai/images."

      What this check looks for
    Description, as the server wrote it
    Ask TypeSafe Jev, a fast judgment model (preview), your questions about a state you give, and get typed answers back in about a second. Jev sees exactly the state: each entry under its name, and your questions refer to entries by name in backticks ("in `passage`"). An entry is text (a string, or a JSON object or array of related facts) or a picture: {media_id} for an imported image, {media_id, at_seconds} for the frame of a video at that time. Mix them freely. Each call stands alone, so put everything a judgment needs into its state. Choose the type by the answer you need. noul: yes or no, answered as noul, the probability of yes from 0 to 1 (0.5 or more reads as yes). choice: one of options you name, answered as choice plus probabilities and confidence. score: a degree on levels you order, answered as score (0 is the first level) plus confidence. box: where one thing is in a picture, answered as box {x, y, w, h} in fractions of that picture plus confidence. Write each question as one thing, worded so yes means it is there. Open with what the state is ("`passage` is a transcript of someone speaking off the cuff"), and give a noul criteria {true, false} with an example of each: Jev answers most accurately from examples. To locate, name the one thing so only it fits ("the yellow headline 'Get started' at the top of `shot`") and ask a noul whether it is there; trust a box with high confidence. One call answers many questions about one state at once, so judge many items together: put the shared text in state once, and give each item its own question carrying its own marked copy. Filler words: state {passage: "So basically the way this works is"}, and per word a noul "`passage` is a transcript of someone speaking off the cuff. With one word marked: "So [[basically]] the way this works is". Is the marked word filler, so the sentence says the same without it?" with criteria {true: "the [[the]] report is late", false: "the report is [[late]]"}. A shot: state {shot: {media_id, at_seconds: 12.5}}, choice "What fills `shot`?" with options {speaker: "A person talking to camera", screen: "A screen recording", none: "Anything else"}. Both: state {line: "Click Get started", screen: {media_id, at_seconds: 4}}, noul "Does `screen` show the button `line` talks about?". Up to 300 questions, 8 pictures and 200k characters of text a call. To find where something shows in a video or an edit, media.seek takes it in plain words; to measure every frame, media.analyze look asks your questions of frames it samples. Guide to writing questions: https://docs.typesafe.ai/primitives and https://docs.typesafe.ai/images.

    Annotations the server declares

    • title: Ask Jev
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: true
  • media.analyzeFind what is in imported media, or in the sound of an edit, as data for edits.Reads text others write2 findings

    Why it is in this group

    • The name "media.analyze" says "analyze": a word for reading.
    • The server marks it as not read-only (readOnlyHint: false).

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.

    Findings

    • Info

      The description is 5,662 characters long, over the 2,000 this check looks for.

      Matched text

      description ends: "...estions: https://docs.typesafe.ai/primitives and https://docs.typesafe.ai/images."

      What this check looks for
    • Warn

      The server marks "media.analyze" as not read-only (readOnlyHint: false), and its words say it reads.

      Matched text

      annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true}; The name "media.analyze" says "analyze": a word for reading.

      What this check looks for
    Description, as the server wrote it
    Find what is in imported media, or in the sound of an edit, as data for edits. transcript: every word with its time (whisper.cpp on the CPU; the model downloads once). For English the word edges are then aligned to the sound (wav2vec2 forced alignment): a word starts and ends within about 0.05 s of where its letters sound, and an end on a soft consonant (s, t, k, f) or a breath can ring on up to about 0.1 s more; timing_confidence says how clearly each word was heard. Other languages keep whisper's own times, up to about a second off. Short ums and uhs are often left out of the words; kind speech still hears them. beats: tempo, beat and downbeat times. faces: face boxes over time, e.g. to reframe to 9:16 with clip.set_transform keyframes. track: follow a region you give from a moment on, a box for each sampled time (found false where the subject was lost); to make a title, sticker, arrow or mask follow the subject, turn the boxes into clip.set_transform (or clip.set_mask) keyframes, no tracking of your own needed. look: your own typed questions about what is on screen, answered on every sampled frame (to find where something happens from plain words, media.seek). silence: stretches quieter than threshold_db for at least min_seconds. scenes: times the picture changes by more than threshold (0–100). speech: the probability that someone is speaking, every 32 ms (Silero VAD), and the spans where it is at least your min_probability; it hears speech, not noise or music, so a cough or a door is not speech. loudness: integrated loudness (LUFS), true peak (dBTP), loudness range (LU), RMS level and noise floor (dBFS) over the whole media or from_seconds to until_seconds. To line up two recordings, media.correlate. sounds: what can be heard and when, every 40 ms, for 447 named sounds (video://catalog/sounds: Laughter, Applause, Cough, Sneeze, Music, Speech, Door, Footsteps, Beep…): give labels for the ones you want, or none for every sound that reaches your min_probability; you get each sound's spans and its probability in every frame (a run over the whole media is kept with it; one over from_seconds to until_seconds comes back only). To find a sound you describe in your own words, media.listen. With timeline_id instead of media_id, speech, loudness, silence, sounds measure the edit's mix as it plays, over from_seconds to until_seconds (timeline seconds). A source or range with no sound fails with no_audio, naming it. Times are media seconds (timeline seconds for a timeline); boxes are fractions of the picture. Results stay with the media (media.get include) except track, silence, scenes and loudness, which come back in the result; speech over the whole media is kept (media.get include speech), so asking again with another min_probability or range answers from it. A result too long to return (a long transcript) comes back as its summary and a note: read it in pieces with media.get include and a time range or page. Long-running: returns a task, or a job_id for job.get. HOW LOOK WORKS. TypeSafe Jev, a fast judgment model (preview), answers your questions about frames sampled from the media. Each sampled frame is its own request: Jev sees that one picture, named `frame`, and with with_previous also the frame sampled just before it, named `previous`, plus any state you give: text or JSON entries by name, the same on every frame (the script, what a term means). Every question is answered on every frame, independently and in parallel (about 0.15 s a frame), as typed data you then combine in your own code. Choose the type by the answer you need. noul: yes or no, answered as noul, the probability of yes from 0 to 1. choice: one of options you name, answered as choice plus probabilities and confidence. score: a degree on levels you order, answered as score (0 is the first level; it can land between levels) plus confidence. box: where one thing is, answered as box {x, y, w, h} in fractions of the picture plus confidence. Write each question about the picture as it looks. Name the picture in backticks ("in `frame`"), ask about one thing, word it so yes means the thing is there, and describe it as it appears: "Does `frame` show a human being, even if only their face fills the picture?", "Is one large word laid over `frame`, much bigger than any other text?". To compare, name both pictures and the thing that differs: "Is there a button in `frame` that is not in `previous`?". To locate, name the one thing so only it fits ("the 'Get started for free' button under the headline in `frame`") and, in the same call, a noul asking whether it is there; use the box on frames where that noul is high. Give a choice a none option for frames where nothing fits, and each score level a concrete situation. Read the answers this way: a noul of 0.5 or more reads as yes, and you can set your own cut-off; confidence tells you how far to trust a choice, a score or a box, and a loose box shows as low confidence. Work in passes: every_seconds 1 over the whole media, then at_seconds around the times where answers change. media.get scenes give when the picture cuts; look tells you what is on it. The result gives each question's spans (when a noul reads yes, which choice holds when); every frame's answers stay with the media (media.get include ['look'], the last 10 runs). Up to 600 frames and 32 questions a call. To find the moments that match a description, media.seek takes it in plain words and returns where it holds. For one judgment about text, a still or a single frame, judge.ask answers at once. Full guide to writing questions: https://docs.typesafe.ai/primitives and https://docs.typesafe.ai/images.

    Annotations the server declares

    • title: Analyze media
    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: true
  • media.importImport the user's own video, audio, image or font to edit with or place as is: probe, fingerprint, conform if needed (VFR, rotation, HDR → BT.709), 540p proxy and integrated loudne…Reads text others writeNo findings

    Why it is in this group

    • The name "media.import" says "import": a word for a change.

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
    Description, as the server wrote it
    Import the user's own video, audio, image or font to edit with or place as is: probe, fingerprint, conform if needed (VFR, rotation, HDR → BT.709), 540p proxy and integrated loudness. A reference image to recreate needs no import: rebuild it with create.motion or create.still. Long-running: returns a task, or {job_id, media_id} for job.get. The media_id is usable in edits as soon as the job reports processing, so with many files, start every import first and edit while they finish. Sources: an http(s) URL (Dropbox and Google Drive share links work as they are), {upload: {name, bytes}} for a file you send yourself (the answer is the new media with upload.url: PUT the file there, curl --fail -T file '<url>', and it imports once the last byte arrives, with no base64 in a message; a broken PUT resumes as media.upload says), the upload_id of a file sent through media.upload, a small file as a data: URI (up to 8 MB, with its sha256 so a garbled copy is refused), or the job_id of a completed export.video (its render becomes media). A URL is fetched once, when the import starts: it only has to work until then (a short-lived signed link from the user's own storage is enough), and the copy stays here 7 days after last use. A file the user attached in the chat comes as file, when the client passes it. Importing the same file again returns the same media_id.

    Annotations the server declares

    • title: Import media
    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: true
  • media.uploadA signed URL to send one of the user's files to this server, for files on their machine that the server can't read: PUT the file there (curl --fail -T interview.mp4 '<url>'), then …1 finding

    Why it is in this group

    • The name "media.upload" says "upload": a word for a change.

    Findings

    • Info

      The description mentions "credentials".

      Matched text

      description: "...e: {upload_id}}. The URL needs no other credentials and works for a day. A broken upload re..."

      What this check looks for
    Description, as the server wrote it
    A signed URL to send one of the user's files to this server, for files on their machine that the server can't read: PUT the file there (curl --fail -T interview.mp4 '<url>'), then media.import {source: {upload_id}}. The URL needs no other credentials and works for a day. A broken upload resumes: HEAD the url for Upload-Offset (the bytes received), then PUT the rest with Content-Range: bytes <offset>-<last>/<total>. Large files can go in parts the same way. Without a way to send it yourself, give the user the url: opened in a browser it is a page to drop the file on, which sends it and resumes on its own. media.import says whether the file is all in yet.

    Annotations the server declares

    • title: Upload media
    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
  • qa.checkMeasure the rendered timeline: gaps in the picture, offline media, rendered against expected frame count, integrated loudness (LUFS) and true peak (dBTP), plus black and silent str…No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
    Description, as the server wrote it
    Measure the rendered timeline: gaps in the picture, offline media, rendered against expected frame count, integrated loudness (LUFS) and true peak (dBTP), plus black and silent stretches when you give their settings. With speech {min_probability}, every cut is listed with speech facts: the speech probability of the mix just before and after it (Silero VAD), whether it lands while someone is speaking, the seconds without speech each side, and, per clip edge, the transcript word it cuts through and how much of that word is lost (from the media's transcript, when it has one). Facts only, no verdicts. Short timelines answer at once; longer ones return a task or job.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: QA check
  • render.framesLook at a timeline (or a media file): up to 16 frames as one contact-sheet image (layout grid) or one image each (single).No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
    Description, as the server wrote it
    Look at a timeline (or a media file): up to 16 frames as one contact-sheet image (layout grid) or one image each (single). Media frames are numbered at the media frame rate; a picture that can be see-through (alpha or a palette) is shown over a light checkerboard, so transparency shows as checks and a background baked into the file as itself. size full: up to 4 frames at the sequence (or media) size from the original media, for thumbnails and stills to keep. format webp (default), png or jpeg, with quality for webp and jpeg. Each image comes inline and with a signed download url.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Render frames
  • text.setChange a title's or caption's text, or restyle many at once (clip_ids, or every one on track_id).No findings

    Why it is in this group

    • The name "text.set" says "set": a word for a change.
    Description, as the server wrote it
    Change a title's or caption's text, or restyle many at once (clip_ids, or every one on track_id). The style is merged; null turns an outline, shadow, box or highlight off. Highlight modes and fonts: video://catalog/text and video://catalog/fonts. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Set text
  • timeline.createStart an empty timeline.Can send data outNo findings

    Why it is in this group

    • The name "timeline.create" says "create": a word for a change.

    What it can reach

    • outboundThe input takes a destination (input.sequence.channels): what the tool writes goes there.
    Description, as the server wrote it
    Start an empty timeline. Returns its timeline_id and its tracks (ids for track_id). Timelines are immutable: every edit returns a new timeline_id, and older ids stay valid for 24 hours after last use. For work longer than a day, keep the timeline.get document on your side and restore it with timeline.load.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Create timeline
  • timeline.historyThe chain of edits that made this timeline, newest first.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
    Description, as the server wrote it
    The chain of edits that made this timeline, newest first. To go back, keep using an older timeline_id.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Timeline history
  • timeline.loadRestore a timeline from the document timeline.get returned, e.g.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    Description, as the server wrote it
    Restore a timeline from the document timeline.get returned, e.g. after it expired (24 h after last use). Its media must still be here: media expires 7 days after last use, so import saved files again with media.import and swap them in with clip.replace.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Load timeline
  • timeline.set_sequenceChange resolution, frame rate or audio format.Can send data outNo findings

    Why it is in this group

    • The name "timeline.set_sequence" says "set": a word for a change.

    What it can reach

    • outboundThe input takes a destination (input.sequence.channels): what the tool writes goes there.
    Description, as the server wrote it
    Change resolution, frame rate or audio format. Clip times are kept in time, so they survive a rate change. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Set sequence
  • title.addText on a video track, over the tracks below: styled with font, size, colour, outline, shadow and box, placed by x/y, revealed with a typewriter or word animation.No findings

    Why it is in this group

    • The name "title.add" says "add": a word for a change.
    Description, as the server wrote it
    Text on a video track, over the tracks below: styled with font, size, colour, outline, shadow and box, placed by x/y, revealed with a typewriter or word animation. A style field you leave out takes the published default (video://catalog/text: bold white Inter at 9% of the frame height, centred, with a soft shadow); timeline.get shows the full style. It is a clip, so transforms, masks, animations and transitions apply. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Add title
  • track.addAdd an empty video or audio track.No findings

    Why it is in this group

    • The name "track.add" says "add": a word for a change.
    Description, as the server wrote it
    Add an empty video or audio track. New video tracks go on top. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Add track
  • track.setRename, mute (audio), hide (video) or lock a track.No findings

    Why it is in this group

    • The name "track.set" says "set": a word for a change.
    Description, as the server wrote it
    Rename, mute (audio), hide (video) or lock a track. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Set track
  • transition.addTransition at the cut after a clip, into the clip that touches it (video://catalog/transitions).No findings

    Why it is in this group

    • The name "transition.add" says "add": a word for a change.
    Description, as the server wrote it
    Transition at the cut after a clip, into the clip that touches it (video://catalog/transitions). Linked audio gets a crossfade at the same cut. kind crossfade is sound only: on a video clip it crossfades the linked audio and the picture cuts hard (use mode handles for that). mode overlap (default) overlaps the clips and moves later clips earlier; handles uses source past the cut and moves nothing. changed lists each transition added, with its track and kind. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Add transition
  • transition.setChange a transition's kind or duration.No findings

    Why it is in this group

    • The name "transition.set" says "set": a word for a change.
    Description, as the server wrote it
    Change a transition's kind or duration. Returns the edit result (see the server instructions).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Set transition
Only reads 11Show 11 read-only tools
  • job.getStatus, progress and, once completed, the result of long-running calls (media.import, media.analyze, create.*, export.video, qa.check).No findings

    Why it is in this group

    • The name "job.get" says "get": a word for reading.
    Description, as the server wrote it
    Status, progress and, once completed, the result of long-running calls (media.import, media.analyze, create.*, export.video, qa.check). Same record as tasks/get. status_message says what it is doing, or, while it waits, where it stands in the queue and what it waits for. It answers at once with where each job stands. job_id reads one job; job_ids reads many in one call and answers {jobs, not_found}.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Get job
  • job.listYour recent jobs, newest first.No findings

    Why it is in this group

    • The name "job.list" says "list": a word for reading.
    Description, as the server wrote it
    Your recent jobs, newest first.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: List jobs
  • media.correlateFind how far one recording sits from another: the sync offset of b against a, by cross-correlating their sound, with how strongly they match.No findings

    Why it is in this group

    • The description's first verb is "find": a word for reading.
    Description, as the server wrote it
    Find how far one recording sits from another: the sync offset of b against a, by cross-correlating their sound, with how strongly they match. Use it to line up a camera with a separate microphone, two cameras of the same moment, or a re-recorded line against the original. Each side is imported media or an edit's mix (timeline_id), over its own from_seconds to until_seconds, so you can match a short stretch of b against a longer stretch of a. offset_seconds: b's moment t lines up with a's moment t + offset_seconds, each in its own seconds. To line them up on a timeline, place b's clip so it starts offset_seconds later than a's (earlier when negative), source starts being equal. strength is the correlation of the overlapping sound at that offset, -1 to 1: near 1 the same sound, near 0 unrelated; next_best is the best offset outside the winning peak, and a strength close to it means the match is unclear (repetitive sound, or not the same moment). Offsets are searched up to max_offset_seconds either way, where at least half of the shorter sound overlaps the other. Up to 600 s read from each side. A side with no sound in its range (no audio stream, a range past its end, or digital silence) fails with no_audio, naming which side. Short reads answer at once; longer ones return a task or job.

    Annotations the server declares

    • title: Sync offset
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • media.getStatus, where it came from (origin: the import source, the export of which timeline_id and preset, or the create.* tool and the media it was made from), a signed download url for t…Reads private dataReads text others writeNo findings

    Why it is in this group

    • The name "media.get" says "get": a word for reading.

    What it can reach

    • private-dataThe description's first sentence says "status" and "file": it reads files.
    • untrusted-inputThe description's first sentence says "status" and "url": it reads web pages, which anyone can write.
    Description, as the server wrote it
    Status, where it came from (origin: the import source, the export of which timeline_id and preset, or the create.* tool and the media it was made from), a signed download url for the file (media is kept 7 days after last use: save the file from it to keep it, and media.import it again later) and a page_url that plays or shows it in any browser (to give a person), its format (extension and mime_type, read from the file, not its name), everything the probe read (probe: the format and every stream, e.g. pix_fmt, colour space, primaries, transfer), duration, frame rate, conform reasons, integrated loudness and summaries of media.analyze results under analyses (counts only: analyses.transcript.words is how many words). include returns those results at the top level, e.g. include ["transcript"] gives transcript.words, the list of words with times. For long media, read them in pieces: from_seconds and to_seconds keep what overlaps that stretch of the media, offset and limit page through what is left, and pages says, per analysis, the index of the first item returned in the whole list (for transcript words, the index clip.add source {words} takes), how many matched and next_offset for the next page (null at the end).

    Annotations the server declares

    • title: Get media
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • media.listWhat the user has here: imported and created media, and files they sent that aren't imported yet (through media.upload, or dropped on their account page at cuttingfloor.ai/account)…Reads private dataNo findings

    Why it is in this group

    • The name "media.list" says "list": a word for reading.

    What it can reach

    • private-dataThe description's first sentence says "file": it reads files.
    Description, as the server wrote it
    What the user has here: imported and created media, and files they sent that aren't imported yet (through media.upload, or dropped on their account page at cuttingfloor.ai/account), with names, sizes and when each expires, plus the account's storage used and its cap. When the user mentions a file they sent or dropped ("the interview I uploaded"), find it here by name and media.import {source: {upload_id}} it; complete says it is all in. Listing does not count as a use, so nothing here lasts longer for being listed.

    Annotations the server declares

    • title: List media
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • media.listenFind when something can be heard in a video or audio file, or in an edit as it plays, from what you describe in plain words, so you go straight to it instead of listening to it all…Reads private data1 finding

    Why it is in this group

    • The description's first verb is "find": a word for reading.

    What it can reach

    • private-dataThe description's first sentence says "find" and "file": it reads files.

    Findings

    • Info

      The description is 2,331 characters long, over the 2,000 this check looks for.

      Matched text

      description ends: "...media.analyze kind sounds. Long-running: returns a task, or a job_id for job.get."

      What this check looks for
    Description, as the server wrote it
    Find when something can be heard in a video or audio file, or in an edit as it plays, from what you describe in plain words, so you go straight to it instead of listening to it all: laughter, applause, a cough, a door slamming, a phone ringing, a dog barking, music starting, someone typing, a car passing. Name each sound and say what it is; you get back the stretches of time where each one can be heard, with the moment it is clearest. Use it to: - Find reactions and moments: where the crew or the audience laughs, where people clap or cheer, a gasp, a scream. - Find trouble to cut or cover: a cough, a sneeze, a phone going off, a door, a siren, wind on the microphone, a click or a bump. - Find sound to cut on: a clap, a bang, a hit, the music starting or stopping. HOW IT WORKS. FlexSED, an open-vocabulary sound detection model (local, on the CPU; about 15 to 20 times faster than real time), listens to every 40 ms of the sound and gives each description the probability that it can be heard there. Describe the sound itself, briefly, as you would caption it ("laughter", "a crowd cheering", "glass breaking"), not the scene or a judgment; it is asked as "The sound of <your words>". Short, common sound names work best; put each sound you want in its own entry, up to 16 a call, all listened for at once. READING THE RESULT. matches gives, per sound, each run of frames at or above min_probability (default 0.5) with its start, end, peak_seconds and frame (for render.frames; media frames for video, timeline frames for an edit). peaks gives the highest probability each sound reaches, and scores every probability (step_seconds apart), for your own cut-off. A sound whose peak stays well under your cut-off is most likely not there; one hovering near it is worth a listen or a lower cut-off. Media or an edit: with media_id, times are the file's own seconds; with timeline_id, it listens to the edit's mix as it plays (cuts, gaps, levels and effects included), over from_seconds to until_seconds, and times are timeline seconds, so a match is where that sound now sits in the edit. A source or range with no sound fails with no_audio, naming it. For the 447 sounds with names (Laughter, Applause, Cough, Speech, Music…) as stored data, media.analyze kind sounds. Long-running: returns a task, or a job_id for job.get.

    Annotations the server declares

    • title: Find sounds by description
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • media.seekFind the moments in a video, or in an edit as it renders, that match what you describe in plain words, so you go straight to them instead of watching it all.Reads text others write1 finding

    Why it is in this group

    • The description's first verb is "find": a word for reading.

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.

    Findings

    • Info

      The description is 3,564 characters long, over the 2,000 this check looks for.

      Matched text

      description ends: "...you need measurements rather than moments; judge.ask judges one picture at once."

      What this check looks for
    Description, as the server wrote it
    Find the moments in a video, or in an edit as it renders, that match what you describe in plain words, so you go straight to them instead of watching it all. Name each criterion and say what a matching frame shows; you get back the stretches of time where each one holds, with the time and picture of the best frame in each. Use it to: - Check quality: find frames that are too dark or blown out, out of focus, black or blank (a gap in an edit), with a microphone or crew in shot, with text cut off at the edge, or with a caption over a face. With timeline_id it checks the edit as it renders, titles, effects and gaps included. - Watch efficiently: looking through a whole video costs you a picture for every moment. Seek judges the frames for you and says where things are, so you look only there: where the demo starts, where the speaker holds up the product, where the second location begins. - Pick shots: B-roll or a thumbnail moment that fits a description ("a wide shot of a city street at night", "she smiles straight at the camera with her eyes open"). - Find changes: with with_previous, where the slide changes, someone walks in or the camera angle switches ("`frame` shows a different slide from `previous`"). - Find room or trouble for overlays: where the lower third stays empty for a title, or where a logo, a licence plate or a face appears that needs a blur. HOW TO WRITE CRITERIA. TypeSafe Jev, a fast judgment model (preview), judges each sampled frame on its own, as a picture named `frame` (about 512 px on its long edge; with with_previous also `previous`, the frame sampled before), and gives each criterion the probability that it is true. A criterion is a statement or a question about how the picture looks. Keep one judgment to a criterion, and say what shows rather than a verdict: not "bad lighting" but "the faces are too dark to make out their eyes"; not "a good thumbnail" but "a person looks straight at the camera with eyes open and mouth closed". Criteria that name no picture or state entry in backticks are asked about `frame` ("In `frame`: <your words>"); name `frame`, `previous` or your state entries yourself to judge them together ("`frame` shows the button `line` talks about"). Jev answers most accurately from examples: give {instructions, criteria: {true: "…", false: "…"}} with a case of each ({true: "the face is a dark silhouette against a bright window", false: "the face is evenly lit, a little dim"}). Detail too small to see at that size (fine print, slight softness) answers poorly; check it with render.frames at full size. READING THE RESULT. matches gives, per criterion, each run of consecutive samples at or above min_probability (default 0.5), with its start, end and best sample: peak_seconds, frame (for render.frames) and uri (a resource to read the picture). samples has every probability, for your own cut-off. A probability near 0.5 means Jev cannot tell, not that the thing is half there: reword a criterion that keeps landing there. asked shows the question each criterion became. COST. Each frame is one judgment however many criteria it carries, so ask everything you are looking for in one call (up to 32 criteria). Work in passes: every_seconds 2 to 5 over the whole video, then at_seconds around a match to find more exactly where it starts. Up to 600 frames a call. Long-running: returns a task, or a job_id for job.get. media.analyze look asks typed questions (a choice, a score, a box) of every frame when you need measurements rather than moments; judge.ask judges one picture at once.

    Annotations the server declares

    • title: Seek by natural language
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: true
  • skills.getThe whole skill as Markdown: when to use it, what it needs, numbered Steps naming the tools to call, a decision table and the rules to keep.Reads private dataNo findings

    Why it is in this group

    • The name "skills.get" says "get": a word for reading.

    What it can reach

    • private-dataThe description's first sentence says "table": it reads databases.
    Description, as the server wrote it
    The whole skill as Markdown: when to use it, what it needs, numbered Steps naming the tools to call, a decision table and the rules to keep. Follow the Steps in order.

    Annotations the server declares

    • title: Read a skill
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • skills.searchFind step-by-step instructions for a common job, written for you to follow with these tools: cutting the pauses, ums and restarts out of a talking video, for one.No findings

    Why it is in this group

    • The name "skills.search" says "search": a word for reading.
    Description, as the server wrote it
    Find step-by-step instructions for a common job, written for you to follow with these tools: cutting the pauses, ums and restarts out of a talking video, for one. Search in the user's words; every skill comes back best first with its score (roughly 0 to 1). Below 0.1 is unrelated; a real fit usually scores 0.15 to 0.45, lower for a short or general ask, and an unrelated skill that shares words can score as high, so read the description of each one above 0.1 to judge the fit. Read one with skills.get, then follow its Steps.

    Annotations the server declares

    • title: Find a skill
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • timeline.diffWhich clips, tracks and settings differ between two timelines.No findings

    Why it is in this group

    • The name "timeline.diff" says "diff": a word for reading.
    Description, as the server wrote it
    Which clips, tracks and settings differ between two timelines.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Diff timelines
  • timeline.getThe full timeline: tracks, clips (frames, end exclusive), link groups and the media it uses.No findings

    Why it is in this group

    • The name "timeline.get" says "get": a word for reading.
    Description, as the server wrote it
    The full timeline: tracks, clips (frames, end exclusive), link groups and the media it uses. The server keeps a timeline 24 hours after last use: for work longer than a day, save this document on your side (it is the edit) and restore it with timeline.load.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • title: Get timeline

This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.

Exfil surface

Which tools read private data, which read text someone else can write, and which can send data out. One of each is a path a prompt injection can use.

72 paths in this server alone from private data, through text someone else wrote, to a way out. Denying 3 outbound tools breaks every one.

Reads private data4
Reads files, mail, messages, databases, secrets, calendars or repositories.
Reads text others write6
Brings in text someone else can write: web pages, inbound email, messages, issues and comments.
Can send data out3
Can carry data to people or systems: it sends, posts or publishes, or takes a recipient, channel or URL.
deny to break every path
{
  "permissions": {
    "deny": [
      "mcp__cuttingfloor__create_matte",
      "mcp__cuttingfloor__timeline_create",
      "mcp__cuttingfloor__timeline_set_sequence"
    ]
  }
}

Other servers in the same agent add their own tools to these paths. Audit your whole setup to see them together.

Remote posture

What anyone on the internet sees at the remote endpoint: an anonymous initialize and tools/list, and the public OAuth metadata.

Tools listed without sign-in

Looked at Oct 29, 2026, 21:55 UTC, unchanged since Oct 29, 2026. No credentials were sent and no tool was called. What is looked at.

Reachable
yes
HTTP status of an anonymous initialize
200
tools/list served without credentials
yes
Tools that change things, listed without credentials
60
Protocol version
2025-06-18
WWW-Authenticate on 401
not observed
resource_metadata in WWW-Authenticate
not observed
RFC 9728 protected resource metadata
https://api.cuttingfloor.ai/.well-known/oauth-protected-resource/mcp
Authorization servers
https://auth.cuttingfloor.ai
Legacy HTTP+SSE transport
no
Dynamic client registration
yes
Client ID metadata documents
yes
  • HighThe whole server

    The endpoint served tools/list without credentials, and the list has 60 tools that change things (8 destructive, 1 irreversible, 51 write). Whether a call also works without credentials was not tested: tools are never called.

    Matched text

    https://api.cuttingfloor.ai/mcp: tools/list returned 71 tools to an anonymous client, including track.remove (destructive), clip.remove (destructive), range.lift (destructive), range.extract (destructive), filter.remove (destructive) and 55 more

    What this check looks for

Posture changes

  1. Oct 29, 2026
    • HTTP status of an anonymous initialize: 401 to 200
    • tools/list served without credentials: no to yes
    • Tools that change things, listed without credentials: 0 to 60
    • Protocol version: none to 2025-06-18
    • WWW-Authenticate on 401: yes to not observed
    • resource_metadata in WWW-Authenticate: https://api.cuttingfloor.ai/.well-known/oauth-protected-resource/mcp to none

Findings

Matches of fixed checks, with the text they matched.

9 warn5 info
  • The server marks "track.remove" not destructive (destructiveHint: false), and its own name, description or input give the class "destructive".

    Matched text

    annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "track.remove" says "remove": a word for removing or ending something.

    What this check looks for
  • The server marks "clip.remove" not destructive (destructiveHint: false), and its own name, description or input give the class "destructive".

    Matched text

    annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "clip.remove" says "remove": a word for removing or ending something.

    What this check looks for
  • The server marks "clip.slip" as not read-only (readOnlyHint: false), and its words say it reads.

    Matched text

    annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The description's first verb is "show": a word for reading.

    What this check looks for
  • The server marks "range.lift" not destructive (destructiveHint: false), and its own name, description or input give the class "destructive".

    Matched text

    annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The description's first verb is "remove": a word for removing or ending something.

    What this check looks for
  • The server marks "range.extract" not destructive (destructiveHint: false), and its own name, description or input give the class "destructive".

    Matched text

    annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The description's first verb is "remove": a word for removing or ending something.

    What this check looks for
  • The server marks "filter.remove" not destructive (destructiveHint: false), and its own name, description or input give the class "destructive".

    Matched text

    annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "filter.remove" says "remove": a word for removing or ending something.

    What this check looks for
Show 8 more findings
  • The server marks "transition.remove" not destructive (destructiveHint: false), and its own name, description or input give the class "destructive".

    Matched text

    annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "transition.remove" says "remove": a word for removing or ending something.

    What this check looks for
  • The server marks "media.analyze" as not read-only (readOnlyHint: false), and its words say it reads.

    Matched text

    annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true}; The name "media.analyze" says "analyze": a word for reading.

    What this check looks for
  • The server marks "job.cancel" not destructive (destructiveHint: false), and its own name, description or input give the class "destructive".

    Matched text

    annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "job.cancel" says "cancel": a word for removing or ending something.

    What this check looks for
  • The description mentions "credentials".

    Matched text

    description: "...e: {upload_id}}. The URL needs no other credentials and works for a day. A broken upload re..."

    What this check looks for
  • The description is 5,662 characters long, over the 2,000 this check looks for.

    Matched text

    description ends: "...estions: https://docs.typesafe.ai/primitives and https://docs.typesafe.ai/images."

    What this check looks for
  • The description is 3,564 characters long, over the 2,000 this check looks for.

    Matched text

    description ends: "...you need measurements rather than moments; judge.ask judges one picture at once."

    What this check looks for
  • The description is 2,331 characters long, over the 2,000 this check looks for.

    Matched text

    description ends: "...media.analyze kind sounds. Long-running: returns a task, or a job_id for job.get."

    What this check looks for
  • The description is 2,634 characters long, over the 2,000 this check looks for.

    Matched text

    description ends: "...estions: https://docs.typesafe.ai/primitives and https://docs.typesafe.ai/images."

    What this check looks for

History

Changes to its tool definitions and to its remote endpoint, newest first.

  1. PostureRemote posture changed. HTTP status of an anonymous initialize: 401 -> 200; tools/list served without credentials: no -> yes; Tools that change things, listed without credentials: 0 -> 60 (and 3 more).View diff
    • HTTP status of an anonymous initialize: 401 to 200
    • tools/list served without credentials: no to yes
    • Tools that change things, listed without credentials: 0 to 60
    • Protocol version: none to 2025-06-18
    • WWW-Authenticate on 401: yes to not observed
    • resource_metadata in WWW-Authenticate: https://api.cuttingfloor.ai/.well-known/oauth-protected-resource/mcp to none

Install

Pinned to version 0.27.3. Values in angle brackets are yours to fill in.

claude mcp add --transport http cuttingfloor https://api.cuttingfloor.ai/mcp
claude mcp add --transport http cuttingfloor https://api.cuttingfloor.ai/mcp

Run in a terminal.

Claude Code permissions

Allow the reads, ask before a change or a way out, deny the deletes. Paste into .claude/settings.json.

.claude/settings.json
{
  "permissions": {
    "allow": [
      "mcp__cuttingfloor__timeline_get",
      "mcp__cuttingfloor__timeline_diff",
      "mcp__cuttingfloor__media_list",
      "mcp__cuttingfloor__media_correlate",
      "mcp__cuttingfloor__media_get",
      "mcp__cuttingfloor__media_seek",
      "mcp__cuttingfloor__media_listen",
      "mcp__cuttingfloor__job_get",
      "mcp__cuttingfloor__job_list",
      "mcp__cuttingfloor__skills_search",
      "mcp__cuttingfloor__skills_get"
    ],
    "ask": [
      "mcp__cuttingfloor__timeline_create",
      "mcp__cuttingfloor__timeline_load",
      "mcp__cuttingfloor__timeline_history",
      "mcp__cuttingfloor__timeline_set_sequence",
      "mcp__cuttingfloor__track_add",
      "mcp__cuttingfloor__track_set",
      "mcp__cuttingfloor__clip_add",
      "mcp__cuttingfloor__clip_move",
      "mcp__cuttingfloor__clip_trim",
      "mcp__cuttingfloor__clip_split",
      "mcp__cuttingfloor__clip_link",
      "mcp__cuttingfloor__clip_unlink",
      "mcp__cuttingfloor__clip_set_enabled",
      "mcp__cuttingfloor__clip_set_speed",
      "mcp__cuttingfloor__clip_freeze",
      "mcp__cuttingfloor__clip_roll",
      "mcp__cuttingfloor__clip_slip",
      "mcp__cuttingfloor__clip_slide",
      "mcp__cuttingfloor__clip_replace",
      "mcp__cuttingfloor__title_add",
      "mcp__cuttingfloor__caption_add",
      "mcp__cuttingfloor__text_set",
      "mcp__cuttingfloor__audio_set_gain",
      "mcp__cuttingfloor__audio_set_pan",
      "mcp__cuttingfloor__audio_fade",
      "mcp__cuttingfloor__audio_set_master",
      "mcp__cuttingfloor__filter_add",
      "mcp__cuttingfloor__filter_set",
      "mcp__cuttingfloor__adjustment_add",
      "mcp__cuttingfloor__transition_add",
      "mcp__cuttingfloor__transition_set",
      "mcp__cuttingfloor__clip_set_transform",
      "mcp__cuttingfloor__clip_set_blend",
      "mcp__cuttingfloor__clip_set_mask",
      "mcp__cuttingfloor__clip_set_animation",
      "mcp__cuttingfloor__edit_batch",
      "mcp__cuttingfloor__media_import",
      "mcp__cuttingfloor__media_upload",
      "mcp__cuttingfloor__media_analyze",
      "mcp__cuttingfloor__judge_ask",
      "mcp__cuttingfloor__create_motion",
      "mcp__cuttingfloor__create_still",
      "mcp__cuttingfloor__create_matte",
      "mcp__cuttingfloor__create_voiceover",
      "mcp__cuttingfloor__create_cutout",
      "mcp__cuttingfloor__create_stabilized",
      "mcp__cuttingfloor__create_stems",
      "mcp__cuttingfloor__create_lipsync",
      "mcp__cuttingfloor__render_frames",
      "mcp__cuttingfloor__export_video",
      "mcp__cuttingfloor__qa_check",
      "mcp__cuttingfloor__export_timeline"
    ],
    "deny": [
      "mcp__cuttingfloor__track_remove",
      "mcp__cuttingfloor__clip_remove",
      "mcp__cuttingfloor__range_lift",
      "mcp__cuttingfloor__range_extract",
      "mcp__cuttingfloor__filter_remove",
      "mcp__cuttingfloor__transition_remove",
      "mcp__cuttingfloor__media_delete",
      "mcp__cuttingfloor__job_cancel"
    ]
  }
}

Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. A read that can send data out (it takes a URL, say) asks first too. It assumes the server is installed as cuttingfloor. Review it before you use it.

Capability tags behind 12 rules
  • mcp__cuttingfloor__timeline_create outbound
  • mcp__cuttingfloor__timeline_set_sequence outbound
  • mcp__cuttingfloor__media_import untrusted-input
  • mcp__cuttingfloor__media_list private-data
  • mcp__cuttingfloor__media_analyze untrusted-input
  • mcp__cuttingfloor__media_get private-data, untrusted-input
  • mcp__cuttingfloor__media_seek untrusted-input
  • mcp__cuttingfloor__media_listen private-data
  • mcp__cuttingfloor__judge_ask untrusted-input
  • mcp__cuttingfloor__create_matte outbound
  • mcp__cuttingfloor__create_lipsync untrusted-input
  • mcp__cuttingfloor__skills_get private-data

Pin

Keep the decision: fail CI when the tools change, follow every change, or show a badge.

Pin in CI

Fail a build when the tools you reviewed are not the tools the server serves today.

curl -s "https://anlyon.dev/api/v1/servers/io.github.Mvp2o-ai/cuttingfloor/verify?hash=a293075362288396d05e77ef588c11bea3425cdd3437995a10c99cd1bd2d013e" | jq -e '.changed == false'

Pinned hash a29307536228, from Oct 30, 2026, 01:18 UTC.

Watch

Get told when its tools change: a new tool, a new description, a new class.

https://anlyon.dev/servers/io.github.Mvp2o-ai/cuttingfloor/changes.xml

An Atom feed. Works in any feed reader or Slack's RSS app.

Badge

anlyon.dev badge for io.github.Mvp2o-ai/cuttingfloor
[![anlyon.dev](https://anlyon.dev/badge/io.github.Mvp2o-ai/cuttingfloor.svg)](https://anlyon.dev/servers/io.github.Mvp2o-ai/cuttingfloor)

Source: MCP Registry · repository. Synced Oct 30, 2026, 01:17 UTC.