davinci-resolve-mcp 2.145.0 → 2.145.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 +32 -0
- package/README.md +6 -1
- package/README.zh-CN.md +2 -2
- package/bin/davinci-resolve-advanced-mcp.mjs +28 -1
- package/install.py +2 -2
- package/package.json +1 -1
- package/scripts/install_resolve_bridge.py +26 -13
- package/src/granular/common.py +1 -1
- package/src/server.py +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,38 @@
|
|
|
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.145.2 — launcher metadata before dependencies
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- **`davinci-resolve-advanced-mcp --help`/`--version` now work in fresh
|
|
10
|
+
source checkouts** (before `npm install`) — adapted from
|
|
11
|
+
[PR #178](https://github.com/samuelgursky/davinci-resolve-mcp/pull/178) by
|
|
12
|
+
@Rohitkanithi: metadata flags are handled before the stdio server import
|
|
13
|
+
(and before the Node-floor refusal — help is harmless on any Node), where
|
|
14
|
+
previously even `--help` died with `ERR_MODULE_NOT_FOUND`.
|
|
15
|
+
- **The installer banner's tool counts were stale** (32/329 vs the real
|
|
16
|
+
36/353) — fixed and wired into the `test_doc_tool_counts` drift guard so
|
|
17
|
+
the banner can never drift independently again.
|
|
18
|
+
|
|
19
|
+
## What's New in v2.145.1 — bridge config override, honored end to end
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- **The free-edition bridge installer now honors
|
|
24
|
+
`DAVINCI_RESOLVE_BRIDGE_CONFIG`** — adapted from
|
|
25
|
+
[PR #177](https://github.com/samuelgursky/davinci-resolve-mcp/pull/177) by
|
|
26
|
+
@altiss. The bridge client already resolved the override, but the installer
|
|
27
|
+
always wrote and embedded the fixed default path, so a client configured
|
|
28
|
+
with an override could look in one place while the in-app bridge was
|
|
29
|
+
installed with another — both sides "successfully" installed yet never
|
|
30
|
+
sharing a token. The installer resolves the effective path at call time
|
|
31
|
+
with the client's exact semantics (env wins, `~` expands, default
|
|
32
|
+
otherwise) across create, report, runtime copy, and launcher embed. One
|
|
33
|
+
correction on top of the PR: the step-4 probe guidance keeps pointing at
|
|
34
|
+
the FIXED default directory — the probe runs inside Resolve, which never
|
|
35
|
+
inherits the shell's environment, so it always writes there.
|
|
36
|
+
|
|
5
37
|
## What's New in v2.145.0 — whole projects, assembled offline
|
|
6
38
|
|
|
7
39
|
### Added
|
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)
|
|
@@ -52,6 +52,11 @@ python scripts/install_resolve_bridge.py
|
|
|
52
52
|
# restart Resolve, open a project, then: Workspace > Scripts > resolve_bridge
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
+
The installer and MCP client use `~/.config/davinci-resolve-mcp/bridge.json`
|
|
56
|
+
by default. To keep the authenticated bridge config elsewhere, set
|
|
57
|
+
`DAVINCI_RESOLVE_BRIDGE_CONFIG` while running the installer and in the MCP
|
|
58
|
+
client environment; both sides will use that path.
|
|
59
|
+
|
|
55
60
|
Once that listener is running it is used **automatically** whenever external
|
|
56
61
|
scripting is unavailable — no environment variable required. Setting
|
|
57
62
|
`DAVINCI_RESOLVE_BRIDGE=1` *forces* the bridge instead: it becomes the only
|
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.145.
|
|
15
|
+
> 本翻译对应 v2.145.2 版 README。如与英文原版有出入,以 [英文原版](README.md) 为准。
|
|
16
16
|
|
|
17
17
|
一个 Model Context Protocol (MCP) 服务器,让 AI 助手通过官方脚本 API 控制 DaVinci Resolve Studio(达芬奇)。它提供完整的 API 覆盖,外加带护栏的工作流助手,涵盖剪辑、媒体池整理、渲染设置、审阅标记、调色、Fusion、Fairlight、项目生命周期任务、扩展开发,以及不碰源媒体的媒体分析。
|
|
18
18
|
|
|
@@ -11,8 +11,36 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
14
|
+
import fs from 'node:fs';
|
|
14
15
|
import path from 'node:path';
|
|
15
16
|
|
|
17
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
18
|
+
const packageRoot = path.resolve(__dirname, '..');
|
|
19
|
+
const packageJson = JSON.parse(fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8'));
|
|
20
|
+
const version = packageJson.version || '0.0.0-dev';
|
|
21
|
+
|
|
22
|
+
function usage() {
|
|
23
|
+
return `DaVinci Resolve Advanced MCP ${version}
|
|
24
|
+
|
|
25
|
+
Usage:
|
|
26
|
+
davinci-resolve-advanced-mcp
|
|
27
|
+
davinci-resolve-advanced-mcp --version
|
|
28
|
+
davinci-resolve-advanced-mcp --help
|
|
29
|
+
|
|
30
|
+
Starts the offline DaVinci Resolve advanced MCP server over stdio.
|
|
31
|
+
`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const command = process.argv[2];
|
|
35
|
+
if (command === '--help' || command === '-h' || command === 'help') {
|
|
36
|
+
process.stdout.write(usage());
|
|
37
|
+
process.exit(0);
|
|
38
|
+
}
|
|
39
|
+
if (command === '--version' || command === '-v' || command === 'version') {
|
|
40
|
+
process.stdout.write(`${version}\n`);
|
|
41
|
+
process.exit(0);
|
|
42
|
+
}
|
|
43
|
+
|
|
16
44
|
// Node floor (package.json engines: >=20.9), enforced at STARTUP rather than
|
|
17
45
|
// discovered per-feature: under an old Node the pure-JS tools limp along
|
|
18
46
|
// while native-dep paths (better-sqlite3: project_read, fairlight DB actions,
|
|
@@ -34,7 +62,6 @@ if (major < 20 || (major === 20 && minor < 9)) {
|
|
|
34
62
|
process.exit(1);
|
|
35
63
|
}
|
|
36
64
|
|
|
37
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
38
65
|
const serverEntry = path.resolve(__dirname, '..', 'resolve-advanced', 'server', 'index.mjs');
|
|
39
66
|
|
|
40
67
|
const { startServer } = await import(pathToFileURL(serverEntry).href);
|
package/install.py
CHANGED
|
@@ -37,7 +37,7 @@ from src.utils.update_check import (
|
|
|
37
37
|
|
|
38
38
|
# ─── Version ──────────────────────────────────────────────────────────────────
|
|
39
39
|
|
|
40
|
-
VERSION = "2.145.
|
|
40
|
+
VERSION = "2.145.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
|
|
@@ -1474,7 +1474,7 @@ def verify_resolve_connection(python_path, api_path, lib_path):
|
|
|
1474
1474
|
|
|
1475
1475
|
def print_banner():
|
|
1476
1476
|
title = f"DaVinci Resolve MCP Server — Installer v{VERSION}"
|
|
1477
|
-
subtitle = "
|
|
1477
|
+
subtitle = "36 compound · 353 full · 3 platforms"
|
|
1478
1478
|
print()
|
|
1479
1479
|
print(bold(" ╔══════════════════════════════════════════════════════╗"))
|
|
1480
1480
|
print(bold(f" ║{title:^54}║"))
|
package/package.json
CHANGED
|
@@ -24,10 +24,17 @@ import sys
|
|
|
24
24
|
from pathlib import Path
|
|
25
25
|
|
|
26
26
|
REPO = Path(__file__).resolve().parent.parent
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
DEFAULT_CONFIG_PATH = Path.home() / ".config/davinci-resolve-mcp/bridge.json"
|
|
28
|
+
ENV_CONFIG_PATH = "DAVINCI_RESOLVE_BRIDGE_CONFIG"
|
|
29
29
|
DEFAULT_PORT = 49632
|
|
30
30
|
|
|
31
|
+
|
|
32
|
+
def config_path() -> Path:
|
|
33
|
+
"""Bridge config written by this installer and read by the MCP client."""
|
|
34
|
+
override = os.environ.get(ENV_CONFIG_PATH)
|
|
35
|
+
return Path(override).expanduser() if override else DEFAULT_CONFIG_PATH
|
|
36
|
+
|
|
37
|
+
|
|
31
38
|
_SCRIPTS_SUFFIX = "Library/Application Support/Blackmagic Design/DaVinci Resolve/Fusion/Scripts/Utility"
|
|
32
39
|
|
|
33
40
|
#: A sandboxed (App Store) build sees its container as HOME, so Resolve's
|
|
@@ -448,10 +455,11 @@ def python_preflight() -> dict:
|
|
|
448
455
|
|
|
449
456
|
|
|
450
457
|
def ensure_config(port: int, rotate: bool) -> dict:
|
|
458
|
+
path = config_path()
|
|
451
459
|
existing: dict = {}
|
|
452
|
-
if
|
|
460
|
+
if path.exists():
|
|
453
461
|
try:
|
|
454
|
-
existing = json.loads(
|
|
462
|
+
existing = json.loads(path.read_text(encoding="utf-8"))
|
|
455
463
|
except (OSError, ValueError):
|
|
456
464
|
existing = {}
|
|
457
465
|
token = existing.get("token")
|
|
@@ -469,12 +477,12 @@ def ensure_config(port: int, rotate: bool) -> dict:
|
|
|
469
477
|
"allowed_media_roots": existing_media or [str(Path.home())],
|
|
470
478
|
"allowed_output_roots": existing_output or [str(Path.home() / "Movies")],
|
|
471
479
|
}
|
|
472
|
-
|
|
473
|
-
tmp =
|
|
480
|
+
path.parent.mkdir(mode=0o700, parents=True, exist_ok=True)
|
|
481
|
+
tmp = path.with_suffix(".tmp")
|
|
474
482
|
tmp.write_text(json.dumps(config, indent=2, sort_keys=True), encoding="utf-8")
|
|
475
483
|
os.chmod(tmp, 0o600)
|
|
476
|
-
tmp.replace(
|
|
477
|
-
os.chmod(
|
|
484
|
+
tmp.replace(path)
|
|
485
|
+
os.chmod(path, 0o600)
|
|
478
486
|
return config
|
|
479
487
|
|
|
480
488
|
|
|
@@ -525,8 +533,9 @@ def install(*, probe_only: bool, port: int, rotate: bool) -> dict:
|
|
|
525
533
|
)
|
|
526
534
|
result["skipped"] = [path for path, _ in skipped]
|
|
527
535
|
if not probe_only:
|
|
528
|
-
|
|
529
|
-
|
|
536
|
+
path = config_path()
|
|
537
|
+
loaded = json.loads(path.read_text(encoding="utf-8"))
|
|
538
|
+
result["config"] = {"path": str(path),
|
|
530
539
|
**{k: v for k, v in loaded.items() if k != "token"}}
|
|
531
540
|
return result
|
|
532
541
|
|
|
@@ -558,9 +567,10 @@ def _install_to(target: Path, *, probe_only: bool, installed: list[str]) -> None
|
|
|
558
567
|
# unreachable by construction (measured: "Operation not permitted").
|
|
559
568
|
# The runtime dir is already inside the container, so the config goes
|
|
560
569
|
# beside the modules. Same token, so the out-of-sandbox client still
|
|
561
|
-
# authenticates against
|
|
570
|
+
# authenticates against the selected config path.
|
|
562
571
|
runtime_config = runtime / "bridge.json"
|
|
563
|
-
|
|
572
|
+
path = config_path()
|
|
573
|
+
shutil.copy2(path, runtime_config)
|
|
564
574
|
os.chmod(runtime_config, 0o600)
|
|
565
575
|
installed.append(str(runtime_config))
|
|
566
576
|
# The launcher IS the menu entry. Without it the modules sit in the
|
|
@@ -571,7 +581,7 @@ def _install_to(target: Path, *, probe_only: bool, installed: list[str]) -> None
|
|
|
571
581
|
base64.urlsafe_b64encode(str(runtime).encode("utf-8")).decode("ascii"),
|
|
572
582
|
).replace(
|
|
573
583
|
"@@CONFIG_PATH_B64@@",
|
|
574
|
-
base64.urlsafe_b64encode(str(
|
|
584
|
+
base64.urlsafe_b64encode(str(path).encode("utf-8")).decode("ascii"),
|
|
575
585
|
)
|
|
576
586
|
launcher_path = target / "resolve_bridge.py"
|
|
577
587
|
launcher_path.write_text(launcher, encoding="utf-8")
|
|
@@ -605,6 +615,9 @@ def main() -> int:
|
|
|
605
615
|
print(" 1. Restart DaVinci Resolve so it re-scans the Scripts folders.")
|
|
606
616
|
print(" 2. Open a saved project (the Scripts menu is empty in Project Manager).")
|
|
607
617
|
print(" 3. Workspace > Scripts > resolve_bridge_probe — run it TWICE.")
|
|
618
|
+
# The probe runs INSIDE Resolve, which never sees the shell's
|
|
619
|
+
# DAVINCI_RESOLVE_BRIDGE_CONFIG — it always writes to the fixed default
|
|
620
|
+
# directory, so the guidance must not follow the override.
|
|
608
621
|
print(" 4. Read ~/.config/davinci-resolve-mcp/host-model-probe.json")
|
|
609
622
|
return 0
|
|
610
623
|
|
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.145.
|
|
90
|
+
VERSION = "2.145.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()}")
|