synology-search-agent
English | 日本語
Let AI agents search your Synology NAS. An MCP server and CLI that searches the existing Universal Search index (file names and full text) of a Synology NAS over SSH and returns JSON.
- MCP server or CLI.
nas-search-mcp offers search and status as MCP tools for MCP apps; nas-search is the same search as a command.
- No sudo, no root. It runs as a normal DSM user.
- Two-factor authentication (OTP) stays on. It never turns it off.
- Read-only. It never changes files, the index or shared folders.
- Runs on the Python 3.8+ standard library only (no extra packages).
[Demo: asked in English for the files of the "Kamome project", an AI agent searches with nas-search for the Japanese name, and lists five files newest first, three of them matched by their text (fictional data)]
[!WARNING]
This tool uses a Web API that Synology does not publish (SYNO.Finder.FileIndexing.Search). A DSM update may break it without notice. This is an unofficial tool and is not affiliated with Synology. Synology, DSM and Universal Search are trademarks of Synology Inc.
[!NOTE]
Messages printed by the commands are in Japanese by default; set lang = en (or UNISEARCH_LANG=en) for English (see Settings files). The detailed documents under docs/ are in Japanese, but their commands can be used as they are. Agents should rely on the JSON fields (error.type) and exit codes, which are stable and documented below.
Use it as an MCP server
On the machine where the AI agent runs (macOS or Linux, Python 3.8+), install the package from PyPI, or run it without installing through uv:
Tell it where the NAS is, in ~/.config/unisearch/client.conf (or the environment variables UNISEARCH_HOST and UNISEARCH_KEY):
Then register it in your MCP app. Claude Code:
Apps with a JSON config (Claude Desktop, Cursor and others):
Desktop apps may not see your shell's PATH. If the app cannot start it, write the full path of uvx (from which uvx) as command.
If uvx fails with invalid peer certificate: UnknownIssuer (common on networks that inspect HTTPS, such as office networks), add --system-certs so it uses the certificates your OS trusts: "args": ["--system-certs", "nas-search-mcp"], or uvx --system-certs nas-search-mcp.
Both are read-only. The server only starts nas-search and passes its JSON on; it sends long searches' progress when the app asks for it, and stops a search when the app cancels it.
The MCP server is the agent's side only. The NAS needs a one-time setup (Before you start and docs/agent-setup.md): place unisearch on the NAS, give the agent a search-only SSH key, and have a person start a search session with the DSM password and OTP. Without a session, the tools return exit code 8 (session_required).
Why
find and grep walk the files on every search. A file-name search can be fast enough, but a full-text search over a large share is not practical. Synology Universal Search already keeps an index that includes file contents, but there is no public way to use it from a program.
This tool does not build a new index. It lets an AI agent use the Universal Search index that already exists. The agent gets only short candidates (name, path, size, date) and opens only the files it needs. It hands the agent the ability to search, and nothing else: no root, no sudo, no shell.
The idea that this API can be called came from atkaper/synology-universal-search-cli (2021). No code from that project is used here (it has no license); only the fact that the API exists and can be called.
The background story (in Japanese) is in docs/background.md.
Tested environment
- Synology DS225+, DSM 7.4.1 (build 90080), Python 3.8.15 on the NAS
- Status: beta. A search session was checked to keep working for about 25 hours (not yet to the end of 90 days). Other models and DSM versions are not verified yet
- What was checked on the device: docs/verification.md (Japanese)
On other models and DSM versions, run --check-api first to see whether the API is there.
How it fits together
Before you start (on the NAS)
-
Make the NAS reachable from the agent over SSH. The author uses Tailscale and does not expose the NAS to the internet. The tool itself does not need Tailscale; any SSH path works. Do not expose the NAS's SSH port to the internet.
-
Check the API. After placing the CLI on the NAS (step 1 of docs/agent-setup.md), run ~/.local/bin/unisearch --check-api on the NAS. No login is needed. It returns "ok": true when the needed APIs exist in a supported version. It does not check the contents of the index or whether a search works.
-
Check Universal Search (if --check-api fails). On DSM 7, Universal Search is normally preinstalled as a built-in package that cannot be removed from Package Center. Synology does not officially state that it is present on every model, though. Look for "Universal Search" in Package Center → Installed and make sure it is running. If it is missing, install it from Package Center.
-
Choose the shared folders to index. In Universal Search, open settings (gear icon, top right) → File Indexing → Indexed Folder List, and add the folders you want to search. If you add none, no index is built and searches return nothing. Synology's help says files in folders that are not indexed do not appear in results, and that folders used through File Station or SMB must be added by hand (File Indexing). To search inside documents, choose "File content indexing".
[Universal Search settings in a Japanese DSM, with English labels added: the File Indexing tab shows the indexed folders and the status "Finished"]
The screenshot is from a Japanese DSM; the yellow English labels were added. The text in the middle says that the folders in Indexed Folder List are indexed for Universal Search and File Station, and that Check Index Database scans the index when search results look wrong.
-
Create a search-only DSM account. Not an administrator, with two-factor authentication, and with read access only to the shared folders you want searched. Be careful with homes: if the account can read it, every user's home folder shows up in results.
-
Try a search. Use the interactive search in Usage step 1 and check that files in the indexed folders are found.
A result of 0 hits in a folder that is not indexed does not mean the file is not there. External USB/SD drives, remote folders and cloud folders are not searched by Universal Search (Universal Search).
[!NOTE]
Universal Search 2.0 (June 2026) is currently available only on some high-end models (Release Notes). This tool has not been tested with 2.0.
[!NOTE]
The command is named unisearch. Up to v0.6 it was synosearch, which clashed with DSM's own /usr/syno/bin/synosearch (an unrelated help-search command), so it was renamed.
Usage
1. Interactive search (for people)
You type the DSM user name, password and OTP in the terminal. Each run logs in and logs out.
2. From an AI agent
- A person starts a search session on the NAS and types the password and OTP. The session lasts 8 hours by default (1 minute to 90 days). When it ends, a person starts it again. DSM kept the login alive for about 25 hours in our test; longer periods are not verified yet.
- The agent calls
nas-search "<query>" with its search-only SSH key. No password or OTP is needed.
For MCP apps, see Use it as an MCP server. Without PyPI, copy clients/nas-search and clients/nas-search-mcp into the same folder and start the server with python3 <folder>/nas-search-mcp.
Setup steps are in docs/agent-setup.md (Japanese; the commands in it can be used as they are).
Output
One JSON line on stdout:
total is always null when results are limited to allowed folders, so the number of out-of-scope hits is never revealed. Use next_offset (not null) to tell whether more results exist.
- Pages are consistent while the index does not change. If files are added or removed between pages, a page can repeat or skip results (on the device, deleting files shown on an earlier page skipped the same number of later results). Deduplicate by
share_path.
Errors are one JSON line on stderr: {"error": {"type", "message", "exit_code"}}.
The full specification (options, fields, exit codes, settings) is in docs/cli-spec.md (Japanese).
Security design
- Passwords, OTPs and SIDs are never written to files or logs. The SID lives only in the memory of the search session.
- Only the owner can talk to the search session: a UNIX socket with mode 0600.
- The agent's key is limited by
restrict,command= in authorized_keys. It can only search: no shell, no port forwarding.
- The search scope is limited twice. The main guard is DSM's shared-folder permissions; the CLI's
--allow-prefix is a second layer. When results are limited, the out-of-scope count is not shown.
- Use a search-only DSM account (not an administrator, with two-factor authentication).
The design discussion (Japanese) is in docs/design-noninteractive-auth.md.
Settings files
Timing values can be changed in settings files. Order of precedence: command-line options > settings file > defaults. Safety limits (for example, a session lasts at most 90 days) are fixed in the code. Passwords, OTPs and SIDs cannot be written in settings files.
For English messages, write lang = en in both files (on the agent's machine, UNISEARCH_LANG=en also works). Messages from a search session that is already running stay in the language it started with. JSON keys, error.type and exit codes are the same in every language.
[!NOTE]
TLS certificate checks are skipped only because the target is the NAS itself (127.0.0.1). Do not point it at a remote URL.
Tests
The tests use only the standard library and do not need a NAS.
The steps for checking on a real NAS are in docs/nas-verification.md (Japanese).
See also
Changes and security
License
MIT