Anpassungen
This commit is contained in:
@@ -0,0 +1 @@
|
||||
reference/
|
||||
@@ -1,92 +1,246 @@
|
||||
# CLAUDE.md – Arbeitsanweisung für mcp-synology-container
|
||||
# mcp-synology-container
|
||||
|
||||
## Deine Aufgabe
|
||||
## Kontext
|
||||
|
||||
Implementiere das Projekt `mcp-synology-container` vollständig gemäß `SPEC.md`.
|
||||
|
||||
Lies `SPEC.md` jetzt vollständig, bevor du anfängst.
|
||||
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.
|
||||
|
||||
---
|
||||
|
||||
## Referenzmaterial
|
||||
## Infrastruktur
|
||||
|
||||
Im Ordner `reference/` findest du zwei Referenzprojekte. Nutze sie aktiv:
|
||||
|
||||
### `reference/cmeans/`
|
||||
Geklontes Repo von `cmeans/mcp-synology` (GitHub).
|
||||
Übernimm daraus die Implementierungsmuster für:
|
||||
- Auth-Flow und 2FA-Device-Token-Flow (`auth.py`)
|
||||
- OS-Keyring-Integration (`keyring` library)
|
||||
- CLI-Struktur mit `click` (`cli.py`)
|
||||
- Config laden/speichern mit YAML (`config.py`)
|
||||
- Credential-Auflösungsreihenfolge (env vars → config → keyring)
|
||||
- `setup`-Wizard mit `rich` für formatierte Ausgabe
|
||||
- Generierung des Claude-Desktop-Config-Snippets
|
||||
|
||||
Passe alle übernommenen Muster an unseren Use-Case an.
|
||||
Kopiere keinen Code blind – verstehe ihn und adaptiere ihn.
|
||||
|
||||
### `reference/n4s4/docker_api.py`
|
||||
Einzelne Datei aus `N4S4/synology-api` (GitHub).
|
||||
Nutze sie als Referenz für die konkreten DSM API-Calls:
|
||||
- Wie `SYNO.Docker.Project` aufgerufen wird (list, start, stop)
|
||||
- Wie `SYNO.Docker.Container` aufgerufen wird (list, logs, exec)
|
||||
- Wie `SYNO.Docker.Image` aufgerufen wird (list)
|
||||
- Welche Parameter und Response-Strukturen die APIs erwarten
|
||||
|
||||
Implementiere **keinen** eigenen Wrapper um `synology-api` –
|
||||
baue einen eigenen schlanken HTTP-Client in `dsm_client.py` mit `httpx`.
|
||||
| | |
|
||||
|---|---|
|
||||
| **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` |
|
||||
|
||||
---
|
||||
|
||||
## Reihenfolge der Implementierung
|
||||
## Deploy-Workflow (nach jeder Code-Änderung)
|
||||
|
||||
Arbeite in dieser Reihenfolge. Schließe jeden Schritt vollständig ab bevor du weitermachst:
|
||||
|
||||
1. **Projektstruktur anlegen** – alle Ordner und leere `__init__.py`-Dateien, `pyproject.toml`
|
||||
2. **`config.py`** – Config laden, speichern, validieren
|
||||
3. **`auth.py`** – Keyring-Integration, Login gegen DSM API, 2FA-Device-Token-Flow
|
||||
4. **`dsm_client.py`** – HTTP-Client mit Session-Management, Auto-Re-Login
|
||||
5. **`cli.py`** – `setup`, `check`, `serve` Befehle
|
||||
6. **`modules/projects.py`** – SYNO.Docker.Project Tools
|
||||
7. **`modules/containers.py`** – SYNO.Docker.Container Tools
|
||||
8. **`modules/compose.py`** – Compose-Datei lesen/schreiben via FileStation API
|
||||
9. **`modules/images.py`** – SYNO.Docker.Image Tools
|
||||
10. **Tests** – für jeden Schritt
|
||||
11. **`README.md`** – Installationsanleitung und Tool-Übersicht
|
||||
12. **`docs/setup.md`** und **`docs/tools.md`**
|
||||
```
|
||||
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)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Wichtige Implementierungsregeln
|
||||
## Aktueller Stand
|
||||
|
||||
- **Confirmation vor destruktiven Operationen:** `stop_project`, `redeploy_project`,
|
||||
`exec_in_container`, `update_image_tag`, `update_env_var`, `update_compose` müssen
|
||||
eine Bestätigung vom Nutzer einholen bevor sie ausgeführt werden. Nutze dafür den
|
||||
MCP-eigenen `confirm`-Mechanismus.
|
||||
### Implementierte Tools (14)
|
||||
|
||||
- **Nach Compose-Änderungen:** Immer automatisch `redeploy_project` vorschlagen.
|
||||
| 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` |
|
||||
| Compose | `read_compose`, `update_compose`, `update_image_tag`, `update_env_var` |
|
||||
| Images | `check_image_updates` |
|
||||
|
||||
- **Fehlerbehandlung:** Alle DSM API-Fehler sauber abfangen und als verständliche
|
||||
Fehlermeldung zurückgeben. Keine Python-Stacktraces zum Nutzer.
|
||||
### Bekannte Bugs
|
||||
|
||||
- **Keine Secrets in Logs:** Passwörter, Tokens und Session-IDs niemals in
|
||||
stderr-Ausgaben schreiben.
|
||||
|
||||
- **HTTPS:** `verify_ssl: true` ist der Standard. Nur auf expliziten Wunsch deaktivierbar.
|
||||
|
||||
- **Compose-Pfade:** Beide Varianten erkennen – `docker-compose.yml` und `compose.yml`.
|
||||
|
||||
- **Type Hints:** Konsequent in allen Funktionen verwenden.
|
||||
|
||||
- **Docstrings:** Für alle öffentlichen Funktionen und Klassen.
|
||||
- Container-Name wird manchmal mit Hash-Präfix zurückgegeben (z.B. `f93cb8b504f7_jenkins`)
|
||||
→ Tritt auf wenn Service-Name in compose.yaml von `container_name` abweicht
|
||||
- `redeploy_project` schlägt mit DSM 2101/1202 fehl bei falschem Projektstatus
|
||||
→ Workaround: `stop_project` + `start_project` separat oder `docker compose` per SSH
|
||||
|
||||
---
|
||||
|
||||
## Projekt-Konventionen
|
||||
## Roadmap (geplante Erweiterungen)
|
||||
|
||||
- Sprache: Python 3.12+
|
||||
- Formatter: `ruff format`
|
||||
- Linter: `ruff check`
|
||||
- Tests: `pytest`
|
||||
### Images
|
||||
- `list_images` – alle lokalen Images mit Größe, Tag, Erstellungsdatum
|
||||
- `delete_image` – nicht mehr benötigte Images löschen
|
||||
- `pull_image` – Image manuell aus Registry ziehen
|
||||
|
||||
### Container
|
||||
- `container_stats` – Live CPU/RAM-Verbrauch pro Container
|
||||
- `rename_container` – Container umbenennen
|
||||
|
||||
### Netzwerke
|
||||
- `list_networks` – alle Docker-Netzwerke auflisten
|
||||
- `create_network` – neues Netzwerk anlegen
|
||||
- `delete_network` – Netzwerk löschen
|
||||
|
||||
### Volumes
|
||||
- `list_volumes` – alle Docker-Volumes auflisten
|
||||
- `delete_volume` – verwaiste Volumes löschen
|
||||
- `inspect_volume` – Volume-Details anzeigen
|
||||
|
||||
### System
|
||||
- `system_df` – Docker Disk Usage (Images, Container, Volumes)
|
||||
- `system_prune` – Aufräumen (dangling Images, gestoppte Container)
|
||||
|
||||
### Registries
|
||||
- `list_registries` – konfigurierte Registries anzeigen
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
|
||||
**`rename_container`**
|
||||
- Signatur: `rename_container(container_name: str, new_name: str, confirmed: bool = False) -> str`
|
||||
- DSM API: `SYNO.Docker.Container` rename (oder Docker Engine API direkt)
|
||||
- Hinweis nach Erfolg: compose.yml ggf. manuell anpassen (`container_name`)
|
||||
- Confirmation: **ja**
|
||||
|
||||
**`container_stats`**
|
||||
- Signatur: `container_stats(container_name: str) -> str`
|
||||
- Ausgabe: CPU %, RAM verwendet/limit, Netzwerk I/O, Block I/O
|
||||
- Confirmation: nein
|
||||
|
||||
---
|
||||
|
||||
#### 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 5 – Volumes `modules/volumes.py` (neu) ✦ Prio: niedrig
|
||||
|
||||
**`list_volumes`**
|
||||
- DSM API: `SYNO.Docker.Volume`, method `list`
|
||||
- Ausgabe: Name, Mountpoint, Größe, ob in Verwendung
|
||||
- Confirmation: nein
|
||||
|
||||
**`inspect_volume`**
|
||||
- Signatur: `inspect_volume(volume_name: str) -> str`
|
||||
- Confirmation: nein
|
||||
|
||||
**`delete_volume`**
|
||||
- Signatur: `delete_volume(volume_name: str, confirmed: bool = False) -> str`
|
||||
- Fehler wenn Volume gemountet → klare Meldung
|
||||
- Confirmation: **ja**
|
||||
|
||||
---
|
||||
|
||||
#### Gruppe 6 – Images Ergänzung `modules/images.py` ✦ Prio: niedrig
|
||||
|
||||
**`pull_image`**
|
||||
- Signatur: `pull_image(image: str) -> str` (z.B. `"postgres:17.8"`)
|
||||
- DSM API: `SYNO.Docker.Image`, method `create` oder pull-Endpunkt
|
||||
- Fortschritt streamen wenn möglich, sonst polling
|
||||
- Confirmation: nein
|
||||
|
||||
---
|
||||
|
||||
#### Gruppe 7 – Registries `modules/registries.py` (neu) ✦ Prio: niedrig
|
||||
|
||||
**`list_registries`**
|
||||
- DSM API: `SYNO.Docker.Registry`, method `list`
|
||||
- Ausgabe: Name, URL, ob authentifiziert
|
||||
- Confirmation: nein
|
||||
|
||||
---
|
||||
|
||||
### 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`).
|
||||
Reference in New Issue
Block a user