davinci-resolve-mcp 2.205.0 → 2.205.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 +58 -0
- package/README.md +15 -1
- package/README.zh-CN.md +8 -2
- package/docs/SKILL.md +8 -0
- package/install.py +1 -1
- package/package.json +1 -1
- package/scripts/install_resolve_bridge.py +111 -13
- package/src/granular/common.py +1 -1
- package/src/server.py +16 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,64 @@
|
|
|
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.205.2 — #184: background analysis actually starts
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- **`background=true` / `async_job=true` silently never ran.**
|
|
10
|
+
`start_batch_job` derived the runner's project root with
|
|
11
|
+
`str(plan["output_root"])`, but that field holds the *mapping*
|
|
12
|
+
`resolve_output_root()` returns, not a path. `str()` on it produced a dict
|
|
13
|
+
repr — and because that repr is a **non-empty** string it satisfied the
|
|
14
|
+
`if wants_runner and job_id and project_root` guard, so the runner was handed
|
|
15
|
+
a "directory" naming nothing on disk. It found no job store, returned
|
|
16
|
+
`job_not_found`, and the caller was told to go debug a job that existed and
|
|
17
|
+
was perfectly healthy. Reported and fixed in #184 by @turapins, who also
|
|
18
|
+
established that `batch_cli` and the analysis dashboard already read the
|
|
19
|
+
field as a mapping — `server.py` was the single consumer out of step, so the
|
|
20
|
+
fix belonged there rather than in the mapping's shape.
|
|
21
|
+
|
|
22
|
+
## What's New in v2.205.1 — #182: the bridge preflight checks both halves of Resolve's Python lookup
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- **A `PYTHON3HOME` prefix with a dylib but no `bin/python3` is no longer
|
|
27
|
+
reported as usable.** fusionscript.so does two things with the prefix — runs
|
|
28
|
+
`<prefix>/bin/python3` and dlopens `<prefix>/lib/libpython3.X.dylib`, whose
|
|
29
|
+
strings sit adjacent in the binary — and the preflight validated only the
|
|
30
|
+
second. It answered `python3_home.usable: true` and
|
|
31
|
+
`resolve_will_list_python_scripts: true` while Resolve listed **zero** Python
|
|
32
|
+
scripts and logged nothing, which is the worst shape this failure can take:
|
|
33
|
+
the user has been told the thing is configured correctly, so the real cause
|
|
34
|
+
is the last place they look. Reported in #182, with the root cause and the
|
|
35
|
+
fix both correct as filed.
|
|
36
|
+
- **The interpreter has to be there under the unversioned name.** `python3` is
|
|
37
|
+
the literal name in the binary, and that is what makes this trap easy to hit:
|
|
38
|
+
a Homebrew framework prefix carries a perfectly good
|
|
39
|
+
`lib/libpython3.13.dylib` next to a `bin/` that has `python3.13` and no
|
|
40
|
+
`python3`. It is formula-dependent — `python@3.14` ships one, `python@3.11`
|
|
41
|
+
and `python@3.13` do not — so the same "Homebrew Python" advice works on one
|
|
42
|
+
machine and silently fails on the next. `framework_pythons()` has always
|
|
43
|
+
required `bin/python3`; this is the same rule applied to the route that
|
|
44
|
+
skipped it.
|
|
45
|
+
- **A set-but-unusable `PYTHON3HOME` is now called out even when another
|
|
46
|
+
discovery route exists.** Resolve reads it first, and whether it falls back
|
|
47
|
+
after choosing a prefix it cannot use is inferred from string adjacency
|
|
48
|
+
rather than established — so resting a clean bill of health on a route
|
|
49
|
+
Resolve may never reach is the same false all-clear in a new place. The
|
|
50
|
+
preflight names the mismatch, prints the exact `ln -s` that repairs it, and
|
|
51
|
+
suggests `launchctl unsetenv` as the alternative.
|
|
52
|
+
|
|
53
|
+
### Changed
|
|
54
|
+
|
|
55
|
+
- **The advice says that `launchctl setenv` does not survive a reboot.** A
|
|
56
|
+
bridge that listed for weeks and then stopped, with no error anywhere, is
|
|
57
|
+
usually that, and nobody connects it back to a step they ran a month
|
|
58
|
+
earlier. `sudo ln -s "$(command -v python3)" /usr/local/bin/python3` is
|
|
59
|
+
offered as the persistent alternative, with the `PATH` caveat — presented
|
|
60
|
+
alongside the sudo-free route rather than replacing it, since avoiding a
|
|
61
|
+
system-wide install is the whole point of the #143 fix.
|
|
62
|
+
|
|
5
63
|
## What's New in v2.205.0 — a standard operation envelope on every tool result
|
|
6
64
|
|
|
7
65
|
Adapted from the design contributed in PR #181.
|
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)
|
|
@@ -80,6 +80,20 @@ never sees your shell's environment. Restart Resolve afterwards. A Lua canary is
|
|
|
80
80
|
installed alongside so you can tell "Python not detected" apart from a wrong
|
|
81
81
|
folder.
|
|
82
82
|
|
|
83
|
+
Two things that bite (#182). The prefix must contain **both**
|
|
84
|
+
`lib/libpython3.X.dylib` and `bin/python3` under that exact **unversioned**
|
|
85
|
+
name — Homebrew's framework builds often ship only `bin/python3.13`, which is
|
|
86
|
+
half a Python as far as Resolve is concerned, and the installer's preflight now
|
|
87
|
+
says so instead of reporting a usable prefix. And `launchctl setenv` **does not
|
|
88
|
+
survive a reboot**; if scripts stop listing weeks later with no error, that is
|
|
89
|
+
why. For something persistent, put an interpreter where Resolve already looks
|
|
90
|
+
(this one needs `sudo`, and check that `/usr/local/bin` does not precede your
|
|
91
|
+
normal Python on `PATH`):
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
sudo ln -s "$(command -v python3)" /usr/local/bin/python3
|
|
95
|
+
```
|
|
96
|
+
|
|
83
97
|
Validated on free 21.0.3.7 and Studio 19.1.3.7, both macOS. The Windows paths
|
|
84
98
|
added in v2.70.1 (issue #106) shipped unverified; reports on free 21.0.1.11
|
|
85
99
|
(issue #109) and free 21.0.3.7 (issue #112) have since shown the bridge
|
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.205.
|
|
15
|
+
> 本翻译对应 v2.205.2 版 README。如与英文原版有出入,以 [英文原版](README.md) 为准。
|
|
16
16
|
|
|
17
17
|
一个 Model Context Protocol (MCP) 服务器,让 AI 助手通过官方脚本 API 控制 DaVinci Resolve Studio(达芬奇)。它提供完整的 API 覆盖,外加带护栏的工作流助手,涵盖剪辑、媒体池整理、渲染设置、审阅标记、调色、Fusion、Fairlight、项目生命周期任务、扩展开发,以及不碰源媒体的媒体分析。
|
|
18
18
|
|
|
@@ -61,6 +61,12 @@ launchctl setenv PYTHON3HOME "$(python3 -c 'import sys; print(sys.prefix)')"
|
|
|
61
61
|
|
|
62
62
|
必须用 `launchctl setenv` 而不是 `export`——Resolve 从 Dock 启动,看不到你 shell 的环境变量。之后重启 Resolve。安装时会顺带装一个 Lua 金丝雀脚本,帮你区分"Python 未被检测到"和"目录放错"。
|
|
63
63
|
|
|
64
|
+
有两个坑(#182)。前缀里必须**同时**有 `lib/libpython3.X.dylib` 和 `bin/python3`——而且是这个**不带版本号**的名字。Homebrew 的 framework 构建经常只提供 `bin/python3.13`,在 Resolve 眼里这只算半个 Python;安装器的预检现在会明说这一点,而不是报告前缀可用。另外,`launchctl setenv` **在重启后不会保留**;如果几周之后脚本又不列出来了且没有任何报错,通常就是这个原因。想要持久生效,就把解释器放到 Resolve 本来就会查的位置(这条需要 `sudo`,并且先确认 `/usr/local/bin` 没有排在你常用 Python 的 `PATH` 前面):
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
sudo ln -s "$(command -v python3)" /usr/local/bin/python3
|
|
68
|
+
```
|
|
69
|
+
|
|
64
70
|
已在免费版 21.0.3.7 和 Studio 19.1.3.7 上验证(均为 macOS)。v2.70.1(issue #106)加入的 Windows 路径发布时未经验证;后续免费版 21.0.1.11(issue #109)和免费版 21.0.3.7(issue #112)的用户报告证实,Windows 11 上桥接在 `%PROGRAMDATA%` 和 `%APPDATA%` **两处**都能安装、列出并正常服务,这些路径现在是已证实而非假设。Linux 同样已获证实:免费版 20.3.2.9 的用户报告(issue #129,Fedora 43)显示桥接可安装到 `~/.local/share/DaVinciResolve/Fusion/Scripts/Utility`,用系统 Python 就能直接枚举脚本(Linux 完全没有这套查找问题),并能端到端正常服务。现在没有任何平台停留在假设上:macOS 为本项目直接验证,Windows 和 Linux 来自用户报告。
|
|
65
71
|
|
|
66
72
|
注意:桥接在服务期间会一直占用端口。v2.70.3 之前,Windows 上的桥接可能在 Resolve 退出后存活,挡住下一个会话的监听器;如果你用的是旧版本且桥接不响应了,检查是否有残留的 `fuscript.exe` 还占着端口。
|
package/docs/SKILL.md
CHANGED
|
@@ -41,6 +41,14 @@ Existing tool call sites work unchanged. Two things to know when diagnosing it:
|
|
|
41
41
|
canary, which always lists, so "Python not detected" is distinguishable from
|
|
42
42
|
"wrong folder". The preflight is macOS-only — off macOS Resolve finds Python
|
|
43
43
|
by other means, and running the check there was a false alarm (#106).
|
|
44
|
+
Two follow-ups from #182 worth having in hand when a user says the menu is
|
|
45
|
+
empty despite a set `PYTHON3HOME`: the prefix needs **both**
|
|
46
|
+
`lib/libpython3.X.dylib` and `bin/python3` under that **unversioned** name
|
|
47
|
+
(Homebrew framework builds often ship only `python3.X`, so half the check
|
|
48
|
+
passes on the very interpreter people reach for), and `launchctl setenv` does
|
|
49
|
+
not survive a reboot — a bridge that listed for weeks and then stopped, with
|
|
50
|
+
no error anywhere, is usually that. `sudo ln -s "$(command -v python3)"
|
|
51
|
+
/usr/local/bin/python3` is the persistent alternative.
|
|
44
52
|
- **Windows: both script folders confirmed.** `%PROGRAMDATA%` (#109) and
|
|
45
53
|
`%APPDATA%` (#112) have each been shown serving the bridge on Windows 11 free
|
|
46
54
|
builds. If a user reports the menu entry missing on Windows, ask whether the
|
package/install.py
CHANGED
|
@@ -37,7 +37,7 @@ from src.utils.update_check import (
|
|
|
37
37
|
|
|
38
38
|
# ─── Version ──────────────────────────────────────────────────────────────────
|
|
39
39
|
|
|
40
|
-
VERSION = "2.205.
|
|
40
|
+
VERSION = "2.205.2"
|
|
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
|
@@ -286,10 +286,14 @@ _LUA_CANARY = """-- Installed by davinci-resolve-mcp as an enumeration canary.
|
|
|
286
286
|
-- Resolve is listing Lua and silently skipping Python: it cannot find a Python 3.
|
|
287
287
|
-- It looks at PYTHON3HOME, then /usr/local/bin/python3 -- and nowhere else, which
|
|
288
288
|
-- is why Homebrew, pyenv, uv and conda interpreters go unseen. Either point it at
|
|
289
|
-
-- the one you have (no sudo):
|
|
289
|
+
-- the one you have (no sudo, but does NOT survive a reboot):
|
|
290
290
|
-- launchctl setenv PYTHON3HOME "$(python3 -c 'import sys; print(sys.prefix)')"
|
|
291
|
-
-- (launchctl, not export -- Resolve never sees your shell
|
|
292
|
-
--
|
|
291
|
+
-- (launchctl, not export -- Resolve never sees your shell; and the prefix needs
|
|
292
|
+
-- BOTH lib/libpython3.X.dylib and bin/python3 under that unversioned name --
|
|
293
|
+
-- Homebrew framework builds often ship only python3.X), or put one where Resolve
|
|
294
|
+
-- already looks, which persists:
|
|
295
|
+
-- sudo ln -s "$(command -v python3)" /usr/local/bin/python3
|
|
296
|
+
-- A python.org build creates that symlink for you. Restart Resolve after.
|
|
293
297
|
print("Resolve is enumerating scripts. If the Python probe is missing, Resolve")
|
|
294
298
|
print("cannot find a Python 3: set PYTHON3HOME with launchctl setenv, or install")
|
|
295
299
|
print("a python.org build. Homebrew/pyenv/uv/conda are not looked at directly.")
|
|
@@ -335,12 +339,28 @@ def launchd_env(name: str) -> str | None:
|
|
|
335
339
|
|
|
336
340
|
|
|
337
341
|
def python3_home_prefix() -> dict:
|
|
338
|
-
"""Is PYTHON3HOME set for Resolve, and does it point at a
|
|
342
|
+
"""Is PYTHON3HOME set for Resolve, and does it point at a usable Python 3?
|
|
339
343
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
+
Usable means BOTH halves of what fusionscript.so does with the prefix, whose
|
|
345
|
+
strings sit adjacent in the binary:
|
|
346
|
+
|
|
347
|
+
python3 -c 'import sys; ...sys.prefix...' # run <prefix>/bin/python3
|
|
348
|
+
/libpython # dlopen <prefix>/lib/libpython3.X.dylib
|
|
349
|
+
|
|
350
|
+
Checking only the dylib reported `usable: true` for a prefix Resolve cannot
|
|
351
|
+
run, and then Resolve listed zero Python scripts — the exact false all-clear
|
|
352
|
+
this function's docstring already warned about, since "the silent
|
|
353
|
+
non-enumeration symptom is identical and the remedy is not" (issue #182).
|
|
354
|
+
|
|
355
|
+
The interpreter must be there under the **unversioned** name. That is the
|
|
356
|
+
literal name in the binary, and it is what makes this trap so easy to hit:
|
|
357
|
+
a Homebrew framework prefix has `bin/python3.13` but no `bin/python3`
|
|
358
|
+
(formula-dependent — python@3.14 ships one, python@3.11 and python@3.13 do
|
|
359
|
+
not), while carrying a perfectly good `lib/libpython3.13.dylib`. Half the
|
|
360
|
+
check passes on exactly the interpreter most likely to be tried.
|
|
361
|
+
|
|
362
|
+
`framework_pythons()` has always required `bin/python3`; this is the same
|
|
363
|
+
rule applied to the route that skipped it.
|
|
344
364
|
"""
|
|
345
365
|
value = launchd_env("PYTHON3HOME")
|
|
346
366
|
result = {
|
|
@@ -348,20 +368,70 @@ def python3_home_prefix() -> dict:
|
|
|
348
368
|
"in_launchd": value is not None,
|
|
349
369
|
"in_this_shell": os.environ.get("PYTHON3HOME") or None,
|
|
350
370
|
"dylib": None,
|
|
371
|
+
"interpreter": None,
|
|
372
|
+
"reason": None,
|
|
351
373
|
"usable": False,
|
|
352
374
|
}
|
|
353
375
|
if not value:
|
|
354
376
|
return result
|
|
377
|
+
|
|
378
|
+
prefix = Path(value)
|
|
355
379
|
try:
|
|
356
|
-
dylibs = sorted(
|
|
380
|
+
dylibs = sorted(prefix.glob("lib/libpython3.*.dylib"))
|
|
357
381
|
except OSError:
|
|
358
382
|
dylibs = []
|
|
383
|
+
interpreter = prefix / "bin" / "python3"
|
|
384
|
+
try:
|
|
385
|
+
# .exists() follows symlinks, so a dangling one reads as absent — which
|
|
386
|
+
# is what it is to a Resolve trying to execute it.
|
|
387
|
+
has_interpreter = interpreter.exists()
|
|
388
|
+
except OSError:
|
|
389
|
+
has_interpreter = False
|
|
390
|
+
|
|
359
391
|
if dylibs:
|
|
360
392
|
result["dylib"] = str(dylibs[0])
|
|
361
|
-
|
|
393
|
+
if has_interpreter:
|
|
394
|
+
result["interpreter"] = str(interpreter)
|
|
395
|
+
result["usable"] = bool(dylibs) and has_interpreter
|
|
396
|
+
|
|
397
|
+
if result["usable"]:
|
|
398
|
+
return result
|
|
399
|
+
if dylibs and not has_interpreter:
|
|
400
|
+
versioned = sorted(
|
|
401
|
+
child.name for child in _safe_iterdir(prefix / "bin")
|
|
402
|
+
if child.name.startswith("python3.")
|
|
403
|
+
and not child.name.endswith("-config")
|
|
404
|
+
)
|
|
405
|
+
result["reason"] = (
|
|
406
|
+
f"{prefix}/lib has a libpython dylib but {interpreter} does not "
|
|
407
|
+
f"exist. Resolve runs the UNVERSIONED name `python3`"
|
|
408
|
+
+ (f"; this prefix ships only {', '.join(versioned)}. " if versioned else ". ")
|
|
409
|
+
+ "Homebrew framework builds are the common case. Either symlink it "
|
|
410
|
+
f"inside the prefix (ln -s {versioned[0] if versioned else 'python3.X'} "
|
|
411
|
+
f"{prefix}/bin/python3), or point PYTHON3HOME at a prefix that has both."
|
|
412
|
+
)
|
|
413
|
+
elif has_interpreter and not dylibs:
|
|
414
|
+
result["reason"] = (
|
|
415
|
+
f"{interpreter} exists but {prefix}/lib has no libpython3.X.dylib "
|
|
416
|
+
"for Resolve to dlopen. A static or non-shared build cannot be "
|
|
417
|
+
"embedded; point PYTHON3HOME at a prefix built with a shared library."
|
|
418
|
+
)
|
|
419
|
+
else:
|
|
420
|
+
result["reason"] = (
|
|
421
|
+
f"{prefix} has neither bin/python3 nor lib/libpython3.X.dylib. "
|
|
422
|
+
"Check the path — it should be a Python `sys.prefix`, which "
|
|
423
|
+
"`python3 -c 'import sys; print(sys.prefix)'` prints."
|
|
424
|
+
)
|
|
362
425
|
return result
|
|
363
426
|
|
|
364
427
|
|
|
428
|
+
def _safe_iterdir(directory: Path) -> list[Path]:
|
|
429
|
+
try:
|
|
430
|
+
return sorted(directory.iterdir())
|
|
431
|
+
except OSError:
|
|
432
|
+
return []
|
|
433
|
+
|
|
434
|
+
|
|
365
435
|
def fallback_python3() -> dict:
|
|
366
436
|
"""`/usr/local/bin/python3` — the path baked into fusionscript.so.
|
|
367
437
|
|
|
@@ -414,7 +484,27 @@ def python_preflight() -> dict:
|
|
|
414
484
|
# the order the binary's strings imply, and it is the one the user chose.
|
|
415
485
|
found = home["usable"] or fallback["exists"] or bool(frameworks)
|
|
416
486
|
advice = None
|
|
417
|
-
if not
|
|
487
|
+
if home["in_launchd"] and not home["usable"]:
|
|
488
|
+
# A set-but-broken PYTHON3HOME has to be said out loud even when another
|
|
489
|
+
# route exists. PYTHON3HOME is read FIRST, and whether Resolve falls
|
|
490
|
+
# back after choosing a prefix it cannot use is not established — the
|
|
491
|
+
# ordering here is inferred from string adjacency in fusionscript.so,
|
|
492
|
+
# not from decompiled control flow. Reporting a clean bill of health on
|
|
493
|
+
# the strength of a route Resolve may never reach is the failure this
|
|
494
|
+
# whole check exists to prevent (issue #182).
|
|
495
|
+
advice = (
|
|
496
|
+
"PYTHON3HOME is set for Resolve but does not point at a Python 3 it "
|
|
497
|
+
f"can use.\n{home['reason']}\n"
|
|
498
|
+
+ ("Another discovery route is present on this machine, but Resolve "
|
|
499
|
+
"reads PYTHON3HOME first and it is NOT established that it falls "
|
|
500
|
+
"back after picking a prefix it cannot use. Fix the prefix or "
|
|
501
|
+
"unset it (launchctl unsetenv PYTHON3HOME) rather than relying "
|
|
502
|
+
"on the fallback.\n" if found else "")
|
|
503
|
+
+ "Restart Resolve after changing it. The Lua canary installed "
|
|
504
|
+
"alongside lists regardless, so 'Python not detected' stays "
|
|
505
|
+
"distinguishable from 'wrong folder'."
|
|
506
|
+
)
|
|
507
|
+
elif not found:
|
|
418
508
|
advice = (
|
|
419
509
|
"Resolve cannot find a Python 3, so it will silently ignore every "
|
|
420
510
|
".py script in its Scripts folders — they will simply not appear in "
|
|
@@ -428,8 +518,16 @@ def python_preflight() -> dict:
|
|
|
428
518
|
"print(sys.prefix)')\"\n"
|
|
429
519
|
" Use launchctl, NOT export — Resolve is launched from the Dock "
|
|
430
520
|
"and never sees your shell's environment. The prefix must contain "
|
|
431
|
-
"lib/libpython3.X.dylib
|
|
432
|
-
"
|
|
521
|
+
"BOTH lib/libpython3.X.dylib and bin/python3 under that exact "
|
|
522
|
+
"unversioned name. Note that launchctl setenv does not survive a "
|
|
523
|
+
"reboot: if scripts stop listing weeks later with no error, this is "
|
|
524
|
+
"why.\n"
|
|
525
|
+
" 2. Or symlink an interpreter where Resolve already looks, which "
|
|
526
|
+
"is a file on disk and does persist (needs sudo):\n"
|
|
527
|
+
" sudo ln -s \"$(command -v python3)\" /usr/local/bin/python3\n"
|
|
528
|
+
" Check that /usr/local/bin does not precede your normal Python "
|
|
529
|
+
"on PATH before doing this.\n"
|
|
530
|
+
" 3. Or install a python.org build, which creates "
|
|
433
531
|
"/usr/local/bin/python3 for you.\n"
|
|
434
532
|
"Restart Resolve either way, then re-check. The Lua canary installed "
|
|
435
533
|
"alongside will list regardless, so you can tell 'Python not "
|
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.205.
|
|
90
|
+
VERSION = "2.205.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.205.
|
|
14
|
+
VERSION = "2.205.2"
|
|
15
15
|
|
|
16
16
|
import base64
|
|
17
17
|
import os
|
|
@@ -9733,6 +9733,20 @@ def _media_analysis_bool(value: Any, default: bool = False) -> bool:
|
|
|
9733
9733
|
return bool(value)
|
|
9734
9734
|
|
|
9735
9735
|
|
|
9736
|
+
def _media_analysis_plan_project_root(created: Any) -> str:
|
|
9737
|
+
"""Extract the project root path from a created batch job.
|
|
9738
|
+
|
|
9739
|
+
`plan["output_root"]` holds the mapping `resolve_output_root()` returns
|
|
9740
|
+
({"success", "base_root", "project_root", "project_directory", ...}), not a
|
|
9741
|
+
path. `str()` on it yields a dict repr, which is a non-empty string and so
|
|
9742
|
+
passes a truthiness guard while naming no directory that exists.
|
|
9743
|
+
"""
|
|
9744
|
+
output_root = (created.get("plan") or {}).get("output_root") or ""
|
|
9745
|
+
if isinstance(output_root, dict):
|
|
9746
|
+
output_root = output_root.get("project_root") or ""
|
|
9747
|
+
return str(output_root)
|
|
9748
|
+
|
|
9749
|
+
|
|
9736
9750
|
MEDIA_ANALYSIS_ASYNC_QUEUED = "queued"
|
|
9737
9751
|
MEDIA_ANALYSIS_ASYNC_RUNNING = "running"
|
|
9738
9752
|
|
|
@@ -22310,7 +22324,7 @@ async def media_analysis(action: str, params: Optional[Dict[str, Any]] = None, c
|
|
|
22310
22324
|
# get a runner. Reached either by the analyze_* divert (which sets
|
|
22311
22325
|
# _async_mode) or by calling start_batch_job with background=true.
|
|
22312
22326
|
job_id = str((created.get("job") or {}).get("job_id") or "")
|
|
22313
|
-
project_root =
|
|
22327
|
+
project_root = _media_analysis_plan_project_root(created)
|
|
22314
22328
|
wants_runner = p.get("_async_mode") == MEDIA_ANALYSIS_ASYNC_RUNNING or (
|
|
22315
22329
|
_media_analysis_bool(p.get("background"), False)
|
|
22316
22330
|
or _media_analysis_bool(p.get("async_job"), False)
|