docs: update CLAUDE.md for v0.3

This commit is contained in:
2026-04-14 16:51:29 +02:00
parent 53d5db142f
commit ff79d438b0
+85 -12
View File
@@ -14,18 +14,37 @@ Sibling project to `mcp-synology-container`.
- **Credentials:** OS keyring, service name `mcp-synology-filestation`
- **Gitea:** `https://gitea.gecheckt.de/marcus/mcp-synology-filestation`
- **Local code:** `D:\Dev\Projects\mcp-synology-filestation`
- **Runtime:** Python 3.12+, `uv`, MCP SDK, `httpx`, `keyring`, `click`, `rich`
- **Runtime:** Python 3.12+, `uv`, MCP SDK (`mcp>=1.0.0`), `httpx`, `keyring`, `click`, `rich`
- **Test share on NAS:** `/test-mcp` — only for MCP tests, no production data
- **DSM test user:** `Testuser` / `Lasdas1234` (read-only, for browser tests)
## Deploy Workflow
1. Commit and push via Claude Code.
2. `uv tool install --reinstall git+https://gitea.gecheckt.de/marcus/mcp-synology-filestation.git`
3. Restart Claude Desktop.
2. **Close Claude Desktop first** (Windows holds file locks — reinstall fails otherwise).
3. Install:
```
uv tool install --reinstall dist\mcp_synology_filestation-X.Y.Z-py3-none-any.whl
```
Or directly from Gitea:
```
uv tool install --reinstall git+https://gitea.gecheckt.de/marcus/mcp-synology-filestation.git
```
4. Restart Claude Desktop.
5. Verify: `uv tool list` shows the expected version.
## Versioning
Bump the patch version on **every commit** in **both** files:
- `pyproject.toml` → `version = "X.Y.Z"`
- `src/mcp_synology_filestation/__init__.py` → `__version__ = "X.Y.Z"`
Current series: `0.3.x`
## Toolchain
| Task | Command |
|------|---------|
|-------------|-------------------------------------------|
| Format | `ruff format src/ tests/` |
| Lint | `ruff check src/ tests/` |
| Tests | `pytest` |
@@ -36,10 +55,16 @@ Sibling project to `mcp-synology-container`.
## Code Standards
- **Type hints** on all public functions and methods.
- **Docstrings** (English) on all public modules, classes, and functions.
- **Docstrings** (English, 1 line max for `@mcp.tool()` functions) on all public modules,
classes, and functions.
- **Async-first:** use `httpx.AsyncClient` throughout; never `requests`.
- **Formatter:** `ruff format` (line length 100).
- **Linter:** `ruff check` — fix all warnings before committing.
- **No `-> str` on `@mcp.tool()` functions.** FastMCP generates `outputSchema` from return
annotations, which bloats the `tools/list` payload and causes Claude Desktop to truncate
the tool list. Omit return type annotations on all tool functions.
- **Short docstrings on tools.** Keep tool docstrings to 1 line. Long docstrings also bloat
the `tools/list` payload.
## Security Rules
@@ -53,8 +78,8 @@ Sibling project to `mcp-synology-container`.
`overwrite=True` are considered destructive.
- The `delete` tool MUST require `confirmed=True` to proceed. Without it, return a preview
message that describes exactly what would be deleted — never silently proceed.
- For overwrite scenarios in `move`/`copy`/`upload`, include a warning in the tool description
and default `overwrite` to `False`.
- For overwrite scenarios in `move`/`copy`/`upload`, include a warning in the tool
description and default `overwrite` to `False`.
## Error Handling Rules
@@ -72,6 +97,33 @@ Sibling project to `mcp-synology-container`.
- Include item counts and pagination hints where relevant.
- Error messages are prefixed with `Error:` for easy recognition by Claude.
## DSM Quirks (hard-won knowledge)
- **JSON-encode path parameters:** `path`, `dest_file_path`, `dest_folder_path`, `name` etc.
must be passed as `json.dumps("/path")` or `json.dumps(["/path1", "/path2"])`.
Plain strings or Python lists are silently ignored by DSM.
- **Share paths only:** always use `/docker`, `/homes/marcus` — never `/volume1/docker`.
Volume paths cause DSM error 408.
- **`additional` field:** must be `json.dumps(["size","time"])` — comma-separated string
does not work.
- **`List::list` additional:** only `["size","time"]` confirmed working on this firmware.
`real_path`, `perm`, `type` cause error 408.
- **`SYNO.FileStation.Stat`:** not in API registry — use `List::getinfo` instead.
- **`SYNO.FileStation.CheckExist`:** returns error 400 — use `List::getinfo` instead
(entries with `name=null` do not exist).
- **DirSize / MD5 one-shot:** `finished=true` is returned exactly once, then the task is
deleted. Implemented via `_start_and_poll_oneshot()` — never poll again after
`finished=true`.
- **DirSize cold start:** after inactivity, DSM's background service needs ~68 s to
initialise. During this window every `status` poll returns 599.
Fix: restart the task (new `start` call) — up to 6 restarts within a 60 s budget.
- **DirSize `status` version:** must use `version=1`. Version 2 always returns 599.
- **`Sharing::delete` id parameter:** must be `json.dumps(link_id)`.
- **`CheckPermission::write`:** `path` and `filename` are plain strings (no `json.dumps`).
Returns `{"blSkip": false}` on success.
- **Error 599:** means "background service not ready / task not found" for DirSize/MD5.
Handled by `_start_and_poll_oneshot()`.
## Module Structure
```
@@ -88,20 +140,41 @@ src/mcp_synology_filestation/
└── filestation.py # register_filestation(mcp, config, client)
```
## Implemented Tools
## Implemented Tools (v0.2.10 — 20 tools)
| Tool | Description |
|------|-------------|
|-----------------------|--------------------------------------------------------------|
| `list_shares` | List all shared folders with volume usage |
| `list_dir` | List directory contents with pagination and sorting |
| `get_info` | Get detailed metadata for one or more paths |
| `check_exist` | Check if one or more paths exist (Yes/No table) |
| `search` | Search for files by glob pattern with async polling |
| `download` | Download a file as base64 (max 10 MB) |
| `create_folder` | Create a new folder (optionally with parent dirs) |
| `rename` | Rename a file or folder |
| `copy` | Copy a file or folder (async polling, overwrite=False default) |
| `move` | Move a file or folder (async polling, overwrite=False default) |
| `copy` | Copy a file or folder (async polling, overwrite=False) |
| `move` | Move a file or folder (async polling, overwrite=False) |
| `delete` | Delete a file or folder — requires confirmed=True |
| `upload` | Upload base64-encoded content to a path (max 50 MB) |
| `compress` | Compress paths into a ZIP or 7z archive |
| `extract` | Extract a ZIP or 7z archive to a destination folder |
| `dir_size` | Total size, file count, folder count for directories |
| `get_md5` | Compute MD5 checksum of a file |
| `check_permission` | Check write permission for a filename in a directory |
| `create_sharing_link` | Create a public sharing link (optional password + expiry) |
| `list_sharing_links` | List all sharing links (paginated table) |
| `delete_sharing_link` | Delete a sharing link by ID |
See [SPEC.md](SPEC.md) for the full planned tool set.
See [SPEC.md](SPEC.md) for full tool specifications and DSM call details.
## Roadmap
### v0.3 — next
| Tool | API |
|--------------------|----------------------------------|
| `get_thumbnail` | `SYNO.FileStation.Thumb` |
| `list_favorites` | `SYNO.FileStation.Favorite` |
| `add_favorite` | `SYNO.FileStation.Favorite` |
| `delete_favorite` | `SYNO.FileStation.Favorite` |
| `list_snapshots` | `SYNO.FileStation.Snapshot` |
| `background_tasks` | `SYNO.FileStation.BackgroundTask`|