# mcp-synology-container An MCP (Model Context Protocol) server for managing Docker on a Synology NAS via Container Manager. Enables Claude Desktop to inspect, start, stop, redeploy, and modify Docker Compose projects directly — including live resource stats, log tailing, network management, and disk usage. ## Features - **Project management**: list, start, stop, redeploy Container Manager projects (status-aware) - **Container inspection**: status with IPs/ports/mounts, live resource stats, log tailing, exec - **Compose file editing**: read, replace, update image tags and env vars - **Image management**: list images with sizes, check for updates, delete unused images - **Network management**: list, create, and delete Docker networks - **System overview**: disk usage (images, containers), prune dangling resources - **Hash-prefix handling**: transparent resolution of DSM hash-prefixed container names - **2FA support**: device token flow for Synology accounts with OTP enabled - **OS keyring integration**: credentials stored securely, never in config files - **Confirmation required** for all destructive operations ## Requirements - Python 3.12+ - Synology NAS with DSM 7.x and Container Manager installed - `pip` or `uv` for installation ## Installation ```bash pip install mcp-synology-container ``` Or with `uv`: ```bash uv tool install mcp-synology-container ``` ## Setup Run the interactive setup wizard: ```bash mcp-synology-container setup ``` The wizard will: 1. Ask for your NAS hostname/IP, port, and HTTPS settings 2. Ask for your DSM username and password 3. Handle 2FA if enabled (stores device token in OS keyring) 4. Save the config to `~/.config/mcp-synology-container/config.yaml` 5. Print the Claude Desktop configuration snippet ### Claude Desktop configuration Add the snippet to `claude_desktop_config.json`: ```json { "mcpServers": { "synology-container": { "command": "mcp-synology-container", "args": ["serve"] } } } ``` ## CLI Commands ### `mcp-synology-container setup` Interactive setup: configure connection and store credentials. ```bash mcp-synology-container setup mcp-synology-container setup --verbose ``` ### `mcp-synology-container check` Test the connection and verify all required APIs are available. ```bash mcp-synology-container check mcp-synology-container check --config /path/to/config.yaml ``` Exit code 0 = OK, 1 = error. ### `mcp-synology-container serve` Start the MCP server (used by Claude Desktop). ```bash mcp-synology-container serve mcp-synology-container serve --config /path/to/config.yaml ``` ## Configuration Config file: `~/.config/mcp-synology-container/config.yaml` ```yaml schema_version: 1 alias: HomeNAS # Optional display name connection: host: dsm.example.com port: 443 https: true verify_ssl: true compose_base_path: /volume1/docker # Base path for compose projects on NAS ``` ### Environment variable overrides | Variable | Description | |---|---| | `SYNOLOGY_HOST` | NAS hostname or IP | | `SYNOLOGY_PORT` | DSM port | | `SYNOLOGY_HTTPS` | Use HTTPS (true/false) | | `SYNOLOGY_VERIFY_SSL` | Verify SSL cert (true/false) | | `SYNOLOGY_USERNAME` | DSM username | | `SYNOLOGY_PASSWORD` | DSM password | Credentials from environment variables take priority over the keyring. ## MCP Tools 22 tools across 6 categories. ### Projects | Tool | Description | Confirmation | |---|---|---| | `list_projects` | List all Container Manager projects with status and container count | — | | `get_project_status` | Detailed status, path, services, and container IDs | — | | `start_project` | Start a stopped project | — | | `stop_project` | Stop a running project (halts all containers) | required | | `redeploy_project` | Stop and restart a project; auto-detects current state (RUNNING/STOPPED/BUILD_FAILED) | required | ### Containers | Tool | Description | Confirmation | |---|---|---| | `list_containers` | List containers, optionally filtered by project | — | | `get_container_status` | Status, running state, image, IP addresses, port bindings, mounts | — | | `get_container_logs` | Fetch log output with optional keyword filter | — | | `exec_in_container` | Execute a shell command inside a running container | required | | `container_stats` | Live CPU %, RAM used/limit, network I/O, block I/O | — | ### Compose Files | Tool | Description | Confirmation | |---|---|---| | `read_compose` | Read the compose file of a project | — | | `update_image_tag` | Update the image tag for a specific service | required | | `update_env_var` | Add or update an environment variable for a service | required | | `update_compose` | Replace the entire compose file | required | ### Images | Tool | Description | Confirmation | |---|---|---| | `list_images` | List local images sorted by size (largest first); marks images in use and available updates | — | | `delete_image` | Delete a local image by `name:tag` or hash; refuses if image is in use | required | | `check_image_updates` | Check which images have updates available; optionally filter by project | — | ### System | Tool | Description | Confirmation | |---|---|---| | `system_df` | Docker disk usage: image count/size, running/stopped containers, reclaimable space | — | | `system_prune` | Remove dangling images, stopped containers, and unused networks | required | ### Networks | Tool | Description | Confirmation | |---|---|---| | `list_networks` | List all Docker networks with driver, subnet, gateway, and attached containers | — | | `create_network` | Create a new Docker network (bridge or other driver) | required | | `delete_network` | Delete a network; refuses if any container is attached | required | ## Development ```bash # Install dev dependencies pip install -e ".[dev]" # Run tests python -m pytest tests/ -v # Lint ruff check src/ tests/ # Format ruff format src/ tests/ ``` ## Security - Credentials are stored in the OS keyring only (never in config files) - All destructive operations require explicit confirmation (`confirmed=True`) - HTTPS with certificate verification is enabled by default - Session IDs and passwords are never written to stderr logs ## License MIT