v0.2.3: scrub operator-specific details from CLAUDE.md

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>
This commit is contained in:
2026-04-21 07:26:56 +02:00
parent 7de4b56962
commit ae36a9fbac
3 changed files with 58 additions and 166 deletions
+49 -165
View File
@@ -1,197 +1,81 @@
# mcp-synology-container
## Kontext
## Project
Dieses Projekt entwickelt und betreibt `mcp-synology-container` einen MCP-Server
für die vollständige Verwaltung von Docker-Projekten auf einer Synology DiskStation
via Container Manager. Der MCP-Server ist in Claude Desktop aktiv verbunden.
`mcp-synology-container` is an MCP server for managing Docker projects on a
Synology DiskStation via Container Manager. It exposes tools for projects,
containers, images, compose files, networks, and system housekeeping.
---
## Infrastruktur
## Tech stack
| | |
|---|---|
| **NAS** | `https://dsm.gecheckt.de` (Split-DNS, intern direkt aufgelöst) |
| **Compose-Pfade** | `/volume1/docker/<projektname>/` |
| **Gitea** | `https://gitea.gecheckt.de/marcus/mcp-synology-container` |
| **Lokaler Code** | `D:\Dev\Projects\mcp-synology-container` |
| **Sprache** | Python 3.12+, `uv`, MCP SDK, `httpx`, `keyring`, `click`, `rich` |
| **Language** | Python 3.12+, `uv` |
| **Key deps** | MCP SDK, `httpx`, `keyring`, `click`, `rich` |
| **Compose paths** | `/volume1/docker/<project>/` (default Synology layout) |
---
## Deploy-Workflow (nach jeder Code-Änderung)
## Deploy workflow (after every code change)
```
1. Claude Code committet und pusht
2. uv tool install --reinstall git+https://gitea.gecheckt.de/marcus/mcp-synology-container.git
3. Claude Desktop neu starten (Tray-Icon → Quit → neu starten)
1. Claude Code commits and pushes
2. uv tool install --reinstall git+<repo-url>
3. Restart Claude Desktop (tray icon → Quit → relaunch)
```
---
## Aktueller Stand
## Implemented tools (23)
### Implementierte Tools (22)
| Kategorie | Tools |
| Category | Tools |
|---|---|
| Projekte | `list_projects`, `get_project_status`, `start_project`, `stop_project`, `redeploy_project` |
| Container | `list_containers`, `get_container_status`, `get_container_logs`, `exec_in_container`, `container_stats` |
| Compose | `read_compose`, `update_compose`, `update_image_tag`, `update_env_var` |
| Images | `check_image_updates`, `list_images`, `delete_image` |
| Netzwerke | `list_networks`, `create_network`, `delete_network` |
| System | `system_df`, `system_prune` |
### Bekannte Bugs
~~- Container-Name mit Hash-Präfix (`f93cb8b504f7_jenkins`) → behoben: `_strip_hash_prefix` + `_resolve_container_name` in allen Container-Tools~~
~~- `redeploy_project` DSM 2101/1202 bei falschem Status → behoben: status-aware Logik (RUNNING/STOPPED/BUILD_FAILED)~~
| Projects | `list_projects`, `get_project_status`, `start_project`, `stop_project`, `redeploy_project` |
| Containers | `list_containers`, `get_container_status`, `get_container_logs`, `exec_in_container`, `container_stats`, `delete_container` |
| Compose | `read_compose`, `update_compose`, `update_image_tag`, `update_env_var` |
| Images | `check_image_updates`, `list_images`, `delete_image` |
| Networks | `list_networks`, `create_network`, `delete_network` |
| System | `system_df`, `system_prune` |
---
## Roadmap (geplante Erweiterungen)
## DSM API quirks
~~Alle geplanten Erweiterungen implementiert.~~
Volumes entfällt — SYNO.Docker.Volume existiert nicht (kein DSM-Endpunkt).
- **Hash-prefixed container names** — DSM sometimes returns names like
`a1b2c3d4e5f6_myservice` when the compose service name differs from
`container_name`. All container tools strip this prefix transparently via
`_strip_hash_prefix` / `_resolve_container_name`.
- **Async project start** — `SYNO.Docker.Project/start` returns immediately
while containers are still initialising. `redeploy_project` polls
`SYNO.Docker.Project/list` every 2 s for up to 30 s after issuing start.
- **Image delete** — requires a form-encoded POST with a JSON `images` array
(confirmed via browser DevTools); uses `DsmClient.post_request()`.
- **`SYNO.Docker.Image/pull`** — API method exists but behaviour varies by
DSM version; not exposed as a standalone tool.
- **`SYNO.Docker.Volume`** — endpoint does not exist; volume management is
not available via the DSM WebAPI.
- **`SYNO.Docker.Registry/get`** — does not behave as documented; registry
listing omitted.
---
## NAS Laufende Container (Stand April 2026)
## Implementation rules
| Container | Image | Status |
|---|---|---|
| `jenkins` | `jenkins/jenkins:2.558-jdk21` | running |
| `openwebui` | `ghcr.io/open-webui/open-webui:v0.8.10` | running |
| `frostiq-gitea` | `gitea/gitea:1.25.4` | running |
| `frostiq-wildfly` | `frostiq/wildfly:39.0.0.Final-jdk21-pg` | running |
| `bookstack` | `linuxserver/bookstack:latest` | running |
| `bookstack-mariadb` | `mariadb:11.8` | running |
| `homeassistant` | `homeassistant/home-assistant:stable` | running |
| `pgadmin` | `dpage/pgadmin4:latest` | running |
| `postgres17` | `postgres:17.7` | running |
| `synology_docviewer_1` | `synology/docviewer:1.3.0.0126` | stopped |
| `synology_docviewer_2` | `synology/docviewer:1.3.0.0126` | stopped |
- Confirmation required before destructive operations: `stop_project`,
`redeploy_project`, `exec_in_container`, `update_image_tag`,
`update_env_var`, `update_compose`, `delete_container`
- After compose changes: suggest `redeploy_project`
- DSM errors → human-readable message, no stack traces
- No secrets in stderr output
- Type hints and docstrings everywhere
- Formatter: `ruff format` · Linter: `ruff check` · Tests: `pytest`
- All text (docstrings, comments, README): English
---
## Claude Code Implementierungsregeln
## DSM API reference
- Confirmation vor destruktiven Operationen: `stop_project`, `redeploy_project`,
`exec_in_container`, `update_image_tag`, `update_env_var`, `update_compose`
- Nach Compose-Änderungen: `redeploy_project` vorschlagen
- Fehlerbehandlung: DSM-Fehler als verständliche Meldung zurückgeben, keine Stacktraces
- Keine Secrets in stderr-Ausgaben
- Type Hints und Docstrings konsequent verwenden
- Formatter: `ruff format`, Linter: `ruff check`, Tests: `pytest`
- Alle Texte (Docstrings, Kommentare, README): Englisch
---
## Hintergrund
Marcus ist Senior Software Engineer (Java, Jakarta EE).
FrostIQ ist eines seiner größeren Projekte (Jenkins, WildFly, Gitea).
Präferenz: State-of-the-Art, Best Practices, saubere Architektur.
Automatisierung spart Zeit für die Familie. 🌱
---
## Aktueller Auftrag (Stand April 2026)
### Rollenteilung
- **Claude Code** Implementierung + Unit Tests (pytest, gemockter DSM-Client)
- **Marcus** Deploy-Workflow (commit → push → install → Desktop-Neustart)
- **Claude Chat** Produkttest live gegen die NAS nach jedem Deploy
### Implementierungsreihenfolge
Implementiere **eine Gruppe nach der anderen**. Commit + Push nach jeder Gruppe, dann Marcus Bescheid geben.
---
#### Gruppe 1 Images `modules/images.py` ✦ Prio: hoch
**`list_images`**
- DSM API: `SYNO.Docker.Image`, method `list`
- Ausgabe: Name:Tag, Größe (human-readable), Erstellungsdatum, ob aktuell von einem Container verwendet
- Sortierung: Größe absteigend
- Confirmation: nein
**`delete_image`**
- Signatur: `delete_image(image_id: str, confirmed: bool = False) -> str`
- `image_id` akzeptiert `name:tag` und Image-Hash
- DSM API: `SYNO.Docker.Image`, method `delete`
- Ohne `confirmed=True`: nur Preview, nicht löschen
- Fehler wenn Image von laufendem Container verwendet → klare Meldung, kein Stacktrace
- Erfolg: `Deleted nouchka/sqlite3:latest 76 MiB freed`
- Confirmation: **ja**
---
#### Gruppe 2 Container `modules/containers.py` ✦ Prio: mittel ✅ erledigt
**`container_stats`** ✅
- Signatur: `container_stats(container_name: str) -> str`
- Ausgabe: CPU %, RAM verwendet/limit, Netzwerk I/O, Block I/O
- Confirmation: nein
**`rename_container`** entfällt (DSM bietet kein Container-Umbenennen)
---
#### Gruppe 3 System `modules/system.py` (neu) ✦ Prio: hoch
**`system_df`**
- DSM API: `SYNO.Docker.System` oder Docker Engine `/system/df`
- Ausgabe: Images (Anzahl, Gesamtgröße, reclaimable), Container, Volumes tabellarisch
- Confirmation: nein
**`system_prune`**
- Signatur: `system_prune(confirmed: bool = False) -> str`
- Löscht: dangling Images, gestoppte Container, ungenutzte Netzwerke
- Ohne `confirmed=True`: zeigt was gelöscht würde
- Ausgabe: freigegebener Speicher
- Confirmation: **ja**
---
#### Gruppe 4 Netzwerke `modules/networks.py` (neu) ✦ Prio: mittel
**`list_networks`**
- DSM API: `SYNO.Docker.Network`, method `list`
- Ausgabe: Name, Driver, Subnet, angebundene Container
- Confirmation: nein
**`create_network`**
- Signatur: `create_network(name: str, driver: str = "bridge", confirmed: bool = False) -> str`
- Confirmation: **ja**
**`delete_network`**
- Signatur: `delete_network(name: str, confirmed: bool = False) -> str`
- Fehler wenn Container angebunden → klare Meldung
- Confirmation: **ja**
---
#### Gruppe 6 Images Ergänzung entfällt
`pull_image` entfällt — SYNO.Docker.Image/pull liefert keinen nutzbaren Endpunkt
(DSM-Methode unbekannt / nicht über WebAPI erreichbar).
---
#### Gruppe 7 Registries entfällt
`list_registries` entfällt — SYNO.Docker.Registry/get funktioniert nicht wie erwartet
(DSM-Methode unbekannt / Produkttest fehlgeschlagen).
---
### Referenz für DSM API-Calls
- `cmeans/mcp-synology` (GitHub) Auth, Keyring, CLI-Struktur
- `N4S4/synology-api` `docker_api.py` (GitHub) SYNO.Docker.* API-Calls
### Start
Beginne mit **Gruppe 1** (`list_images` + `delete_image`).
- `cmeans/mcp-synology` (GitHub) — auth, keyring, CLI structure
- `N4S4/synology-api` `docker_api.py` (GitHub) — `SYNO.Docker.*` calls