Files
mcp-synology-container/CLAUDE.md
T
marcus c8cda5ef2b Fix container hash-prefix + status-aware redeploy
Bug 1: Container name hash-prefix (e.g. f93cb8b504f7_jenkins)
- _strip_hash_prefix(): strips 12-char hex prefix and leading slash
- _resolve_container_name(): looks up actual DSM name from container list
- Applied in list_containers (display), container_stats (matching),
  get_container_status/get_container_logs/exec_in_container (lookup)

Bug 2: redeploy_project DSM 2101/1202 on wrong project state
- Fetch project status before acting
- RUNNING     → stop then start
- STOPPED     → start directly (nothing to stop)
- BUILD_FAILED → suppress stop error, then start
- Other       → return error with workaround hint

36 tests all passing.

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

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