diff --git a/src/mcp_synology_filestation/tools/filestation.py b/src/mcp_synology_filestation/tools/filestation.py index 299f2a7..b746fc0 100644 --- a/src/mcp_synology_filestation/tools/filestation.py +++ b/src/mcp_synology_filestation/tools/filestation.py @@ -106,10 +106,7 @@ def register_filestation( @mcp.tool() async def list_shares(): - """List all shared folders visible to the authenticated user. - - Returns a formatted table with share name, path, and volume status. - """ + """List all shared folders. Returns name/path/volume-usage table.""" from mcp_synology_filestation.client import SynologyError try: @@ -164,23 +161,8 @@ def register_filestation( sort_by: str = "name", sort_direction: str = "asc", ): - """List the contents of a directory on the NAS. - - Use share paths as returned by list_shares (e.g. "/dev", "/data"), - not volume paths (e.g. "/volume1/dev" will not work). - - Args: - path: Share-relative path on the NAS (e.g. "/dev" or "/data/photos"). - offset: Number of items to skip (for pagination). - limit: Maximum items to return (1-500, default 100). - sort_by: Sort field — one of: name, size, user, group, mtime, atime, - crtime, posix, type. - sort_direction: "asc" or "desc". - - Returns: - Formatted table with name and type, plus the total item count - for pagination context. - """ + """List directory contents. path: share-relative (e.g. /docker). + offset/limit for pagination, sort_by/sort_direction for ordering.""" from mcp_synology_filestation.client import SynologyError # Validate inputs @@ -266,21 +248,8 @@ def register_filestation( recursive: bool = True, max_results: int = 200, ): - """Search for files matching a glob pattern within a directory. - - Starts an async DSM search task, polls until complete, then cleans up. - Use share paths as returned by list_shares (e.g. "/docker"). - - Args: - path: Root directory to search from (e.g. "/docker"). - pattern: Filename glob pattern (e.g. "*.yaml", "report*.pdf"). - recursive: Search subdirectories (default True). - max_results: Maximum number of matches to return (default 200, max 1000). - - Returns: - Formatted table with path, type, size, and modification time, - plus total match count. - """ + """Search files by glob pattern under path. pattern: e.g. "*.yaml". + recursive/max_results optional.""" from mcp_synology_filestation.client import SynologyError limit = max(1, min(max_results, 1000)) @@ -400,17 +369,8 @@ def register_filestation( @mcp.tool() async def download(path: str): - """Download a single file from the NAS and return its content as base64. - - Files larger than 10 MB are rejected — use SFTP or another method instead. - Use share paths as returned by list_shares (e.g. "/docker/app/config.yaml"). - - Args: - path: Absolute share-relative path to the file on the NAS. - - Returns: - JSON object with "filename", "size" (bytes), and "content_base64". - """ + """Download a file as base64 (max 10 MB). path: share-relative. + Returns JSON {filename, size, content_base64}.""" import base64 from mcp_synology_filestation.client import SynologyError @@ -439,19 +399,8 @@ def register_filestation( @mcp.tool() async def get_info(path: str): - """Get detailed metadata for one or more files or folders on the NAS. - - Accepts a single path or a comma-separated list of paths. - Use share paths as returned by list_shares (e.g. "/dev/file.txt"). - - Args: - path: One or more share-relative paths, comma-separated - (e.g. "/dev/notes.txt" or "/dev/notes.txt,/data/photo.jpg"). - - Returns: - Formatted table with type, size, owner, permissions, and timestamps - for each requested path. - """ + """Get metadata (type/size/owner/permissions/timestamps) for one or more paths. + path: comma-separated share-relative paths.""" from mcp_synology_filestation.client import SynologyError paths = [p.strip() for p in path.split(",") if p.strip()] @@ -540,22 +489,8 @@ def register_filestation( @mcp.tool() async def check_exist(path: str): - """Check whether one or more files or folders exist on the NAS. - - Accepts a single path or a comma-separated list of paths. - Use share paths as returned by list_shares (e.g. "/dev/file.txt"). - - Note: SYNO.FileStation.CheckExist returns error 400 on this firmware for all - parameter formats. This tool falls back to SYNO.FileStation.List::getinfo, which - returns an entry per path with name=None when the path does not exist. - - Args: - path: One or more share-relative paths, comma-separated - (e.g. "/dev/notes.txt" or "/dev/notes.txt,/data/photo.jpg"). - - Returns: - Formatted table with each path and whether it exists (Yes / No). - """ + """Check if one or more paths exist. path: comma-separated share-relative paths. + Returns Yes/No table.""" from mcp_synology_filestation.client import SynologyError paths = [p.strip() for p in path.split(",") if p.strip()] @@ -603,17 +538,8 @@ def register_filestation( name: str, create_parents: bool = False, ): - """Create a new folder on the NAS. - - Args: - path: Parent directory path (e.g. "/docker"). - name: New folder name — not a full path (e.g. "my-app"). - create_parents: Create missing intermediate parent directories - if True (default False). - - Returns: - Full path of the created folder, or an Error: message. - """ + """Create a folder. path: parent dir, name: folder name (not full path). + create_parents: make missing parents.""" from mcp_synology_filestation.client import SynologyError try: @@ -635,16 +561,8 @@ def register_filestation( @mcp.tool() async def rename(path: str, new_name: str): - """Rename a file or folder on the NAS. - - Args: - path: Absolute share-relative path to the item - (e.g. "/docker/old-name.yaml"). - new_name: New name — not a full path (e.g. "new-name.yaml"). - - Returns: - New absolute path after rename, or an Error: message. - """ + """Rename a file or folder. path: current share-relative path, + new_name: bare name only (not full path).""" from mcp_synology_filestation.client import SynologyError try: @@ -666,19 +584,8 @@ def register_filestation( @mcp.tool() async def copy(src: str, dst: str, overwrite: bool = False): - """Copy a file or folder to a new location on the NAS. - - WARNING: Set overwrite=True only when you intentionally want to replace - an existing item at the destination. - - Args: - src: Source absolute path (e.g. "/docker/app/compose.yaml"). - dst: Destination directory path (e.g. "/backup/docker"). - overwrite: Replace existing item at destination (default False). - - Returns: - Destination path on success, or an Error: message. - """ + """Copy src to dst directory. + WARNING: overwrite=True replaces existing items (default False).""" from mcp_synology_filestation.client import SynologyError try: @@ -711,19 +618,8 @@ def register_filestation( @mcp.tool() async def move(src: str, dst: str, overwrite: bool = False): - """Move a file or folder to a new location on the NAS. - - WARNING: Set overwrite=True only when you intentionally want to replace - an existing item at the destination. - - Args: - src: Source absolute path (e.g. "/docker/app/old-compose.yaml"). - dst: Destination directory path (e.g. "/backup/docker"). - overwrite: Replace existing item at destination (default False). - - Returns: - Destination path on success, or an Error: message. - """ + """Move src to dst directory. + WARNING: overwrite=True replaces existing items (default False).""" from mcp_synology_filestation.client import SynologyError try: @@ -756,20 +652,8 @@ def register_filestation( @mcp.tool() async def delete(path: str, confirmed: bool = False): - """Delete a file or folder on the NAS. - - WARNING: This operation is irreversible. Without confirmed=True, - returns only a preview — no changes are made. - - Args: - path: Absolute share-relative path to delete. - confirmed: Must be True to actually delete. Defaults to False - (preview only — no DSM call). - - Returns: - Preview message if confirmed=False; success or Error: message - if confirmed=True. - """ + """Delete a file or folder. IRREVERSIBLE. + confirmed=False (default) shows preview only; pass confirmed=True to actually delete.""" from mcp_synology_filestation.client import SynologyError if not confirmed: @@ -810,25 +694,8 @@ def register_filestation( format: str = "zip", password: str = "", ): - """Compress files or folders into an archive on the NAS. - - Creates a new archive asynchronously. Progress is polled until the operation - completes. Use share paths as returned by list_shares. - - Args: - paths: List of share-relative paths to include in the archive - (e.g. ["/data/report.pdf", "/data/photos"]). - dest_file_path: Full destination path including filename - (e.g. "/backup/archive.zip"). - level: Compression level — "store", "fastest", "fast", "normal", - "moderate" (default), or "maximum". - mode: Archive write mode — "add" (default), "update", or "refreshen". - format: Archive format — "zip" (default) or "7z". - password: Optional password to encrypt the archive (default: none). - - Returns: - Path of the created archive on success, or an Error: message. - """ + """Compress paths into an archive. dest_file_path: full path incl. filename. + level: store/fastest/fast/normal/moderate/maximum. format: zip/7z.""" from mcp_synology_filestation.client import SynologyError _valid_levels = {"store", "fastest", "fast", "normal", "moderate", "maximum"} @@ -880,26 +747,8 @@ def register_filestation( create_subfolder: bool = False, password: str = "", ): - """Extract an archive file to a destination folder on the NAS. - - Supports ZIP and 7z archives. Runs asynchronously; progress is polled - until the extraction completes. Use share paths as returned by list_shares. - - Args: - file_path: Share-relative path to the archive file - (e.g. "/backup/archive.zip"). - dest_folder_path: Destination folder for extracted contents - (e.g. "/data/extracted"). - overwrite: Replace existing files at the destination (default False). - keep_dir: Preserve the directory structure inside the archive - (default True). - create_subfolder: Create a subfolder named after the archive to hold - extracted contents (default False). - password: Password for encrypted archives (default: none). - - Returns: - Destination folder path on success, or an Error: message. - """ + """Extract a ZIP or 7z archive to dest_folder_path. + overwrite/keep_dir/create_subfolder/password optional.""" from mcp_synology_filestation.client import SynologyError try: @@ -940,21 +789,8 @@ def register_filestation( overwrite: bool = False, create_parents: bool = True, ): - """Upload a file to a directory on the NAS from base64-encoded content. - - WARNING: Set overwrite=True only when you intentionally want to replace - an existing file. - - Args: - path: Destination directory path on the NAS (e.g. "/docker/app"). - filename: Filename to create (e.g. "compose.yaml"). - content_base64: Base64-encoded file content. - overwrite: Replace existing file at destination (default False). - create_parents: Create missing parent directories (default True). - - Returns: - Full path of the uploaded file, or an Error: message. - """ + """Upload base64-encoded content as filename into path (max 50 MB). + WARNING: overwrite=True replaces existing file (default False).""" import base64 from mcp_synology_filestation.client import SynologyError