davinci-resolve-mcp 2.61.1 → 2.62.1

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,98 @@
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.62.1
6
+
7
+ Two correctness fixes for real-world project/DRP layouts. No new tool surface;
8
+ default behavior is unchanged.
9
+
10
+ ### Fixed
11
+
12
+ - **Timeline archiving survives out-of-band archive names** — the archive
13
+ version counter was sourced solely from the local brain DB, so any
14
+ `<name>_archived_vNN` timeline the DB hadn't recorded (another
15
+ session/machine, or a crash between `DuplicateTimeline` and the version
16
+ `INSERT`) collided on the next archive: `DuplicateTimeline` failed and Resolve
17
+ raised a blocking "Unable to Rename Timeline" modal that wedged the UI.
18
+ `archive_current_timeline` now scans every existing `_archived_vNN` suffix in
19
+ the project and treats the DB counter as a floor, not the source of truth.
20
+ - **`inject_grades` handles the `SeqContainer/<uuid>.xml` folder layout** —
21
+ `listSeqContainerEntries` only matched the legacy flat `SeqContainer<N>.xml`
22
+ naming, so `inject_grades` threw `No SeqContainer*.xml found` on DRPs using
23
+ the `SeqContainer/<uuid>.xml` folder layout that Resolve 19 exports (the same
24
+ layout the grade-node extractor already handles). Both shapes are now matched.
25
+
26
+ ### Validation
27
+
28
+ - Static checks and focused unit tests
29
+ (`tests.test_timeline_versioning`, `tests.test_import_from_drp`) run. The DRP
30
+ fix is offline zip surgery requiring no Resolve; the archiving fix is
31
+ defensive counter logic covered by unit tests.
32
+
33
+ ## What's New in v2.62.0
34
+
35
+ Community contribution by [@lukeashford](https://github.com/lukeashford)
36
+ ([#87](https://github.com/samuelgursky/davinci-resolve-mcp/pull/87), closing
37
+ [#88](https://github.com/samuelgursky/davinci-resolve-mcp/issues/88)): server
38
+ robustness for long operations plus a batch of timeline-tool ergonomics and
39
+ correctness fixes. Every new option is opt-in; default behavior is unchanged.
40
+
41
+ ### Added
42
+
43
+ - **Background jobs for long ops** — transcription, subtitle generation,
44
+ scene-cut/Dolby analysis, and timeline export/import can exceed the MCP
45
+ client's tool-window timeout. Passing `background=true` now returns a
46
+ `job_id` immediately; poll with `resolve_control(action="job_status")` or
47
+ list with `list_jobs` (both connection-free). Generic registry in
48
+ `src/utils/background_jobs.py`; workers run under the `resolve_busy` gate,
49
+ and finished jobs are pruned after an hour.
50
+ - **`create_variant_from_ranges` pack mode** — `pack=true` butts clips
51
+ together at the end of each track (omits `recordFrame`), gap-free even when
52
+ source and timeline frame rates differ. Live-validated.
53
+ - **`timeline set_current` by id/name** — accepts a stable `id`/`name`
54
+ selector (precedence id → name → index), not only the shifting 1-based
55
+ index.
56
+
57
+ ### Fixed
58
+
59
+ - **Transport wedge** — synchronous tool bodies ran inline on the single
60
+ asyncio event-loop thread, so a blocking Resolve call (or the up-to-60s
61
+ launch wait) froze the whole server including the stdio read loop. Sync tool
62
+ bodies now run in a worker thread, serialized on a bridge lock so the
63
+ single-threaded scripting bridge is never entered concurrently; degrades to
64
+ inline behavior if the SDK shape changes.
65
+ - **`create_variant_from_ranges` honesty** — results report actual placement
66
+ (`items[].placed` in both frame spaces, plus a `placement_mismatches`
67
+ count) instead of echoing the requested frames; `dry_run` resolves clip ids
68
+ and validates frame ranges so it fails on the same errors as the commit
69
+ path (and no longer leaves an orphan timeline on a bad id); the response
70
+ reports audio presence and warns on a video-only (silent) range list.
71
+ - **`get_items` / `get_items_in_track`** — validate their track selector
72
+ (structured error instead of a bare `KeyError`), accept `index` or
73
+ `track_index`, and gained `action_help` entries.
74
+ - **`apply_cuts`** — reports `skipped` cuts with reasons instead of silently
75
+ dropping non-applicable entries.
76
+ - **`action_help`** — lists every valid action (not only the documented
77
+ subset) and distinguishes an unknown action (`UNKNOWN_ACTION`) from a
78
+ valid-but-undocumented one (`HELP_NOT_REGISTERED`).
79
+
80
+ ### Documentation
81
+
82
+ - Corrected `create_variant_from_ranges` help: `clip_id` is a media-pool item
83
+ id (not a timeline-item id); `start_frame`/`end_frame` are SOURCE frames,
84
+ `end_frame` exclusive. Stated the timeline tool's frame-space convention
85
+ once, clarified `lift_range` ripple behavior on empty gaps,
86
+ `begin_run`/`end_run` batching, and the timeline-subtitle vs clip-level
87
+ transcript distinction.
88
+
89
+ ### Validation
90
+
91
+ - Full offline suite: 1,483 tests green (70 new).
92
+ - Transport offload, background jobs, and `create_variant_from_ranges`
93
+ placement/pack behavior were live-validated against Resolve Studio 21 by
94
+ the contributor; the threaded-dispatch SDK coupling was additionally
95
+ verified against the pinned mcp SDK (1.27) over a real stdio session.
96
+
5
97
  ## What's New in v2.61.1
6
98
 
7
99
  The strata cleanup batch deferred from the v2.61.0 review — behavior-neutral
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # DaVinci Resolve MCP Server
2
2
 
3
- [![Version](https://img.shields.io/badge/version-2.61.1-blue.svg)](https://github.com/samuelgursky/davinci-resolve-mcp/releases)
3
+ [![Version](https://img.shields.io/badge/version-2.62.1-blue.svg)](https://github.com/samuelgursky/davinci-resolve-mcp/releases)
4
4
  [![npm](https://img.shields.io/npm/v/davinci-resolve-mcp.svg?label=npm&color=CB3837)](https://www.npmjs.com/package/davinci-resolve-mcp)
5
5
  [![API Coverage](https://img.shields.io/badge/API%20Coverage-100%25-brightgreen.svg)](docs/reference/api-coverage.md)
6
6
  [![Tools](https://img.shields.io/badge/MCP%20Tools-34%20(341%20full)-blue.svg)](#server-modes)
package/install.py CHANGED
@@ -35,7 +35,7 @@ from src.utils.update_check import (
35
35
 
36
36
  # ─── Version ──────────────────────────────────────────────────────────────────
37
37
 
38
- VERSION = "2.61.1"
38
+ VERSION = "2.62.1"
39
39
  # Only hard floor: mcp[cli] requires Python 3.10+. There is no upper bound —
40
40
  # Resolve's scripting bridge loads into newer interpreters on recent builds
41
41
  # (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": "2.61.1",
3
+ "version": "2.62.1",
4
4
  "description": "NPM bootstrapper for the DaVinci Resolve MCP Server.",
5
5
  "license": "MIT",
6
6
  "author": "Samuel Gursky <samgursky@gmail.com>",
@@ -22,8 +22,10 @@ function listSeqContainerEntries(zip) {
22
22
  const out = [];
23
23
  zip.forEach((relativePath, entry) => {
24
24
  if (entry.dir) return;
25
- // Match any "<anything>/SeqContainer<N>.xml" path.
26
- if (/(^|\/)SeqContainer\d*\.xml$/.test(relativePath)) {
25
+ // Two shapes in the wild: legacy flat "SeqContainer<N>.xml" files, and the
26
+ // "SeqContainer/<uuid>.xml" folder layout Resolve 19 exports (which
27
+ // grade-node-extractor already handles). Match both.
28
+ if (/(^|\/)SeqContainer\d*\.xml$/.test(relativePath) || /(^|\/)SeqContainer\/[^/]+\.xml$/.test(relativePath)) {
27
29
  out.push(relativePath);
28
30
  }
29
31
  });
@@ -80,7 +80,7 @@ if not logging.getLogger().handlers:
80
80
  handlers=[logging.StreamHandler()],
81
81
  )
82
82
 
83
- VERSION = "2.61.1"
83
+ VERSION = "2.62.1"
84
84
  logger = logging.getLogger("davinci-resolve-mcp")
85
85
  logger.info(f"Starting DaVinci Resolve MCP Server v{VERSION}")
86
86
  logger.info(f"Detected platform: {get_platform()}")