Files
mcp-synology-container/CLAUDE.md
T
marcus a8da306ce5 Add container_stats tool (Gruppe 2); remove rename_container
container_stats(container_name) calls SYNO.Docker.Container/stats,
locates the entry by name (stripping the DSM-added leading slash),
and reports:
  - CPU %  (standard Docker formula: cpu_delta / system_delta * cpus * 100)
  - Memory used / limit  (human-readable)
  - Network I/O rx / tx  (summed across all interfaces)
  - Block I/O read / write  (from io_service_bytes_recursive)

Gracefully handles first-poll (precpu system_cpu_usage absent → 0%).
7 unit tests covering: found, CPU formula, memory format, slash-strip,
not-found, API error, no-precpu fallback.

rename_container removed: DSM Container Manager offers no rename API.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 18:29:17 +02:00

7.9 KiB
Raw Blame History

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 (17)

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

Bekannte Bugs

  • 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

Roadmap (geplante Erweiterungen)

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 implementiert
  • rename_container entfällt (DSM bietet kein 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 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 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).