{
  "markdown": "<p align=\"center\">\n  <picture>\n    <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/cmeans/mcp-synology/main/src/mcp_synology/icons/mcp-synology-logo-dark.svg\" width=\"128\">\n    <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/cmeans/mcp-synology/main/src/mcp_synology/icons/mcp-synology-logo-light.svg\" width=\"128\">\n    <img src=\"https://raw.githubusercontent.com/cmeans/mcp-synology/main/src/mcp_synology/icons/mcp-synology-logo-light.svg\" alt=\"mcp-synology logo\" width=\"128\">\n  </picture>\n</p>\n\n# mcp-synology\n\n[![PyPI version](https://img.shields.io/pypi/v/mcp-synology)](https://pypi.org/project/mcp-synology/)\n[![Python versions](https://img.shields.io/pypi/pyversions/mcp-synology)](https://pypi.org/project/mcp-synology/)\n[![License](https://img.shields.io/pypi/l/mcp-synology)](https://github.com/cmeans/mcp-synology/blob/main/LICENSE)\n[![Tests](https://img.shields.io/github/actions/workflow/status/cmeans/mcp-synology/ci.yml?label=tests)](https://github.com/cmeans/mcp-synology/actions/workflows/ci.yml)\n[![Coverage](https://codecov.io/gh/cmeans/mcp-synology/graph/badge.svg)](https://codecov.io/gh/cmeans/mcp-synology)\n[![Downloads](https://img.shields.io/endpoint?url=https%3A%2F%2Fpypi-badges.intfar.com%2Fmcp-synology%2Fdownloads-30d-non-ci.json)](https://github.com/cmeans/pypi-winnow-downloads)\n\n[![pip downloads](https://img.shields.io/endpoint?url=https%3A%2F%2Fpypi-badges.intfar.com%2Fmcp-synology%2Finstaller-pip-30d-non-ci.json)](https://github.com/cmeans/pypi-winnow-downloads)\n[![pipenv downloads](https://img.shields.io/endpoint?url=https%3A%2F%2Fpypi-badges.intfar.com%2Fmcp-synology%2Finstaller-pipenv-30d-non-ci.json)](https://github.com/cmeans/pypi-winnow-downloads)\n[![pipx downloads](https://img.shields.io/endpoint?url=https%3A%2F%2Fpypi-badges.intfar.com%2Fmcp-synology%2Finstaller-pipx-30d-non-ci.json)](https://github.com/cmeans/pypi-winnow-downloads)\n[![uv downloads](https://img.shields.io/endpoint?url=https%3A%2F%2Fpypi-badges.intfar.com%2Fmcp-synology%2Finstaller-uv-30d-non-ci.json)](https://github.com/cmeans/pypi-winnow-downloads)\n[![poetry downloads](https://img.shields.io/endpoint?url=https%3A%2F%2Fpypi-badges.intfar.com%2Fmcp-synology%2Finstaller-poetry-30d-non-ci.json)](https://github.com/cmeans/pypi-winnow-downloads)\n[![pdm downloads](https://img.shields.io/endpoint?url=https%3A%2F%2Fpypi-badges.intfar.com%2Fmcp-synology%2Finstaller-pdm-30d-non-ci.json)](https://github.com/cmeans/pypi-winnow-downloads)\n\n[![linux downloads](https://img.shields.io/endpoint?url=https%3A%2F%2Fpypi-badges.intfar.com%2Fmcp-synology%2Fos-linux-30d-non-ci.json)](https://github.com/cmeans/pypi-winnow-downloads)\n[![macos downloads](https://img.shields.io/endpoint?url=https%3A%2F%2Fpypi-badges.intfar.com%2Fmcp-synology%2Fos-macos-30d-non-ci.json)](https://github.com/cmeans/pypi-winnow-downloads)\n[![windows downloads](https://img.shields.io/endpoint?url=https%3A%2F%2Fpypi-badges.intfar.com%2Fmcp-synology%2Fos-windows-30d-non-ci.json)](https://github.com/cmeans/pypi-winnow-downloads)\n\nMCP server for Synology NAS devices. Exposes Synology DSM API functionality as MCP tools that Claude can use.\n\n<!-- mcp-name: io.github.cmeans/mcp-synology -->\n\n## Migrating from synology-mcp\n\nIf you're upgrading from `synology-mcp` (v0.3.x or earlier), the package has been renamed. A migration script handles config, state, keyring entries, and Claude Desktop config automatically:\n\n```bash\n# Download and run the migration script\ncurl -O https://raw.githubusercontent.com/cmeans/mcp-synology/main/scripts/migrate-from-synology-mcp.py\npython migrate-from-synology-mcp.py          # dry run — preview changes\npython migrate-from-synology-mcp.py --apply  # apply changes\n```\n\nThe script migrates:\n- Config directory (`~/.config/synology-mcp/` → `~/.config/mcp-synology/`)\n- State directory (`~/.local/state/synology-mcp/` → `~/.local/state/mcp-synology/`)\n- Keyring credentials\n- Claude Desktop `claude_desktop_config.json` (updates command and paths)\n\nSee [CHANGELOG.md](CHANGELOG.md) for full details on breaking changes.\n\n## Supported Modules\n\n### File Station\n\nBrowse, search, transfer, and manage files on your NAS. 14 tools across two permission tiers:\n\n- **READ** — list_shares, list_files, list_recycle_bin, search_files, get_file_info, get_dir_size, download_file\n- **WRITE** — create_folder, rename, copy_files, move_files, delete_files, restore_from_recycle_bin, upload_file\n\n### System\n\nMonitor NAS health and resource utilization. 2 read-only tools:\n\n- **get_system_info** — model, firmware version, RAM, temperature, uptime (works for all users)\n- **get_resource_usage** — live CPU load, memory usage, disk I/O, network throughput (requires admin account)\n\n## Features\n\n- **Interactive setup** — guided configuration that creates your config, stores credentials, handles 2FA, and emits a Claude Desktop snippet\n- **Permission tiers** — READ or WRITE per module, enforced at tool registration\n- **2FA support** — auto-detected; device token bootstrap with automatic silent re-auth\n- **Secure credentials** — OS keyring integration that works transparently on macOS, Windows, and Linux (including from Claude Desktop). See [docs/credentials.md](docs/credentials.md).\n- **Multi-NAS** — manage multiple NAS devices with separate configs, credentials, and state\n\n## Quick Start\n\n### 1. Run setup\n\n```bash\nuvx mcp-synology setup\n```\n\nRequires [uv](https://docs.astral.sh/uv/). `uvx` downloads and runs the latest version automatically — no separate install step needed.\n\nSetup will prompt for your NAS host, credentials, and preferences. If your account has 2FA enabled, it will prompt for an OTP code and store a device token for automatic future logins.\n\nAt the end, it prints a Claude Desktop JSON snippet ready to copy-paste.\n\n### 2. Add to Claude Desktop\n\nCopy the snippet from setup into your `claude_desktop_config.json` and restart Claude Desktop. It will look something like:\n\n```json\n{\n  \"mcpServers\": {\n    \"synology-nas\": {\n      \"command\": \"uvx\",\n      \"args\": [\"mcp-synology\", \"serve\", \"--config\", \"~/.config/mcp-synology/nas.yaml\"]\n    }\n  }\n}\n```\n\nThe config file name (e.g., `nas.yaml`) also serves as a natural identifier for the connection — you can name it to match your NAS (e.g., `home-nas.yaml`, `office-nas.yaml`).\n\nOn Linux, the server auto-detects the D-Bus session socket for keyring access. If auto-detection fails, add `\"env\": {\"DBUS_SESSION_BUS_ADDRESS\": \"unix:path=/run/user/<uid>/bus\"}` to the Claude Desktop config. The setup command includes this in the generated snippet.\n\n### 3. Verify\n\n```bash\nuvx mcp-synology check                # Validates credentials work\nuvx mcp-synology setup --list         # Shows all configured NAS instances\n```\n\n### Alternative: global install\n\nIf you prefer a persistent install (avoids download on each invocation). Requires [uv](https://docs.astral.sh/uv/getting-started/installation/) — install with `curl -LsSf https://astral.sh/uv/install.sh | sh` (macOS/Linux) or see the [installation guide](https://docs.astral.sh/uv/getting-started/installation/) for other options.\n\n```bash\nuv tool install mcp-synology\nmcp-synology setup\nmcp-synology check\n```\n\n### Alternative: env-var-only mode\n\nNo config file needed if `SYNOLOGY_HOST` is set. This is useful for Docker or CI environments:\n\n```json\n{\n  \"mcpServers\": {\n    \"synology\": {\n      \"command\": \"uvx\",\n      \"args\": [\"mcp-synology\", \"serve\"],\n      \"env\": {\n        \"SYNOLOGY_HOST\": \"192.168.1.100\",\n        \"SYNOLOGY_USERNAME\": \"your_user\",\n        \"SYNOLOGY_PASSWORD\": \"your_password\"\n      }\n    }\n  }\n}\n```\n\nOr from the CLI:\n\n```bash\nSYNOLOGY_HOST=192.168.1.100 uvx mcp-synology check\n```\n\n## 2FA Support\n\nmcp-synology fully supports DSM accounts with two-factor authentication. It's auto-detected — you don't need to configure anything special:\n\n1. **Bootstrap** — `mcp-synology setup` detects 2FA, prompts for your OTP code, and stores a device token in the keyring\n2. **Silent re-auth** — subsequent logins use the device token automatically (no OTP prompts)\n3. **Per-instance** — each NAS config gets its own device token, so mixed 2FA/non-2FA setups work fine\n\nDevice tokens persist until you explicitly revoke them in DSM (Personal > Security > Sign-in Activity). They do not expire on their own. If a token is revoked, run `mcp-synology setup` again to re-bootstrap.\n\n## Keyring & Credentials\n\nCredentials are stored in the OS keyring and accessed transparently:\n\n| Platform | Backend | Notes |\n|----------|---------|-------|\n| macOS | Keychain | Just works |\n| Windows | Credential Manager | Just works |\n| Linux | GNOME Keyring / KWallet | Auto-detects D-Bus session, works from Claude Desktop |\n\nCredential resolution order: **env vars > config file > keyring**. Explicit sources override the implicit default.\n\nFor environments without a keyring (Docker, CI), use environment variables or inline credentials in the config file.\n\nSee [docs/credentials.md](docs/credentials.md) for keyring service names, multi-NAS setup, and how to inspect/remove stored credentials.\n\n## Updates\n\nmcp-synology checks for updates and notifies you in your Claude Desktop conversation — the first tool response in each session will include a notice if a newer version is available on PyPI.\n\nTo manage updates from the CLI:\n\n```bash\nmcp-synology --check-update                 # Check for a newer version\nmcp-synology --auto-upgrade enable           # Auto-upgrade on each interactive run\nmcp-synology --revert                        # Roll back to previous version\nmcp-synology --revert 0.1.0                  # Roll back to a specific version\n```\n\nTo disable update notifications, add to your config (top level):\n\n```yaml\n# ~/.config/mcp-synology/config.yaml\ncheck_for_updates: false\n```\n\n## Configuration\n\nInteractive setup creates a config file for you. For manual configuration or advanced options, see `examples/`:\n- `config-minimal.yaml` — simplest possible config\n- `config-power-user.yaml` — HTTPS, custom timeouts, logging, instructions\n- `config-docker.yaml` — environment-variable-driven\n\n### Multi-NAS\n\nEach NAS gets its own config file, credentials, and Claude Desktop entry. The config file name serves as a natural identifier (e.g., `home-nas.yaml`, `media-server.yaml`).\n\nSet `alias` to give Claude a display name for the connection:\n\n```yaml\n# ~/.config/mcp-synology/home-nas.yaml\nalias: HomeNAS\n```\n\nThe alias appears in the MCP server name (e.g., `synology-HomeNAS`) so Claude knows which NAS it's talking to.\n\n### Custom Instructions\n\nCustom instructions let you shape how Claude interacts with your NAS tools. This is useful when:\n\n- **Multiple NAS connections** — tell Claude which connection to prefer for different tasks (\"use this for media, use admin for cross-user operations\")\n- **Safety guardrails** — add rules like \"always confirm before deleting\" or \"never touch /Backups\"\n- **Context** — explain what's on the NAS (\"this is a media server, /video has our library sorted by genre\")\n\n**Add context** — `custom_instructions` is prepended to the built-in prompt (higher priority):\n\n```yaml\n# ~/.config/mcp-synology/config.yaml\ncustom_instructions: |\n  This is the admin NAS with elevated privileges.\n  Prefer this connection for file operations requiring cross-user access.\n  Never delete files from /Backups without explicit confirmation.\n```\n\n**Full control** — `instructions_file` replaces the built-in prompt entirely. Copy the [built-in server.md](src/mcp_synology/instructions/server.md) as a starting point:\n\n```yaml\n# ~/.config/mcp-synology/config.yaml\ninstructions_file: ~/.config/mcp-synology/my-instructions.md\n```\n\nBoth support template variables: `{display_name}`, `{instance_id}`, `{host}`, `{port}`.\n\n## Debugging\n\nTwo ways to enable debug logging:\n\n```bash\nmcp-synology check --verbose                          # --verbose flag on setup/check\nSYNOLOGY_LOG_LEVEL=debug mcp-synology serve           # env var, works for all commands\n```\n\nOr set it persistently in your config file:\n\n```yaml\n# ~/.config/mcp-synology/config.yaml\nlogging:\n  level: debug\n  file: ~/.local/state/mcp-synology/nas/server.log  # optional, logs to stderr by default\n```\n\nDebug output includes every DSM API request/response (passwords masked), credential resolution steps, config discovery, version negotiation, and module registration decisions.\n\n## Contributing\n\nSee [DEVELOPMENT.md](DEVELOPMENT.md) for build commands, testing, integration test setup, and design docs.\n\n## Acknowledgements\n\nThis project was built using a **Spec-First Coding** approach — a human-AI collaboration model where design precedes implementation and specs are the contract between the two.\n\nUnlike vibe coding, where you describe what you want and let the AI generate code on the fly, spec-first coding treats design as a separate, deliberate phase. The four specs in `docs/specs/` were developed through extended conversation — exploring trade-offs, rejecting alternatives, and documenting decisions with rationale. Implementation then used the specs as the source of truth across 11 build phases.\n\nLive testing against real hardware revealed behaviors the specs couldn't anticipate (DSM API quirks, search service throttling, version format incompatibilities). These discoveries are documented in `CLAUDE.md` and the code, which is authoritative where specs diverge.\n\n## License\n\n[Apache 2.0](LICENSE)\n\n---\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/cmeans/mcp-synology/main/src/mcp_synology/icons/mcp-synology-logo-dark.svg\" width=\"24\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/cmeans/mcp-synology/main/src/mcp_synology/icons/mcp-synology-logo-light.svg\" width=\"24\">\n  <img src=\"https://raw.githubusercontent.com/cmeans/mcp-synology/main/src/mcp_synology/icons/mcp-synology-logo-light.svg\" alt=\"\" width=\"24\" align=\"top\">\n</picture> © 2026 Chris Means\n",
  "bytes": 13983,
  "sha": "0749fd88ec1f315189a6b2b92509fba85c280723f2aea659561641bdda72e4a4",
  "repo_slug": "cmeans/mcp-synology",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_cmeans_mcp_synology_9a2f6755/readme"
}