High-performance code intelligence MCP server. Indexes codebases into a persistent knowledge graph โ average repo in milliseconds. 158 languages, sub-ms queries, 99% fewer tokens. Single static binary, zero dependencies.
MCP server for Synology NAS tools
This repository provides an MCP server that lets an agent talk to a Synology NAS through its APIs. It supports file operations, downloads, system health, containers, and NFS, and can run locally over stdio or as a remote HTTP MCP endpoint.
Builders who want their agent to manage files, downloads, and system tasks on a Synology NAS.
You can ask your agent to inspect and change your NAS without leaving your chat or editor.
What it does
File system tools
List shares and directories, read file info, search by name, create folders and files, rename, move, and delete items.
Download Station tools
Check download status, create tasks from URLs or magnets, pause or resume tasks, delete tasks, and read transfer statistics.
Health monitoring tools
Read system info, CPU and memory usage, disk SMART data, volume status, storage pools, network status, UPS state, and logs.
Container Manager tools
List, start, stop, restart, delete, inspect, and log containers, plus manage projects, images, registries, and networks.
NFS management tools
Check NFS status, enable or disable it, list share permissions, and set client access rules.
Docker and HTTP deployment
Run the server with Docker Compose for stdio clients, or use the HTTP compose file for remote MCP clients through a reverse proxy.
Claude Code skill pack
Ships a `skills/synology-nas/` folder that teaches Claude how to pick the right NAS tool and use the right path conventions.
How to get it
- 1Run
# Clone repository git clone https://github.com/atom2ueki/mcp-server-synology.git cd mcp-server-synology # Create environment file cp env.example .env
- 2Basic 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
- 3One 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
- 4Run
# Install the package and its dependencies pip install . # Run with environment control python main.py
- 5Add to your .env file
ENABLE_XIAOZHI=true XIAOZHI_TOKEN=your_xiaozhi_token_here
- 6Run normally
# Same command, different behavior based on environment python main.py # OR docker-compose up
README
๐พ Synology MCP Server

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!
๐ Quick Start with Docker
1๏ธโฃ Setup Environment
# Clone repository
git clone https://github.com/atom2ueki/mcp-server-synology.git
cd mcp-server-synology
# Create environment file
cp env.example .env
2๏ธโฃ Configure .env File
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/
3๏ธโฃ Run with Docker
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
4๏ธโฃ Alternative: Local Python
# Install the package and its dependencies
pip install .
# Run with environment control
python main.py
๐ Client Setup
๐ค Claude Desktop
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"
}
}
}
โ๏ธ Cursor
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"
}
}
}
๐ Continue (VS Code Extension)
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"
}
}
}
๐ป Codeium
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"
}
}
}
๐ Alternative: Direct Python Execution
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"
}
}
}
}
๐ Remote Streamable HTTP Deployment
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.
Architecture
[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
Deploy
- All dependencies come from
pyproject.toml:mcp>=2.0.0ships starlette, uvicorn, and sse-starlette, so the same image serves both stdio and Streamable HTTP โ no extra build arg or separate requirements file. - Use the provided
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.
Reverse proxy
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:
- Source:
HTTPS, hostnamesynology-mcp.example.com, port443 - Destination:
HTTP,localhost, port8765 - Custom Headers: none required โ Streamable HTTP is plain POST/GET on a single endpoint, not a WebSocket upgrade. The Create โ WebSocket preset is harmless if you already apply it elsewhere (it sets
Connection: upgradeonly for real upgrade requests), but it is not what keeps a stream open
For 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;
}
Client configuration
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.
Security
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:
- Keep it on a private network or behind a VPN
- Leave the published port on loopback (
docker-compose.http.ymlbinds127.0.0.1:8765) so only a same-host reverse proxy can reach it - Use the reverse proxy to enforce an IP allow-list
- Add Basic Auth / mTLS / OAuth2 proxy at the reverse proxy layer
- Use a dedicated low-privilege DSM user (already recommended in the security warning above)
๐ Xiaozhi Integration
New unified architecture supports both clients simultaneously!
How It Works
- ENABLE_XIAOZHI=false (default): Standard MCP server for Claude/Cursor via stdio
- ENABLE_XIAOZHI=true: Multi-client bridge supporting both:
- ๐ก Xiaozhi: WebSocket connection
- ๐ป Claude/Cursor: stdio connection
Setup Steps
- Add to your .env file:
ENABLE_XIAOZHI=true
XIAOZHI_TOKEN=your_xiaozhi_token_here
- Run normally:
# Same command, different behavior based on environment
python main.py
# OR
docker-compose up
Key Features
- โ Zero Configuration Conflicts: One server, multiple clients
- โ Parallel Operation: Both clients can work simultaneously
- โ All Tools Available: Xiaozhi gets access to all Synology MCP tools
- โ Backward Compatible: Existing setups work unchanged
- โ Auto-Reconnection: Handles WebSocket connection drops
- โ Environment Controlled: Simple boolean flag to enable/disable
Startup Messages
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!
๐ ๏ธ Available MCP Tools
๐ Authentication
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)
๐ File System Operations
list_shares- List all available NAS shareslist_directory- List directory contents with metadatapath(required): Directory path starting with/
get_file_info- Get detailed file/directory informationpath(required): File path starting with/
search_files- Recursively search for files and folders by namepath(required): Search directorypattern(required): Case-insensitive substring of the name (e.g.,invoice,.pdf). Wildcards are not special โ DSM matchesreportand*report*identically.
create_file- Create new files with contentpath(required): Full file path starting with/content(optional): File content (default: empty string)overwrite(optional): Overwrite existing files (default: false)
create_directory- Create new directoriesfolder_path(required): Parent directory path starting with/name(required): New directory nameforce_parent(optional): Create parent directories if needed (default: false)
delete- Delete files or directories (auto-detects type)path(required): File/directory path starting with/
rename_file- Rename files or directoriespath(required): Current file pathnew_name(required): New filename
move_file- Move files to new locationsource_path(required): Source file pathdestination_path(required): Destination pathoverwrite(optional): Overwrite existing files
๐ฅ Download Station Management
ds_get_info- Get Download Station informationds_list_tasks- List all download tasks with statusoffset(optional): Pagination offsetlimit(optional): Max tasks to return
ds_create_task- Create new download taskuri(required): Download URL or magnet linkdestination(optional): Download folder path
ds_pause_tasks- Pause download taskstask_ids(required): Array of task IDs
ds_resume_tasks- Resume paused taskstask_ids(required): Array of task IDs
ds_delete_tasks- Delete download taskstask_ids(required): Array of task IDsforce_complete(optional): Force delete completed
ds_get_statistics- Get download/upload statistics
๐ฅ Health Monitoring
synology_system_info- Get system model, serial, DSM version, uptime, temperaturesynology_utilization- Get real-time CPU, memory, swap, and disk I/O utilizationsynology_disk_health- List all physical disks with SMART status, model, temp, sizesynology_disk_smart- Get detailed SMART attributes for a specific disksynology_volume_status- List all volumes with status, size, usage, filesystem typesynology_storage_pool- List RAID/storage pools with level, status, member diskssynology_lun_list- List all iSCSI LUNs with name, UUID, size, usage, status, mapped targets, and backing volumesynology_lun_get- Get details for a single iSCSI LUNname(required): LUN name or UUID fromsynology_lun_listoutput
synology_network- Get network interface status and transfer ratessynology_ups- Get UPS status, battery level, power readingssynology_services- List installed packages and their running statussynology_system_log- Get recent system log entriessynology_health_summary- Aggregate system info, utilization, disk health, and volume status
๐ณ Container Manager
synology_container_list- List Container Manager containersoffset(optional): Pagination offsetlimit(optional): Maximum containers to returncontainer_type(optional): Container filter (default:all)
synology_container_health_summary- Summarize container status, health, restart counts, and imagessynology_container_disk_usage- Show the read-only disk-usage summary available through Container Manager APIssynology_container_get- Get a Container Manager containername(required): Container name
synology_container_start- Start a Container Manager containername(required): Container name
synology_container_stop- Stop a Container Manager containername(required): Container name
synology_container_restart- Restart a Container Manager containername(required): Container name
synology_container_delete- Delete a Container Manager containername(required): Container nameforce(optional): Force deletion (default: false)preserve_profile(optional): Preserve Synology container profile (default: true)
synology_container_logs- Get Container Manager container logsname(required): Container namesince(optional): Log start time/filteroffset(optional): Pagination offset (default: 0)limit(optional): Maximum log lines to return (default: 1000)
synology_container_resource- Get real-time resource usage for a Container Manager containername(required): Container name
synology_container_project_list- List Container Manager projectssynology_container_project_get- Get a Container Manager projectname(required): Project name
synology_container_project_create- Create a Container Manager projectname(required): Project nameshare_path(required): Project folder path on the NAScontent(required): Docker Compose YAML contentenable_service_portal(optional): Enable Synology service portal (default: false)service_portal_name(optional): Service portal nameservice_portal_port(optional): Service portal portservice_portal_protocol(optional): Service portal protocol (default:http)
synology_container_project_update- Update a Container Manager projectname(required): Project namecontent(required): Docker Compose YAML contentenable_service_portal(optional): Enable Synology service portalservice_portal_name(optional): Service portal nameservice_portal_port(optional): Service portal portservice_portal_protocol(optional): Service portal protocol
synology_container_project_start- Start a Container Manager projectname(required): Project name
synology_container_project_stop- Stop a Container Manager projectname(required): Project name
synology_container_project_restart- Restart a Container Manager projectname(required): Project name
synology_container_project_build- Build a Container Manager projectname(required): Project name
synology_container_project_clean- Clean a Container Manager projectname(required): Project name
synology_container_project_delete- Delete a Container Manager projectname(required): Project name
synology_container_image_list- List Container Manager imagesoffset(optional): Pagination offsetlimit(optional): Maximum images to returnshow_dsm(optional): Include DSM images (default: false)
synology_container_image_get- Get a Container Manager imagename(required): Image repository nametag(optional): Image tag (default:latest)
synology_container_image_delete- Delete a Container Manager imagename(required): Image repository nametag(optional): Image tag (default:latest)
synology_container_image_prune- Remove images unused by any containersynology_container_image_prune_previewprovides a read-only candidate list before cleanup- Uses only Container Manager APIs to delete safely identifiable unused tagged images and reports dangling images it cannot remove through DSM
- Does not remove containers, networks, or build cache
synology_container_image_pull- Pull a Container Manager imagerepository(required): Image repository nametag(optional): Image tag (default:latest)
synology_container_registry_list- List Container Manager registriessynology_container_registry_search- Search Container Manager registriesquery(required): Image search queryoffset(optional): Pagination offsetlimit(optional): Maximum results to return
synology_container_registry_tags- List tags for a registry imagerepository(required): Image repository nameoffset(optional): Pagination offsetlimit(optional): Maximum tags to return
synology_container_registry_download- Download a registry imagerepository(required): Image repository nametag(optional): Image tag (default:latest)
synology_container_network_list- List Container Manager networkssynology_container_network_get- Get a Container Manager networkname(required): Network name
synology_container_network_create- Create a Container Manager networkname(required): Network namedriver(optional): Network driver (default:bridge)subnet(optional): Subnet CIDRgateway(optional): Gateway IPip_range(optional): Allocatable IP range CIDRenable_ipv6(optional): Enable IPv6 (default: false)
synology_container_network_delete- Delete a Container Manager networkname(required): Network name
๐ฆ NFS Management
synology_nfs_status- Get NFS service status and configurationsynology_nfs_enable- Enable or disable the NFS servicesynology_nfs_list_shares- List all shared folders with their NFS permissionssynology_nfs_set_permission- Set NFS client access permissions on a shared folder
๐ง Claude Code / Claude.ai Skill
For Claude Code, Claude Desktop, and claude.ai users, this repo ships an Anthropic Agent Skill that teaches Claude how to use the MCP tools effectively โ picking the right tool, targeting the right NAS in multi-NAS setups, preferring aggregate health checks over fan-out calls, and using correct path conventions.
The skill lives at skills/synology-nas/ and uses progressive disclosure across seven domains (auth, files, downloads, health, containers, shares/NFS, user management).
Install:
- Claude Code: copy or symlink the folder into
~/.claude/skills/synology-nas/ - Claude.ai / Claude Desktop: upload the
synology-nas/folder via the Skills settings page
The skill is purely additive โ it works alongside the MCP and only triggers on Synology/NAS-related prompts.
โ๏ธ Configuration Options
โ ๏ธ Security Warning: Use a Dedicated Account
For this MCP server, create a dedicated Synology user account with appropriate permissions. This account should:
- Have minimal required permissions only (not admin!)
- Be used exclusively for MCP server automation
- 2FA is now supported โ if your DSM account has 2FA enabled, see the 2FA / OTP Accounts section below to supply an
otp_code(one-shot) ordevice_id(persistent) field. Older guidance of "no 2FA" is no longer required.
Using settings.json (Recommended)
| Variable | Required | Default | Description |
|---|---|---|---|
SYNOLOGY_URL | Yes* | - | NAS base URL (e.g., http://192.168.1.100:5000) |
SYNOLOGY_USERNAME | Yes* | - | Username for authentication |
SYNOLOGY_PASSWORD | Yes* | - | Password for authentication |
AUTO_LOGIN | No | true | Auto-login on server start |
VERIFY_SSL | No | false | Verify SSL certificates |
DEBUG | No | false | Enable debug logging |
ENABLE_XIAOZHI | No | false | Enable Xiaozhi WebSocket bridge |
XIAOZHI_TOKEN | Xiaozhi only | - | Authentication token for Xiaozhi |
XIAOZHI_MCP_ENDPOINT | No | wss://api.xiaozhi.me/mcp/ | Xiaozhi WebSocket endpoint |
*Required for auto-login and default operations
Using settings.json (Multi-NAS Support)
For managing multiple Synology NAS devices, use the XDG standard config directory (~/.config/synology-mcp/settings.json):
mkdir -p ~/.config/synology-mcp
touch ~/.config/synology-mcp/settings.json
chmod 600 ~/.config/synology-mcp/settings.json # Important: secure permissions!
Note: This follows the XDG Base Directory Specification - ~/.config/ is the standard location for user configuration files on Linux/macOS. You can customize the location by setting the XDG_CONFIG_HOME environment variable.
With Docker:
The docker-compose.yml automatically mounts your ~/.config/synology-mcp directory into the container at /home/mcpuser/.config/synology-mcp, so multi-NAS works out of the box with Docker as well.
settings.json format:
{
"synology": {
"nas1": {
"host": "192.168.1.100",
"port": 5000,
"username": "admin",
"password": "your_password",
"note": "Primary NAS at home"
},
"nas2": {
"host": "192.168.1.200",
"port": 5001,
"username": "admin",
"password": "your_password",
"note": "Backup NAS"
},
"nas3": {
"url": "https://nas.example.com",
"username": "admin",
"password": "your_password",
"note": "NAS behind a reverse proxy"
}
},
"xiaozhi": {
"enabled": false,
"token": "your_xiaozhi_token",
"endpoint": "wss://api.xiaozhi.me/mcp/"
},
"server": {
"auto_login": true,
"verify_ssl": false,
"session_timeout": 3600,
"debug": false,
"log_level": "INFO"
}
}
Configuration fields:
| Field | Required | Description |
|---|---|---|
host | Yes* | NAS hostname or IP address |
port | No | API port (default: 5000 for HTTP, 5001 for HTTPS) |
url | Yes* | Full base URL (e.g., https://nas.example.com); wins over host/port โ use for a NAS behind a reverse proxy |
username | Yes | NAS username |
password | Yes | NAS password |
otp_code | No | One-shot 6-digit 2FA code (first login only, then remove) |
device_id | No | Long-lived trusted-device token from DSM (did); skip OTP on all future logins |
note | No | Optional description for your reference |
*Either host or url is required per NAS entry.
Notes:
- The server will use port 5001 (HTTPS) if port is 5001, otherwise defaults to HTTP (5000)
- The
host/portform always appends a port and derives the scheme from it, so it cannot expresshttps://nas.example.comon the default 443 โ seturldirectly for reverse-proxied setups - File permissions:
chmod 600 ~/.config/synology-mcp/settings.jsonis required for security - The server will refuse to load settings if permissions are too open
- Both .env and settings.json can be used together (settings.json takes priority)
โ ๏ธ Security Recommendations
settings.json File Permissions:
- Linux/macOS (POSIX):
chmod 600 ~/.config/synology-mcp/settings.jsonis required. The server refuses to load the file if it is group- or world-readable/writable, or owned by another user. - Windows: Access control is enforced via NTFS ACLs, not POSIX mode bits. The server audits the file's security descriptor and refuses to load unless all three hold: (1) the owner SID matches the current user; (2) the DACL is present (a NULL DACL โ "everyone full access" โ is rejected); (3) no allow-ACE grants access to a principal outside the allowlist: the current user,
NT AUTHORITY\SYSTEM, andBUILTIN\Administrators. Any inheritedEveryone/BUILTIN\Users/Authenticated Usersgrant fails the check.-
Requires the optional
pywin32package:pip install pywin32. If pywin32 is not installed, the server fails closed and refuses to loadsettings.json. Operators who accept the risk of an unverified file can opt back in by settingSYNOLOGY_MCP_ALLOW_UNVERIFIED_WINDOWS_ACL=true. -
The server resolves the file via
XDG_CONFIG_HOME(defaultPath.home() / ".config"), so on Windows it lives at%USERPROFILE%\.config\synology-mcp\settings.jsonunlessXDG_CONFIG_HOMEis set. -
Lock down the file from an elevated PowerShell prompt (uses the same path the server loads):
# Resolve the path the SAME way the server does: $XDG_CONFIG_HOME if set, # otherwise %USERPROFILE%\.config. This honors the override documented above. $cfg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$env:USERPROFILE\.config" } $f = "$cfg\synology-mcp\settings.json" # The server's ACL audit requires: owner == current user, no NULL DACL, and # no allow-ACE outside {current user, SYSTEM, Administrators}. The steps # below enforce all three. # # Use the *<SID> form for every built-in principal: account names like # "Administrators" / "Everyone" / "Users" are localized on non-English # Windows (e.g. German "Administratoren") and won't resolve. The # locale-independent SIDs: # *S-1-1-0 Everyone # *S-1-5-11 Authenticated Users # *S-1-5-32-545 BUILTIN\Users # *S-1-5-32-544 BUILTIN\Administrators # # 1. Ensure the file is owned by the current user (the audit rejects any # other owner). /setowner requires elevation. icacls $f /setowner "${env:USERNAME}" # 2. Drop inherited ACEs, then revoke the common foreign grants. /grant:r # only replaces the named principal, so revoke first. icacls $f /inheritance:r icacls $f /remove:g "*S-1-1-0" "*S-1-5-11" "*S-1-5-32-545" # Re-run `icacls $f` here; if any principal other than your user or # Administrators still appears, run: icacls $f /remove:g "<that principal>" # 3. Grant the current user and Administrators full control. icacls $f /grant:r "${env:USERNAME}:(F)" icacls $f /grant:r "*S-1-5-32-544:(F)" # BUILTIN\Administrators (locale-independent)If the file is brand new, the
/remove:gstep is a harmless no-op. -
Verify:
icacls "$f"โ only your user and*S-1-5-32-544(Administrators) should appear.
-
SSL Certificate Verification (VERIFY_SSL):
- Default is
falseto support self-signed certificates on internal NAS devices - If your NAS has a valid SSL certificate (e.g., from Let's Encrypt or a corporate CA), set
VERIFY_SSL=true - Setting
VERIFY_SSL=falsedisables certificate verification and makes your connection vulnerable to man-in-the-middle (MITM) attacks - Never disable SSL verification on untrusted networks
Auto-Login (AUTO_LOGIN):
- Default is
truefor convenience with settings.json - Credentials are stored securely in
~/.config/synology-mcp/settings.jsonwith 0600 permissions - If you prefer manual login, set
AUTO_LOGIN=falseand use thesynology_logintool
2FA / OTP Accounts (optional):
The MCP server supports DSM accounts with 2FA enabled. There are two ways to use it:
-
One-shot OTP via
synology_logintool (interactive):{ "base_url": "https://nas.lan:5001", "username": "alice", "password": "โฆ", "otp_code": "123456" }DSM will return a
did(device token) in the response โ copy that value intosettings.json(below) to skip OTP on future process restarts. -
Persistent trusted-device token (recommended for
AUTO_LOGIN=true):Add
otp_code(one-shot, first login only) and/ordevice_id(long-lived, ongoing) fields per-NAS insettings.json:{ "synology": { "nas1": { "host": "192.168.1.100", "port": 5001, "username": "alice", "password": "โฆ", "otp_code": "123456", "note": "primary โ 2FA enabled" } } }Workflow:
- Set
otp_codeto a fresh 6-digit code from your authenticator and start the server. - On the first successful login, the server logs a warning line like:
nas1: 2FA bootstrap โ copy this device_id into settings.json to skip OTP on future starts: <did>Copy the<did>value. - Paste it into
device_idand deleteotp_code. - From now on, DSM treats this process as a trusted device โ restarts, relogins after DSM error 119, and container-manager sessions all skip OTP.
When
device_idis present, it takes precedence overotp_code(trusted-device path). Legacy.envusers can set the one-shotSYNOLOGY_OTP_CODEenv var; for persistentdevice_id, migrate tosettings.json(long opaque token doesn't fit an env var cleanly). - Set
๐ Usage Examples
๐ File Operations
โ Creating Files and Directories

// List directory
{
"path": "/volume1/homes"
}
// Search for PDFs
{
"path": "/volume1/documents",
"pattern": "*.pdf"
}
// Create new file
{
"path": "/volume1/documents/notes.txt",
"content": "My important notes\nLine 2 of notes",
"overwrite": false
}
๐๏ธ Deleting Files and Directories

// Delete file or directory (auto-detects type)
{
"path": "/volume1/temp/old-file.txt"
}
// Move file
{
"source_path": "/volume1/temp/file.txt",
"destination_path": "/volume1/archive/file.txt"
}
โฌ๏ธ Download Management
๐ ๏ธ Creating a Download Task

// Create download task
{
"uri": "https://example.com/file.zip",
"destination": "/volume1/downloads"
}
// Pause tasks
{
"task_ids": ["dbid_123", "dbid_456"]
}
๐ฆฆ Download Results

โจ Features
- โ
Unified Entry Point - Single
main.pysupports both stdio and WebSocket clients - โ
Environment Controlled - Switch modes via
ENABLE_XIAOZHIenvironment variable - โ Multi-Client Support - Simultaneous Claude/Cursor + Xiaozhi access
- โ Secure Authentication - RSA encrypted password transmission
- โ Session Management - Persistent sessions across multiple NAS devices
- โ Complete File Operations - Create, delete, list, search, rename, move files with detailed metadata
- โ Directory Management - Recursive directory operations with safety checks
- โ Download Station - Complete torrent and download management
- โ Docker Support - Easy containerized deployment
- โ Backward Compatible - Existing configurations work unchanged
- โ Error Handling - Comprehensive error reporting and recovery
๐๏ธ Architecture
File Structure
mcp-server-synology/
โโโ main.py # ๐ฏ Unified entry point
โโโ src/
โ โโโ mcp_server.py # Standard MCP server
โ โโโ multiclient_bridge.py # Multi-client bridge
โ โโโ auth/ # Authentication modules
โ โโโ filestation/ # File operations
โ โโโ downloadstation/ # Download management
โโโ docker-compose.yml # Single service, environment-controlled
โโโ Dockerfile
โโโ pyproject.toml # Dependencies (single source of truth)
โโโ .env # Configuration
Mode Selection
ENABLE_XIAOZHI=falseโmain.pyโmcp_server.py(stdio only)ENABLE_XIAOZHI=trueโmain.pyโmulticlient_bridge.pyโmcp_server.py(both clients)
Perfect for any workflow - from simple Claude/Cursor usage to advanced multi-client setups! ๐
Files in the repo
- .github
- assets
- skills
- src
- tests
- .dockerignore
- .gitignore
- CHANGELOG.md
- docker-compose.http.yml
- docker-compose.yml
- Dockerfile
- env.example
- LICENSE
- main.py
- pyproject.toml
- pytest.ini
- README.md
Discussion (0)
Ask about usage, or say what you built with itSign in to join the discussion.
No comments yet. Be the first to say what this is good for.
More connectors

Universal provider proxy for OpenAI Codex & Claude Code โ use any LLM (Claude, Gemini, Grok, DeepSeek, Ollamaโฆ) with Codex CLI, App, SDK, and Claude Code
Git-native persistent memory for AI coding agents. Implements Google OKF v0.2 with sub-300ยตs in-memory BM25 search, embedded MCP server, and progressive disclosure. Slashes token bloat by 80% with zero external databases or dependencies. Built in pure Go.
Local-first code intelligence graph for MCP and CLI. Builds a persistent map of your codebase so AI coding tools read only what matters, with benchmarked context reductions on reviews and large-repo workflows.
Stop your AI from making things up โ it proposes, deterministic tools decide, every claim checked against ground truth with evidence. Grounded facts and context survive resets. Reverse engineering is the proving ground. MCP server + CLI.
20 MB lightweight cross-platform database client for 90+ databases, including MySQL, PostgreSQL, SQLite, Redis, MongoDB, DuckDB, SQL Server, and Dameng. Built-in AI, MCP Server, CLI, desktop and Docker. | ่ฝป้็บง่ทจๅนณๅฐๆฐๆฎๅบ็ฎก็ๅทฅๅ ท๏ผๆฏๆ MySQLใPostgreSQLใSQLiteใRedisใMongoDBใ่พพๆขฆ็ญ 90+ ๆฐๆฎๅบ๏ผๆไพๆก้ข็ซฏใDockerใCLIใๅ ็ฝฎ AI ๅฉๆๅ MCP Serverใ