davinci-resolve-mcp 2.94.0 → 2.94.2
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 +52 -6
- package/README.md +1 -1
- package/README.zh-CN.md +2 -2
- package/docs/reference/api-limitations.md +2 -2
- package/install.py +1 -1
- package/package.json +1 -1
- package/src/granular/common.py +1 -1
- package/src/server.py +8 -2
- package/src/utils/api_truth.py +14 -2
- package/src/utils/delivery_targets.py +16 -18
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,53 @@
|
|
|
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.2
|
|
6
|
+
|
|
7
|
+
Changelog repair. No code changed.
|
|
8
|
+
|
|
9
|
+
- **v2.93.3 carried two separate `What's New in v2.93.3` sections.** Two sessions
|
|
10
|
+
were working in one checkout, and one of them ran `git add -A` while the
|
|
11
|
+
other's edits were still uncommitted — so a delivery-target commit swept up an
|
|
12
|
+
unrelated `api_truth` correction, and both wrote their own heading under the
|
|
13
|
+
same version. The two sections are now merged into one entry that describes
|
|
14
|
+
everything v2.93.3 actually shipped: the delivery-target re-verification **and**
|
|
15
|
+
the issue #74 nested-timeline finding. The v2.93.3 GitHub release notes, which
|
|
16
|
+
described only the delivery work, have been amended in place for the same
|
|
17
|
+
reason. No commit or tag was rewritten — both are public.
|
|
18
|
+
|
|
19
|
+
## What's New in v2.94.1
|
|
20
|
+
|
|
21
|
+
Removes the `hls_h264` target added in v2.94.0 — it could never work — and fixes
|
|
22
|
+
a QC note that told the truth only for image sequences.
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- **`hls_h264` is withdrawn.** It resolved cleanly against the format/codec
|
|
27
|
+
matrix, which is why it shipped, but it can never render: on Studio 21.0.4.5
|
|
28
|
+
`GetRenderCodecs('m3u8')` returns `{'H.264': 'H264'}` and
|
|
29
|
+
`GetRenderResolutions('m3u8', 'H264')` returns real rasters, yet
|
|
30
|
+
`SetCurrentRenderFormatAndCodec('m3u8', ...)` is False for every value tried
|
|
31
|
+
(`'H264'`, `'H.264'`, `'h264'`, `''`) while `('mp4', 'H264')` succeeds. Caught
|
|
32
|
+
by queuing an actual job rather than by resolving a name. A target that always
|
|
33
|
+
fails is worse than no target, so it is gone along with its `hls` and
|
|
34
|
+
`streaming` aliases.
|
|
35
|
+
- **`qc_note` reported every target's missing QC projection as an image
|
|
36
|
+
sequence.** It was hard-coded, so `webp_animated` — which declines QC because
|
|
37
|
+
its ffprobe values are unmeasured — told callers its output was a many-file
|
|
38
|
+
sequence. It now surfaces the target's own `qc_skip_reason`.
|
|
39
|
+
|
|
40
|
+
### Notes
|
|
41
|
+
|
|
42
|
+
- New API-truth finding, folded into the existing `Project.GetRenderCodecs`
|
|
43
|
+
entry: **the format/codec matrix is not a capability contract.** A format can
|
|
44
|
+
advertise a codec, and rasters for it, and still refuse to be selected. That is
|
|
45
|
+
worse than the zero-codec formats, which at least advertise nothing. Presence
|
|
46
|
+
in the matrix proves a pair is *listed*, never that it is usable — the
|
|
47
|
+
authoritative test is setting it and reading the boolean back, which
|
|
48
|
+
`prepare_render_job` and `prepare_delivery_job` already do.
|
|
49
|
+
- 31 targets, all verified end to end on Studio 21.0.4.5: resolved, queued as a
|
|
50
|
+
real render job, then deleted.
|
|
51
|
+
|
|
5
52
|
## What's New in v2.94.0
|
|
6
53
|
|
|
7
54
|
Adds four delivery targets for deliverable classes the table did not cover:
|
|
@@ -44,9 +91,10 @@ Streaming package. All 32 targets resolve live on Studio 21.0.4.5.
|
|
|
44
91
|
|
|
45
92
|
## What's New in v2.93.3
|
|
46
93
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
than the 19.1.3.7
|
|
94
|
+
Two independent pieces of work landed in this release, both measured against the
|
|
95
|
+
**installed** build, Studio 21.0.4.5: the delivery-target table re-verified
|
|
96
|
+
against that build rather than the 19.1.3.7 it was first measured on, and a
|
|
97
|
+
correction to the issue #74 ledger entry.
|
|
50
98
|
|
|
51
99
|
### Changed
|
|
52
100
|
|
|
@@ -79,9 +127,7 @@ than the 19.1.3.7 they were first measured on.
|
|
|
79
127
|
|
|
80
128
|
`docs/reference/api-limitations.md` regenerated from those entries.
|
|
81
129
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
Ledger correction, measured live on DaVinci Resolve Studio **21.0.4.5**.
|
|
130
|
+
### Fixed — issue #74: titles can be placed by track and frame after all
|
|
85
131
|
|
|
86
132
|
- **A native Text+ CAN be placed at an exact track and frame, and stay editable
|
|
87
133
|
— entirely through the public API.** The issue #74 entry has said for two
|
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.94.
|
|
15
|
+
> 本翻译对应 v2.94.2 版 README。如与英文原版有出入,以 [英文原版](README.md) 为准。
|
|
16
16
|
|
|
17
17
|
一个 Model Context Protocol (MCP) 服务器,让 AI 助手通过官方脚本 API 控制 DaVinci Resolve Studio(达芬奇)。它提供完整的 API 覆盖,外加带护栏的工作流助手,涵盖剪辑、媒体池整理、渲染设置、审阅标记、调色、Fusion、Fairlight、项目生命周期任务、扩展开发,以及不碰源媒体的媒体分析。
|
|
18
18
|
|
|
@@ -470,8 +470,8 @@ values, or automation-hostile modal prompts.
|
|
|
470
470
|
|
|
471
471
|
- **Object:** `Project`
|
|
472
472
|
- **Signature:** `(renderFormat) -> {codec description: codec name}`
|
|
473
|
-
- **Behavior:** Returns {description: id} — the human-readable description is the KEY and the id Resolve actually accepts is the VALUE. SetCurrentRenderFormatAndCodec, GetRenderCodecs and GetRenderResolutions all require the id, so passing the description a user sees in the Deliver page is rejected. Verified live on Studio 19.1.3.7 and re-confirmed unchanged on 21.0.4.5: ('mov', 'Apple ProRes 422 HQ') -> False while ('mov', 'ProRes422HQ') -> True, and ('mp4', 'H.264') -> False while ('mp4', 'H264') -> True. It affects every family, not only the ones whose id differs obviously. Mirrors the same trap in GetRenderFormats, which returns {format: extension}. Descriptions also DRIFT between majors while ids do not — every DNx description gained an 'Avid ' prefix in 21.x ('DNxHR HQ' -> 'Avid DNxHR HQ 12-bit') while the ids (DNxHRHQ, DNxHRLB, DNxHRHQX_10) were unchanged. Key on ids.
|
|
474
|
-
- **Workaround / current handling:** Normalize both arguments through the live maps before calling: src.utils.render_ids.render_format_id_from_formats and render_codec_id_from_codecs accept a description or an id and return the id.
|
|
473
|
+
- **Behavior:** Returns {description: id} — the human-readable description is the KEY and the id Resolve actually accepts is the VALUE. SetCurrentRenderFormatAndCodec, GetRenderCodecs and GetRenderResolutions all require the id, so passing the description a user sees in the Deliver page is rejected. Verified live on Studio 19.1.3.7 and re-confirmed unchanged on 21.0.4.5: ('mov', 'Apple ProRes 422 HQ') -> False while ('mov', 'ProRes422HQ') -> True, and ('mp4', 'H.264') -> False while ('mp4', 'H264') -> True. It affects every family, not only the ones whose id differs obviously. Mirrors the same trap in GetRenderFormats, which returns {format: extension}. Descriptions also DRIFT between majors while ids do not — every DNx description gained an 'Avid ' prefix in 21.x ('DNxHR HQ' -> 'Avid DNxHR HQ 12-bit') while the ids (DNxHRHQ, DNxHRLB, DNxHRHQX_10) were unchanged. Key on ids. SEPARATELY, the returned map is not a capability contract: a format can ADVERTISE a codec it will not accept. On 21.0.4.5 GetRenderCodecs('m3u8') returns {'H.264': 'H264'} and GetRenderResolutions('m3u8','H264') returns real rasters, yet SetCurrentRenderFormatAndCodec('m3u8', ...) is False for every value tried ('H264', 'H.264', 'h264', '') while ('mp4','H264') succeeds. That is worse than the zero-codec formats, which at least advertise nothing.
|
|
474
|
+
- **Workaround / current handling:** Never treat presence in the matrix as proof a pair is usable — set it and read the boolean back (prepare_render_job / prepare_delivery_job do this and refuse to queue on False). Normalize both arguments through the live maps before calling: src.utils.render_ids.render_format_id_from_formats and render_codec_id_from_codecs accept a description or an id and return the id.
|
|
475
475
|
- **Reference:** [issue #59](https://github.com/samuelgursky/davinci-resolve-mcp/issues/59)
|
|
476
476
|
- **Tags:** render, deliver, silent-failure, id-vs-label
|
|
477
477
|
|
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.
|
|
39
|
+
VERSION = "2.94.2"
|
|
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
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.94.
|
|
90
|
+
VERSION = "2.94.2"
|
|
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.
|
|
14
|
+
VERSION = "2.94.2"
|
|
15
15
|
|
|
16
16
|
import base64
|
|
17
17
|
import os
|
|
@@ -17007,10 +17007,16 @@ def _resolve_delivery_target_live(proj, p: Dict[str, Any]):
|
|
|
17007
17007
|
"timeline_fps": fps,
|
|
17008
17008
|
"settings": _delivery_targets.to_render_settings(target, timeline_fps=fps),
|
|
17009
17009
|
"qc_spec": qc_spec,
|
|
17010
|
+
# Surface the target's OWN reason. This used to hard-code an
|
|
17011
|
+
# image-sequence message, which was simply false for any other kind
|
|
17012
|
+
# of target that declines a QC projection.
|
|
17010
17013
|
"qc_note": (
|
|
17011
17014
|
None
|
|
17012
17015
|
if qc_spec
|
|
17013
|
-
else
|
|
17016
|
+
else (
|
|
17017
|
+
target.qc_skip_reason
|
|
17018
|
+
or "This target has no single-file QC projection."
|
|
17019
|
+
)
|
|
17014
17020
|
),
|
|
17015
17021
|
"loudness_target": loudness,
|
|
17016
17022
|
"loudness_note": (
|
package/src/utils/api_truth.py
CHANGED
|
@@ -1689,8 +1689,20 @@ API_TRUTH: List[Dict[str, Any]] = [
|
|
|
1689
1689
|
"Descriptions also DRIFT between majors while ids do not — "
|
|
1690
1690
|
"every DNx description gained an 'Avid ' prefix in 21.x "
|
|
1691
1691
|
"('DNxHR HQ' -> 'Avid DNxHR HQ 12-bit') while the ids "
|
|
1692
|
-
"(DNxHRHQ, DNxHRLB, DNxHRHQX_10) were unchanged. Key on ids."
|
|
1693
|
-
|
|
1692
|
+
"(DNxHRHQ, DNxHRLB, DNxHRHQX_10) were unchanged. Key on ids. "
|
|
1693
|
+
"SEPARATELY, the returned map is not a capability contract: a "
|
|
1694
|
+
"format can ADVERTISE a codec it will not accept. On 21.0.4.5 "
|
|
1695
|
+
"GetRenderCodecs('m3u8') returns {'H.264': 'H264'} and "
|
|
1696
|
+
"GetRenderResolutions('m3u8','H264') returns real rasters, yet "
|
|
1697
|
+
"SetCurrentRenderFormatAndCodec('m3u8', ...) is False for every "
|
|
1698
|
+
"value tried ('H264', 'H.264', 'h264', '') while ('mp4','H264') "
|
|
1699
|
+
"succeeds. That is worse than the zero-codec formats, which at "
|
|
1700
|
+
"least advertise nothing.",
|
|
1701
|
+
"recommended": "Never treat presence in the matrix as proof a pair is "
|
|
1702
|
+
"usable — set it and read the boolean back "
|
|
1703
|
+
"(prepare_render_job / prepare_delivery_job do this and "
|
|
1704
|
+
"refuse to queue on False). Normalize both arguments "
|
|
1705
|
+
"through the live maps before "
|
|
1694
1706
|
"calling: src.utils.render_ids.render_format_id_from_formats "
|
|
1695
1707
|
"and render_codec_id_from_codecs accept a description or an "
|
|
1696
1708
|
"id and return the id.",
|
|
@@ -110,11 +110,15 @@ major-version upgrade.
|
|
|
110
110
|
|
|
111
111
|
Two findings changed between the builds and should not be treated as fixed facts:
|
|
112
112
|
|
|
113
|
-
- **PNG
|
|
114
|
-
`png_sequence
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
113
|
+
- **PNG and WebP.** Not render formats on 19.1.3.7; they *are* on 21.0.4.5, so
|
|
114
|
+
`png_sequence` and `webp_animated` resolve on 21.x and fail loudly on 19.x,
|
|
115
|
+
which is correct behavior rather than a regression. PNG exposes RGB only — no
|
|
116
|
+
alpha codec — so it does not replace `dpx_sequence` for transparency.
|
|
117
|
+
- **A format can advertise a codec it will not accept.** `HLS` (m3u8) returns a
|
|
118
|
+
codec from `GetRenderCodecs` and real rasters from `GetRenderResolutions`, yet
|
|
119
|
+
`SetCurrentRenderFormatAndCodec` rejects every value. Resolving a target proves
|
|
120
|
+
only that the pair is *listed*; the authoritative test is queuing a job, which
|
|
121
|
+
is why `prepare_delivery_job` refuses to queue on a rejected pair.
|
|
118
122
|
- **Zero-codec formats.** `wav` and `gif` on 19.x; `braw`, `mts` and `wav` on
|
|
119
123
|
21.x — `gif` gained codecs, BRAW and MTS lost them. `wav` is the constant, so
|
|
120
124
|
an audio-only WAV target remains inexpressible through
|
|
@@ -703,17 +707,13 @@ DELIVERY_TARGETS: Dict[str, DeliveryTarget] = {
|
|
|
703
707
|
"need a human. easyDCP variants exist on this install too.",
|
|
704
708
|
),
|
|
705
709
|
),
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
"— this selects the format/codec only.",
|
|
714
|
-
"HLS is not a render format on Resolve 19.x; this target resolves on 21.x+.",
|
|
715
|
-
),
|
|
716
|
-
),
|
|
710
|
+
# No HLS target. `HLS` (m3u8) looks fully supported through the query APIs on
|
|
711
|
+
# 21.0.4.5 — GetRenderCodecs returns {'H.264': 'H264'} and GetRenderResolutions
|
|
712
|
+
# returns real rasters — but SetCurrentRenderFormatAndCodec('m3u8', ...) is
|
|
713
|
+
# rejected for every value tried ('H264', 'H.264', 'h264', ''), while the same
|
|
714
|
+
# call for mp4/H264 succeeds. The matrix advertises a pair that cannot be
|
|
715
|
+
# selected, so a target for it would fail 100% of the time.
|
|
716
|
+
# Verified on Studio 21.0.4.5, 2026-08-12. See api_truth.py.
|
|
717
717
|
}
|
|
718
718
|
|
|
719
719
|
VALID_TARGETS = frozenset(DELIVERY_TARGETS)
|
|
@@ -749,8 +749,6 @@ TARGET_ALIASES: Dict[str, str] = {
|
|
|
749
749
|
"png": "png_sequence",
|
|
750
750
|
"gif": "gif_animated",
|
|
751
751
|
"webp": "webp_animated",
|
|
752
|
-
"hls": "hls_h264",
|
|
753
|
-
"streaming": "hls_h264",
|
|
754
752
|
}
|
|
755
753
|
|
|
756
754
|
#: Fields a caller may override per call. Deliberately excludes id/label/tier/
|