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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user