036429e9bf4b2647e854190b3b36aac3c658ac5b
DSM emits a readable plaintext build log over the build_stream HTTP body (one short status line per step) and closes the connection when the build is done. The 0.2.5 implementation sent the request and dropped the body unread, leaving users with nothing more than a BUILD_FAILED polling status and no actionable diagnostic. DsmClient.trigger_build_stream now consumes the body line-by-line and returns the collected log as a string. Wall-clock budget of 210 s (under the Claude Desktop ~4 min ceiling); on timeout the partial log is returned with a "[build_stream: timeout — stream still open server-side]" marker so callers know the build continues server-side. Per-chunk ReadTimeout is treated the same way. JSON error envelope, transport-error mapping (M-4), and SID-scrubbed HTTP-error formatting are unchanged. redeploy_project and create_project now parse the returned log via _parse_build_stream_log (any line containing "Error response from daemon:" or ending in " Error" counts as a failure). On a failed log the tools abort immediately, surface the daemon line(s) in the result (e.g. "Error response from daemon: manifest for nginx:9.9.9 not found: manifest unknown"), and skip the polling step. The BUILD_FAILED polling guard (M-5) stays as a second safety net for late failures where the stream was clean but the container exited after start. No new MCP tool: the build log is a live stream and cannot be re-fetched after the build ends, so it is surfaced during redeploy_project / create_project rather than exposed as a standalone get_project_build_log call. Minor version bump because redeploy_project and create_project return materially different strings on a failed build and exit earlier in the failure path. Signatures unchanged. Tests: streamed-log collection, daemon-error log, header ReadTimeout marker, per-chunk ReadTimeout partial log, wall-clock budget truncation, _parse_build_stream_log unit tests, redeploy/create end- to-end behavior with a failing log. Closes #2 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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
piporuvfor installation
Installation
pip install mcp-synology-container
Or with uv:
uv tool install mcp-synology-container
Setup
Run the interactive setup wizard:
mcp-synology-container setup
The wizard will:
- Ask for your NAS hostname/IP, port, and HTTPS settings
- Ask for your DSM username and password
- Handle 2FA if enabled (stores device token in OS keyring)
- Save the config to
~/.config/mcp-synology-container/config.yaml - Print the Claude Desktop configuration snippet
Claude Desktop configuration
Add the snippet to claude_desktop_config.json:
{
"mcpServers": {
"synology-container": {
"command": "mcp-synology-container",
"args": ["serve"]
}
}
}
CLI Commands
mcp-synology-container setup
Interactive setup: configure connection and store credentials.
mcp-synology-container setup
mcp-synology-container setup --verbose
mcp-synology-container check
Test the connection and verify all required APIs are available.
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).
mcp-synology-container serve
mcp-synology-container serve --config /path/to/config.yaml
Configuration
Config file: ~/.config/mcp-synology-container/config.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
23 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 |
Redeploy a project via DSM build_stream (equivalent to the DSM "Erstellen" button); pulls latest images and restarts; 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 | — |
delete_container |
Delete a stopped container by name; refuses if container is still running | required |
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
# 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
Description
Languages
Python
100%