davinci-resolve-mcp 2.94.2 → 2.94.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,56 @@
2
2
 
3
3
  Release history for the DaVinci Resolve MCP Server. The latest release is summarized in the root README; older entries live here to keep the README focused.
4
4
 
5
+ ## What's New in v2.94.3
6
+
7
+ A systematic sweep of catalogued API gaps against **Studio 21.0.4.5**, prompted
8
+ by an external report. Two ledger entries were wrong and are corrected; a new
9
+ harness proves the routes that DO work.
10
+
11
+ ### Fixed — transitions are not invisible to scripting
12
+
13
+ - **`Transition create / copy / clone` claimed transitions applied in the UI are
14
+ "invisible to and unmodifiable by scripts". Both halves were wrong.** A
15
+ 12-frame Cross Dissolve applied through the Edit-page right-click menu
16
+ enumerates in `GetItemListInTrack` as `GetName() == 'Cross Dissolve'`,
17
+ `GetStart() == 86426`, `GetDuration() == 12` — centered on a cut at 86432 —
18
+ with a stable `GetUniqueId()`. One authored offline into a `.drp` and imported
19
+ reads identically, so the creating route is irrelevant. It is also removable:
20
+ `DeleteClips([transition], False)` returns True and leaves both adjacent clips
21
+ untouched. **The discriminator** is `GetProperty()`: empty on a transition, 26
22
+ transform keys on a clip. Automated QC of existing transitions is therefore
23
+ possible. Genuinely missing: creation, cloning, and any type/alignment detail —
24
+ the kind is knowable only from the name string.
25
+
26
+ ### Fixed — CreateProject is not an "Untitled project" problem
27
+
28
+ - **`CreateProject` returned None with a NAMED project current and no modal on
29
+ screen** (screenshot-confirmed), while `OpenPage('edit')` succeeded in the same
30
+ session — so the connection was healthy and the documented modal is not the
31
+ only mechanism. Loading any clean project unblocked it on the next call. The
32
+ entry's recommended workaround was `CloseProject`, which **discards unsaved
33
+ changes** — acceptable for a throwaway Untitled project, destructive when the
34
+ current project is a named one belonging to another session. It now recommends
35
+ `LoadProject(clean project)` instead.
36
+
37
+ ### Added — `tests/live_workaround_verification.py`
38
+
39
+ The sibling of the gap harness: where that one proves absence, this proves
40
+ presence, performing each operation and reading the result back. Seven routes
41
+ verified on 21.0.4.5 — nested-timeline title placement with a later text edit,
42
+ ripple delete (with a non-ripple control showing the gap), the take selector as
43
+ an in-place source swap, `GetSelectedClips`, and constant retime through both
44
+ OTIO `LinearTimeWarp` and EDL `M2` (each a true 200%: 96 source frames over a
45
+ 48-frame record, alongside a 1.0 control). It also records the compound-clip trap
46
+ as a deliberate `ROUTE FAILS`.
47
+
48
+ ### Changed — the gap harness covers 13 gaps, up from 8
49
+
50
+ Added control-paired repros for the Source/Auto Track Selector (locking V1 blocks
51
+ the insert rather than redirecting it, while a media-backed clip targets V2
52
+ fine), transitions, native multicam creation, per-caption subtitle text, and
53
+ per-clip audio channel mapping. **13/13 confirmed missing** on 21.0.4.5.
54
+
5
55
  ## What's New in v2.94.2
6
56
 
7
57
  Changelog repair. No code changed.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  English | [简体中文](README.zh-CN.md)
4
4
 
5
- [![Version](https://img.shields.io/badge/version-2.94.2-blue.svg)](https://github.com/samuelgursky/davinci-resolve-mcp/releases)
5
+ [![Version](https://img.shields.io/badge/version-2.94.3-blue.svg)](https://github.com/samuelgursky/davinci-resolve-mcp/releases)
6
6
  [![npm](https://img.shields.io/npm/v/davinci-resolve-mcp.svg?label=npm&color=CB3837)](https://www.npmjs.com/package/davinci-resolve-mcp)
7
7
  [![API Coverage](https://img.shields.io/badge/API%20Coverage-100%25-brightgreen.svg)](docs/reference/api-coverage.md)
8
8
  [![Tools](https://img.shields.io/badge/MCP%20Tools-34%20(353%20full)-blue.svg)](#server-modes)
package/README.zh-CN.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [English](README.md) | 简体中文
4
4
 
5
- [![Version](https://img.shields.io/badge/version-2.94.2-blue.svg)](https://github.com/samuelgursky/davinci-resolve-mcp/releases)
5
+ [![Version](https://img.shields.io/badge/version-2.94.3-blue.svg)](https://github.com/samuelgursky/davinci-resolve-mcp/releases)
6
6
  [![npm](https://img.shields.io/npm/v/davinci-resolve-mcp.svg?label=npm&color=CB3837)](https://www.npmjs.com/package/davinci-resolve-mcp)
7
7
  [![API Coverage](https://img.shields.io/badge/API%20Coverage-100%25-brightgreen.svg)](docs/reference/api-coverage.md)
8
8
  [![Tools](https://img.shields.io/badge/MCP%20Tools-34%20(353%20full)-blue.svg)](#服务器模式)
@@ -12,7 +12,7 @@
12
12
  [![Python](https://img.shields.io/badge/python-3.10+-green.svg)](https://www.python.org/downloads/)
13
13
  [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
14
14
 
15
- > 本翻译对应 v2.94.2 版 README。如与英文原版有出入,以 [英文原版](README.md) 为准。
15
+ > 本翻译对应 v2.94.3 版 README。如与英文原版有出入,以 [英文原版](README.md) 为准。
16
16
 
17
17
  一个 Model Context Protocol (MCP) 服务器,让 AI 助手通过官方脚本 API 控制 DaVinci Resolve Studio(达芬奇)。它提供完整的 API 覆盖,外加带护栏的工作流助手,涵盖剪辑、媒体池整理、渲染设置、审阅标记、调色、Fusion、Fairlight、项目生命周期任务、扩展开发,以及不碰源媒体的媒体分析。
18
18
 
@@ -89,8 +89,8 @@ equivalent, blocking full automation.
89
89
  ### Transition create / copy / clone
90
90
 
91
91
  - **Object:** `Timeline / TimelineItem`
92
- - **Behavior:** The scripting API exposes no method to add, read, copy, or clone an edit transition (cross-dissolve, etc.). Transitions applied in the UI are invisible to and unmodifiable by scripts.
93
- - **Workaround / current handling:** Apply/duplicate transitions in the Resolve UI; no scripted equivalent exists.
92
+ - **Behavior:** There is no method to ADD or CLONE an edit transition — no AddTransition/CreateTransition/AddVideoTransition on Timeline or TimelineItem (dir(), 21.0.4.5). CORRECTION, measured on Studio 21.0.4.5 (2026-08-12): this entry previously said transitions applied in the UI are 'invisible to and unmodifiable by scripts'. BOTH HALVES WERE WRONG and are withdrawn. A transition IS a first-class timeline item: a 12-frame Cross Dissolve applied through the Edit-page right-click menu enumerates in GetItemListInTrack('video', 1) as GetName()=='Cross Dissolve', GetStart()==86426, GetDuration()==12 — centered on a cut at 86432 — with a stable GetUniqueId() and a working GetTrackTypeAndIndex(). A transition authored offline into a .drp and imported reads IDENTICALLY, so the route that created it does not matter. It is also REMOVABLE: Timeline.DeleteClips([transition], False) returns True and deletes it, leaving both adjacent clips at their original starts and durations. THE DISCRIMINATOR between a transition item and a clip item is GetProperty(): a transition returns an EMPTY dict where a video clip returns 26 transform keys; it also has no MediaPoolItem and no Fusion comp. WHAT IS GENUINELY MISSING: creation, cloning, and any type/alignment/parameter detail — the transition's kind is knowable ONLY from its name string, and there is no way to read its alignment (centered/start/end) or edit its duration.
93
+ - **Workaround / current handling:** Automated QC of existing transitions IS possible and is the main practical need — enumerate GetItemListInTrack, treat any item whose GetProperty() is empty and whose GetMediaPoolItem() is None as a transition, and read its name, start and duration. Removal is scriptable via Timeline.DeleteClips. To CREATE one, either apply it in the Resolve UI, or author it offline and import: the advanced server's drp place_transition writes a cross dissolve at an abutting cut ({track, atFrame, durationFrames}) and it round-trips into Resolve 21.0.4.5 reading back at the expected centered range.
94
94
  - **Tags:** missing-method, timeline, transition
95
95
 
96
96
  ### Cloud project enumeration / export / user management
@@ -367,11 +367,11 @@ values, or automation-hostile modal prompts.
367
367
  - **Workaround / current handling:** Treat a trailing ellipsis as truncation (see media_pool_item get_transcription's `truncated` flag).
368
368
  - **Tags:** transcription, truncation
369
369
 
370
- ### ProjectManager.CreateProject (with a dirty Untitled project)
370
+ ### ProjectManager.CreateProject (blocked by the current project)
371
371
 
372
372
  - **Object:** `ProjectManager`
373
- - **Behavior:** Returns None and pops a modal 'Save Current Project' dialog when the current unsaved/Untitled project blocks the switch. SaveProject() on an Untitled project re-triggers the same modal.
374
- - **Workaround / current handling:** CloseProject(current) to discard the untitled project without a prompt, then CreateProject; restore with LoadProject afterward.
373
+ - **Behavior:** Returns None and pops a modal 'Save Current Project' dialog when the current unsaved/Untitled project blocks the switch. SaveProject() on an Untitled project re-triggers the same modal. BROADER THAN 'UNTITLED', measured on Studio 21.0.4.5 (2026-08-12): with a NAMED project current (a conform project left open on the Deliver page), CreateProject returned None for a brand-new name and SaveProject returned False — with NO modal on screen, confirmed by screenshot, so the dialog is not the only mechanism. The connection was healthy throughout: OpenPage('edit') returned True in the same session, and moving to the Edit page did not help. Loading ANY clean project immediately unblocked it — CreateProject succeeded on the very next call. So the trigger is the current project, not the 'Untitled' name, and a bare False/None is the only signal.
374
+ - **Workaround / current handling:** LoadProject(any clean project) first, then CreateProject; restore the caller's project afterward. PREFER THAT OVER CloseProject, which this entry used to recommend: CloseProject DISCARDS unsaved changes, which is fine for a throwaway Untitled project but destroys work when the current project is a named one belonging to someone else's session — and the failure is NOT limited to Untitled projects, so that is a live risk. Never assume a bare None here means the name is taken; check GetProjectListInCurrentFolder().
375
375
  - **Tags:** project, modal, silent-failure
376
376
 
377
377
  ### TimelineItem.GetSourceStartFrame
package/install.py CHANGED
@@ -36,7 +36,7 @@ from src.utils.update_check import (
36
36
 
37
37
  # ─── Version ──────────────────────────────────────────────────────────────────
38
38
 
39
- VERSION = "2.94.2"
39
+ VERSION = "2.94.3"
40
40
  # Only hard floor: mcp[cli] requires Python 3.10+. There is no upper bound —
41
41
  # Resolve's scripting bridge loads into newer interpreters on recent builds
42
42
  # (Python 3.14 verified against Resolve Studio 20.3.2). Older Resolve builds
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "davinci-resolve-mcp",
3
- "version": "2.94.2",
3
+ "version": "2.94.3",
4
4
  "description": "NPM bootstrapper for the DaVinci Resolve MCP Server.",
5
5
  "license": "MIT",
6
6
  "author": "Samuel Gursky <samgursky@gmail.com>",
@@ -87,7 +87,7 @@ if not logging.getLogger().handlers:
87
87
  handlers=[logging.StreamHandler()],
88
88
  )
89
89
 
90
- VERSION = "2.94.2"
90
+ VERSION = "2.94.3"
91
91
  logger = logging.getLogger("davinci-resolve-mcp")
92
92
  logger.info(f"Starting DaVinci Resolve MCP Server v{VERSION}")
93
93
  logger.info(f"Detected platform: {get_platform()}")
package/src/server.py CHANGED
@@ -11,7 +11,7 @@ Usage:
11
11
  python src/server.py --full # Start the 353-tool granular server instead
12
12
  """
13
13
 
14
- VERSION = "2.94.2"
14
+ VERSION = "2.94.3"
15
15
 
16
16
  import base64
17
17
  import os
@@ -525,14 +525,32 @@ API_TRUTH: List[Dict[str, Any]] = [
525
525
  "submit": "bug",
526
526
  },
527
527
  {
528
- "symbol": "ProjectManager.CreateProject (with a dirty Untitled project)",
528
+ "symbol": "ProjectManager.CreateProject (blocked by the current project)",
529
529
  "object": "ProjectManager",
530
530
  "reality": "Returns None and pops a modal 'Save Current Project' dialog "
531
531
  "when the current unsaved/Untitled project blocks the switch. "
532
- "SaveProject() on an Untitled project re-triggers the same modal.",
533
- "recommended": "CloseProject(current) to discard the untitled project "
534
- "without a prompt, then CreateProject; restore with "
535
- "LoadProject afterward.",
532
+ "SaveProject() on an Untitled project re-triggers the same modal. "
533
+ "BROADER THAN 'UNTITLED', measured on Studio 21.0.4.5 "
534
+ "(2026-08-12): with a NAMED project current (a conform project "
535
+ "left open on the Deliver page), CreateProject returned None for "
536
+ "a brand-new name and SaveProject returned False — with NO modal "
537
+ "on screen, confirmed by screenshot, so the dialog is not the "
538
+ "only mechanism. The connection was healthy throughout: "
539
+ "OpenPage('edit') returned True in the same session, and moving "
540
+ "to the Edit page did not help. Loading ANY clean project "
541
+ "immediately unblocked it — CreateProject succeeded on the very "
542
+ "next call. So the trigger is the current project, not the "
543
+ "'Untitled' name, and a bare False/None is the only signal.",
544
+ "recommended": "LoadProject(any clean project) first, then CreateProject; "
545
+ "restore the caller's project afterward. PREFER THAT OVER "
546
+ "CloseProject, which this entry used to recommend: "
547
+ "CloseProject DISCARDS unsaved changes, which is fine for a "
548
+ "throwaway Untitled project but destroys work when the "
549
+ "current project is a named one belonging to someone else's "
550
+ "session — and the failure is NOT limited to Untitled "
551
+ "projects, so that is a live risk. Never assume a bare None "
552
+ "here means the name is taken; check "
553
+ "GetProjectListInCurrentFolder().",
536
554
  "tags": ["project", "modal", "silent-failure"],
537
555
  "submit": "bug",
538
556
  },
@@ -663,11 +681,41 @@ API_TRUTH: List[Dict[str, Any]] = [
663
681
  {
664
682
  "symbol": "Transition create / copy / clone",
665
683
  "object": "Timeline / TimelineItem",
666
- "reality": "The scripting API exposes no method to add, read, copy, or "
667
- "clone an edit transition (cross-dissolve, etc.). Transitions "
668
- "applied in the UI are invisible to and unmodifiable by scripts.",
669
- "recommended": "Apply/duplicate transitions in the Resolve UI; no scripted "
670
- "equivalent exists.",
684
+ "reality": "There is no method to ADD or CLONE an edit transition — no "
685
+ "AddTransition/CreateTransition/AddVideoTransition on Timeline "
686
+ "or TimelineItem (dir(), 21.0.4.5). CORRECTION, measured on "
687
+ "Studio 21.0.4.5 (2026-08-12): this entry previously said "
688
+ "transitions applied in the UI are 'invisible to and "
689
+ "unmodifiable by scripts'. BOTH HALVES WERE WRONG and are "
690
+ "withdrawn. A transition IS a first-class timeline item: a "
691
+ "12-frame Cross Dissolve applied through the Edit-page "
692
+ "right-click menu enumerates in GetItemListInTrack('video', 1) "
693
+ "as GetName()=='Cross Dissolve', GetStart()==86426, "
694
+ "GetDuration()==12 — centered on a cut at 86432 — with a stable "
695
+ "GetUniqueId() and a working GetTrackTypeAndIndex(). A "
696
+ "transition authored offline into a .drp and imported reads "
697
+ "IDENTICALLY, so the route that created it does not matter. It "
698
+ "is also REMOVABLE: Timeline.DeleteClips([transition], False) "
699
+ "returns True and deletes it, leaving both adjacent clips at "
700
+ "their original starts and durations. THE DISCRIMINATOR between "
701
+ "a transition item and a clip item is GetProperty(): a "
702
+ "transition returns an EMPTY dict where a video clip returns 26 "
703
+ "transform keys; it also has no MediaPoolItem and no Fusion "
704
+ "comp. WHAT IS GENUINELY MISSING: creation, cloning, and any "
705
+ "type/alignment/parameter detail — the transition's kind is "
706
+ "knowable ONLY from its name string, and there is no way to "
707
+ "read its alignment (centered/start/end) or edit its duration.",
708
+ "recommended": "Automated QC of existing transitions IS possible and is "
709
+ "the main practical need — enumerate GetItemListInTrack, "
710
+ "treat any item whose GetProperty() is empty and whose "
711
+ "GetMediaPoolItem() is None as a transition, and read its "
712
+ "name, start and duration. Removal is scriptable via "
713
+ "Timeline.DeleteClips. To CREATE one, either apply it in the "
714
+ "Resolve UI, or author it offline and import: the advanced "
715
+ "server's drp place_transition writes a cross dissolve at an "
716
+ "abutting cut ({track, atFrame, durationFrames}) and it "
717
+ "round-trips into Resolve 21.0.4.5 reading back at the "
718
+ "expected centered range.",
671
719
  "tags": ["missing-method", "timeline", "transition"],
672
720
  "submit": "missing",
673
721
  },