81d5acd83e
- README: complete 22-tool reference table across 6 categories; updated feature list to reflect all additions and bug fixes - CHANGELOG: added with [0.2.0] and [0.1.0] entries - pyproject.toml: 0.1.0 → 0.2.0 - CLAUDE.md: corrected tool count 17 → 22 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
197 lines
6.6 KiB
Markdown
197 lines
6.6 KiB
Markdown
# mcp-synology-container
|
||
|
||
## Kontext
|
||
|
||
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.
|
||
|
||
---
|
||
|
||
## Infrastruktur
|
||
|
||
| | |
|
||
|---|---|
|
||
| **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` |
|
||
|
||
---
|
||
|
||
## Deploy-Workflow (nach jeder Code-Änderung)
|
||
|
||
```
|
||
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)
|
||
```
|
||
|
||
---
|
||
|
||
## Aktueller Stand
|
||
|
||
### Implementierte Tools (22)
|
||
|
||
| Kategorie | 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)~~
|
||
|
||
---
|
||
|
||
## Roadmap (geplante Erweiterungen)
|
||
|
||
~~Alle geplanten Erweiterungen implementiert.~~
|
||
|
||
Volumes entfällt — SYNO.Docker.Volume existiert nicht (kein DSM-Endpunkt).
|
||
|
||
---
|
||
|
||
## NAS – Laufende Container (Stand April 2026)
|
||
|
||
| 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 |
|
||
|
||
---
|
||
|
||
## Claude Code – Implementierungsregeln
|
||
|
||
- 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`). |