davinci-resolve-mcp 4.10.3 → 4.10.5

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 CHANGED
@@ -2,6 +2,56 @@
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 v4.10.5 — `rename_plan` sees a name the plan keeps
6
+
7
+ ### Fixes
8
+
9
+ - **`media(action="rename_plan")` missed a rename onto a name that stays in
10
+ place.** It counted collisions only among the names it renames *to*, so a
11
+ name it leaves alone was invisible to the check. With
12
+ `names: ["A001_C001.mov", "dailies_A001_C001.mov"]`, `find: "dailies_"`,
13
+ `replace: ""`, the camera original was correctly refused, and the plan then
14
+ proposed renaming `dailies_A001_C001.mov` onto it with `collisions: 0`.
15
+ Applying that plan overwrites the file the refusal was protecting.
16
+ - A name the plan keeps now occupies its target: a refused camera original,
17
+ and a name `find` leaves unchanged. The same call returns
18
+ `action: "collision"`, `collisions: 1`, `renameCount: 0`.
19
+ - **`reel_normalize` had the same gap**: a reel already at its normalized
20
+ name was not counted, so `["card1", "CARD001"]` both landed on `CARD001`
21
+ with no collision. It is counted now.
22
+ - A swap (`b → x` while `x → y`) is still not a collision, since `x` is
23
+ leaving. Noops stay noops and refusals stay refusals.
24
+ - Lands #284 from @Dev-next-gen, as submitted, with two tests that fail on
25
+ the old code.
26
+
27
+ ### Validation
28
+
29
+ - Planning code only; nothing touches Resolve or media. Advanced suite
30
+ green; Python suite green.
31
+
32
+ ## What's New in v4.10.4 — enrolled in Anthropic's OSS Scanner
33
+
34
+ ### Security
35
+
36
+ - **The repository now carries an OSS Scanner build and threat model**
37
+ under `.oss-scanner/`. [OSS Scanner](https://github.com/anthropics/oss-scanner)
38
+ builds a project in an isolated VM, scans it offline, and emails findings
39
+ to the maintainer. Keeping both files here means they can change without a
40
+ pull request to the scanner's repository.
41
+ - `.oss-scanner/Dockerfile` mirrors CI: Python 3.11, Node 22, ffmpeg, both
42
+ lockfiles via `npm ci`, then the offline suites. Built with the
43
+ scanner's `tools/check`: Python 4027 passed (26 skipped), advanced
44
+ server 1113 passed (60 skipped), 0 failed. Resolve is not in the image;
45
+ the suite stubs it as in CI.
46
+ - `.oss-scanner/threat_model.md` treats every MCP tool argument as
47
+ untrusted (LLM context can carry attacker text), and names the
48
+ properties a finding would break: no caller-supplied code execution,
49
+ the destructive-op gate, immutable source media, and the token- and
50
+ Host/Origin-gated local listeners. It points at the subprocess call
51
+ sites and the archive/XML/SQLite parsers, cites the four published
52
+ advisories as examples of each class, and sets severity tiers.
53
+ - No server code changed.
54
+
5
55
  ## What's New in v4.10.3 — the conform-qc tests run, and run in `npm test`
6
56
 
7
57
  ### Tests
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  English | [简体中文](README.zh-CN.md)
4
4
 
5
- [![Version](https://img.shields.io/badge/version-4.10.3-blue.svg)](https://github.com/samuelgursky/davinci-resolve-mcp/releases)
5
+ [![Version](https://img.shields.io/badge/version-4.10.5-blue.svg)](https://github.com/samuelgursky/davinci-resolve-mcp/releases)
6
6
  [![npm](https://img.shields.io/npm/v/davinci-resolve-mcp.svg?label=npm&color=CB3837)](https://www.npmjs.com/package/davinci-resolve-mcp)
7
7
  [![API Coverage](https://img.shields.io/badge/API%20Coverage-100%25-brightgreen.svg)](docs/reference/api-coverage.md)
8
8
  [![Tools](https://img.shields.io/badge/MCP%20Tools-37%20(389%20full)-blue.svg)](#server-modes)
package/README.zh-CN.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [English](README.md) | 简体中文
4
4
 
5
- [![Version](https://img.shields.io/badge/version-4.10.3-blue.svg)](https://github.com/samuelgursky/davinci-resolve-mcp/releases)
5
+ [![Version](https://img.shields.io/badge/version-4.10.5-blue.svg)](https://github.com/samuelgursky/davinci-resolve-mcp/releases)
6
6
  [![npm](https://img.shields.io/npm/v/davinci-resolve-mcp.svg?label=npm&color=CB3837)](https://www.npmjs.com/package/davinci-resolve-mcp)
7
7
  [![API Coverage](https://img.shields.io/badge/API%20Coverage-100%25-brightgreen.svg)](docs/reference/api-coverage.md)
8
8
  [![Tools](https://img.shields.io/badge/MCP%20Tools-37%20(389%20full)-blue.svg)](#服务器模式)
@@ -12,7 +12,7 @@
12
12
  [![Python](https://img.shields.io/badge/python-3.10+-green.svg)](https://www.python.org/downloads/)
13
13
  [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
14
14
 
15
- > 本翻译对应 v4.10.3 版 README。如与英文原版有出入,以 [英文原版](README.md) 为准。
15
+ > 本翻译对应 v4.10.5 版 README。如与英文原版有出入,以 [英文原版](README.md) 为准。
16
16
 
17
17
  一个 Model Context Protocol (MCP) 服务器,让 AI 助手通过官方脚本 API 控制 DaVinci Resolve Studio(达芬奇)。它提供完整的 API 覆盖,外加带护栏的工作流助手,涵盖剪辑、媒体池整理、渲染设置、审阅标记、调色、Fusion、Fairlight、项目生命周期任务、扩展开发,以及不碰源媒体的媒体分析。
18
18
 
package/install.py CHANGED
@@ -37,7 +37,7 @@ from src.utils.update_check import (
37
37
 
38
38
  # ─── Version ──────────────────────────────────────────────────────────────────
39
39
 
40
- VERSION = "4.10.3"
40
+ VERSION = "4.10.5"
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "davinci-resolve-mcp",
3
- "version": "4.10.3",
3
+ "version": "4.10.5",
4
4
  "description": "NPM bootstrapper for the DaVinci Resolve MCP Server.",
5
5
  "license": "MIT",
6
6
  "author": "Samuel Gursky <samgursky@gmail.com>",
@@ -133,19 +133,18 @@ export function renamePlan(names, rule = {}) {
133
133
  const camRe = rule.cameraOriginalRe || CAMERA_ORIGINAL_RE;
134
134
  const plan = [];
135
135
  const targets = new Map();
136
+ // A name the plan leaves in place still occupies it — a refused camera original
137
+ // above all — so it counts as a target too, or a rename onto it reads as free.
136
138
  for (const name of names) {
137
139
  const isCam = camRe.test(name);
138
140
  if (isCam && !rule.allowCameraOriginals) {
139
141
  plan.push({ from: name, action: 'refuse-camera-original', note: 'camera original — rename via sidecar/DB only, never the file' });
142
+ targets.set(name, (targets.get(name) || 0) + 1);
140
143
  continue;
141
144
  }
142
145
  const to = name.replace(re, rule.replace ?? '');
143
- if (to === name) {
144
- plan.push({ from: name, to, action: 'noop' });
145
- continue;
146
- }
147
146
  targets.set(to, (targets.get(to) || 0) + 1);
148
- plan.push({ from: name, to, action: 'rename' });
147
+ plan.push({ from: name, to, action: to === name ? 'noop' : 'rename' });
149
148
  }
150
149
  // Flag collisions (two sources → one target).
151
150
  for (const p of plan) if (p.action === 'rename' && targets.get(p.to) > 1) p.action = 'collision';
@@ -168,7 +167,7 @@ export function reelNormalize(reels, opts = {}) {
168
167
  const to = String(r)
169
168
  .toUpperCase()
170
169
  .replace(/(\d+)\s*$/, (m) => m.padStart(pad, '0'));
171
- if (to !== r) targets.set(to, (targets.get(to) || 0) + 1);
170
+ targets.set(to, (targets.get(to) || 0) + 1);
172
171
  plan.push({ from: r, to, action: to === r ? 'noop' : 'normalize' });
173
172
  }
174
173
  for (const p of plan) if (p.action === 'normalize' && targets.get(p.to) > 1) p.action = 'collision';
@@ -91,7 +91,7 @@ if not logging.getLogger().handlers:
91
91
  handlers=[logging.StreamHandler()],
92
92
  )
93
93
 
94
- VERSION = "4.10.3"
94
+ VERSION = "4.10.5"
95
95
  logger = logging.getLogger("davinci-resolve-mcp")
96
96
  logger.info(f"Starting DaVinci Resolve MCP Server v{VERSION}")
97
97
  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 377-tool granular server instead
12
12
  """
13
13
 
14
- VERSION = "4.10.3"
14
+ VERSION = "4.10.5"
15
15
 
16
16
  import base64
17
17
  import os