resolve-mcp
The resolve-mcp server provides programmatic control over DaVinci Resolve Studio, enabling AI-driven editorial and media management tasks directly inside Resolve. Key capabilities:
Session & project management: Check connection state, Resolve version, current project/timeline (
get_status); list available projects (list_projects); open a specific project by exact name (open_project); create.drpbackup snapshots (snapshot_project).Media pool operations: Import files and image sequences (
import_media); list clips with offline state (list_media); inspect clip properties, metadata, markers, and time bounds (inspect_clip); batch update clip metadata (set_clip_metadata); organize media by creating nested bins and moving clips (organize_media); relink offline clips to new paths (relink_media).Escape hatch: Run arbitrary DaVinci Resolve scripting‑API Python code (
run_python) withresolve,project_manager,project, andtimelinepre‑bound in the namespace, returning the last expression's value and captured stdout.
All tools return structured JSON and echo context (project/timeline) for confirmation.
Enables interaction with DaVinci Resolve Studio, providing tools to manage projects and timelines, create snapshots, and run Python scripting API commands for editorial automation.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@resolve-mcpopen project 'Docu' and snapshot before render"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
resolve-mcp
An MCP server that gives Claude Code hands inside DaVinci Resolve Studio — so the musical and editorial reasoning happens in Claude and the mechanical work happens in Resolve.
Build contract: issue #22.
Status
P1 in progress, P2 titling started. Shipped so far: the server skeleton, the
session/project tools, the media pool tools, the timeline read, marker and interchange
tools, the declarative cut file and build_timeline, the titling tools on both the Text+
and PNG routes, the background-job infrastructure with audio acquisition, frame grabs and
scene-cut detection, the render/deliver tools, and the run_python escape hatch.
Tool | What it does |
| Connection state, Resolve version, current project + timeline, fps |
| Project names in the current database folder |
| Loads a project by name; the result echoes the new context |
| Writes an opaque |
| Imports files and image sequences into a bin, still-duration workaround applied |
| Summarises media pool clips, with offline state; spills big listings to disk |
| One clip in full: properties, metadata, audio mapping, markers, dual-time bounds |
| Batch metadata writes, each field routed by what the clip reports |
| Batch bin operations: create nested bins, move clips |
| Points offline clips at media that moved (folder relink or file replace) |
| Timelines with version, duration, fps and track stack; names the newest cut |
| One timeline at a chosen detail and range, in dual time; |
| Markers in record time, narrowed by colour and range |
| Batch marker writes; an existing marker is never overwritten unless asked |
| Writes a timeline out as OTIO, FCPXML or DRT |
| Materialises a new timeline from such a file — never overwrites one |
| The cut-file contract, its annotated example and the validation rules |
| Dry-runs a cut file: every error and warning at once, with fix hints |
| Builds a cut file into a fresh |
| The titles-file contract, its annotated example and the validation rules |
| Dry-runs a titles file before the Titles track is touched |
| Places Text+ and PNG titles from |
| Reads the Titles track back: what each placed title says and which inputs it exposes |
| Fixes one placed title in place — its words or its exposed params, neighbours untouched |
| Grabs chosen moments on a clip as JPEGs (≤1568px) the agent reads off disk |
| Job: catalogs where a clip changes shot, gist inline and the full list on disk |
| Two-pass GPU stem separation: mix → 4 stems, drums → kick/snare/toms/ride/crash |
| The project's render presets, spelled the way |
| Renders a timeline or a range of one as a background job |
| Polls one background job: progress, result, or a structured failure |
| Lists jobs newest first — how a restarted session finds what it started |
| Escape hatch: runs scripting-API Python in the server process |
Bin paths are slash-separated from the media pool root (Concert/Angles) and
case-sensitive. A clip counts as offline when it has a file path that is not on
disk — Resolve's scripting API exposes no offline flag.
Interchange is the structural escape hatch. The scripting API cannot cut a transition,
so a dissolve is made by exporting the cut to OTIO, editing the transition into that
document, and importing it back. An .otio or .fcpxml import is given a name no timeline
in the project answers to — colliding names walk the <base> v<N> convention. A .drt is
Resolve's own document and accepts no import options at all, so it names its own timeline;
what holds there is the check on the way out. Either way the cut already in the project is
never the thing that gets written over.
Three fields read null on any timeline that is not the one open in Resolve: a track's
enabled and locked, and a shot's takes. Resolve answers those from editor state and
reports False/0 for every other timeline — no error to catch, just a plausible wrong
number — so the server reports "unknown" rather than passing it on. The currency block in
the reply names them, and make_current switches to the timeline for the read and switches
back when you want the real values. It is opt-in because the switch is visible in the
Resolve window. ADR 0004
has the sweep that established which getters this covers, and which are proven safe.
Editing is declarative and split across two files that never mention each other. The
cut file owns the cut and materialises as a new <name> v<N> timeline every build.
titles.json owns the titles, and apply_titles owns the topmost video track named
Titles — every apply clears that track whole and re-places from the file, so the same
file always produces the same track. Title positions are offsets from the blue marker
naming their song rather than timeline frames, which is what lets one titles file be
re-applied unchanged to every rebuild.
Each event picks one of two routes, and both land in the same pass. Text+ places an
instance of a GUI-authored template and writes its words and its fade into that instance's
Fusion comp — clip-level fades are not exposed to the scripting API at all, so the fade is
an opacity spline. PNG places a designed card exported to frames with alpha, its words
and its ramps already in the pixels; the server consumes cards, never generates them. A
card is imported once into 04_Assets/Text/<song> and found rather than re-imported on
every later apply, and gets the one-time out-point write that makes Resolve honour the
requested length instead of dropping every image at the default still duration.
A typo is the exception to all of that. edit_title writes new words or new exposed
params straight into one already-placed Text+ instance — no clear, no append, no rebuild —
and proves it reached only that one by reading every other title on the track before and
after the write. list_titles is how you find the title and see which Fusion input ids it
exposes, since a media-pool template has no comp to ask. The edit changes the timeline
and not titles.json, so the next apply_titles puts the old wording back: fix the file
too whenever the change is one worth keeping.
Heavy work runs as a background job: the starter returns a job_id immediately, get_job
polls it, and results are cached under the cache root against the media and the parameters,
so an unchanged rerun is instant. Job records live on disk, which is what lets list_jobs
recover after a restart — a job that was still running when the server went down comes back
failed with code job_interrupted. Audio acquisition is internal to the starters: a
timeline is exported through Resolve's render queue (the only route that captures the
timeline mix, 48 kHz/24-bit WAV), a single source clip is extracted with ffmpeg unless its
audio mapping says the audio is linked or offset away from the file.
Seeing the picture takes two routes, both reading the file on disk rather than rendering
anything. grab_frames is not a job — a seek and one frame is faster than a poll would be,
so it runs inline and hands back JPEG paths at or under the client's 1568px image cap, cached
against the media all the same. detect_scene_cuts decodes the whole clip, so it is a job:
the catalog of every cut and shot goes to the cache in dual-time JSON and only a gist (how
many cuts, the shot lengths, the first few times, the path) comes back inline.
Deliverables come off one timeline the same way: render_timeline renders with a preset
— what a preset renders was decided in the Deliver page and saved there, so the server
overrides only where the file goes and which frames it covers. Name none and the configured
default is used (H.265 Master, a Resolve built-in; RESOLVE_MCP_DEFAULT_RENDER_PRESET
points it elsewhere), and the job says which preset ran and whether it was the default or
explicit. An unknown name is refused with the list of names that exist, never swapped for a
near-enough preset. On top of that goes an optional half-open
[start, end) range in the timeline's own frames, the numbers inspect_timeline and
list_markers report. That is a per-song file out of a concert set. Without a target_dir
the file lands in the cache's renders folder, which the server replaces freely on a
re-render; a directory you name is yours, and a file already sitting there is refused until
you pass refresh.
Related MCP server: DaVinci MCP Professional
Requirements
Windows 11, DaVinci Resolve Studio 21.0.3 (external scripting must be enabled: Preferences > System > General > External scripting using = Local)
CPython 3.12 x64 installed from python.org — not a uv-managed interpreter. See ADR 0001: the Resolve scripting library crashes the process outright on a standalone build, so the server refuses to attach on one. uv still manages the venv and the lockfile.
Resolve running, with a project open, before the first Resolve-touching tool call
ffmpeg on PATH for per-clip audio extraction, frame grabs and scene-cut detection (
RESOLVE_MCP_FFMPEGpoints at it elsewhere). Timeline-scope audio goes through Resolve's own render queue and needs none.python-audio-separator on PATH for
separate_stems(pip install "audio-separator[gpu]", orRESOLVE_MCP_AUDIO_SEPARATORpoints at the executable). It is run as a subprocess, not imported, so it can live in its own environment and its torch/CUDA stack never loads into the server. The two model files download on first use.uv sync --extra analysisfor transcription. The extra carries faster-whisper and the CUDA 12 runtime it needs (~1.3 GiB): the transcriber takes the GPU by default, and a runtime nobody installed is the one thing that breaks it. No hand-installed wheels, noPATHset before launch — the server puts the venv's own copy within reach. A box without an NVIDIA card still transcribes; setRESOLVE_MCP_WHISPER_DEVICE=cpuand expect it to be slow.
Install
uv venv --python "C:/Users/<you>/AppData/Local/Programs/Python/Python311/python.exe"
uv syncuv sync alone will pick a uv-managed interpreter, which runs the unit suite fine but
cannot attach to Resolve.
Run
uv run resolve-mcpThe server speaks MCP over stdio and logs to stderr only. Register it with Claude Code:
claude mcp add resolve -- uv --directory C:/Users/Daniel/repos/resolve-mcp run resolve-mcpConfiguration
Zero-config by default; every path has an environment override.
Variable | Default | Purpose |
|
| Scripting API root (holds |
|
| Scripting library |
|
| Cache root: snapshots, job records, cached results, acquired audio, grabbed frames, analysis catalogs, separated stems, model weights |
|
| ffmpeg executable used for per-clip audio extraction, frame grabs and scene-cut detection |
|
| python-audio-separator CLI used for stem separation |
|
| Pass one: the 4-stem model (vocals, drums, bass, other) |
|
| Pass two: the drum decomposition model (kick, snare, toms, ride, crash) |
|
| Render preset |
|
| Device faster-whisper transcribes on: |
|
| Precision: |
|
| Log level for the stderr logger |
| unset | Bypass the interpreter check (see ADR 0001) |
Development
uv run pytest # unit suite — runs with Resolve closed, against the fake seam
uv run pytest -m live # live smoke tier — needs real Resolve running, on a python.org interpreter
uv run mypy # type check
uv run ruff check . # lintTests exercise external behaviour only: they call the tool functions in-process (no stdio transport) against a fake Resolve API object substituted at the connection singleton.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Flicense-qualityBmaintenanceA Model Context Protocol server that enables AI assistants like Claude to interact with DaVinci Resolve Studio, providing advanced control over editing, color grading, audio, and other video production tasks.17
- AlicenseAqualityAmaintenanceA professional implementation of a Model Context Protocol server that enables integration between DaVinci Resolve video editing software and AI assistants like Claude Desktop or Cursor.1323GPL 3.0
- Alicense-qualityFmaintenanceComprehensive MCP server for DaVinci Resolve with 295+ tools to control projects, timelines, editing, color grading, rendering, and more via natural language.3MIT
- Alicense-qualityDmaintenanceA Model Context Protocol (MCP) server that connects AI coding assistants to DaVinci Resolve, enabling query and control through natural language.MIT
Related MCP Connectors
Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer
Augments MCP Server - A comprehensive framework documentation provider for Claude Code
MCP server for Google Veo AI video generation
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/danielbaldwin47/resolve-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server