Skip to main content
Glama
sanjaypsachdev

SSH Command Executor MCP Server

README.md
# SSH Command Executor MCP Server

A secure MCP (Model Context Protocol) server that enables AI assistants to execute commands on remote servers via SSH. Cross-platform support for Windows, macOS, and Linux.

## Features

- **Secure SSH execution** - Execute commands on remote servers with encrypted config storage
- **Multiple transport protocols** - Support for both stdio and HTTP/WebSocket protocols
- **Connection management** - Persistent connections with pooling and health checks
- **Cross-platform** - Works from any OS to any SSH-enabled server
- **Security-first** - Command validation, audit logging, and access controls
- **Easy integration** - Works with Claude Desktop, Cursor, VS Code, web apps, and other MCP clients

## Quick Start

### Installation

```bash
git clone <repository-url>
cd ssh-command-executor-mcp
uv sync  # or: pip install -r requirements.txt
```

**Requirements**: Python 3.10+

### Running the Server

**Stdio Transport (for MCP clients like Claude Desktop):**
```bash
# Using uv (recommended)
uv run -- python run_server.py

# Or using Python directly  
python run_server.py
```

**HTTP Transport (for web applications and direct API access):**
```bash
# Start HTTP server on localhost:8000
python run_http_server.py

# Or with custom host/port
SSH_MCP_HTTP_HOST=0.0.0.0 SSH_MCP_HTTP_PORT=9000 python run_http_server.py
```

## Integration

### Claude Desktop

Add to your config file:
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows**: `%APPDATA%/Claude/claude_desktop_config.json`

```json
{
  "mcpServers": {
    "ssh-command-executor": {
      "command": "uv",
      "args": ["run", "--", "python", "/path/to/ssh-command-executor-mcp/run_server.py"]
    }
  }
}
```

Replace `/path/to/ssh-command-executor-mcp` with the actual absolute path to your project directory.

### Other MCP Clients

For Cursor, VS Code, or other MCP-compatible tools, configure them to run:
```bash
# Using uv (recommended)
uv run -- python /path/to/ssh-command-executor-mcp/run_server.py

# Or using Python directly
python /path/to/ssh-command-executor-mcp/run_server.py
```

Replace `/path/to/ssh-command-executor-mcp` with the actual absolute path to your project directory.

### Web Applications & Direct API Access

**HTTP REST API:**
```bash
# Start the HTTP server
python run_http_server.py

# Available endpoints:
# GET  /health          - Health check
# GET  /tools           - List available tools
# POST /tools/{name}    - Execute a tool
# GET  /prompts         - List available prompts  
# POST /prompts/{name}  - Execute a prompt
```

**WebSocket (Real-time):**
```javascript
const ws = new WebSocket('ws://localhost:8000/ws');

// Execute a tool
ws.send(JSON.stringify({
  type: 'tool_call',
  tool: 'ssh_execute',
  arguments: {
    host: '192.168.1.100',
    username: 'admin',
    command: 'df -h'
  }
}));

// Handle response
ws.onmessage = (event) => {
  const response = JSON.parse(event.data);
  console.log('Result:', response.result);
};
```

## Usage

### Method 1: Configure Once, Use Repeatedly (Recommended)

**Configure a server:**
```json
{
  "name": "ssh_configure",
  "arguments": {
    "name": "production",
    "host": "prod-server.com",
    "username": "deploy",
    "key_path": "~/.ssh/deploy_key"
  }
}
```

**Execute commands:**
```json
{
  "name": "ssh_run",
  "arguments": {
    "command": "systemctl status nginx"
  }
}
```

### Method 2: Full Configuration Per Command

```json
{
  "name": "ssh_execute",
  "arguments": {
    "host": "192.168.1.100",
    "username": "admin",
    "command": "df -h",
    "key_path": "/path/to/key"
  }
}
```

## Available Tools

| Tool | Description | Stdio | HTTP | WebSocket |
|------|-------------|:-----:|:----:|:---------:|
| `ssh_configure` | Configure server connection details for reuse | ✅ | ✅ | ✅ |
| `ssh_run` | Execute commands on pre-configured servers | ✅ | ✅ | ✅ |
| `ssh_execute` | Execute commands with full connection details | ✅ | ✅ | ✅ |
| `ssh_test_connection` | Test SSH connectivity | ✅ | ✅ | ✅ |
| `ssh_list_servers` | List configured servers | ✅ | ✅ | ✅ |

## Available Resources

| Resource | Description | Content Type |
|----------|-------------|:------------:|
| `ssh://servers` | List all configured SSH servers | 📋 Server Inventory |
| `ssh://history` | Recent SSH command execution history | 📈 Command History |
| `ssh://servers/{name}/status` | Real-time status of specific server | 📊 Server Status |
| `ssh://config/security` | Current security configuration | 🔒 Security Settings |
| `ssh://troubleshooting` | SSH troubleshooting guide | 📚 Help Documentation |

### HTTP API Examples

**Execute a command:**
```bash
curl -X POST http://localhost:8000/tools/ssh_execute \
  -H "Content-Type: application/json" \
  -d '{
    "arguments": {
      "host": "192.168.1.100",
      "username": "admin", 
      "command": "df -h",
      "key_path": "/path/to/key"
    }
  }'
```

**Test connection:**
```bash
curl -X POST http://localhost:8000/tools/ssh_test_connection \
  -H "Content-Type: application/json" \
  -d '{
    "arguments": {
      "host": "server.example.com",
      "username": "user"
    }
  }'
```

### Resource Access Examples

**View server inventory:**
```bash
# Via HTTP
curl http://localhost:8000/resources/ssh://servers

# MCP clients can access: ssh://servers
```

**Check command history:**
```bash
# Via HTTP  
curl http://localhost:8000/resources/ssh://history

# MCP clients can access: ssh://history
```

**Get server status:**
```bash
# Via HTTP
curl http://localhost:8000/resources/ssh://servers/production/status

# MCP clients can access: ssh://servers/production/status
```

## Security Features

- **🔐 Encrypted Storage** - Server configs encrypted with Fernet (AES-128)
- **🛡️ Access Controls** - Host/user validation, SSH key verification
- **🚨 Command Security** - Injection prevention, dangerous command blocking
- **📋 Audit Logging** - Complete operation trail with timestamps

### Security Configuration

```bash
# Environment variables for enhanced security
export SSH_MCP_ALLOWED_HOSTS="prod.com,staging.com"
export SSH_MCP_BLOCKED_COMMANDS="rm -rf,shutdown,reboot"
export SSH_MCP_AUDIT_LOG=true

# Transport configuration
export SSH_MCP_TRANSPORT=stdio          # or 'http'
export SSH_MCP_HTTP_HOST=0.0.0.0       # HTTP server host
export SSH_MCP_HTTP_PORT=8000           # HTTP server port
```

## Project Structure

```
├── src/
│   ├── server.py          # Main MCP server
│   ├── transport.py       # Transport layer (stdio/HTTP/WebSocket)
│   ├── ssh_tool.py        # SSH execution logic
│   ├── config.py          # Configuration management
│   ├── security.py        # Security controls
│   └── audit.py           # Audit logging
├── tests/                 # Test suite
├── scripts/dev.py         # Development utilities
├── run_server.py          # Stdio transport runner
├── run_http_server.py     # HTTP transport runner
└── requirements.txt       # Dependencies
```

## Development

```bash
# Install dependencies
uv sync

# Run tests
uv run pytest

# Format code
uv run black src/ tests/
uv run isort src/ tests/

# Type checking
uv run mypy src/
```

## AI Assistant Usage

### With MCP Clients (Claude Desktop, Cursor, etc.)
Once integrated, ask your AI assistant:
- "Execute `df -h` on my production server to check disk space"
- "Test SSH connection to staging server" 
- "Run system updates on my Ubuntu servers"
- "Deploy my application using the deployment script"

### With HTTP API
Use the REST API or WebSocket for web applications:
```bash
# Check server health
curl http://localhost:8000/health

# List available tools
curl http://localhost:8000/tools

# Execute SSH command
curl -X POST http://localhost:8000/tools/ssh_execute \
  -H "Content-Type: application/json" \
  -d '{"arguments": {"host": "server.com", "username": "user", "command": "uptime"}}'
```

## Best Practices

- **Use SSH keys** instead of passwords
- **Configure allowed hosts** to restrict access
- **Use service accounts** with minimal permissions
- **Enable audit logging** for monitoring
- **Keep dependencies updated** for security

⚠️ **Warning**: Commands execute with SSH user permissions. Use appropriate access controls.

## License

MIT License - see LICENSE file for details.