davinci-resolve-mcp 2.212.2 → 2.212.4
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 +76 -0
- package/README.md +2 -2
- package/README.zh-CN.md +3 -3
- package/install.py +2 -2
- package/package.json +9 -10
- package/resolve-advanced/package.json +5 -5
- package/src/granular/common.py +1 -1
- package/src/server.py +1 -1
- package/src/utils/update_check.py +26 -5
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,82 @@
|
|
|
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.212.4 — both dependency manifests move together again
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- **The root `package.json` had lagged `resolve-advanced/package.json` since
|
|
10
|
+
July.** The advanced manifest was brought to zero advisories on 2026-08-30;
|
|
11
|
+
the root one still carried the SDK at 1.27, adm-zip 0.5, sharp 0.33, zod 3
|
|
12
|
+
and uuid 9, so `npm audit` on the root read nine advisories (five high)
|
|
13
|
+
while the advanced package read one. Both manifests now agree:
|
|
14
|
+
`@modelcontextprotocol/sdk` 1.30, `fast-xml-parser` 5.11, `adm-zip` 0.6,
|
|
15
|
+
`sharp` 0.35, `zod` 4, `js-yaml` 4.3, `pg` 8.23, `better-sqlite3` held on
|
|
16
|
+
the 11.x line. Contributed in #193 by @federicosada-pixel.
|
|
17
|
+
- **`uuid` is gone from the root manifest.** Nothing under `bin/`, `src/` or
|
|
18
|
+
`scripts/` imports it — the code uses `crypto.randomUUID` — so rather than
|
|
19
|
+
carry the bump to 14.x it was removed on landing.
|
|
20
|
+
- **Python floor for the MCP SDK is now `mcp[cli]>=1.30,<2`** in
|
|
21
|
+
`requirements.txt` and the installer; the `<2` pin stays because the 2.x
|
|
22
|
+
SDK dropped `mcp.server.fastmcp`. `pyaaf2` floor moves to 1.7.1.
|
|
23
|
+
|
|
24
|
+
### What was checked
|
|
25
|
+
|
|
26
|
+
- **zod 3 → 4 is a major bump the advanced server takes directly.** Its two
|
|
27
|
+
single-argument `z.record()` sites (a documented zod 4 removal) were probed
|
|
28
|
+
on zod 4.5.4 for both parsing and JSON-schema conversion, and a real stdio
|
|
29
|
+
`tools/list` returns the same 18 tools before and after.
|
|
30
|
+
- **The five remaining root advisories are all transitive under the MCP
|
|
31
|
+
SDK** — hono, @hono/node-server, ajv → fast-uri, express-rate-limit →
|
|
32
|
+
ip-address, express → qs — and `npm audit fix --dry-run` reports the same
|
|
33
|
+
five, so they clear only when the SDK bumps its own dependencies.
|
|
34
|
+
- The Python suite was also run with the 1.30.0 SDK wheel shadowing the venv
|
|
35
|
+
before the venv itself was upgraded.
|
|
36
|
+
|
|
37
|
+
### Validation
|
|
38
|
+
|
|
39
|
+
- Full offline Python suite, the drift guards (including the lockfile-sync
|
|
40
|
+
guard), `npm ci` from both lockfiles, the advanced Node suite, the CLI
|
|
41
|
+
smoke and pack checks, and pip-audit on the upgraded venv. No Resolve
|
|
42
|
+
behavior changed; live test not required.
|
|
43
|
+
|
|
44
|
+
## What's New in v2.212.3 — a cached update prompt is re-judged against the version actually running
|
|
45
|
+
|
|
46
|
+
### Fixed
|
|
47
|
+
|
|
48
|
+
- **A persisted "update available" outlived the upgrade it recommended.** The
|
|
49
|
+
update checker caches its last verdict (in memory and in
|
|
50
|
+
`logs/update-check.json`) and serves it without network for the throttle
|
|
51
|
+
interval. That verdict was stored as a *status*, not as a comparison, so
|
|
52
|
+
after upgrading from the version it was computed for — 2.135.0 → 2.210.0,
|
|
53
|
+
say — a server now running 2.212.1 kept prompting to update to 2.210.0.
|
|
54
|
+
Every cached path (in-memory, persisted, and the throttled branch of
|
|
55
|
+
`check_for_updates`) now re-compares the cached `latest_version` against
|
|
56
|
+
the running version and reclassifies to `update_available` /
|
|
57
|
+
`up_to_date` / `current_ahead`; `error` and `disabled` results are left
|
|
58
|
+
as they were. Contributed in #194 by @diesdaas.
|
|
59
|
+
|
|
60
|
+
### Documentation
|
|
61
|
+
|
|
62
|
+
- **The READMEs said there was no beat detection; there has been for some
|
|
63
|
+
time.** Both the English and Simplified Chinese "not supported" tables
|
|
64
|
+
claimed "no beat or downbeat detection yet" — twenty lines below an
|
|
65
|
+
optional-extras table listing `pip install librosa` for exactly that. The
|
|
66
|
+
row now describes what actually exists: optional `librosa` beat detection
|
|
67
|
+
and beat / bar / phrase cut-point plans, downbeats inferred from the first
|
|
68
|
+
beat with `beat_offset` for pickups, and cut *points* rather than a finished
|
|
69
|
+
music edit. Speech-silence tools remain the wrong instrument for music.
|
|
70
|
+
|
|
71
|
+
### Validation
|
|
72
|
+
|
|
73
|
+
- Four regression tests from the PR cover the persisted, in-memory and
|
|
74
|
+
throttled cache paths plus the preserved error/disabled states. On landing,
|
|
75
|
+
the update-check tests gained a `setUp` that resets the module-wide cache
|
|
76
|
+
around every test, so a seeded verdict cannot leak into another module's
|
|
77
|
+
cached-status read later in the run. Full offline suite, drift guards and
|
|
78
|
+
the advanced Node suite are green. No Resolve behavior changed; live test
|
|
79
|
+
not required.
|
|
80
|
+
|
|
5
81
|
## What's New in v2.212.2 — failed verification evidence survives the operation envelope
|
|
6
82
|
|
|
7
83
|
### Fixed
|
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)
|
|
@@ -339,7 +339,7 @@ cheaper to read it here than to discover it mid-project.
|
|
|
339
339
|
| Not supported | Why, and what you get instead |
|
|
340
340
|
|---|---|
|
|
341
341
|
| **Choosing the best take** | Performance is most of what makes a take right, and none of it is measurable from a waveform or a transcript. `rank_takes` ranks *fluency* — fillers, restarts, script coverage — and says so in every response. The take that plays is regularly the least fluent one, because the hesitation is often the acting. Use it to find the clean safety take, not to choose the read. |
|
|
342
|
-
| **
|
|
342
|
+
| **Automatic music editing** | Optional `librosa` support provides beat detection and beat/bar/phrase cut-point plans, not a finished assembly. Downbeats are inferred from the first beat; use `beat_offset` for pickups. Speech-silence tools are unsuitable for finding musical edit points. |
|
|
343
343
|
| **Judging a cut** | Nothing here has an opinion about whether an edit is good. Every destructive action is plan → review → confirm for that reason. |
|
|
344
344
|
| **Replacing an editor** | The output is a first-pass assembly, in the assistant-editor sense: ingest, sync, organize, string out, flag problems. It is a starting point you cut, not a finished cut. Defaults are deliberately **generous** — a first assembly is supposed to run long, because trimming is fast and visible while recovering discarded material is slow and invisible. |
|
|
345
345
|
| **Modifying your source media** | By design and without exception — see below. |
|
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.212.
|
|
15
|
+
> 本翻译对应 v2.212.4 版 README。如与英文原版有出入,以 [英文原版](README.md) 为准。
|
|
16
16
|
|
|
17
17
|
一个 Model Context Protocol (MCP) 服务器,让 AI 助手通过官方脚本 API 控制 DaVinci Resolve Studio(达芬奇)。它提供完整的 API 覆盖,外加带护栏的工作流助手,涵盖剪辑、媒体池整理、渲染设置、审阅标记、调色、Fusion、Fairlight、项目生命周期任务、扩展开发,以及不碰源媒体的媒体分析。
|
|
18
18
|
|
|
@@ -207,7 +207,7 @@ DRX 调色写入**针对 Resolve Studio 做过实机校准**:调色参数默
|
|
|
207
207
|
| 不支持 | 原因,以及你能得到什么 |
|
|
208
208
|
|---|---|
|
|
209
209
|
| **挑选最佳条次** | 表演是决定一条好坏的大头,而这些从波形或转写里都量不出来。`rank_takes` 排的是*流畅度*——填充词、重来、稿子覆盖率——并在每次响应里说明这一点。最终用的那条常常是最不流畅的一条,因为迟疑往往正是表演。用它找干净的保底条,别用它挑读法。 |
|
|
210
|
-
|
|
|
210
|
+
| **自动音乐剪辑** | 可选的 `librosa` 支持节拍检测和按节拍、小节、乐句规划剪切点,但不会生成完整剪辑。强拍从第一个节拍推断;遇到弱起时用 `beat_offset` 调整。语音静音检测工具不适合寻找音乐剪切点。 |
|
|
211
211
|
| **评判剪辑好坏** | 这里没有任何东西对"这一刀剪得好不好"持有观点。正因如此,一切破坏性操作都走 计划 → 审阅 → 确认。 |
|
|
212
212
|
| **取代剪辑师** | 输出是助理剪辑意义上的初剪:摄入、同步、整理、串片、标记问题。它是给你继续剪的起点,不是成片。默认参数刻意**宽松**——初剪本来就该偏长,因为往下修快且看得见,而找回已丢弃的素材慢且看不见。 |
|
|
213
213
|
| **修改你的源媒体** | 设计如此,无例外——见下文。 |
|
package/install.py
CHANGED
|
@@ -37,7 +37,7 @@ from src.utils.update_check import (
|
|
|
37
37
|
|
|
38
38
|
# ─── Version ──────────────────────────────────────────────────────────────────
|
|
39
39
|
|
|
40
|
-
VERSION = "2.212.
|
|
40
|
+
VERSION = "2.212.4"
|
|
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
|
|
@@ -1385,7 +1385,7 @@ def install_dependencies(venv_path, project_dir):
|
|
|
1385
1385
|
# downgrade it, and the fix does not depend on install ordering. Lift both
|
|
1386
1386
|
# together when server.py is ported to the 2.x layout.
|
|
1387
1387
|
subprocess.run(
|
|
1388
|
-
[str(pip), "install", "-q", "mcp[cli]>=1.
|
|
1388
|
+
[str(pip), "install", "-q", "mcp[cli]>=1.30,<2"],
|
|
1389
1389
|
check=True, capture_output=True
|
|
1390
1390
|
)
|
|
1391
1391
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "davinci-resolve-mcp",
|
|
3
|
-
"version": "2.212.
|
|
3
|
+
"version": "2.212.4",
|
|
4
4
|
"description": "NPM bootstrapper for the DaVinci Resolve MCP Server.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Samuel Gursky <samgursky@gmail.com>",
|
|
@@ -18,20 +18,19 @@
|
|
|
18
18
|
"davinci-resolve-advanced-mcp": "./bin/davinci-resolve-advanced-mcp.mjs"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
22
|
-
"adm-zip": "^0.
|
|
23
|
-
"fast-xml-parser": "^5.
|
|
21
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
22
|
+
"adm-zip": "^0.6.0",
|
|
23
|
+
"fast-xml-parser": "^5.11.1",
|
|
24
24
|
"fzstd": "^0.1.1",
|
|
25
25
|
"jszip": "^3.10.1",
|
|
26
|
-
"
|
|
27
|
-
"zod": "^3.25.76",
|
|
26
|
+
"zod": "^4.5.4",
|
|
28
27
|
"zstd-codec": "^0.1.5"
|
|
29
28
|
},
|
|
30
29
|
"optionalDependencies": {
|
|
31
|
-
"better-sqlite3": "^11.
|
|
32
|
-
"js-yaml": "^4.
|
|
33
|
-
"pg": "^8.
|
|
34
|
-
"sharp": "^0.
|
|
30
|
+
"better-sqlite3": "^11.10.0",
|
|
31
|
+
"js-yaml": "^4.3.2",
|
|
32
|
+
"pg": "^8.23.0",
|
|
33
|
+
"sharp": "^0.35.4"
|
|
35
34
|
},
|
|
36
35
|
"files": [
|
|
37
36
|
"bin/",
|
|
@@ -19,18 +19,18 @@
|
|
|
19
19
|
"LICENSE"
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
22
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
23
23
|
"adm-zip": "^0.6.0",
|
|
24
|
-
"fast-xml-parser": "^5.
|
|
24
|
+
"fast-xml-parser": "^5.11.1",
|
|
25
25
|
"fzstd": "^0.1.1",
|
|
26
26
|
"jszip": "^3.10.1",
|
|
27
|
-
"zod": "^
|
|
27
|
+
"zod": "^4.5.4",
|
|
28
28
|
"zstd-codec": "^0.1.5"
|
|
29
29
|
},
|
|
30
30
|
"optionalDependencies": {
|
|
31
31
|
"better-sqlite3": "^11.10.0",
|
|
32
|
-
"js-yaml": "^4.3.
|
|
33
|
-
"pg": "^8.
|
|
32
|
+
"js-yaml": "^4.3.2",
|
|
33
|
+
"pg": "^8.23.0",
|
|
34
34
|
"sharp": "^0.35.4"
|
|
35
35
|
},
|
|
36
36
|
"peerDependenciesMeta": {
|
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.212.
|
|
90
|
+
VERSION = "2.212.4"
|
|
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
|
@@ -135,14 +135,13 @@ def get_cached_update_status(
|
|
|
135
135
|
with _cached_lock:
|
|
136
136
|
cached = dict(_cached_status)
|
|
137
137
|
if cached.get("status") != "unknown":
|
|
138
|
-
|
|
139
|
-
|
|
138
|
+
cached = _reclassify_cached_status(cached, current_version)
|
|
139
|
+
_set_cached_status(cached)
|
|
140
140
|
return cached
|
|
141
141
|
|
|
142
142
|
state = _read_state(update_state_path(project_dir, env))
|
|
143
143
|
if state:
|
|
144
|
-
|
|
145
|
-
state["current_version"] = current_version
|
|
144
|
+
state = _reclassify_cached_status(state, current_version)
|
|
146
145
|
if "update_mode" not in state:
|
|
147
146
|
state["update_mode"] = get_update_mode(project_dir, env)
|
|
148
147
|
return state
|
|
@@ -193,11 +192,12 @@ def check_for_updates(
|
|
|
193
192
|
and previous
|
|
194
193
|
and checked_at - float(previous.get("checked_at", 0)) < interval_seconds
|
|
195
194
|
):
|
|
196
|
-
cached =
|
|
195
|
+
cached = _reclassify_cached_status(previous, current_version)
|
|
197
196
|
cached["cached"] = True
|
|
198
197
|
cached["update_mode"] = update_mode
|
|
199
198
|
cached["next_check_at"] = float(previous.get("checked_at", 0)) + interval_seconds
|
|
200
199
|
cached["next_check_at_iso"] = _format_timestamp(cached["next_check_at"])
|
|
200
|
+
_write_state(state_path, cached)
|
|
201
201
|
_set_cached_status(cached)
|
|
202
202
|
return cached
|
|
203
203
|
|
|
@@ -621,6 +621,27 @@ def _version_text(value: Any) -> str:
|
|
|
621
621
|
return match.group(0) if match else str(value or "").strip()
|
|
622
622
|
|
|
623
623
|
|
|
624
|
+
def _reclassify_cached_status(
|
|
625
|
+
result: Mapping[str, Any], current_version: Optional[str]
|
|
626
|
+
) -> Dict[str, Any]:
|
|
627
|
+
"""Refresh cached status against the version of the running MCP."""
|
|
628
|
+
refreshed = dict(result)
|
|
629
|
+
if refreshed.get("status") not in _SUCCESS_STATUSES:
|
|
630
|
+
return refreshed
|
|
631
|
+
if current_version:
|
|
632
|
+
refreshed["current_version"] = current_version
|
|
633
|
+
comparison = compare_versions(current_version, refreshed.get("latest_version"))
|
|
634
|
+
if comparison is None:
|
|
635
|
+
return refreshed
|
|
636
|
+
if comparison < 0:
|
|
637
|
+
refreshed["status"] = "update_available"
|
|
638
|
+
elif comparison > 0:
|
|
639
|
+
refreshed["status"] = "current_ahead"
|
|
640
|
+
else:
|
|
641
|
+
refreshed["status"] = "up_to_date"
|
|
642
|
+
return refreshed
|
|
643
|
+
|
|
644
|
+
|
|
624
645
|
def _read_state(path: Path) -> Dict[str, Any]:
|
|
625
646
|
try:
|
|
626
647
|
with path.open("r", encoding="utf-8") as handle:
|