Files
mcp-synology-container/CLAUDE.md
T
marcus 5fe8f5bc73 Add pull_image + list_registries; remove Gruppe 5 (no Volume API)
- pull_image: SYNO.Docker.Image/pull with repository+tag split via
  rpartition; polls image list every 3 s until image appears, 120 s timeout
- list_registries: SYNO.Docker.Registry/get; shows name, URL, active marker
- Gruppe 5 (Volumes) removed from roadmap — SYNO.Docker.Volume does not exist
- CLAUDE.md: tool count 17 → 19, Volumes section removed
- 28 tests all passing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 19:28:45 +02:00

6.8 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 (19)

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, pull_image
Netzwerke list_networks, create_network, delete_network
System system_df, system_prune
Registries list_registries

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)

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 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).