Closes the project lifecycle (create → start/stop/redeploy → delete).
The tool calls SYNO.Docker.Project/delete with the UUID JSON-encoded
as the `id` parameter (per DSM convention) and removes only the
Container Manager registration — the project folder and compose
file remain on the NAS. This mirrors DSM's own "Delete project"
behaviour, not a bug; the success message states the folder was
preserved so the user is not surprised.
Safety:
- Project-name validation runs before any I/O.
- A `_find_project` pre-flight returns "not found" with a clear
message rather than letting DSM reject an unknown UUID.
- No automatic stop. If the project is RUNNING and DSM rejects
the delete, the response tells the user to `stop_project` first
rather than silently halting containers under the guise of a
"delete" call.
- Requires confirmed=True; preview shows name, UUID, status, full
path, and share path so the user can verify before deleting.
Tests cover preview-only, not-found, invalid-name, happy path
(verifies the UUID is JSON-encoded in the delete call), and the
running-project rejection path that surfaces the stop_project hint.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds `create_project` for registering a new Container Manager project
from a compose YAML string. Three-step flow that mirrors the DSM
"Create Project" wizard:
1. SYNO.FileStation.CreateFolder with force_parent=true (idempotent
— does not fail if the folder already exists, and creates missing
intermediate directories). Without this step, Docker.Project/create
fails with DSM error 2100.
2. SYNO.Docker.Project/create (form-encoded POST; JSON-encoded string
parameters per DSM convention) returns the new project UUID.
3. trigger_build_stream + _wait_for_project_running, reusing the
existing image-pull / start / poll machinery (including the
BUILD_FAILED early-exit from welle 2).
Safety:
- Project-name validation (Welle-1 regex) runs before any I/O.
- Compose content is YAML-parsed and must contain a top-level
`services` key before any side effects.
- A pre-flight list_projects check rejects duplicate names with a
clear message rather than leaving an orphaned folder on the NAS.
- share_path defaults to compose_base_path + project_name (e.g.
/volume1/docker + myapp → /docker/myapp); a caller-supplied value
overrides it.
- Requires confirmed=True; the preview shows the resolved share path
and the service count parsed from the compose content.
- DSM error 2100 surfaces as "target folder issue" with the attempted
path. A build_stream failure after a successful Project/create tells
the user the project is registered-but-not-started and points at
redeploy_project for recovery.
Tests cover preview-only, already-exists, happy path (with parameter
JSON-encoding assertions), explicit share_path, malformed YAML,
missing services key, invalid project name, error 2100, and
build_stream failure after registration.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add an explicit rule that every user-visible change updates
CHANGELOG.md in the same commit, under an `## [Unreleased]` heading
between releases. References the C-2 gap (0.2.7 and 0.2.8 shipped
without changelog entries) so the motivation is durable.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Document that git push to gitea.gecheckt.de occasionally returns
Unauthorized on the first attempt and must be retried once after a
1 s wait before reporting an auth failure.
- Codify the version-consistency invariant: pyproject.toml, uv.lock,
and the latest CHANGELOG heading must move together;
src/mcp_synology_container/__init__.py reads __version__ from
importlib.metadata and is never hand-edited.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Remove hostnames, concrete container names, image tags, personal notes,
and the completed task backlog. Replace with generic DSM quirks reference,
implementation rules, and tool inventory — suitable for a public connector.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bug 1: Container name hash-prefix (e.g. f93cb8b504f7_jenkins)
- _strip_hash_prefix(): strips 12-char hex prefix and leading slash
- _resolve_container_name(): looks up actual DSM name from container list
- Applied in list_containers (display), container_stats (matching),
get_container_status/get_container_logs/exec_in_container (lookup)
Bug 2: redeploy_project DSM 2101/1202 on wrong project state
- Fetch project status before acting
- RUNNING → stop then start
- STOPPED → start directly (nothing to stop)
- BUILD_FAILED → suppress stop error, then start
- Other → return error with workaround hint
36 tests all passing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
DSM methods for SYNO.Docker.Image/pull and SYNO.Docker.Registry/get
did not behave as expected in production testing against the NAS.
Tools deregistered, modules deleted, tests removed, CLAUDE.md updated.
Tool count: 19 → 17.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- pull_image: SYNO.Docker.Image/pull with repository+tag split via
rpartition; polls image list every 3 s until image appears, 120 s timeout
- list_registries: SYNO.Docker.Registry/get; shows name, URL, active marker
- Gruppe 5 (Volumes) removed from roadmap — SYNO.Docker.Volume does not exist
- CLAUDE.md: tool count 17 → 19, Volumes section removed
- 28 tests all passing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>