Skip to main content
Glama
nas-search-mcp

nas-search-mcp

by umayado17

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; setlang = 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:

pipx install nas-search-mcp      # installs nas-search-mcp and nas-search
uvx nas-search-mcp --version     # or run it with uvx, no install

Tell it where the NAS is, in ~/.config/unisearch/client.conf (or the environment variables UNISEARCH_HOST and UNISEARCH_KEY):

host=<ssh-user>@<nas-host>
key=~/.ssh/unisearch_agent
lang=en

Then register it in your MCP app. Claude Code:

claude mcp add nas-search -- uvx nas-search-mcp

Apps with a JSON config (Claude Desktop, Cursor and others):

{
  "mcpServers": {
    "nas-search": { "command": "uvx", "args": ["nas-search-mcp"] }
  }
}

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.

Tool

What it does

search

Search by file name and document text. Arguments: query, limit (1-100), offset, max_results (pages automatically, up to 1,000). Returns the JSON below

status

The search session: time left, allowed folders, number of searches, last error

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).

Related MCP server: synology-filestation-mcp

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. Two articles on Zenn (in Japanese) tell more: how it works and what was checked on a real NAS, and how it was built with three AI agents in five days.

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

AI agent ──ssh (search-only key)──▶ NAS: unisearch --agent-gateway
  nas-search                                │ (UNIX socket)
                                            ▼
                               search session (started by a person with OTP)
                                            │
                                            ▼
                               DSM Web API (127.0.0.1:5001)

File

Role

unisearch

Runs on the NAS. Interactive search, the search session, and the SSH entry point

clients/nas-search

Runs on the agent's machine. Builds the ssh call and returns the result

clients/nas-search-mcp

Offers the same search as MCP tools (search, status); runs nas-search inside

skills/nas-search/SKILL.md

Instructions for agents (Claude Code skill format)

scripts/remote-run.sh

Try the CLI without placing any file on the NAS

Before you start (on the NAS)

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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 namedunisearch. 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)

ssh -t <ssh-user>@<nas-host> '~/.local/bin/unisearch "test" --limit 5'
ssh -t <ssh-user>@<nas-host> '~/.local/bin/unisearch "test" --limit 20 --json'

You type the DSM user name, password and OTP in the terminal. Each run logs in and logs out.

2. From an AI agent

  1. 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.

  2. The agent calls nas-search "<query>" with its search-only SSH key. No password or OTP is needed.

nas-search "test" --limit 20
nas-search --status

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:

{"schema_version": 1, "query": "test", "offset": 0, "limit": 20, "total": null,
 "returned": 20, "next_offset": 20, "has_error": false, "unavailable": null,
 "hits": [{"name": "test.pdf", "share_path": "/archive/Drive/test.pdf",
           "path": "/volume1/archive/Drive/test.pdf", "extension": "pdf",
           "size": 12345, "is_dir": false, "modified": 1396685721,
           "modified_utc": "2014-04-05T08:15:21Z", "readable": true}]}
  • 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"}}.

Exit code

Meaning

0

Success (0 hits is possible)

1

Unexpected internal error (internal)

2

Usage or settings error (usage, config)

3

Login failed (auth, interactive search)

4

Search API error (api), or scan_limit (too many out-of-scope results; call again to continue)

5

Connection failed or no response in time (network on the NAS, ssh from nas-search)

6

Unexpected response format (response; the API may have changed)

7

No terminal for interactive input (no_tty)

8

No search session, or it has ended (session_required): ask a person to start one

9

A search session is already running (session_running), or the state folder is wrong (state)

130

Interrupted with Ctrl-C (interrupted)

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.

Where

File

Main settings

NAS

~/.config/unisearch/server.conf

Session length, keepalive, timeouts, language

Agent's machine

~/.config/unisearch/client.conf

Host, key, wait time, language

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.

python3 -m unittest discover -s tests -v

The steps for checking on a real NAS are in docs/nas-verification.md (Japanese).

See also

Changes and security

License

MIT

Available Tools

2 tools
statusNAS search session statusA
Read-onlyIdempotent

Show the NAS search session: expiry, time left (remaining_seconds), allowed folders, number of searches and the last error.

NameRequiredDescriptionDefault

No parameters

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description adds genuine value by enumerating the returned fields (expiry, remaining_seconds, folder scope, search count, last error), which matters because no output schema exists. It stops short of explaining what happens when a session has expired or is absent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with a colon-separated field list and zero filler; every element maps to something the agent actually needs to know.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no inputs, no output schema and rich annotations, the definition covers most of what an agent needs by describing the return payload. The remaining gap is lifecycle behavior, i.e. what an expired or missing session looks like in the response.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline is 4; there is nothing for the description to disambiguate and it correctly implies a no-argument call that reads the current session.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Show') and resource ('NAS search session'), then enumerates exactly what is reported: expiry, remaining_seconds, allowed folders, search count, last error. An agent can immediately tell this apart from the 'search' sibling since this reads session state rather than executing a search, though the description never names that sibling explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the mention of expiry and remaining_seconds hints that this is a precondition/health check for a search session, but the description never says when to call it (before searching? after a failure?) nor explicitly points to 'search' as the follow-up action.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updatesv0.1.0
    • First observedsearch
    • First observedstatus

TDQS

A4.1/5.0

Scored across 2 tools

Disambiguation5/5

The two tools serve entirely different purposes: 'search' performs content/name queries over the NAS, while 'status' only reports session metadata (expiry, folders, counters, last error). There is no realistic scenario where an agent would confuse the two, and the descriptions reinforce the distinction.

Naming Consistency4/5

Both names are single, lowercase, underscore-free tokens with no prefix clutter, so the style is consistent. The only minor deviation is grammatical: 'search' is a verb while 'status' is a noun, which slightly breaks a verb_noun prediction but remains perfectly readable.

Tool Count3/5

Two tools is thin even for a search-only server; the surface is essentially one operation plus a diagnostics call. The narrow purpose prevents it being a mismatch, but there is little headroom for anything beyond querying and checking state.

Completeness3/5

Search covers paging (offset/next_offset), sizing, and a detailed error taxonomy, which is solid for the core workflow. However, there is no way to browse a share or folder hierarchy, inspect a single file's details, or start/refresh the search session — a missing-session error (exit_code 8) leaves the agent with only 'ask the user', a dead end.

Maintenance

ActivityMaintained
ResponsivenessNo recent community issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    D
    maintenance
    MCP server enabling AI agents to manage and monitor Synology NAS via official DSM API, including file operations, system stats, backups, downloads, and camera lists.
    15
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to manage files on Synology NAS via the File Station API, supporting operations like browsing, searching, uploading/downloading, creating, renaming, copying, moving, deleting, compressing, and extracting.
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables self-hosted access to Synology NAS files, system monitoring, container management, and download tasks through MCP clients, with optional connectivity to ChatGPT via a secure tunnel.
    3
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to inspect and operate a UGOS Pro NAS through its built-in HTTPS API via 25 tools covering system stats, storage volumes, files, downloads, photos, and media libraries, without SSH. Read-only tools run directly, write tools prompt for confirmation, destructive deletes require an explicit second confirmation, and it can be deployed either locally over stdio or on the NAS via Docker SSE.
    2
    MIT