A Model Context Protocol (MCP) server for Synology NAS devices.
$ npx -y skills add atom2ueki/mcp-server-synology --agent claude-code

A Model Context Protocol (MCP) server for Synology NAS devices. Enables AI assistants to manage files and downloads through secure authentication and session management.
๐ NEW: Unified server supports both Claude/Cursor (stdio) and Xiaozhi (WebSocket) simultaneously!
No need to clone the repository โ install the package directly from PyPI:
# With pip
pip install mcp-server-synology
# Or with pipx (isolated environment)
pipx install mcp-server-synology
# Or with uv
uv tool install mcp-server-synology
This installs two equivalent commands: synology-mcp and mcp-server-synology.
For MCP clients, uvx is the simplest option โ it downloads and caches the package automatically, no manual install or local clone required:
{
"mcpServers": {
"synology": {
"command": "uvx",
"args": ["mcp-server-synology"]
}
}
}
Configuration lives outside the package, so it works the same as a source checkout: create ~/.config/synology-mcp/settings.json as described in Configuration Options.
# Clone repository
git clone https://github.com/atom2ueki/mcp-server-synology.git
cd mcp-server-synology
# Create environment file
cp env.example .env
Basic Configuration (Claude/Cursor only):
# Required: Synology NAS connection
SYNOLOGY_URL=http://192.168.1.100:5000
SYNOLOGY_USERNAME=your_username
SYNOLOGY_PASSWORD=your_password
# Optional: Auto-login on startup
AUTO_LOGIN=true
VERIFY_SSL=false
Extended Configuration (Both Claude/Cursor + Xiaozhi):
# Required: Synology NAS connection
SYNOLOGY_URL=http://192.168.1.100:5000
SYNOLOGY_USERNAME=your_username
SYNOLOGY_PASSWORD=your_password
# Optional: Auto-login on startup
AUTO_LOGIN=true
VERIFY_SSL=false
# Enable Xiaozhi support
ENABLE_XIAOZHI=true
XIAOZHI_TOKEN=your_xiaozhi_token_here
XIAOZHI_MCP_ENDPOINT=wss://api.xiaozhi.me/mcp/
.env is read at run time, never baked into the image โ docker-compose.yml
injects its entries as container environment variables via env_file, so the
file itself is not present inside the container. It is optional: if you
configure NASes with settings.json instead (recommended), you can skip this
file entirely.
One simple command supports both modes:
# Claude/Cursor only mode (default if ENABLE_XIAOZHI not set)
docker-compose up -d
# Both Claude/Cursor + Xiaozhi mode (if ENABLE_XIAOZHI=true in .env)
docker-compose up -d
# Build and run
docker-compose up -d --build
# Install the package and its dependencies (from PyPI, or from a clone with 'pip install .')
pip install mcp-server-synology
# Run with environment control
python main.py
The examples below use Docker with a local clone of this repository. If you installed from PyPI, use the uvx configuration from Install from PyPI instead โ it works for Claude Desktop, Cursor, Continue and Codeium alike, with no local paths to adjust.
Add to your Claude Desktop configuration file:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"synology": {
"command": "docker-compose",
"args": [
"-f", "/path/to/your/mcp-server-synology/docker-compose.yml",
"run", "--rm", "synology-mcp"
],
"cwd": "/path/to/your/mcp-server-synology"
}
}
}
Add to your Cursor MCP settings:
{
"mcpServers": {
"synology": {
"command": "docker-compose",
"args": [
"-f", "/path/to/your/mcp-server-synology/docker-compose.yml",
"run", "--rm", "synology-mcp"
],
"cwd": "/path/to/your/mcp-server-synology"
}
}
}
Add to your Continue configuration (.continue/config.json):
{
"mcpServers": {
"synology": {
"command": "docker-compose",
"args": [
"-f", "/path/to/your/mcp-server-synology/docker-compose.yml",
"run", "--rm", "synology-mcp"
],
"cwd": "/path/to/your/mcp-server-synology"
}
}
}
For Codeium's MCP support:
{
"mcpServers": {
"synology": {
"command": "docker-compose",
"args": [
"-f", "/path/to/your/mcp-server-synology/docker-compose.yml",
"run", "--rm", "synology-mcp"
],
"cwd": "/path/to/your/mcp-server-synology"
}
}
}
If you prefer not to use Docker:
{
"mcpServers": {
"synology": {
"command": "python",
"args": ["main.py"],
"cwd": "/path/to/your/mcp-server-synology",
"env": {
"SYNOLOGY_URL": "http://192.168.1.100:5000",
"SYNOLOGY_USERNAME": "your_username",
"SYNOLOGY_PASSWORD": "your_password",
"AUTO_LOGIN": "true",
"ENABLE_XIAOZHI": "false"
}
}
}
}
By default the server speaks stdio, which means the MCP client has to spawn the process locally (or via a bridge such as SSH/docker exec). For setups where the NAS is remote (different machine from where Claude/Cursor runs), set MCP_HTTP=true and the server serves native Streamable HTTP from uvicorn in the same process โ no mcp-proxy sidecar and no separate /sse endpoint. This makes it consumable by any MCP client that supports URL-based connectors โ exactly like ha-mcp or other "remote" MCP servers.
[Claude Desktop / Cursor / ...]
โ
โ HTTPS (URL connector)
โผ
[Reverse proxy: DSM / Nginx / Traefik / Caddy]
โ (TLS termination + auth)
โ HTTP localhost:8765
โผ
[Docker container]
โโ python main.py
โโ uvicorn โ Streamable HTTP at /mcp
pyproject.toml: mcp>=2.0.0 ships starlette,
uvicorn, and sse-starlette, so the same image serves both stdio and
Streamable HTTP โ no extra build arg or separate requirements file.docker-compose.http.yml:# Edit credentials in docker-compose.http.yml first
docker compose -f docker-compose.http.yml up -d --build
docker logs -f synology-mcp-http
You should see the server log Starting Streamable HTTP MCP server on http://0.0.0.0:8765/mcp and the auto-login succeed. uvicorn's own Uvicorn running on โฆ banner is not printed at the compose file's defaults โ it is INFO on the uvicorn.error logger, which the server pins to warning unless DEBUG=true.
Most MCP clients require HTTPS, so the HTTP endpoint must be fronted by a TLS-terminating reverse proxy. For DSM users, the built-in Login Portal โ Reverse Proxy does the job:
HTTPS, hostname synology-mcp.example.com, port 443HTTP, localhost, port 8765Connection: upgrade only for real upgrade requests), but it is not what keeps a stream openFor Nginx, the equivalent is:
location / {
proxy_pass http://localhost:8765;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Responses may stream as long-lived text/event-stream
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 24h;
}
In Claude Desktop (or any MCP client that supports remote connectors), add a custom connector pointing at:
https://synology-mcp.example.com/mcp
The path is whatever MCP_HTTP_PATH is set to (default /mcp). No command, no args, no local Python โ just a URL.
The server does not implement any application-level authentication โ anything that can reach the HTTP endpoint can call every tool. It does enable the MCP SDK's DNS-rebinding protection, which rejects requests whose Host/Origin headers are not on an allowlist (MCP_HTTP_ALLOWED_HOSTS / MCP_HTTP_ALLOWED_ORIGINS, defaulting to loopback). Behind a reverse proxy set both, minding the differing formats โ hosts are bare (synology-mcp.example.com), origins are scheme-qualified (https://synology-mcp.example.com), as in the commented examples in docker-compose.http.yml. That guards browsers against rebinding attacks; it is not authentication. Mitigations:
docker-compose.http.yml binds 127.0.0.1:8765) so only a same-host reverse proxy can reach itNew unified architecture supports both clients simultaneously!
ENABLE_XIAOZHI=true
XIAOZHI_TOKEN=your_xiaozhi_token_here
# Same command, different behavior based on environment
python main.py
# OR
docker-compose up
Claude/Cursor only mode:
๐ Synology MCP Server
==============================
๐ Claude/Cursor only mode (ENABLE_XIAOZHI=false)
Both clients mode:
๐ Synology MCP Server with Xiaozhi Bridge
==================================================
๐ Supports BOTH Xiaozhi and Claude/Cursor simultaneously!
synology_status - Check authentication status and active sessionssynology_list_nas - List all configured NAS units from settings.jsonsynology_login - Authenticate with Synology NAS (conditional)synology_logout - Logout from session (conditional)list_shares - List all available NAS shareslist_directory - List directory contents with metadata
path (required): Directory path starting with /get_file_info - Get detailed file/directory information
path (required): File path starting with /get_file_content - Read strict UTF-8 text or lossless base64 content
path (required): File path starting with /encoding (optional): text (default) or base64max_bytes (optional): Maximum raw bytes to read (default 1 MiB, hard limit 8 MiB)search_files - Recursively search for files and folders by name
path (required): Search directorypattern (required): Case-insensitive substring of the name (e.g., invoice, .pdf). Wildcards are not special โ DSM matches report and *report* identically.create_file - Create new files with contentmcp-server-synology is a Claude Code plugin with 1 hand-picked skill, indexed on Flowy in the MCP Servers category. Install it with the command on its page. It includes synology-nas. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.
Is this plugin yours?
Claim it with GitHubSubmit a pluginPromote it