{
  "markdown": "# davinci-resolve-lite-mcp\n\n[![test](https://github.com/2sem/davinci-resolve-lite-mcp/actions/workflows/test.yml/badge.svg)](https://github.com/2sem/davinci-resolve-lite-mcp/actions/workflows/test.yml)\n[![PyPI](https://img.shields.io/pypi/v/davinci-resolve-lite-mcp)](https://pypi.org/project/davinci-resolve-lite-mcp/)\n[![MCP Registry](https://img.shields.io/badge/MCP%20Registry-listed-6f42c1)](server.json)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Python 3.9+](https://img.shields.io/badge/Python-3.9%2B-3776AB?logo=python&logoColor=white)](CONTRIBUTING.md#ground-rules)\n[![Platform: macOS](https://img.shields.io/badge/Platform-macOS-lightgrey?logo=apple&logoColor=white)](#requirements)\n[![DaVinci Resolve: Lite \\| Studio](https://img.shields.io/badge/DaVinci%20Resolve-Lite%20%7C%20Studio-E4405F)](#why-this-works-on-the-free-edition)\n[![163 tools](https://img.shields.io/badge/tools-163-brightgreen)](docs/TOOLS.md)\n[![Zero dependencies](https://img.shields.io/badge/dependencies-0-success)](#why-this-works-on-the-free-edition)\n\nhttps://github.com/user-attachments/assets/8429932f-643b-4131-bdf6-dad0d3399137\n\n*Claude builds an opening title in DaVinci Resolve Lite — a gold \"GameHelper\"\nText+ node with glow and a zoom-in keyframe reveal — from a plain-language\nrequest, via `insert_fusion_title` + `style_fusion_title`.*\n\nAn [MCP](https://modelcontextprotocol.io) server that lets an AI client such as\n**Claude Code** control **DaVinci Resolve** — including the **free (Lite)\nedition**, which the existing\n[davinci-resolve-mcp](https://github.com/samuelgursky/davinci-resolve-mcp)\nproject cannot drive.\n\nThe free edition blocks *external* scripting, but it still runs Python scripts\nlaunched from its own **Workspace > Scripts** menu. This project rides that path:\nthe MCP server runs **inside** Resolve as a menu script, and exposes Resolve's\nPython API over a small local HTTP endpoint that Claude connects to.\n\n```\nClaude Code ──HTTP JSON-RPC (MCP)──▶  127.0.0.1:8765/mcp\n                                          │   server runs INSIDE Resolve\n                                          │   (Workspace > Scripts > Utility)\n                                          ▼\n                              command queue → main script thread\n                                          ▼\n                              global `resolve` object → Resolve API\n```\n\n## Tools\n\nAsk Claude in plain language; it drives Resolve through the tools — see the\ndemo above. See the [tools reference](docs/TOOLS.md) for the full 163-tool\nsurface — editing, color, render, media pool, and Fusion title styling.\n\n## Why this works on the free edition\n\n* Free Resolve permits scripts run from its **Scripts menu** (only *external*\n  network scripting is restricted).\n* A menu script gets the `resolve` object for free and may run a long-lived\n  loop — long enough to host a server.\n* The sandboxed Lite app ships the `com.apple.security.network.server`\n  entitlement, so it can open a localhost listening socket.\n* **Zero dependencies** — pure Python standard library. Nothing to `pip install`\n  into Resolve's interpreter.\n\n## Requirements\n\n* macOS with DaVinci Resolve (Lite/free or Studio).\n* Claude Code (or any MCP client that speaks the Streamable HTTP transport).\n\n## Install\n\n```bash\ngit clone https://github.com/2sem/davinci-resolve-lite-mcp.git\ncd davinci-resolve-lite-mcp\n./install.sh\n```\n\nOr via pip, if you'd rather not clone the repo:\n\n```bash\npip install davinci-resolve-lite-mcp\ndavinci-mcp-install\n```\n\n`davinci-mcp-install` does exactly what `install.sh` does (same Lite/Studio\ndetection, same copy-vs-symlink logic) — it just reads the files from your\npip-installed package instead of a git checkout. `davinci-mcp-uninstall`\nreverses it. Either way, the sandbox note below still applies, and you still\nstart the server from Resolve's own menu — see [Run](#run).\n\n> **macOS user-install note.** If you see `Defaulting to user installation\n> because normal site-packages is not writeable`, pip installed the console\n> scripts under `$(python3 -m site --user-base)/bin`, which usually isn't on\n> `PATH`. Either run the full path —\n> `\"$(python3 -m site --user-base)/bin/davinci-mcp-install\"` — or add that\n> `bin` directory to `PATH`. And use `&&`, not `&`, between the two commands:\n> a bare `&` backgrounds `pip install` and races `davinci-mcp-install` before\n> the package exists.\n\nAlso listed on the [MCP Registry](https://registry.modelcontextprotocol.io) as\n`io.github.2sem/davinci-resolve-lite-mcp`\n([verify](https://registry.modelcontextprotocol.io/v0.1/servers?search=davinci-resolve-lite-mcp)) —\nfor discoverability only. The listing is metadata-only (no auto-install\n`packages`/`remotes` entry): this server can't be spawned by an MCP client the\nway a typical registry server can, since it must run inside Resolve's own\nembedded Python interpreter, started by hand from the Scripts menu. Install it\none of the two ways above.\n\n`install.sh` deploys:\n\n* the two launcher scripts into `Fusion/Scripts/Utility` (a folder Resolve scans\n  for the Scripts menu; **Utility** shows on every page), and\n* the `resolve_mcp` package into `Fusion/Scripts/MCP` — a folder Resolve does\n  **not** scan, so the helper modules stay out of the menu.\n\nThe Lite container path is detected automatically.\n\n> **Sandbox note (important).** DaVinci Resolve Lite is sandboxed and can only\n> read its own container, `~/Movies`, and files you pick interactively. A\n> symlink that points outside those locations (e.g. into a clone under\n> `~/Projects`) **cannot be followed by the sandboxed app**, so the menu script\n> would silently never run. For that reason `install.sh` **copies** the files\n> into the container on Lite (and symlinks only on the non-sandboxed Studio\n> build). **Re-run `./install.sh` after pulling updates.**\n>\n> Resolve enumerates only the category folders (`Utility / Comp / Tool / Edit /\n> Color / Deliver`) for its Scripts menu — that is why the launchers go in\n> `Utility` and the package hides in `MCP`.\n>\n> The same sandboxing applies to file paths you ask the tools to use:\n> exports/imports should target `~/Movies` (or other granted locations),\n> otherwise Resolve cannot write/read them.\n\n## Run\n\n1. In DaVinci Resolve: **Workspace > Scripts > Utility > davinci_mcp_server**.\n\n   ![Workspace > Scripts menu showing davinci_mcp_server and stop_davinci_mcp_server](docs/images/menu.png)\n\n2. Open **Workspace > Console** — it prints the endpoint and port:\n\n   ```\n   MCP endpoint:  http://127.0.0.1:8765/mcp\n   Add to Claude Code:\n     claude mcp add --transport http davinci http://127.0.0.1:8765/mcp\n   ```\n\n   > The startup guide prints to the Resolve Console (Workspace > Console).\n   > Because the server runs continuously, its Console output can buffer until\n   > it stops, so both scripts also mirror every line to a logfile:\n   >\n   > ```\n   > ~/Movies/davinci-resolve-lite-mcp.log\n   > ```\n   >\n   > Watch it live with `./logs.sh`. (Override the directory with\n   > `DAVINCI_MCP_LOG_DIR`.) `~/Movies` is used because the sandboxed Lite app\n   > is allowed to write there.\n\n   Once running, every tool call is logged to the Console as a single line\n   (`[davinci-mcp] <name> <args> -> ok|error (Nms)`):\n\n   ![Resolve Console showing per-command davinci-mcp log lines](docs/images/console.png)\n\n   > **Update check.** Like `brew`/CocoaPods, each launch checks PyPI in the\n   > background for a newer release and prints a one-line nudge to the Console\n   > if one exists — never blocks startup, and any failure (offline, PyPI\n   > down) stays silent in the logfile only. Disable with\n   > `DAVINCI_MCP_SKIP_UPDATE_CHECK=1`.\n\n3. Register it with Claude Code (one-time):\n\n   ```bash\n   claude mcp add --transport http davinci http://127.0.0.1:8765/mcp\n   ```\n\n   Then verify / reconnect with the **`/mcp`** command inside Claude Code — it\n   lists connected servers and reconnects them. If Claude was already running\n   when you launched the script, type `/mcp` (or restart the session) so it\n   picks up the `davinci` server.\n\n4. Ask Claude to control Resolve.\n\n### Configure the port (stable, recommended)\n\nBy default the server listens on `8765` and **auto-increments to `8766`, `8767`,\n… if that port is busy** (another local tool may already hold `8765`). Because\nthe winner of that race can change between launches, the URL you registered with\nClaude can drift, surfacing as:\n\n```\nFailed to reconnect to davinci: HTTP 404 at http://127.0.0.1:8765/mcp\n```\n\nTo lock the port for good, drop a small JSON config file. **When a port is set\nthis way it is *pinned* — the server binds exactly that port and never\nauto-increments**, so you register Claude once and the URL never moves.\n\nCreate `~/Movies/davinci-resolve-lite-mcp.config.json`:\n\n```json\n{ \"host\": \"127.0.0.1\", \"port\": 8770 }\n```\n\n> **Why `~/Movies` and not `~/.config`?** The Lite app is sandboxed and can only\n> read its own container, `~/Movies`, and files you pick interactively —\n> `~/.config` is outside the sandbox, so Lite cannot read it (this is the same\n> reason the logfile lives in `~/Movies`). The server also checks\n> `~/.config/davinci-resolve-lite-mcp/config.json` for the **non-sandboxed\n> Studio** build, where that path is conventional.\n\nThen restart the server (Scripts > Utility > **stop_davinci_mcp_server**, then\n**davinci_mcp_server**) and register Claude once at the fixed port:\n\n```bash\nclaude mcp add --transport http davinci http://127.0.0.1:8770/mcp\n```\n\nThe Console banner confirms the source — look for\n`Port : pinned (from …) — will not auto-increment`.\n\n**Resolution order** (highest priority first): the `DAVINCI_MCP_PORT` /\n`DAVINCI_MCP_HOST` environment variables, then the config file, then the\nbuilt-in defaults. The env vars also pin the port, but a Dock-launched Resolve\nwon't see a shell `export`; the config file is the simplest persistent option.\n`DAVINCI_MCP_CONFIG=/path/to.json` forces a specific config file **exclusively**\n— if that path is missing or malformed the server falls back to the built-in\ndefaults rather than reading `~/Movies` / XDG.\n\nIf the port already drifted and Claude points at the wrong one, re-point it:\n\n```bash\nclaude mcp remove davinci\nclaude mcp add --transport http davinci http://127.0.0.1:<actual-port>/mcp\n```\n\n### Stopping\n\nAny of these stops the server:\n\n* **From the menu:** Workspace > Scripts > Utility > **stop_davinci_mcp_server**\n* **From a terminal:** `./stop.sh`\n* **Quit DaVinci Resolve**\n\nThe menu stop script and `stop.sh` both POST to the server's `/shutdown`\nendpoint, scanning the same port range the server uses on startup.\n\n> The port auto-increments from `8765` only when it is **not** pinned. To lock\n> it so the URL never moves between launches, see\n> [Configure the port](#configure-the-port-stable-recommended).\n\n## Tools\n\n**163 tools**, spanning the full pipeline:\n\n- **Status & navigation** — page switching, project/timeline settings\n- **Projects & timelines** — load/create/duplicate, markers, scene cuts, lifecycle\n- **Tracks** — add/delete, enable/lock/rename\n- **Editing** — place/append/delete clips, titles & generators, transform/crop/zoom\n- **Media pool & storage** — import/delete, properties & metadata, tagging, disk browse\n- **Color** — node graph LUT/enable, reset grades, stills\n- **Render & export** — render queue, formats/codec, frame/timeline/project export & import\n\nSee **[docs/TOOLS.md](docs/TOOLS.md)** for the complete per-tool reference.\n\nEvery tool call is logged to the Resolve Console and the logfile as a single\nline: `[davinci-mcp] <name> <args> -> ok|error|EXCEPTION (Nms)`.\n\n## Project layout\n\n```\nsrc/davinci_mcp_server.py        thin launcher (deployed to Scripts/Utility)\nsrc/stop_davinci_mcp_server.py   stop launcher\nsrc/resolve_mcp/                 the server package (deployed to Scripts/MCP, hidden)\n    config · logio · connection · bridge · tools · server\ntests/test_server.py             offline tests (fake Resolve, no app needed)\ninstall.sh · uninstall.sh · stop.sh · logs.sh\ndocs/TOOLS.md                    full per-tool reference\nfallbacks/                       documented gotchas + fixes\n```\n\n## Testing\n\n- **Offline** (no Resolve, no server) — import + dispatcher + tool-count smoke:\n  ```bash\n  python3 tests/test_server.py\n  ```\n- **Live integration** — one test per tool against a running server (Resolve open\n  with a project + a media clip, and `davinci_mcp_server` launched):\n  ```bash\n  python3 tests/live_test.py                 # all features\n  python3 tests/live_test.py set_timecode    # run the test(s) for given feature(s)\n  ```\n  Each test name equals the tool name, so when you change a tool you can run just\n  its test: `python3 tests/live_test.py <tool>`. Tests are reversible (scratch\n  timeline + temp files, cleaned up). File-dependent and session-destructive\n  tools are checked via their error path; Studio-only / heavy tools (e.g.\n  `detect_scene_cuts`, `render_current_timeline`, `quick_export`) are skipped\n  with a reason. A few marker / still tests depend on a clean Resolve session\n  state — re-run them after a fresh launch if they flake.\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for how to add a tool, run the suites,\nthe stdlib-only / Lite-first constraints, and the release flow.\n\n## Scope\n\nThis server targets the **free (Lite) edition** and intentionally covers only\nAPI that runs there. Studio-only / paid features are **deliberately omitted**\n(they no-op or error on Lite), namely: audio transcription, subtitles-from-audio,\nMagic Mask, Stabilize, Smart Reframe, Dolby Vision analysis, Voice Isolation,\nand cloud projects / database management. The remaining unwrapped methods are\ntrivial accessors (`GetUniqueId`, cache modes, Fusion-comp internals, takes,\nstereo/3D, layout & burn-in presets, mattes) — not functional gaps.\n\n## Known limitations\n\n- Clips can be addressed by **name** (within the current media-pool folder) or\n  by **id** (`id`/`ids`, resolvable across any bin) — pass `id`/`ids` when names\n  are ambiguous or the clip lives in another folder.\n- Tool arguments are validated against each tool's JSON Schema (required fields,\n  basic types, and enums); a malformed call returns a clear error naming the\n  offending argument. Deep/nested schema constraints are not exhaustively checked.\n\n## Security note\n\nThe server binds to `127.0.0.1` only, so it is reachable from your machine\nonly. It exposes control of DaVinci Resolve to any local process that can reach\nthe port — only run it on a machine you trust.\n\nThe one outbound call the server makes on its own is the startup update check\n(a `GET` to PyPI's public JSON API for the current version number — no other\ndata sent). Disable it with `DAVINCI_MCP_SKIP_UPDATE_CHECK=1` if you'd rather\nit made none.\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n",
  "bytes": 14837,
  "sha": "9550d999c1cbc707fc32df93ab92ec98df6fb9702b67abec61423361af4cba33",
  "repo_slug": "2sem/davinci-resolve-lite-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_2sem_davinci_resolve_lite_mcp_8ea9f8e5/readme"
}