davinci-resolve-mcp 2.98.7 → 2.98.8
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 +58 -0
- package/README.md +1 -1
- package/README.zh-CN.md +2 -2
- package/docs/SKILL.md +7 -7
- package/docs/reference/api-limitations.md +1 -1
- package/install.py +1 -1
- package/package.json +1 -1
- package/src/granular/common.py +1 -1
- package/src/server.py +1 -1
- package/src/utils/api_truth.py +14 -16
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,59 @@
|
|
|
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.98.8
|
|
6
|
+
|
|
7
|
+
**The comp-lock mechanism, settled — and the v2.98.6 scope correction was itself
|
|
8
|
+
wrong.** Chasing why `add_fusion_mask` and `set_text_plus` escaped the bug found
|
|
9
|
+
that they don't. Their test cases were priming the comp and could not have
|
|
10
|
+
failed.
|
|
11
|
+
|
|
12
|
+
### The mechanism
|
|
13
|
+
|
|
14
|
+
| | |
|
|
15
|
+
| --- | --- |
|
|
16
|
+
| **Precondition** | The comp's graph was built through lock-wrapped `AddTool`/`ConnectInput`. The same locked write against a graph wired by plain attribute assignment renders normally. |
|
|
17
|
+
| **Trigger** | The locked write is the **first value write to that comp** since the build. |
|
|
18
|
+
| **Primes it away** | **Any** unlocked value write anywhere in the comp — even writing a *default* value to an *unrelated* tool. Also `StartUndo`/`EndUndo` around the write. |
|
|
19
|
+
| **Does not** | A structural `ConnectInput` inside the same lock; a `GetInput` readback after `Unlock`. |
|
|
20
|
+
|
|
21
|
+
Priming is why every raw-API attempt to reproduce the bug kept coming back green,
|
|
22
|
+
and why a control that was supposed to fail didn't.
|
|
23
|
+
|
|
24
|
+
### The corrected scope
|
|
25
|
+
|
|
26
|
+
| path | locked write |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| `set_input` | **suppressed** |
|
|
29
|
+
| `safe_set_inputs` | **suppressed** |
|
|
30
|
+
| `set_text_plus` | **suppressed** |
|
|
31
|
+
| `add_fusion_mask` | **suppressed** |
|
|
32
|
+
| `bulk_set_inputs` | escapes — wrapped in `StartUndo`/`EndUndo` |
|
|
33
|
+
| `bulk_set_expressions` | escapes — wrapped in `StartUndo`/`EndUndo` |
|
|
34
|
+
|
|
35
|
+
So **four of six** paths were genuinely broken, not two. v2.98.5's original
|
|
36
|
+
"all six were the same bug" was closer to right than v2.98.6's correction of it;
|
|
37
|
+
the two real escapes are explained by their undo wrapper.
|
|
38
|
+
|
|
39
|
+
### Fixed in the tests
|
|
40
|
+
|
|
41
|
+
`tests/live_fusion_value_write_validation.py` had two cases that could not fail.
|
|
42
|
+
Both set up their graph with plain `SetInput` calls — a text `Size`, a blur
|
|
43
|
+
amount — before the call under test, which primed the comp. Removing that:
|
|
44
|
+
|
|
45
|
+
- the `set_text_plus` case now builds its rooted graph and writes **nothing**
|
|
46
|
+
before the call, leaving the Text+ at its default size;
|
|
47
|
+
- the `add_fusion_mask` case composites a **Background** rather than making a
|
|
48
|
+
Blur visible, because a Background is visible at its defaults and needs no
|
|
49
|
+
setup write.
|
|
50
|
+
|
|
51
|
+
Both now report `PSNR inf -> IGNORED at render` with the lock reintroduced, and
|
|
52
|
+
13–17 dB APPLIED without it. The header carries a standing rule: a case in that
|
|
53
|
+
file must perform no value write of any kind before the call it is testing.
|
|
54
|
+
|
|
55
|
+
No production code changed. The v2.98.5 fix has been correct throughout; this is
|
|
56
|
+
the third and final correction to the *description* of what it fixed.
|
|
57
|
+
|
|
5
58
|
## What's New in v2.98.7
|
|
6
59
|
|
|
7
60
|
**Identifying the mechanism behind the Fusion comp-lock bug — and correcting the
|
|
@@ -61,6 +114,11 @@ it. What changed is the explanation, in `api_truth` and the harness docs.
|
|
|
61
114
|
|
|
62
115
|
## What's New in v2.98.6
|
|
63
116
|
|
|
117
|
+
> **Corrected in v2.98.8.** The table below says four of six paths escape the
|
|
118
|
+
> bug. Two of those four — `set_text_plus` and `add_fusion_mask` — do not; their
|
|
119
|
+
> test cases primed the comp with setup writes and could not fail. Only
|
|
120
|
+
> `bulk_set_inputs` and `bulk_set_expressions` genuinely escape.
|
|
121
|
+
|
|
64
122
|
**Correcting the scope of the v2.98.5 Fusion fix, and covering all six paths
|
|
65
123
|
with a render.** v2.98.5 removed a `Comp.Lock()` from six Fusion value writes and
|
|
66
124
|
described all six as the same bug. Only two of them were proven with a render at
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
English | [简体中文](README.zh-CN.md)
|
|
4
4
|
|
|
5
|
-
[](https://github.com/samuelgursky/davinci-resolve-mcp/releases)
|
|
6
6
|
[](https://www.npmjs.com/package/davinci-resolve-mcp)
|
|
7
7
|
[](docs/reference/api-coverage.md)
|
|
8
8
|
[-blue.svg)](#server-modes)
|
package/README.zh-CN.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[English](README.md) | 简体中文
|
|
4
4
|
|
|
5
|
-
[](https://github.com/samuelgursky/davinci-resolve-mcp/releases)
|
|
6
6
|
[](https://www.npmjs.com/package/davinci-resolve-mcp)
|
|
7
7
|
[](docs/reference/api-coverage.md)
|
|
8
8
|
[-blue.svg)](#服务器模式)
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
[](https://www.python.org/downloads/)
|
|
13
13
|
[](https://opensource.org/licenses/MIT)
|
|
14
14
|
|
|
15
|
-
> 本翻译对应 v2.98.
|
|
15
|
+
> 本翻译对应 v2.98.8 版 README。如与英文原版有出入,以 [英文原版](README.md) 为准。
|
|
16
16
|
|
|
17
17
|
一个 Model Context Protocol (MCP) 服务器,让 AI 助手通过官方脚本 API 控制 DaVinci Resolve Studio(达芬奇)。它提供完整的 API 覆盖,外加带护栏的工作流助手,涵盖剪辑、媒体池整理、渲染设置、审阅标记、调色、Fusion、Fairlight、项目生命周期任务、扩展开发,以及不碰源媒体的媒体分析。
|
|
18
18
|
|
package/docs/SKILL.md
CHANGED
|
@@ -1691,13 +1691,13 @@ Target a comp either from a timeline item (pass `clip_id`, `timeline_item_id`, o
|
|
|
1691
1691
|
page comp (omit timeline scope).
|
|
1692
1692
|
|
|
1693
1693
|
READBACK IS NOT PROOF FOR FUSION PARAMETERS. Up to v2.98.4 every value write
|
|
1694
|
-
here ran inside a `Comp.Lock()
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1694
|
+
here ran inside a `Comp.Lock()`, and a value written under a comp lock is stored
|
|
1695
|
+
in the graph and returned by `get_input` while the RENDER ignores it entirely
|
|
1696
|
+
(Studio 19.1.3.7: PSNR inf vs the no-comp baseline). Four of the six affected
|
|
1697
|
+
paths — `set_input`, `safe_set_inputs`, `set_text_plus`, `add_fusion_mask` — were
|
|
1698
|
+
confirmed broken by rendering; `bulk_set_inputs` and `bulk_set_expressions`
|
|
1699
|
+
escape because they wrap their write in `StartUndo`/`EndUndo`. Fixed in v2.98.5,
|
|
1700
|
+
mechanism settled in v2.98.8, and guarded by
|
|
1701
1701
|
`tests/test_fusion_value_write_lock.py` plus the rendered-frame harness
|
|
1702
1702
|
`tests/live_fusion_value_write_validation.py`. The lesson outlives the bug: a
|
|
1703
1703
|
Fusion parameter that reads back correctly has proven nothing about the output,
|
|
@@ -343,7 +343,7 @@ values, or automation-hostile modal prompts.
|
|
|
343
343
|
|
|
344
344
|
- **Object:** `Composition (Fusion, via TimelineItem comps)`
|
|
345
345
|
- **Signature:** `Lock() / Unlock()`
|
|
346
|
-
- **Behavior:** A numeric tool.SetInput() performed between Comp.Lock() and Comp.Unlock(), when that write is the only thing the call does, is stored in the graph and reads back correctly from GetInput() but is NOT applied when the timeline is rendered. Measured live on Studio 19.1.3.7 (2026-08-21) with MediaIn -> Blur(XBlurSize 20) -> MediaOut on a media-backed clip: written under the lock the delivered H.264 render is bit-identical to the no-comp baseline (ffmpeg PSNR inf); the identical write with the lock removed renders at PSNR 24.38 dB and the file shrinks 2.0 MB -> 727 KB, as a blur should. The variable was isolated against the comp handle (AddFusionComp, GetFusionCompByIndex and GetFusionCompByName all render), the node name, and the write form (attribute assignment and SetInput both render unlocked). STRUCTURAL edits are unaffected: AddTool and ConnectInput inside a lock render normally, so the lock is not broadly unsafe — it suppresses the parameter-change invalidation that a value write depends on. Lock() is widely recommended for batching Fusion edits, which is how this reaches production code.
|
|
346
|
+
- **Behavior:** A numeric tool.SetInput() performed between Comp.Lock() and Comp.Unlock(), when that write is the only thing the call does, is stored in the graph and reads back correctly from GetInput() but is NOT applied when the timeline is rendered. Measured live on Studio 19.1.3.7 (2026-08-21) with MediaIn -> Blur(XBlurSize 20) -> MediaOut on a media-backed clip: written under the lock the delivered H.264 render is bit-identical to the no-comp baseline (ffmpeg PSNR inf); the identical write with the lock removed renders at PSNR 24.38 dB and the file shrinks 2.0 MB -> 727 KB, as a blur should. The variable was isolated against the comp handle (AddFusionComp, GetFusionCompByIndex and GetFusionCompByName all render), the node name, and the write form (attribute assignment and SetInput both render unlocked). STRUCTURAL edits are unaffected: AddTool and ConnectInput inside a lock render normally, so the lock is not broadly unsafe — it suppresses the parameter-change invalidation that a value write depends on. Lock() is widely recommended for batching Fusion edits, which is how this reaches production code. MECHANISM (settled 2026-08-22). PRECONDITION: it only reproduces on a comp whose graph was BUILT through lock-wrapped AddTool/ConnectInput; the same locked write against a graph wired by plain attribute assignment renders normally. TRIGGER: the locked write is lost when it is the FIRST value write to that comp since the build. PRIMING: any unlocked value write anywhere in the comp clears the condition permanently — even writing a DEFAULT value to an unrelated tool — and so does StartUndo/EndUndo around the write. A structural ConnectInput inside the same lock does NOT clear it, and neither does a GetInput readback. Priming makes false negatives easy: a test that sets anything up with a plain SetInput before the call under test will pass even with the bug present.
|
|
347
347
|
- **Workaround / current handling:** Never hold a comp lock across a value write. Lock only structural work (AddTool/ConnectInput) and set inputs outside it. Because every readback the API offers agrees with the value that was written, this failure is invisible without a render — prove Fusion parameter changes with a delivered frame or gallery_stills grab_and_export, never with GetInput.
|
|
348
348
|
- **Tags:** fusion, silent-failure, render, readback
|
|
349
349
|
|
package/install.py
CHANGED
|
@@ -37,7 +37,7 @@ from src.utils.update_check import (
|
|
|
37
37
|
|
|
38
38
|
# ─── Version ──────────────────────────────────────────────────────────────────
|
|
39
39
|
|
|
40
|
-
VERSION = "2.98.
|
|
40
|
+
VERSION = "2.98.8"
|
|
41
41
|
# Only hard floor: mcp[cli] requires Python 3.10+. There is no upper bound —
|
|
42
42
|
# Resolve's scripting bridge loads into newer interpreters on recent builds
|
|
43
43
|
# (Python 3.14 verified against Resolve Studio 20.3.2). Older Resolve builds
|
package/package.json
CHANGED
package/src/granular/common.py
CHANGED
|
@@ -87,7 +87,7 @@ if not logging.getLogger().handlers:
|
|
|
87
87
|
handlers=[logging.StreamHandler()],
|
|
88
88
|
)
|
|
89
89
|
|
|
90
|
-
VERSION = "2.98.
|
|
90
|
+
VERSION = "2.98.8"
|
|
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
package/src/utils/api_truth.py
CHANGED
|
@@ -427,23 +427,21 @@ API_TRUTH: List[Dict[str, Any]] = [
|
|
|
427
427
|
"suppresses the parameter-change invalidation that a value "
|
|
428
428
|
"write depends on. Lock() is widely recommended for "
|
|
429
429
|
"batching Fusion edits, which is how this reaches "
|
|
430
|
-
"production code.
|
|
431
|
-
"
|
|
432
|
-
"through lock-wrapped AddTool/ConnectInput
|
|
430
|
+
"production code. MECHANISM (settled 2026-08-22). "
|
|
431
|
+
"PRECONDITION: it only reproduces on a comp whose graph was "
|
|
432
|
+
"BUILT through lock-wrapped AddTool/ConnectInput; the same "
|
|
433
433
|
"locked write against a graph wired by plain attribute "
|
|
434
|
-
"assignment renders normally
|
|
435
|
-
"
|
|
436
|
-
"
|
|
437
|
-
"
|
|
438
|
-
"
|
|
439
|
-
"
|
|
440
|
-
"inside the same lock
|
|
441
|
-
"
|
|
442
|
-
"
|
|
443
|
-
"
|
|
444
|
-
"
|
|
445
|
-
"reasons still unidentified. Keep value writes outside the "
|
|
446
|
-
"lock everywhere rather than relying on an escape.",
|
|
434
|
+
"assignment renders normally. TRIGGER: the locked write is "
|
|
435
|
+
"lost when it is the FIRST value write to that comp since "
|
|
436
|
+
"the build. PRIMING: any unlocked value write anywhere in "
|
|
437
|
+
"the comp clears the condition permanently — even writing a "
|
|
438
|
+
"DEFAULT value to an unrelated tool — and so does "
|
|
439
|
+
"StartUndo/EndUndo around the write. A structural "
|
|
440
|
+
"ConnectInput inside the same lock does NOT clear it, and "
|
|
441
|
+
"neither does a GetInput readback. Priming makes false "
|
|
442
|
+
"negatives easy: a test that sets anything up with a plain "
|
|
443
|
+
"SetInput before the call under test will pass even with the "
|
|
444
|
+
"bug present.",
|
|
447
445
|
"recommended": "Never hold a comp lock across a value write. Lock only "
|
|
448
446
|
"structural work (AddTool/ConnectInput) and set inputs "
|
|
449
447
|
"outside it. Because every readback the API offers "
|