davinci-resolve-mcp 2.214.3 → 2.214.4

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,35 @@
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.214.4 — the offline test suite no longer writes into the operator's server.log
6
+
7
+ ### Fixed
8
+
9
+ - **The unit suite was appending to `logs/server.log`.** Importing
10
+ `src/server.py` attaches the root logger's FileHandler to that file, and the
11
+ suite imports the server, so every MagicMock "connection" the bridge tests
12
+ provoke and every lifecycle warning about a MagicMock timeline landed in the
13
+ operator's real log — the file a live debugging session reads. On the
14
+ maintainer's machine that log had grown to 128 MB with 240 such lines in it.
15
+ The log target is now `RESOLVE_MCP_LOG_FILE`: unset means `logs/server.log`
16
+ as before, a path means that file, empty means no file. `tests/__init__.py`
17
+ sets it to a temporary file before any test module imports the server, on
18
+ both the `unittest` and `pytest` paths, and `tests/test_log_isolation.py`
19
+ fails the suite if a handler on the root or `resolve-mcp` logger ever targets
20
+ the real log during a run. The live server's behaviour is unchanged, and the
21
+ transport-token redaction test, which builds its own root FileHandler, still
22
+ passes.
23
+ - **The existing log is untouched.** The 128 MB file is the operator's; this
24
+ change only stops adding to it. Rotate or trim it by hand if wanted.
25
+
26
+ ### Validation
27
+
28
+ - `tests/test_log_isolation.py` (four tests, including the unset-means-real-log
29
+ case that pins the live behaviour). Proven with an audited full run — a
30
+ `sys.addaudithook` on every `open` of the operator's log — that recorded zero
31
+ opens across 3371 tests. Full offline suite, drift guards and the advanced
32
+ Node suite green.
33
+
5
34
  ## What's New in v2.214.3 — the advanced launcher heals a wrong-Node registration
6
35
 
7
36
  ### Fixed
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-2.214.3-blue.svg)](https://github.com/samuelgursky/davinci-resolve-mcp/releases)
5
+ [![Version](https://img.shields.io/badge/version-2.214.4-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-36%20(353%20full)-blue.svg)](#server-modes)
@@ -298,7 +298,9 @@ and an audit document is the last place to let a reader read it as an all-clear.
298
298
 
299
299
  Traces live in a 100-entry in-memory ring and are appended to
300
300
  `logs/execution-traces.jsonl` beside `server.log` — `RESOLVE_MCP_TRACE_FILE`
301
- moves it. `list_recent_executions` reports that path and whether it is
301
+ moves it, and `RESOLVE_MCP_LOG_FILE` moves `server.log` itself (a path, or empty
302
+ for no file; the offline test suite points it at a temporary file so it never
303
+ writes into the operator's log). `list_recent_executions` reports that path and whether it is
302
304
  writable, so "the log is empty" and "nothing is being written" are
303
305
  distinguishable without reading the source. What is recorded is tool name,
304
306
  action, timing, status, semantic deltas and verification — no parameters and no
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-2.214.3-blue.svg)](https://github.com/samuelgursky/davinci-resolve-mcp/releases)
5
+ [![Version](https://img.shields.io/badge/version-2.214.4-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-36%20(353%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
- > 本翻译对应 v2.214.3 版 README。如与英文原版有出入,以 [英文原版](README.md) 为准。
15
+ > 本翻译对应 v2.214.4 版 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 = "2.214.3"
40
+ VERSION = "2.214.4"
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": "2.214.3",
3
+ "version": "2.214.4",
4
4
  "description": "NPM bootstrapper for the DaVinci Resolve MCP Server.",
5
5
  "license": "MIT",
6
6
  "author": "Samuel Gursky <samgursky@gmail.com>",
@@ -87,7 +87,7 @@ if not logging.getLogger().handlers:
87
87
  handlers=[logging.StreamHandler()],
88
88
  )
89
89
 
90
- VERSION = "2.214.3"
90
+ VERSION = "2.214.4"
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.214.3"
14
+ VERSION = "2.214.4"
15
15
 
16
16
  import base64
17
17
  import os
@@ -185,10 +185,40 @@ if RESOLVE_MODULES_PATH not in sys.path:
185
185
 
186
186
  log_dir = os.path.join(project_dir, "logs")
187
187
  os.makedirs(log_dir, exist_ok=True)
188
+
189
+ #: Where this process logs. Unset: `logs/server.log` under the repository, as
190
+ #: always. A path: that file (its directory is created). Empty: no file at all.
191
+ #:
192
+ #: The variable exists because importing this module attaches the file handler,
193
+ #: and the offline unit suite imports this module. Without it the suite's
194
+ #: MagicMock "connections" and lifecycle warnings landed in the operator's real
195
+ #: server.log — 240 such lines in a 128 MB log on the maintainer's machine —
196
+ #: which is the file every live debugging session reads. `tests/__init__.py`
197
+ #: points it at a temporary file before any test module runs.
198
+ ENV_LOG_FILE = "RESOLVE_MCP_LOG_FILE"
199
+
200
+
201
+ def _log_file_from_env(env=None) -> str:
202
+ """The log path this process should use, or "" for none."""
203
+ values = os.environ if env is None else env
204
+ value = values.get(ENV_LOG_FILE)
205
+ if value is None:
206
+ return os.path.join(log_dir, "server.log")
207
+ return os.path.expanduser(value.strip())
208
+
209
+
210
+ def _log_handlers():
211
+ target = _log_file_from_env()
212
+ if not target:
213
+ return [logging.NullHandler()]
214
+ os.makedirs(os.path.dirname(target) or ".", exist_ok=True)
215
+ return [logging.FileHandler(target)]
216
+
217
+
188
218
  logging.basicConfig(
189
219
  level=logging.INFO,
190
220
  format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
191
- handlers=[logging.FileHandler(os.path.join(log_dir, "server.log"))]
221
+ handlers=_log_handlers(),
192
222
  )
193
223
  logger = logging.getLogger("resolve-mcp")
194
224