From d7343e0bfd52b4355eea2a4341c27e4efe9fa70f Mon Sep 17 00:00:00 2001 From: "cmeans-claude-dev[bot]" <272174644+cmeans-claude-dev[bot]@users.noreply.github.com> Date: Fri, 1 May 2026 09:17:37 -0500 Subject: [PATCH] Release v0.5.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch release rolling up the post-0.5.0 fixes: - #69 Atomic state-file writes (closes #36) - #71 Atomic write for cli/setup.py interactive config (closes #70) - #72 README per-installer and per-OS download-breakdown badges - #73 Recycle-bin status probed per share (closes #37) - #77 Per-path serial for multi-path getinfo + delete (closes #68) #77 in particular fixes a v0.5.0 silent-no-op regression on delete_files with multi-path arrays — caller would see "[+] Deleted N item(s)" but no paths were actually deleted on real DSM 7.x. Files touched per project release procedure: - pyproject.toml: 0.5.0 → 0.5.1 - server.json: synced via scripts/sync-server-json.py - uv.lock: refreshed via `uv lock` - CHANGELOG.md: ## Unreleased renamed to ## 0.5.1 (2026-05-01), fresh empty Unreleased added above Local verification on release/v0.5.1: - uv run pytest: 550 passed, 100 deselected, 96.13% coverage - uv run ruff check src/ tests/ scripts/: clean - uv run ruff format --check src/ tests/ scripts/: clean - uv run mypy src/ scripts/: clean - python scripts/sync-server-json.py --check: in sync (0.5.1) Co-Authored-By: Claude Opus 4.7 (1M context) --- CHANGELOG.md | 2 ++ pyproject.toml | 2 +- server.json | 4 ++-- uv.lock | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cd7a56..f0ce043 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.5.1 (2026-05-01) + ### Fixed - **`get_file_info` and `delete_files` correctly handle multi-path inputs on real DSM 7.x** (#77) — closes #68. DSM 7.x's `SYNO.FileStation.List getinfo` and `SYNO.FileStation.Delete start` do **not** honor the documented comma-joined multi-path format, even on v2: a request with `path=/a,/b` is treated as a single literal path. For `getinfo` this surfaces as one synthetic record whose `path` field IS the literal comma-joined string (the handler's `len(files) == 1` branch then renders it as a single info card). For `delete_files` this surfaces as a successful task that actually no-ops on every input, returning `[+] Deleted N item(s)` with all paths listed but none removed. The round-1 hypothesis (pin `getinfo` to v2 to dodge a v3 quirk) was disproven by vdsm CI on DSM 7.2.2 — the comma-joined-as-single-path symptom reproduces on v2 too. Fix matches the user's documented workaround on #68: **one DSM call per input path**. Both tools now iterate `paths` and issue per-path requests, aggregating results into the same response shape callers already expect (single info card for one path, table for multiple; per-share recycle-bin messaging unchanged for delete). Trade-off is N round-trips for N paths, which is fine for typical small-N usage and trivially correct. Refactor extracted `_delete_one_path` from `delete_files` so the per-path async-task pattern (start → poll → stop in `try`/`finally`) lives in one place; `get_file_info` simply loops `client.request` since it's synchronous. Bumped `tests/conftest.py` `SYNO.FileStation.List max_version` from 2 to 3 to match DSM 7.x reality so future regression tests don't get fooled by a max-resolves-to-2 default. New `TestGetFileInfo::test_multipath_uses_per_path_serial_calls` asserts (a) N requests for N paths, (b) each request carries a single path with no commas, (c) all pinned to v2, (d) results aggregate correctly. New `TestMultiPathDelete` integration test (re-exported in `tests/vdsm/test_vdsm_integration.py`) creates two folders, deletes both in one multi-path call, verifies via `list_files` that both are actually gone — would have caught the original #68 regression before it shipped if it had existed in v0.5.0. 550 unit tests pass at 96.13% coverage. diff --git a/pyproject.toml b/pyproject.toml index 19e8d74..7025c2b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "mcp-synology" -version = "0.5.0" +version = "0.5.1" description = "MCP server for Synology NAS — manage files on your NAS via Claude" readme = "README.md" license = "Apache-2.0" diff --git a/server.json b/server.json index bf42b77..4b6af14 100644 --- a/server.json +++ b/server.json @@ -3,7 +3,7 @@ "name": "io.github.cmeans/mcp-synology", "title": "Synology NAS", "description": "MCP server for Synology NAS — browse files, monitor health, and automate operations", - "version": "0.5.0", + "version": "0.5.1", "repository": { "url": "https://github.com/cmeans/mcp-synology", "source": "github" @@ -12,7 +12,7 @@ { "registryType": "pypi", "identifier": "mcp-synology", - "version": "0.5.0", + "version": "0.5.1", "transport": { "type": "stdio" } diff --git a/uv.lock b/uv.lock index 5b204c1..8161623 100644 --- a/uv.lock +++ b/uv.lock @@ -726,7 +726,7 @@ wheels = [ [[package]] name = "mcp-synology" -version = "0.5.0" +version = "0.5.1" source = { editable = "." } dependencies = [ { name = "click" },