LinuxAgent MCP Commands

November 12, 2025 · View on GitHub

LinuxAgent interacts with Linux systems through MCP (Model Context Protocol) tools provided by the Linux MCP Server. These tools provide atomic building blocks for CLI task execution, isolating system-specific operations within the MCP server layer.

Command Architecture

MCP Server Integration

LinuxAgent commands are executed through the MCP server infrastructure:

graph LR
    A[LinuxAgent] --> B[Command Dispatcher]
    B --> C[MCP Server]
    C --> D[Linux Shell]
    D --> E[stdout/stderr]
    E --> C
    C --> B
    B --> A

Command Dispatcher

The command dispatcher routes commands to the appropriate MCP server:

from aip.messages import Command

# Create command
command = Command(
    tool_name="execute_command",
    parameters={"command": "df -h", "timeout": 30},
    tool_type="action"
)

# Execute command via dispatcher
results = await command_dispatcher.execute_commands([command])
execution_result = results[0].result

Primary MCP Tools

1. execute_command - Execute Shell Commands

Purpose: Execute arbitrary shell commands and capture structured results.

Tool Specification

tool_name = "execute_command"
parameters = {
    "command": "df -h",              # Shell command to execute
    "timeout": 30,                   # Execution timeout (seconds, default: 30)
    "cwd": "/home/user"              # Optional working directory
}

Execution Flow

sequenceDiagram
    participant Agent
    participant Dispatcher
    participant MCP
    participant Shell
    
    Agent->>Dispatcher: execute_command: df -h
    Dispatcher->>MCP: Forward command
    MCP->>Shell: Execute: df -h
    Shell->>Shell: Run command
    Shell-->>MCP: stdout + stderr + exit_code
    MCP->>MCP: Structure result
    MCP-->>Dispatcher: Execution result
    Dispatcher-->>Agent: Structured result

Result Structure

{
  "success": True,                  # Boolean indicating success
  "exit_code": 0,                   # Process exit code
  "stdout": "Filesystem      Size  Used Avail Use% Mounted on\n/dev/sda1       100G   50G   46G  52% /\n",
  "stderr": ""                      # Standard error output
}

Common Use Cases

Use CaseCommand ExampleDescription
File Operationsls -la /home/userList directory contents
Text Processinggrep "error" /var/log/syslogSearch log files
System Monitoringtop -bn1Check system processes
Disk Managementdf -hCheck disk space
Network Operationsping -c 4 example.comTest network connectivity
Archive Creationtar -czf backup.tar.gz /dataCreate compressed archives
Package Managementapt list --installedList installed packages

Error Handling

Exit Code Interpretation:

  • 0: Success
  • 1-125: Command-specific errors
  • 126: Command not executable
  • 127: Command not found
  • 128+n: Terminated by signal n

Example Error Result:

{
  "success": False,
  "error": "Command not found: invalid_cmd"
}

Security Considerations

!!!warning "Command Safety" The MCP server blocks dangerous commands including:

- `rm -rf /` - Recursive root deletion
- Fork bombs - `:(){ :|:& };:`
- `mkfs` - Filesystem formatting
- `dd if=/dev/zero` - Device overwriting
- `shutdown`, `reboot` - System shutdown

Commands execute with user permissions, no automatic privilege escalation. Timeout protection prevents hung processes.

2. get_system_info - Collect System Information

Purpose: Gather basic Linux system information using standard commands.

Tool Specification

tool_name = "get_system_info"
parameters = {}  # No parameters required

Information Collected

The tool executes these commands and returns their output:

Info TypeCommandData Returned
unameuname -aSystem and kernel information
uptimeuptimeSystem uptime and load averages
memoryfree -hMemory usage statistics (human-readable)
diskdf -hDisk space for all mounted filesystems

Execution Flow

sequenceDiagram
    participant Agent
    participant Dispatcher
    participant MCP
    participant System
    
    Agent->>Dispatcher: get_system_info
    Dispatcher->>MCP: Forward request
    MCP->>System: Execute uname, uptime, free, df
    System-->>MCP: Command outputs
    MCP->>MCP: Aggregate results
    MCP-->>Dispatcher: Structured info
    Dispatcher-->>Agent: System information

Result Example

{
  "uname": "Linux hostname 5.15.0-91-generic #101-Ubuntu SMP x86_64 GNU/Linux",
  "uptime": " 14:23:45 up 5 days,  3:12,  2 users,  load average: 0.52, 0.58, 0.59",
  "memory": "              total        used        free      shared  buff/cache   available\nMem:           15Gi       8.2Gi       1.5Gi       256Mi       5.8Gi       7.0Gi\nSwap:         8.0Gi       512Mi       7.5Gi",
  "disk": "Filesystem      Size  Used Avail Use% Mounted on\n/dev/sda1       100G   50G   46G  52% /\n/dev/sdb1       500G  200G  276G  42% /data"
}

Command Execution Pipeline

Atomic Building Blocks

The MCP tools execute_command and get_system_info serve as atomic operations:

graph TD
    A[User Request] --> B[LLM Reasoning]
    B --> C{Select Tool}
    C -->|Execute CLI| D[execute_command]
    C -->|Get System Info| E[get_system_info]
    
    D --> F[Capture Result]
    E --> F
    
    F --> G[Update Memory]
    G --> H{Task Complete?}
    H -->|No| B
    H -->|Yes| I[FINISH]

Isolation of System Operations

By isolating system operations in the MCP server layer, the architecture achieves clear separation: the Agent layer focuses on LLM reasoning and workflow orchestration, while the MCP layer handles system-specific command execution. This provides testability (commands can be mocked) and portability (MCP servers can be deployed remotely).

Command Composition

Sequential Execution

LinuxAgent executes commands sequentially, building on previous results:

# Round 1: Check disk space
{
  "action": {
    "tool": "execute_command",
    "arguments": {"command": "df -h /data"}
  }
}
# Result: 276GB available

# Round 2: Create backup (informed by Round 1 result)
{
  "action": {
    "tool": "execute_command",
    "arguments": {
      "command": "tar -czf /data/backup.tar.gz /home/user"
    }
  }
}

Conditional Execution

LLM can make decisions based on command results:

# Round 1: Check if file exists
{
  "action": {
    "tool": "execute_command",
    "arguments": {"command": "ls /data/backup.tar.gz"}
  }
}
# Result: exit_code=2 (file not found)

# Round 2: File doesn't exist, create it
{
  "thought": "Backup doesn't exist, creating new one",
  "action": {
    "tool": "execute_command",
    "arguments": {"command": "tar -czf /data/backup.tar.gz /home/user"}
  }
}

Error Recovery

Commands can be retried or alternatives attempted:

# Round 1: Try privileged command
{
  "action": {
    "tool": "execute_command",
    "arguments": {"command": "systemctl restart nginx"}
  }
}
# Result: success=False, error="Permission denied"

# Round 2: Switch to user-level alternative
{
  "thought": "Don't have sudo access, using alternative approach",
  "action": {
    "tool": "execute_command",
    "arguments": {"command": "kill -HUP $(cat /var/run/nginx.pid)"}
  }
}

Command Implementation

MCP Server Location

The MCP server implementation for Linux commands can be found in:

ufo/client/mcp/http_servers/
└── linux_mcp_server.py

Example Implementation Skeleton

class LinuxMCPServer:
    """MCP server for Linux CLI commands"""
    
    @mcp.tool()
    async def execute_command(
        self, 
        command: str, 
        timeout: int = 30,
        cwd: Optional[str] = None
    ) -> Dict:
        """Execute a shell command"""
        # Block dangerous commands
        dangerous = ["rm -rf /", ":(){ :|:& };:", "mkfs", ...]
        if any(d in command.lower() for d in dangerous):
            return {"success": False, "error": "Blocked dangerous command."}
        
        try:
            proc = await asyncio.create_subprocess_shell(
                command,
                stdout=asyncio.subprocess.PIPE,
                stderr=asyncio.subprocess.PIPE,
                cwd=cwd
            )
            try:
                stdout, stderr = await asyncio.wait_for(
                    proc.communicate(), 
                    timeout=timeout
                )
            except asyncio.TimeoutError:
                proc.kill()
                await proc.wait()
                return {"success": False, "error": f"Timeout after {timeout}s."}
            
            return {
                "success": proc.returncode == 0,
                "exit_code": proc.returncode,
                "stdout": stdout.decode("utf-8", errors="replace"),
                "stderr": stderr.decode("utf-8", errors="replace")
            }
        except Exception as e:
            return {"success": False, "error": str(e)}
    
    @mcp.tool()
    async def get_system_info(self) -> Dict:
        """Collect system information"""
        info = {}
        cmds = {
            "uname": "uname -a",
            "uptime": "uptime",
            "memory": "free -h",
            "disk": "df -h"
        }
        
        for k, cmd in cmds.items():
            try:
                proc = await asyncio.create_subprocess_shell(
                    cmd, stdout=asyncio.subprocess.PIPE
                )
                out, _ = await proc.communicate()
                info[k] = out.decode("utf-8", errors="replace").strip()
            except Exception as e:
                info[k] = f"Error: {e}"
        
        return info

Best Practices

Tool Usage

  • Use get_system_info for quick system overview
  • Use execute_command for custom or complex operations
  • Check success field and exit_code to detect errors
  • Parse stdout for structured data when possible
  • Set timeouts appropriately to prevent hung processes

Security

!!!warning "Security Best Practices" The MCP server has built-in protections, but be cautious:

- Dangerous commands are automatically blocked
- Commands execute with user permissions only
- Avoid sudo when possible (requires user interaction)
- Sanitize outputs before logging (may contain sensitive data)

Error Handling

  • Check success field before considering command successful
  • Parse stderr for error messages
  • Implement retries for transient errors
  • Provide alternatives when primary approach fails

Comparison with Other Agent Commands

AgentCommand TypesExecution LayerResult Format
LinuxAgentCLI + SysInfoMCP serversuccess/exit_code/stdout/stderr
AppAgentUI + APIAutomator + MCPUI state + API responses
HostAgentDesktop + ShellAutomator + MCPDesktop state + results

LinuxAgent's command set is intentionally minimal and focused:

  • execute_command: General-purpose command execution
  • get_system_info: Standardized system information

This simplicity reflects the CLI environment's text-based, command-driven nature.

Next Steps