Skip to main content
Glama
gjenkins20

webmin-mcp-server

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

TableJSON Schema
NameRequiredDescriptionDefault
serverNoServer alias (e.g., 'pi1', 'web-server'). Uses default server if not specified.
pathYesAbsolute path to the file or directory to delete

Implementation Reference

  • 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}",
            )
  • 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"],
        },
    ),
  • 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,
        )
  • `_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, ""
  • `_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
Behavior4/5

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

Without any annotations, the description effectively discloses the destructive nature, safe mode constraints, and protection of system directories. It does not specify error behavior for non-empty directories or required permissions, but the critical behavioral traits are covered.

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?

The description is extremely concise at three sentences with no redundant information. It front-loads the core action and then adds necessary safety warnings, making it easy for an AI agent to parse quickly.

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?

The description covers the tool's purpose and key safety contexts, but does not explain return values (no output schema) or error handling. It is sufficient for a straightforward destructive operation given the schema provides parameter details.

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

Parameters3/5

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

The input schema already provides descriptions for both parameters (server and path) with 100% coverage. The description adds no new semantic meaning beyond restating the tool's purpose, so it does not enhance parameter understanding beyond the schema baseline.

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

Purpose5/5

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

The description clearly states the tool deletes a file or empty directory, using a specific verb and resource. It distinguishes itself from sibling tools like read_file, rename_file, and copy_file by indicating a destructive operation, though it does not explicitly differentiate from other deletion tools like delete_user (which target different entities).

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

Usage Guidelines4/5

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

The description provides explicit usage context by warning that the operation is dangerous and specifying safe mode restrictions (only /tmp, /var/tmp) and that system directories are always protected. However, it does not advise when not to use the tool (e.g., for non-empty directories) or mention alternatives, leaving some ambiguity.

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

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/gjenkins20/webmin-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server