delete_file
Delete a file or empty directory from a server. Safe mode restricts deletion to /tmp and /var/tmp, protecting system directories.
Instructions
Delete a file or empty directory. This is a dangerous operation. In safe mode, only deletes in /tmp and /var/tmp are allowed. System directories are always protected.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| server | No | Server alias (e.g., 'pi1', 'web-server'). Uses default server if not specified. | |
| path | Yes | Absolute path to the file or directory to delete |
Implementation Reference
- src/tools/files.py:232-305 (handler)The `delete_file` async function that implements the delete file tool logic. It validates the path (non-empty, absolute), checks blocked system paths via `_is_path_blocked()`, enforces safe mode restrictions via `_is_safe_write_path()`, then calls `client.call('webmin', 'unlink_file', path)` to perform the actual deletion via the Webmin API. Returns success/failure with appropriate error codes.
async def delete_file( client: WebminClient, path: str, safe_mode: bool = True, ) -> ToolResult: """Delete a file or empty directory. This is a dangerous operation and is blocked in safe mode. Args: client: Authenticated WebminClient instance. path: Absolute path to the file/directory to delete. safe_mode: Whether safe mode is enabled. Returns: ToolResult with deletion status. """ if not path or not path.strip(): return ToolResult.fail( code="INVALID_ARGUMENT", message="File path cannot be empty", ) if not path.startswith("/"): return ToolResult.fail( code="INVALID_PATH", message="File path must be absolute (start with /)", ) # Check for blocked paths is_blocked, reason = _is_path_blocked(path) if is_blocked: return ToolResult.fail( code="PATH_BLOCKED", message=f"Cannot delete this path: {reason}", ) # In safe mode, only allow deletes in safe paths if safe_mode and not _is_safe_write_path(path): return ToolResult.fail( code="SAFETY_BLOCKED", message=f"Deleting '{path}' is blocked in safe mode. " "Only /tmp and /var/tmp are allowed. " "Disable safe mode (WEBMIN_SAFE_MODE=false) to delete elsewhere.", ) try: result = await client.call("webmin", "unlink_file", path) # Result is [success, error_message] success = result[0] == 1 if isinstance(result, list) else result == 1 return ToolResult.ok({ "action": "delete", "path": path, "success": success, }) except Exception as e: error_msg = str(e).lower() if "no such file" in error_msg or "does not exist" in error_msg: return ToolResult.fail( code="FILE_NOT_FOUND", message=f"File not found: {path}", ) if "permission denied" in error_msg: return ToolResult.fail( code="PERMISSION_DENIED", message=f"Permission denied deleting: {path}", ) return ToolResult.fail( code="DELETE_FILE_ERROR", message=f"Failed to delete '{path}': {e}", ) - src/server.py:666-684 (schema)Registration of the 'delete_file' MCP tool with its input schema (requires 'path' as a string). The description explains it can delete a file or empty directory, is blocked in safe mode for non-/tmp paths, and protects system directories.
Tool( name="delete_file", description=( "Delete a file or empty directory. This is a dangerous operation. " "In safe mode, only deletes in /tmp and /var/tmp are allowed. " "System directories are always protected." ), inputSchema={ "type": "object", "properties": { **SERVER_PARAM, "path": { "type": "string", "description": "Absolute path to the file or directory to delete", }, }, "required": ["path"], }, ), - src/server.py:1619-1630 (registration)The dispatch logic in `call_tool`/`dispatch_tool` that routes the 'delete_file' tool name to the `files.delete_file()` handler, passing the path argument and safe_mode flag.
if name == "delete_file": path = arguments.get("path") if not path: return ToolResult.fail( code="MISSING_ARGUMENT", message="Missing required argument: path", ) return await files.delete_file( client, path=path, safe_mode=config.safe_mode, ) - src/tools/files.py:56-80 (helper)`_is_path_blocked()` helper function that checks whether a path is in a blocked system directory (like /etc, /bin, /usr, etc.) or matches blocked file patterns (like .ssh, shadow, passwd, sudoers). Used by delete_file to prevent deletion of critical system files.
def _is_path_blocked(path: str) -> tuple[bool, str]: """Check if a path is blocked for write/delete operations. Args: path: The file path to check. Returns: Tuple of (is_blocked, reason). """ # Normalize the path normalized = os.path.normpath(path) # Check for blocked patterns in filename basename = os.path.basename(normalized) for pattern in BLOCKED_PATTERNS: if pattern in basename: return True, f"File pattern '{pattern}' is protected" # Check if path is in or under a blocked directory for blocked in BLOCKED_PATHS: if normalized == blocked or normalized.startswith(blocked + "/"): # Allow reads but block writes to these paths return True, f"Path '{blocked}' is a protected system directory" return False, "" - src/tools/files.py:83-96 (helper)`_is_safe_write_path()` helper function that checks if a path is within /tmp or /var/tmp, used by delete_file to enforce safe mode restrictions.
def _is_safe_write_path(path: str) -> bool: """Check if a path is in a safe write location. Args: path: The file path to check. Returns: True if the path is in a safe write location. """ normalized = os.path.normpath(path) for safe_path in SAFE_WRITE_PATHS: if normalized.startswith(safe_path + "/") or normalized == safe_path: return True return False