davinci-resolve-mcp 2.63.0 → 2.63.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 CHANGED
@@ -2,6 +2,46 @@
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.63.2
6
+
7
+ Installer fix for Windows MSIX builds of Claude Desktop (issue #93, reported by
8
+ @corolorn). No tool-surface change.
9
+
10
+ ### Fixed
11
+
12
+ - **Installer writes Claude Desktop config to the MSIX-virtualized path on
13
+ Windows** — Claude Desktop for Windows ships as an MSIX package (even from
14
+ the official website), and MSIX filesystem virtualization redirects the
15
+ app's config to
16
+ `%LOCALAPPDATA%\Packages\Claude_<publisherhash>\LocalCache\Roaming\Claude\claude_desktop_config.json`.
17
+ The installer previously wrote to the documented `%APPDATA%\Claude\` path,
18
+ which the MSIX-packaged app never reads, so the server silently never
19
+ appeared. The installer now detects the containerized path (publisher hash
20
+ globbed, not hard-coded) and writes there when present, falling back to
21
+ `%APPDATA%\Claude\` for non-MSIX installs. Documented both locations in
22
+ `docs/install.md`.
23
+
24
+ ## What's New in v2.63.1
25
+
26
+ Documentation-only. Records the `Graph.SetLUT` master-LUT-dir behavior (from the
27
+ v2.62.3 fix) in the canonical reference surfaces. No code or tool-surface change.
28
+
29
+ ### Documentation
30
+
31
+ - **`api_truth` + api-limitations report** — added a `Graph.SetLUT` entry
32
+ (`submit: bug`, #90): `SetLUT` resolves LUT paths only against the master
33
+ (system) LUT dir and configured custom paths, never the per-user dir the
34
+ `dctl` tool installs to; an absolute user-dir path fails too, and
35
+ `RefreshLUTList()` does not help, while a master-subfolder path resolves.
36
+ Verified live on Studio 19.1.3.7 (same behavior reported on 21.0.2 in #90).
37
+ Regenerated `docs/reference/api-limitations.md`.
38
+ - **`docs/notes/lut-notes.md`** — corrected a misleading claim that any valid
39
+ absolute path resolves (an absolute path into the user LUT dir does not),
40
+ added a "master LUT dir only" section, and documented the per-user install
41
+ location.
42
+ - **`docs/notes/dctl-notes.md`** — noted the same caveat on the `set_lut`
43
+ action, including that `set_lut` now auto-relocates into the master dir.
44
+
5
45
  ## What's New in v2.63.0
6
46
 
7
47
  Waveform silence ripple for the edit engine (PR #91, by @EliteSystemsAI),
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.63.0-blue.svg)](https://github.com/samuelgursky/davinci-resolve-mcp/releases)
3
+ [![Version](https://img.shields.io/badge/version-2.63.2-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/docs/install.md CHANGED
@@ -50,7 +50,7 @@ The installer can automatically configure any of these clients:
50
50
 
51
51
  | Client | Config Written To |
52
52
  |--------|-------------------|
53
- | Claude Desktop | `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) |
53
+ | Claude Desktop | `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS); `%APPDATA%\Claude\claude_desktop_config.json` (Windows, see MSIX note below) |
54
54
  | Claude Code | `.mcp.json` (project root) |
55
55
  | Cursor | `~/.cursor/mcp.json` |
56
56
  | VS Code (Copilot) | `.vscode/mcp.json` (workspace) |
@@ -64,6 +64,15 @@ The installer can automatically configure any of these clients:
64
64
 
65
65
  You can configure multiple clients at once, or use `--clients manual` to get copy-paste config snippets.
66
66
 
67
+ > **Windows MSIX note (Claude Desktop):** Claude Desktop for Windows is
68
+ > distributed as an MSIX package — even when downloaded from the official
69
+ > website. MSIX filesystem virtualization redirects the app's config to
70
+ > `%LOCALAPPDATA%\Packages\Claude_<publisherhash>\LocalCache\Roaming\Claude\claude_desktop_config.json`,
71
+ > and the app never reads the documented `%APPDATA%\Claude\` path (which may
72
+ > still exist on disk). The installer detects the virtualized location and
73
+ > writes there automatically. If the server does not appear in Claude Desktop
74
+ > after a manual setup, check both locations.
75
+
67
76
  For [Autohand Code](https://github.com/autohandai/code-cli/), register the managed launcher after setup:
68
77
 
69
78
  ```bash
@@ -19,7 +19,12 @@ Relevant existing actions:
19
19
  Resolve's LUT folders.
20
20
  - `graph(action="set_lut", params={"node_index": 1, "lut_path": "..."})`
21
21
  wraps `Graph.SetLUT(nodeIndex, lutPath)`. DCTLs that Resolve exposes through
22
- LUT selection follow the same discovery constraints as LUTs.
22
+ LUT selection follow the same discovery constraints as LUTs. **Caveat:**
23
+ `install` writes to the per-user LUT dir, but `SetLUT` resolves only against
24
+ the *master* LUT dir (not even an absolute user-dir path works, and
25
+ `refresh_luts` does not help). `set_lut` now auto-relocates the file into an
26
+ `MCP/` subfolder of the master dir and retries — see `docs/notes/lut-notes.md`
27
+ ("master LUT dir only") and the `Graph.SetLUT` entry in `api_truth.py`.
23
28
  - `graph(action="get_lut", params={"node_index": 1})` wraps `Graph.GetLUT()`.
24
29
  - `graph(action="get_tools_in_node", ...)` may report ResolveFX tools present
25
30
  in a Color page node, but the scripting API does not expose a general
@@ -21,8 +21,32 @@ The scripting API already exposes the important LUT operations:
21
21
  can include LUTs in a `.drp` export.
22
22
 
23
23
  `SetLUT()` uses 1-based node indexes and succeeds only for LUT paths Resolve has
24
- already discovered. The `lut_path` may be absolute or relative to Resolve's
25
- master/custom LUT paths.
24
+ already discovered.
25
+
26
+ ### `SetLUT` resolves against the master LUT dir only
27
+
28
+ Resolve resolves the `lut_path` given to `SetLUT()` **only against the master
29
+ (system) LUT directory and its configured custom LUT paths — not the per-user
30
+ LUT directory** that the `dctl` tool and Project-level LUT installs write to.
31
+ This trips up the obvious workflow (install a LUT/DCTL, then apply it):
32
+
33
+ - A bare basename that lives only in the user LUT dir returns `False`.
34
+ - An **absolute path into the user LUT dir also returns `False`** — absolute
35
+ paths are not a workaround.
36
+ - `project_settings(action="refresh_luts")` (`RefreshLUTList()`) does **not**
37
+ change this; the file is discovered but still not resolvable by `SetLUT`.
38
+ - A **subfolder-relative** path under the master root (e.g. `MCP/Foo.cube`)
39
+ *does* resolve.
40
+
41
+ Verified live on Studio 19.1.3.7; the same behavior was reported on 21.0.2
42
+ (PR #90), so it is not version-specific. See the `Graph.SetLUT` entry in
43
+ `src/utils/api_truth.py`.
44
+
45
+ `graph.set_lut` (and the granular `graph_set_lut`) handle this automatically:
46
+ on a `False` return they stage the LUT into an `MCP/` subfolder of the master
47
+ LUT dir, refresh, and retry, returning `resolved_lut` on success. If you call
48
+ `Graph.SetLUT` directly, relocate the file into the master dir yourself first
49
+ (`src.utils.lut_paths.ensure_lut_in_master`).
26
50
 
27
51
  ## Cube LUT Format
28
52
 
@@ -100,16 +124,25 @@ Blackmagic's examples live in the installed LUT folder:
100
124
  Example built-in LUT categories include `VFX IO`, `Blackmagic Design`, and
101
125
  `ACES`.
102
126
 
127
+ The `dctl` tool and Project-level LUT installs instead write to the **per-user**
128
+ LUT dir (macOS `~/Library/Application Support/Blackmagic Design/DaVinci Resolve/LUT`,
129
+ Windows `%APPDATA%\Blackmagic Design\DaVinci Resolve\Support\LUT`). Files there
130
+ are discovered by the LUT browser but are **not** resolvable by `SetLUT` until
131
+ relocated into the master dir above — see "master LUT dir only".
132
+
103
133
  ## Practical Failure Checks
104
134
 
105
135
  If `graph.set_lut` fails or `graph.get_lut` returns empty:
106
136
 
107
137
  - Confirm the current page/context has a valid Color graph and the node index is
108
138
  1-based.
109
- - Confirm the LUT file is in a Resolve LUT folder or is referenced by a valid
110
- absolute path.
139
+ - Confirm the LUT is in the **master** LUT folder (or a configured custom LUT
140
+ path) — not just the per-user LUT dir. A file only in the user dir fails even
141
+ by absolute path (see "master LUT dir only" above). `graph.set_lut` relocates
142
+ it for you; a direct `Graph.SetLUT` call does not.
111
143
  - Call `project_settings(action="refresh_luts")` after adding or changing LUT
112
- files.
144
+ files (note: refresh alone does not make a user-dir LUT resolvable by
145
+ `SetLUT`).
113
146
  - Check the `.cube` header and row count. 3D LUTs must contain exactly
114
147
  `N * N * N` rows.
115
148
  - Confirm the file extension is `.cube` and the content is plain text.
@@ -12,7 +12,7 @@ that none exists).
12
12
 
13
13
  **Verified on:** DaVinci Resolve Studio 21.0.0
14
14
 
15
- **Totals:** 19 missing capabilities, 11 bugs / unreliable behaviors.
15
+ **Totals:** 19 missing capabilities, 12 bugs / unreliable behaviors.
16
16
 
17
17
  The authoritative source is the runtime-queryable `api_truth` ledger
18
18
  (`resolve_control api_truth "<query>"`); this document is generated from
@@ -265,3 +265,12 @@ values, or automation-hostile modal prompts.
265
265
  - **Workaround / current handling:** After writing 'Reel Name', read it back with GetClipProperty('Reel Name') and refuse to report success on mismatch; surface the project-setting gate to the caller (server._verify_clip_property_writeback).
266
266
  - **Reference:** [issue #77](https://github.com/samuelgursky/davinci-resolve-mcp/issues/77)
267
267
  - **Tags:** unreliable-return, silent-failure, metadata, reel-name
268
+
269
+ ### Graph.SetLUT (master-LUT-dir-only resolution)
270
+
271
+ - **Object:** `Graph`
272
+ - **Signature:** `(nodeIndex, lutPath) -> bool`
273
+ - **Behavior:** SetLUT resolves lutPath ONLY against the master (system) LUT directory and its configured custom LUT paths -- NOT the per-user LUT dir that the dctl tool / Project LUT install writes to. A bare basename in the user dir returns False, and so does an ABSOLUTE path pointing into the user dir; RefreshLUTList() does not change this. A subfolder-relative path under the master root (e.g. 'MCP/Foo.cube') DOES resolve. Net effect: a LUT/DCTL the dctl tool just installed can never be applied by SetLUT as-is, so set_lut used to always return {success: false}. Verified live on Studio 19.1.3.7 (basename and absolute user-dir path both False, before and after RefreshLUTList; master-dir and master-subfolder paths True); the originating report (PR #90) observed the same on 21.0.2, so it is not version-specific.
274
+ - **Workaround / current handling:** On a False return, locate the LUT, copy it into a namespaced subfolder of the master LUT dir (MCP/, so it does not clobber stock LUTs by basename), call RefreshLUTList(), and retry with the master-relative path. graph.set_lut and the granular graph_set_lut now do this automatically via src.utils.lut_paths.ensure_lut_in_master.
275
+ - **Reference:** [issue #90](https://github.com/samuelgursky/davinci-resolve-mcp/issues/90)
276
+ - **Tags:** color, lut, path-resolution, silent-failure
package/install.py CHANGED
@@ -35,7 +35,7 @@ from src.utils.update_check import (
35
35
 
36
36
  # ─── Version ──────────────────────────────────────────────────────────────────
37
37
 
38
- VERSION = "2.63.0"
38
+ VERSION = "2.63.2"
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
@@ -282,6 +282,37 @@ def appdata():
282
282
  """Windows %APPDATA% equivalent."""
283
283
  return Path(os.environ.get("APPDATA", home() / "AppData" / "Roaming"))
284
284
 
285
+ def localappdata():
286
+ """Windows %LOCALAPPDATA% equivalent."""
287
+ return Path(os.environ.get("LOCALAPPDATA", home() / "AppData" / "Local"))
288
+
289
+ def windows_claude_desktop_config():
290
+ """Resolve the Claude Desktop config path on Windows, MSIX-aware (issue #93).
291
+
292
+ Claude Desktop for Windows ships as an MSIX package (even when downloaded
293
+ from the official website, not the Store). MSIX filesystem virtualization
294
+ redirects the app's %APPDATA% reads/writes into a per-package container,
295
+ so the app actually uses:
296
+
297
+ %LOCALAPPDATA%\\Packages\\Claude_<publisherhash>\\LocalCache\\Roaming\\Claude\\
298
+
299
+ A config written to the documented %APPDATA%\\Claude\\ location is invisible
300
+ to the app -- the server silently never appears. Prefer the containerized
301
+ path whenever a Claude MSIX package directory with that structure exists;
302
+ fall back to %APPDATA%\\Claude\\ otherwise. The publisher-hash suffix is
303
+ globbed rather than hard-coded so a re-signed package still matches.
304
+ """
305
+ packages = localappdata() / "Packages"
306
+ try:
307
+ candidates = sorted(packages.glob("Claude_*"))
308
+ except OSError:
309
+ candidates = []
310
+ for pkg in candidates:
311
+ virtual = pkg / "LocalCache" / "Roaming" / "Claude"
312
+ if virtual.is_dir():
313
+ return virtual / "claude_desktop_config.json"
314
+ return appdata() / "Claude" / "claude_desktop_config.json"
315
+
285
316
  def xdg_config():
286
317
  """Linux XDG_CONFIG_HOME or default."""
287
318
  return Path(os.environ.get("XDG_CONFIG_HOME", home() / ".config"))
@@ -314,7 +345,7 @@ MCP_CLIENTS = [
314
345
  "name": "Claude Desktop",
315
346
  "get_path": lambda: {
316
347
  "Darwin": home() / "Library" / "Application Support" / "Claude" / "claude_desktop_config.json",
317
- "Windows": appdata() / "Claude" / "claude_desktop_config.json",
348
+ "Windows": windows_claude_desktop_config(),
318
349
  "Linux": xdg_config() / "Claude" / "claude_desktop_config.json",
319
350
  }.get(SYSTEM),
320
351
  "config_key": "mcpServers",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "davinci-resolve-mcp",
3
- "version": "2.63.0",
3
+ "version": "2.63.2",
4
4
  "description": "NPM bootstrapper for the DaVinci Resolve MCP Server.",
5
5
  "license": "MIT",
6
6
  "author": "Samuel Gursky <samgursky@gmail.com>",
@@ -80,7 +80,7 @@ if not logging.getLogger().handlers:
80
80
  handlers=[logging.StreamHandler()],
81
81
  )
82
82
 
83
- VERSION = "2.63.0"
83
+ VERSION = "2.63.2"
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()}")
package/src/server.py CHANGED
@@ -11,7 +11,7 @@ Usage:
11
11
  python src/server.py --full # Start the 341-tool granular server instead
12
12
  """
13
13
 
14
- VERSION = "2.63.0"
14
+ VERSION = "2.63.2"
15
15
 
16
16
  import base64
17
17
  import os
@@ -564,6 +564,35 @@ API_TRUTH: List[Dict[str, Any]] = [
564
564
  "when mirroring keep-ranges into clipInfos.",
565
565
  "tags": ["timeline", "edit", "off-by-one", "readback"],
566
566
  },
567
+ {
568
+ "symbol": "Graph.SetLUT (master-LUT-dir-only resolution)",
569
+ "object": "Graph",
570
+ "signature": "(nodeIndex, lutPath) -> bool",
571
+ "reality": "SetLUT resolves lutPath ONLY against the master (system) LUT "
572
+ "directory and its configured custom LUT paths -- NOT the "
573
+ "per-user LUT dir that the dctl tool / Project LUT install "
574
+ "writes to. A bare basename in the user dir returns False, and "
575
+ "so does an ABSOLUTE path pointing into the user dir; "
576
+ "RefreshLUTList() does not change this. A subfolder-relative "
577
+ "path under the master root (e.g. 'MCP/Foo.cube') DOES resolve. "
578
+ "Net effect: a LUT/DCTL the dctl tool just installed can never "
579
+ "be applied by SetLUT as-is, so set_lut used to always return "
580
+ "{success: false}. Verified live on Studio 19.1.3.7 (basename "
581
+ "and absolute user-dir path both False, before and after "
582
+ "RefreshLUTList; master-dir and master-subfolder paths True); "
583
+ "the originating report (PR #90) observed the same on 21.0.2, "
584
+ "so it is not version-specific.",
585
+ "recommended": "On a False return, locate the LUT, copy it into a "
586
+ "namespaced subfolder of the master LUT dir (MCP/, so it "
587
+ "does not clobber stock LUTs by basename), call "
588
+ "RefreshLUTList(), and retry with the master-relative path. "
589
+ "graph.set_lut and the granular graph_set_lut now do this "
590
+ "automatically via src.utils.lut_paths.ensure_lut_in_master.",
591
+ "tags": ["color", "lut", "path-resolution", "silent-failure"],
592
+ "submit": "bug",
593
+ "issue": 90,
594
+ "mitigation": ["_ensure_lut_in_master"],
595
+ },
567
596
  ]
568
597
 
569
598