Skip to main content
Glama

free-video-edit-mcp

Free, open-source MCP server for programmatic video editing via FFmpeg/ffprobe.

Gives AI agents deterministic, verifiable edit tools without DaVinci Resolve or any paid NLE. Structured edits, a powerful argv escape hatch, live docs for your installed FFmpeg build, simple LUT helpers, and plan-vs-output verification over the Model Context Protocol.

Not affiliated with Blackmagic Design. This project does not reverse engineer Resolve, touch Resolve binaries, or implement proprietary Resolve APIs. It is a clean-room FFmpeg workflow exposed as an MCP server (MIT).

Features

  • 16 tools for probe, trim, concat, timeline compose, markers, LUT generate/apply, render presets, docs search, and verify

  • Dual transport: stdio (Cursor / Claude Desktop) and streamable HTTP (ChatGPT remote connectors)

  • Deterministic JSON results (paths, durations, exit codes, stderr tails)

  • Safety guards on run_ffmpeg (argv only, workspace path checks)

Related MCP server: ffmpeg-mcp

Requirements

  • Python 3.10+

  • FFmpeg + ffprobe on PATH (tested with FFmpeg 7.x)

  • An MCP host: Cursor, Claude Desktop, or ChatGPT (remote HTTP)

Install from clone

git clone https://github.com/breverdbidder/free-video-edit-mcp.git
cd free-video-edit-mcp
python3 -m venv .venv
source .venv/bin/activate   # Windows: .venv\\Scripts\\activate
pip install -e ".[dev]"

Set a media workspace (optional; defaults to ~/video-projects):

export FREE_VIDEO_EDIT_ROOT="$HOME/video-projects"
mkdir -p "$FREE_VIDEO_EDIT_ROOT"

Run

Stdio (default Cursor / Claude Desktop)

python -m free_video_edit_mcp
# or after install:
free-video-edit-mcp

Streamable HTTP (ChatGPT / remote)

python -m free_video_edit_mcp --transport streamable-http --host 127.0.0.1 --port 8765
# alias for the same transport:
python -m free_video_edit_mcp --transport http --host 127.0.0.1 --port 8765

MCP endpoint (local): http://127.0.0.1:8765/mcp

Legacy SSE is also available via --transport sse (prefer streamable-http for new remote clients).


Cursor

  1. Install the package (see above).

  2. Open Cursor MCP settings and merge the server block (or copy from configs/cursor.mcp.json).

Exact JSON (adjust the Python path if you use a venv):

{
  "mcpServers": {
    "free-video-edit": {
      "command": "/absolute/path/to/free-video-edit-mcp/.venv/bin/python",
      "args": ["-m", "free_video_edit_mcp"],
      "env": {
        "FREE_VIDEO_EDIT_ROOT": "/absolute/path/to/your/video-projects"
      }
    }
  }
}

On Windows, use the venv interpreter, for example:

C:\\path\\to\\free-video-edit-mcp\\.venv\\Scripts\\python.exe

Restart Cursor (or reload MCP servers) after saving.


Claude Desktop

  1. Install the package.

  2. Edit Claude Desktop’s config file:

    • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

    • Windows: %APPDATA%\\Claude\\claude_desktop_config.json

  3. Merge the server block (also in configs/claude_desktop.mcp.json):

{
  "mcpServers": {
    "free-video-edit": {
      "command": "/absolute/path/to/free-video-edit-mcp/.venv/bin/python",
      "args": ["-m", "free_video_edit_mcp"],
      "env": {
        "FREE_VIDEO_EDIT_ROOT": "/absolute/path/to/your/video-projects"
      }
    }
  }
}

Fully quit and reopen Claude Desktop so it picks up the config.


ChatGPT (remote / streamable HTTP)

ChatGPT does not use local stdio MCP. It expects a remote MCP connector pointing at a URL your machine (or host) serves — almost always a public HTTPS URL.

Steps

  1. Start the HTTP transport locally:

python -m free_video_edit_mcp --transport http --host 127.0.0.1 --port 8765
  1. Expose it with a tunnel (examples):

# Cloudflare Tunnel
cloudflared tunnel --url http://127.0.0.1:8765

# or ngrok
ngrok http 8765
  1. In ChatGPT → Settings → Connectors / Advanced → MCP (labels vary by plan), add a remote MCP server URL such as:

https://YOUR-TUNNEL-HOST/mcp
  1. Enable the connector in a tools-capable chat.

Full notes: configs/chatgpt.remote.md.

Caveats

  • Public HTTPS is typically required; http://127.0.0.1:8765/mcp alone will not work for ChatGPT.

  • A public tunnel exposes FFmpeg tools on your machine. Use auth, IP allowlists, or a private deployment; do not leave an open tunnel unattended.

  • ChatGPT MCP / connector UI availability depends on your OpenAI plan and product surface. If you cannot add a remote MCP connector, use Cursor or Claude Desktop with stdio instead.


Tool list (16)

Tool

Purpose

get_version

FFmpeg/ffprobe + server version

probe_media

ffprobe JSON + summary (duration, resolution, codecs)

search_ffmpeg_docs

Search filters/encoders/decoders listings

get_ffmpeg_docs

Detailed help for a filter/encoder/muxer by name

get_whats_new

Server notes + notable FFmpeg build flags

run_ffmpeg

Escape hatch: argv list (not shell). Path guards unless allow_any_path

trim_clip

Trim by start/end or start+duration

concat_clips

Concat demuxer (copy) or filter (re-encode)

compose_timeline

JSON timeline → single rendered file

add_marker

Write marker to sidecar JSON

list_markers

Read sidecar markers

generate_lut

Write a .cube LUT from exposure/contrast/saturation/temperature

apply_lut

Apply .cube via lut3d

set_render_job

Queue export preset (h264_mp4, prores, webm)

run_render

Execute a render job

verify_edit

Pass/fail plan vs probe (duration, resolution)

Limitations vs DaVinci Resolve

Area

Resolve

This project

Node graph / Fusion

Yes

No

Fairlight audio

Yes

Basic A/V via FFmpeg only

Resolve color management / DCTL

Yes

Simple creative .cube LUTs (not Resolve CMS)

Multi-track timeline UI

Full NLE

JSON timeline → sequential concat of track 0

GPU accelerated grading

Yes

Whatever your FFmpeg build provides

Markers

Native

Sidecar .markers.json files

Codecs / delivery

Broad, licensed

Whatever FFmpeg was compiled with

If you need a full NLE, use Resolve (or another editor). If you need an agent to trim, concat, grade lightly, export, and verify on a headless box, use this.

Safety notes for run_ffmpeg

  • Never pass a shell string; always an argv list[str].

  • Default workspace guard: paths outside FREE_VIDEO_EDIT_ROOT are rejected unless allow_any_path=true.

  • Overwrite only when overwrite=true (passes -y); otherwise -n.

  • Prefer structured tools (trim_clip, concat_clips, …) so results stay verifiable.

  • On remote/HTTP deployments, treat tool access as equivalent to running FFmpeg as the server user.

Example agent prompts

  • “Probe interview.mp4, trim the intro to the first 5 seconds, concat with broll.mp4, then verify_edit for ~duration and 1280×720.”

  • “Generate a slight warm LUT (temperature +20, saturation 1.1), apply it to hero.mp4, export h264_mp4.”

  • “Search FFmpeg docs for lut3d and show me the filter help for the installed build.”

  • “Compose this timeline JSON and verify the output is between 12 and 16 seconds.”

Sample plan: examples/sample_edit_plan.json.

Development / pytest

source .venv/bin/activate
pip install -e ".[dev]"
pytest -q

Smoke tests synthesize tiny color-bars + sine clips with FFmpeg, then trim, concat, LUT, render, and verify.

Project layout

configs/                 # Cursor, Claude Desktop, ChatGPT connector helpers
examples/                # Sample MCP config + edit plan
src/free_video_edit_mcp/ # Server + FFmpeg helpers
tests/                   # Smoke tests

License

MIT — see LICENSE.

Available Tools

16 tools
add_markerC

Add a marker to a sidecar JSON next to a media or timeline file (FFmpeg has no built-in markers).

Inputs: name (required), time (required), target (required), note, +2 more. Returns: object

apply_lutB

Apply a .cube LUT to a clip using ffmpeg lut3d.

Inputs: lut_path (required), input_path (required), output_path (required), interp, +2 more. Returns: object

compose_timelineB

Render a JSON timeline (clips with path, start/in, end/out, track) to one output file.

Timeline schema: {name, clips:[{path,start,end,track,label}], width, height, fps, markers}. Track 0 clips are concatenated in order. Optional save_as persists the timeline JSON.

Inputs: timeline (required), output_path (required), save_as, reencode, +2 more. Returns: object

concat_clipsA

Concatenate clips. method='demuxer' (same codec, stream copy) or 'filter' (re-encode, more robust).

Inputs: inputs (required), output_path (required), method, overwrite, +1 more. Returns: object

generate_lutA

Generate a .cube 3D LUT from simple creative params (exposure stops, contrast, saturation, temperature).

This is a free approximation for grading workflows — not DaVinci Resolve color management.

Inputs: output_path (required), size, title, contrast, +4 more. Returns: object

get_ffmpeg_docsC

Get detailed help for a filter, encoder, decoder, muxer, or demuxer by name (matches live build).

Inputs: name (required), kind. Returns: object

get_versionA

Return ffmpeg/ffprobe versions and this MCP server version.

Inputs: no named parameters. Returns: object

get_whats_newA

Brief notes for this server version plus a summary of notable FFmpeg build flags.

Inputs: no named parameters. Returns: object

list_markersA

List markers from the sidecar JSON associated with a media or timeline file.

Inputs: target (required), allow_any_path. Returns: object

probe_mediaC

Probe a media file with ffprobe. Returns streams, duration, resolution, codecs, and raw JSON.

Inputs: path (required), allow_any_path. Returns: object

run_ffmpegA

Run ffmpeg with an argv argument list (NOT a shell string). Prefer structured edit tools when possible.

Safety: output paths outside the media workspace are blocked unless allow_any_path=true. Uses -y only when overwrite=true; otherwise -n. Never uses shell=True.

Inputs: args (required), overwrite, allow_any_path, timeout_seconds, +1 more. Returns: object

run_renderA

Run a previously defined render job and return exit code + output probe summary.

Inputs: job_id (required), overwrite, allow_any_path. Returns: object

search_ffmpeg_docsB

Search installed FFmpeg filters/encoders/decoders help listings for a query string.

Inputs: query (required), limit. Returns: object

set_render_jobC

Define an export/render job with a preset: h264_mp4, prores, or webm.

Inputs: job_id (required), input_path (required), preset, extra_args, +1 more. Returns: object

trim_clipC

Trim a clip to start/end or start+duration and write output_path.

Inputs: input_path (required), output_path (required), end, start, +4 more. Returns: object

verify_editA

Compare an output file against an expected edit plan (duration, resolution). Returns pass/fail + diffs.

This is the deterministic verification bridge: agents can assert plan vs probe results. expected_clip_count is recorded for plan bookkeeping (single rendered file cannot recover clip count).

Inputs: output_path (required), max_duration, min_duration, allow_any_path, +5 more. Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.4/5.0

    Scored across 16 tools

    Disambiguation4/5

    Most tools target distinct actions (trim, concat, LUT, markers, rendering). compose_timeline has some overlap with concat_clips and trim_clip, but the JSON-based workflow described makes the intended use clear enough to avoid frequent misselection.

    Naming Consistency5/5

    All tool names follow a consistent verb_noun pattern in snake_case (e.g., compose_timeline, generate_lut, set_render_job). There are no mixed conventions or vague verbs, making the naming highly predictable.

    Tool Count4/5

    16 tools is just above the ideal 3–15 range, but each tool serves a clear purpose in the video-editing workflow. The count is slightly heavy but still well-scoped and not excessive.

    Completeness4/5

    The structured tools cover trimming, concatenation, timeline rendering, LUTs, markers, and verification. Advanced operations like audio processing or filters are missing, but the run_ffmpeg fallback allows agents to work around these gaps.

    Related MCP Connectors

    Related MCP Servers