๐ง Linux SSH MCP Server
A powerful Python-based Model Context Protocol (MCP) server that enables AI assistants to manage remote Linux machines over SSH โ directly from your chat interface.
๐ Table of Contents
- Overview
- Key Features
- Architecture
- Prerequisites
- Installation & Setup
- Configuring Your AI IDE
- Cursor
- Claude Desktop
- Antigravity (Google DeepMind)
- VS Code with Continue / Cline
- Windsurf
- How It Works
- Environment Variables
- Complete Tool Reference
- Session & Authentication (6 tools)
- Command Execution (3 tools)
- File & Directory Operations (12 tools)
- Log & Search (5 tools)
- System Monitoring (8 tools)
- Network (5 tools)
- Docker Operations (7 tools)
- Package Management (4 tools)
- User Management (4 tools)
- Cron Jobs (3 tools)
- Archive & Compression (2 tools)
- Security & Audit (3 tools)
- Multi-Session Usage Examples
- Security Best Practices
- Troubleshooting
- License
๐ Overview
Linux SSH MCP Server is a Python application built with FastMCP and Paramiko that exposes 50+ tools across 12 categories to any MCP-compatible AI assistant. Once connected, your AI can execute commands, manage files, monitor systems, control Docker containers, and much more โ all on remote Linux servers, all through natural language in your chat.
How is this different from just "running commands"?
Traditional AI code assistants can run commands on your local machine. This MCP server lets them operate on remote Linux servers โ your production boxes, staging environments, cloud VMs, Raspberry Pis, or any machine reachable via SSH. The AI gets structured, typed tools (not raw shell access), meaning it can reason about parameters, handle errors gracefully, and chain operations intelligently.
โจ Key Features
| Feature | Description |
|---|---|
| 50+ Specialized Tools | Purpose-built tools across 12 categories โ not just raw command execution |
| Multi-Session Support | Connect to multiple Linux hosts simultaneously with named sessions |
| Interactive Credentials | If environment variables aren't set, the server prompts for credentials directly in the chat |
| Credential Caching | Saves credentials in memory and optionally to ~/.ssh-mcp-cache/credentials.json for reuse |
| SSH Key Authentication | Supports password auth, key-based auth, or both |
| Auto-Detection | Automatically detects package managers (apt/yum/dnf/pacman) and adjusts commands |
| stdio Transport | Runs via stdio using uv, the standard transport for MCP servers in AI IDEs |
| Zero Config Start | Works with environment variables, saved credentials, or interactive prompting โ your choice |
๐ Architecture
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ AI IDE (Client) โ
โ Cursor / Claude Desktop / Antigravity โ
โ VS Code / Windsurf โ
โโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ stdio (stdin/stdout)
โ
โโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ MCP Server (server.py) โ
โ Built with FastMCP + Python โ
โ โ
โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ โ
โ โ Session โ โ Credential โ โ Tool โ โ
โ โ Manager โ โ Cache โ โ Registry โ โ
โ โ (multi-host)โ โ (mem+disk) โ โ (50+ tools) โ โ
โ โโโโโโโโฌโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ SSH (Paramiko)
โ
โโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Remote Linux Server(s) โ
โ Ubuntu / Debian / CentOS / Arch / etc. โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ฆ Prerequisites
Before you begin, make sure you have the following installed on your local machine (the machine running the AI IDE):
1. Python 3.10 or higher
Verify your Python version:
python --version
# Should output: Python 3.10.x or higher
If you don't have Python 3.10+, download it from python.org.
2. uv (Python Package Manager by Astral)
uv is a blazing-fast Python package manager that replaces pip, venv, and more. Install it:
# Using pip
pip install uv
# Or using the standalone installer (recommended)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
Verify the installation:
uv --version
Why uv? MCP servers launched by AI IDEs use
uv runto automatically create virtual environments, install dependencies, and start the server โ all in one command. It's the de facto standard for MCP server management.
3. A Remote Linux Server with SSH Access
You need at least one Linux machine you can SSH into. This can be:
- A cloud VM (AWS EC2, GCP, Azure, DigitalOcean, etc.)
- A local VM (VirtualBox, VMware, WSL2, etc.)
- A Raspberry Pi or any other Linux device
- A container with SSH enabled
Make sure you have:
- The server's hostname or IP address
- A valid username and password (or SSH private key)
- SSH port (default:
22) is open and accessible from your machine
๐ Installation & Setup
Step 1: Navigate to the project directory
cd C:\AI_Workspaces\Anti_Workspace\linux-ssh-mcp
Step 2: Install dependencies
uv sync
This single command will:
- Create a virtual environment (
.venv/) if one doesn't exist - Read
pyproject.tomlfor dependency declarations - Install all required packages (FastMCP, Paramiko, etc.)
- Lock dependency versions in
uv.lock
Step 3: Verify the installation
uv run python -c "import mcp; import paramiko; print('All dependencies installed successfully!')"
Step 4 (Optional): Test with MCP Inspector
The MCP Inspector is a browser-based debugging tool that lets you test your server's tools interactively:
uv run mcp dev server.py
This opens a web UI where you can invoke any tool, inspect inputs/outputs, and debug issues before connecting to your AI IDE.
๐ Configuring Your AI IDE
Each AI IDE reads MCP server configurations from a JSON file. The server is launched automatically when the IDE starts โ you do not need to start it manually.
Understanding the Configuration
Every IDE uses the same core JSON structure:
{
"mcpServers": {
"linux-ssh": {
"command": "uv",
"args": [
"run",
"--directory",
"C:\\AI_Workspaces\\Anti_Workspace\\linux-ssh-mcp",
"server.py"
],
"env": {
"SSH_HOST": "your-host",
"SSH_PORT": "22",
"SSH_USERNAME": "your-username",
"SSH_PASSWORD": "your-password"
}
}
}
}
| Field | Purpose |
|---|---|
"linux-ssh" |
A unique name for this MCP server (you can change it) |
"command" |
The executable to run (uv) |
"args" |
Arguments passed to uv: run the server from its directory |
"env" |
OPTIONAL โ Environment variables for default SSH credentials |
๐ก The
envsection is entirely optional. If you omit it, the server will interactively ask for credentials in the chat when you first try to connect. This is the recommended approach for security-sensitive environments.
1. ๐ฑ Cursor
Cursor supports both project-level and global MCP configurations.
Project-Level Configuration (Recommended)
Create the file .cursor/mcp.json in your project root:
your-project/
โโโ .cursor/
โ โโโ mcp.json โ Create this file
โโโ src/
โโโ ...
{
"mcpServers": {
"linux-ssh": {
"command": "uv",
"args": [
"run",
"--directory",
"C:\\AI_Workspaces\\Anti_Workspace\\linux-ssh-mcp",
"server.py"
],
"env": {
"SSH_HOST": "your-host",
"SSH_PORT": "22",
"SSH_USERNAME": "your-username",
"SSH_PASSWORD": "your-password"
}
}
}
}
Global Configuration
To make the MCP server available across all Cursor projects, add it to your global configuration:
~/.cursor/mcp.json
The JSON format is identical to the project-level config above.
Without Environment Variables (Interactive Mode)
If you prefer the server to ask for credentials in the chat:
{
"mcpServers": {
"linux-ssh": {
"command": "uv",
"args": [
"run",
"--directory",
"C:\\AI_Workspaces\\Anti_Workspace\\linux-ssh-mcp",
"server.py"
]
}
}
}
Verifying in Cursor
- Open Cursor
- Go to Settings โ MCP (or press
Ctrl+Shift+Pโ "MCP") - You should see
linux-sshlisted with a green status indicator - If red, check the logs for error details
2. ๐ค Claude Desktop
Configuration File Location
| OS | Path |
|---|---|
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
Configuration
Open (or create) the config file and add the MCP server:
{
"mcpServers": {
"linux-ssh": {
"command": "uv",
"args": [
"run",
"--directory",
"C:\\AI_Workspaces\\Anti_Workspace\\linux-ssh-mcp",
"server.py"
]
}
}
}
Note for macOS users: Replace the Windows path in
--directorywith the equivalent macOS path where the project is located.
Verifying in Claude Desktop
- Restart Claude Desktop after saving the config
- Look for the ๐ง (tools) icon in the chat input area
- Click it to see the list of available tools from
linux-ssh
3. ๐ Antigravity (Google DeepMind)
Antigravity can be configured via the MCP settings panel within the application.
Configuration
Use the same JSON format as Cursor:
{
"mcpServers": {
"linux-ssh": {
"command": "uv",
"args": [
"run",
"--directory",
"C:\\AI_Workspaces\\Anti_Workspace\\linux-ssh-mcp",
"server.py"
],
"env": {
"SSH_HOST": "your-host",
"SSH_USERNAME": "your-username",
"SSH_PASSWORD": "your-password"
}
}
}
}
Steps
- Open Antigravity
- Navigate to the MCP settings panel
- Add a new MCP server configuration
- Paste the JSON above (adjust credentials as needed)
- Save and restart if prompted
4. ๐ป VS Code with Continue / Cline
Continue Extension
Add the MCP server to .continue/config.json in your project or home directory:
{
"mcpServers": {
"linux-ssh": {
"command": "uv",
"args": [
"run",
"--directory",
"C:\\AI_Workspaces\\Anti_Workspace\\linux-ssh-mcp",
"server.py"
]
}
}
}
Cline Extension
- Open VS Code
- Open Cline's settings (click the gear icon in the Cline sidebar)
- Navigate to the MCP Servers section
- Add a new server with the same
commandandargsformat
5. ๐ Windsurf
Configuration File Location
~/.codeium/windsurf/mcp_config.json
Configuration
{
"mcpServers": {
"linux-ssh": {
"command": "uv",
"args": [
"run",
"--directory",
"C:\\AI_Workspaces\\Anti_Workspace\\linux-ssh-mcp",
"server.py"
],
"env": {
"SSH_HOST": "your-host",
"SSH_USERNAME": "your-username",
"SSH_PASSWORD": "your-password"
}
}
}
}
Steps
- Open (or create) the file at
~/.codeium/windsurf/mcp_config.json - Add the configuration above
- Restart Windsurf to pick up the changes
โก How It Works
Startup Flow
1. AI IDE starts
โ
2. Reads mcp.json / config file
โ
3. Runs: uv run --directory <path> server.py
โ
4. uv automatically:
โโโ Creates .venv if needed
โโโ Installs dependencies from pyproject.toml
โโโ Launches server.py
โ
5. server.py initializes FastMCP
โโโ Registers all 50+ tools
โโโ Reads SSH_* environment variables (if set)
โโโ Loads cached credentials (if available)
โ
6. Server communicates via stdio (stdin/stdout)
โ
7. AI IDE discovers tools and makes them available in chat
Connection Flow
User: "Connect to my production server at 10.0.1.50"
โ
AI calls: ssh_connect(host='10.0.1.50')
โ
โโโ ENV vars set? โ Uses SSH_USERNAME / SSH_PASSWORD
โโโ Cached creds? โ Uses saved credentials
โโโ Neither? โ Prompts user in chat for username/password
โ
SSH connection established โ Session "default" created
โ
User: "Show me disk usage"
โ
AI calls: ssh_disk_usage(session_name='default')
โ
Returns: Formatted df -h output
For Manual Testing / Debugging
# Open the MCP Inspector (browser-based tool debugger)
uv run mcp dev server.py
The Inspector lets you:
- See all registered tools and their schemas
- Invoke tools with custom parameters
- Inspect raw JSON responses
- Debug connection issues
๐ Environment Variables
All environment variables are optional. If not set, the server will either use defaults or prompt interactively.
| Variable | Required | Default | Description |
|---|---|---|---|
SSH_HOST |
No | โ | Hostname or IP address of the remote Linux server. If not set, you must provide it when calling ssh_connect. |
SSH_PORT |
No | 22 |
SSH port number. Only change this if your server uses a non-standard SSH port. |
SSH_USERNAME |
No | root |
SSH username for authentication. |
SSH_PASSWORD |
No | โ | SSH password for password-based authentication. Mutually optional with SSH_KEY_PATH. |
SSH_KEY_PATH |
No | โ | Absolute path to an SSH private key file (e.g., C:\Users\pawan\.ssh\id_rsa). Used for key-based authentication. |
SSH_MCP_CACHE_DIR |
No | ~/.ssh-mcp-cache |
Directory where credential cache files are stored. The server creates this directory automatically if it doesn't exist. |
Authentication Priority
When connecting, the server checks for credentials in this order:
- Explicit parameters passed to
ssh_connect(highest priority) - Environment variables (
SSH_HOST,SSH_USERNAME, etc.) - Cached credentials from
~/.ssh-mcp-cache/credentials.json - Interactive prompt โ asks the user in chat (lowest priority / fallback)
๐ Complete Tool Reference
This section documents every tool exposed by the MCP server. All tools return structured responses with clear success/error indicators.
Category 1: Session & Authentication (6 tools)
These tools manage SSH connections, sessions, and credential storage.
๐ง ssh_connect
Connect to a remote Linux host and create a named session.
Establishes an SSH connection to the specified host. Multiple simultaneous connections are supported via named sessions. If credentials are not provided as parameters, the server falls back to environment variables, then cached credentials, then interactive prompting.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
host |
str |
Yes* | โ | Hostname or IP address of the remote server. *Optional if SSH_HOST env var is set. |
username |
str |
No | 'root' |
SSH username. |
password |
str |
No | โ | SSH password. Either password or key_path should be provided. |
key_path |
str |
No | โ | Path to SSH private key file. |
port |
int |
No | 22 |
SSH port number. |
session_name |
str |
No | 'default' |
A unique name for this session. Use different names to manage multiple connections. |
Examples:
# Basic connection with password
ssh_connect(host='192.168.1.100', username='admin', password='s3cret')
# Connection with SSH key
ssh_connect(host='10.0.1.50', username='deploy', key_path='/home/user/.ssh/id_rsa')
# Named session for production server
ssh_connect(host='prod.example.com', username='admin', password='s3cret', session_name='prod')
# Named session for staging server (simultaneously)
ssh_connect(host='staging.example.com', username='admin', password='s3cret', session_name='staging')
# Using non-standard port
ssh_connect(host='bastion.example.com', port=2222, username='jump', key_path='/keys/bastion.pem')
Returns: Confirmation message with session name, connected host, and server OS info.
๐ง ssh_disconnect
Disconnect a specific SSH session.
Gracefully closes the SSH connection for the named session and frees associated resources.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
session_name |
str |
No | 'default' |
Name of the session to disconnect. |
Examples:
# Disconnect the default session
ssh_disconnect()
# Disconnect a named session
ssh_disconnect(session_name='prod')
Returns: Confirmation that the session was disconnected.
๐ง ssh_disconnect_all
Disconnect all active SSH sessions.
Iterates through all active sessions and disconnects each one. Useful for cleanup.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| (none) | โ | โ | โ | This tool takes no parameters. |
Example:
ssh_disconnect_all()
Returns: Summary of how many sessions were disconnected and their names.
๐ง ssh_list_sessions
List all active SSH sessions with connection details.
Provides a comprehensive overview of all currently active sessions including connection status, hostname, uptime, and the number of commands executed in each session.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| (none) | โ | โ | โ | This tool takes no parameters. |
Example:
ssh_list_sessions()
Returns: A formatted table/list with:
- Session name
- Connected host and port
- Username
- Connection status (active/disconnected)
- Uptime (how long the session has been active)
- Number of commands executed
๐ง ssh_save_credentials
Save SSH credentials for future reuse.
Persists credentials to disk at ~/.ssh-mcp-cache/credentials.json. Saved credentials are automatically loaded on server startup and can be used when connecting to a host without explicitly providing credentials. The credential file is created with restricted permissions (600) for security.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
session_name |
str |
No | 'default' |
Name to identify these saved credentials. |
host |
str |
Yes | โ | Hostname or IP address. |
username |
str |
No | 'root' |
SSH username. |
password |
str |
No | โ | SSH password. |
key_path |
str |
No | โ | Path to SSH private key. |
port |
int |
No | 22 |
SSH port number. |
Example:
ssh_save_credentials(
session_name='prod',
host='prod.example.com',
username='deploy',
key_path='/home/user/.ssh/prod_key',
port=22
)
Returns: Confirmation that credentials were saved and the file path.
๐ง ssh_list_saved_credentials
List all saved credentials.
Displays all credentials stored in the cache file. Passwords are masked for security (only the first and last characters are shown).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| (none) | โ | โ | โ | This tool takes no parameters. |
Example:
ssh_list_saved_credentials()
Returns: A formatted list of saved credentials with:
- Session/credential name
- Host and port
- Username
- Password (masked, e.g.,
s****t) - Key path (if set)
Category 2: Command Execution (3 tools)
General-purpose command execution tools for running anything on the remote host.
๐ง ssh_execute
Execute any shell command on the remote host.
The most versatile tool โ runs a single shell command and returns stdout, stderr, and the exit code. Use this for any command not covered by a specialized tool.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
command |
str |
Yes | โ | The shell command to execute. |
session_name |
str |
No | 'default' |
Session to execute on. |
timeout |
int |
No | 30 |
Maximum execution time in seconds. |
Examples:
# Simple command
ssh_execute(command='whoami')
# Command with timeout
ssh_execute(command='find / -name "*.log" -size +100M', timeout=120)
# Execute on a specific session
ssh_execute(command='uptime', session_name='prod')
# Piped commands
ssh_execute(command='cat /var/log/syslog | grep ERROR | tail -20')
Returns: An object containing:
stdoutโ Standard output of the commandstderrโ Standard error output (if any)exit_codeโ Exit code (0 = success)
๐ง ssh_execute_script
Execute a multi-line bash script on the remote host.
Uploads and runs a complete bash script. Useful for complex operations that span multiple commands with control flow (if/else, loops, etc.).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
script |
str |
Yes | โ | Multi-line bash script content. |
session_name |
str |
No | 'default' |
Session to execute on. |
timeout |
int |
No | 30 |
Maximum execution time in seconds. |
Example:
ssh_execute_script(script="""
#!/bin/bash
set -e
echo "=== System Health Check ==="
echo ""
echo "Hostname: $(hostname)"
echo "Uptime: $(uptime -p)"
echo "Kernel: $(uname -r)"
echo ""
echo "=== Disk Usage ==="
df -h | grep -E '^/dev'
echo ""
echo "=== Memory ==="
free -h
echo ""
echo "=== Top 5 CPU Processes ==="
ps aux --sort=-%cpu | head -6
""", timeout=60)
Returns: Combined output from the script execution with exit code.
๐ง ssh_execute_background
Run a command in the background using nohup.
Launches a long-running command that persists even after the SSH session ends. Output is redirected to a log file.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
command |
str |
Yes | โ | The command to run in the background. |
log_file |
str |
No | /tmp/bg_<timestamp>.log |
Path to redirect stdout/stderr. |
session_name |
str |
No | 'default' |
Session to execute on. |
Examples:
# Run a backup in the background
ssh_execute_background(
command='tar czf /backups/full-backup-$(date +%Y%m%d).tar.gz /var/www',
log_file='/var/log/backup.log'
)
# Start a long-running data processing job
ssh_execute_background(command='python3 /scripts/process_data.py --all')
Returns: Confirmation with the PID of the background process and the log file path.
Category 3: File & Directory Operations (12 tools)
Comprehensive file management capabilities โ browse, read, write, copy, move, delete, search, and manage permissions.
๐ง ssh_list_directory
List the contents of a directory (equivalent to ls -la).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
path |
str |
No | '/' |
Directory path to list. |
session_name |
str |
No | 'default' |
Session to use. |
show_hidden |
bool |
No | True |
Whether to include hidden files (dotfiles). |
Examples:
# List root directory
ssh_list_directory(path='/')
# List home directory without hidden files
ssh_list_directory(path='/home/admin', show_hidden=False)
# List on a specific session
ssh_list_directory(path='/var/www', session_name='prod')
Returns: Formatted directory listing with permissions, owner, group, size, modification date, and filename.
๐ง ssh_create_directory
Create a directory, including any necessary parent directories (equivalent to mkdir -p).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
path |
str |
Yes | โ | Directory path to create. |
session_name |
str |
No | 'default' |
Session to use. |
Example:
# Creates /var/www/myapp/static/images and all parents
ssh_create_directory(path='/var/www/myapp/static/images')
๐ง ssh_read_file
Read the contents of a file on the remote server.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
path |
str |
Yes | โ | File path to read. |
session_name |
str |
No | 'default' |
Session to use. |
max_lines |
int |
No | โ | Maximum number of lines to read. If omitted, reads the entire file. |
Examples:
# Read entire file
ssh_read_file(path='/etc/nginx/nginx.conf')
# Read first 50 lines of a large file
ssh_read_file(path='/var/log/syslog', max_lines=50)
๐ง ssh_write_file
Write content to a file. Creates the file if it doesn't exist, or overwrites/appends to it.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
path |
str |
Yes | โ | File path to write to. |
content |
str |
Yes | โ | Content to write. |
session_name |
str |
No | 'default' |
Session to use. |
append |
bool |
No | False |
If True, appends to the file instead of overwriting. |
Examples:
# Write a new config file
ssh_write_file(path='/etc/myapp/config.yml', content="""
database:
host: localhost
port: 5432
name: myapp_prod
""")
# Append a line to a file
ssh_write_file(path='/etc/hosts', content='10.0.1.50 api.internal\n', append=True)
๐ง ssh_delete
Delete a file or directory.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
path |
str |
Yes | โ | Path to delete. |
session_name |
str |
No | 'default' |
Session to use. |
recursive |
bool |
No | False |
If True, deletes directories recursively (rm -rf). Required for non-empty directories. |
Examples:
# Delete a single file
ssh_delete(path='/tmp/old-backup.tar.gz')
# Delete a directory and all its contents
ssh_delete(path='/var/www/old-site', recursive=True)
โ ๏ธ Warning: Recursive delete is permanent. There is no recycle bin on Linux.
๐ง ssh_move
Move or rename a file or directory.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
source |
str |
Yes | โ | Source path. |
destination |
str |
Yes | โ | Destination path. |
session_name |
str |
No | 'default' |
Session to use. |
Example:
# Rename a file
ssh_move(source='/var/www/index.html', destination='/var/www/index.html.bak')
# Move a directory
ssh_move(source='/tmp/release-v2', destination='/var/www/app')
๐ง ssh_copy
Copy a file or directory.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
source |
str |
Yes | โ | Source path. |
destination |
str |
Yes | โ | Destination path. |
session_name |
str |
No | 'default' |
Session to use. |
recursive |
bool |
No | False |
If True, copies directories recursively (cp -r). |
Example:
# Copy a file
ssh_copy(source='/etc/nginx/nginx.conf', destination='/etc/nginx/nginx.conf.bak')
# Copy a directory
ssh_copy(source='/var/www/app', destination='/var/www/app-backup', recursive=True)
๐ง ssh_file_info
Get detailed information about a file or directory (equivalent to stat).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
path |
str |
Yes | โ | Path to inspect. |
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_file_info(path='/var/log/syslog')
Returns: File type, size, permissions, owner, group, creation time, modification time, access time, inode, and link count.
๐ง ssh_file_permissions
Change file or directory permissions (equivalent to chmod).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
path |
str |
Yes | โ | Path to modify. |
permissions |
str |
Yes | โ | Permission string in octal format (e.g., '755', '644', '600'). |
session_name |
str |
No | 'default' |
Session to use. |
recursive |
bool |
No | False |
If True, applies permissions recursively. |
Examples:
# Make a script executable
ssh_file_permissions(path='/opt/scripts/deploy.sh', permissions='755')
# Secure a private key file
ssh_file_permissions(path='/home/admin/.ssh/id_rsa', permissions='600')
# Recursively set directory permissions
ssh_file_permissions(path='/var/www/html', permissions='755', recursive=True)
๐ง ssh_change_owner
Change file or directory ownership (equivalent to chown).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
path |
str |
Yes | โ | Path to modify. |
owner |
str |
Yes | โ | New owner username. |
group |
str |
No | โ | New group name. If omitted, only the owner is changed. |
session_name |
str |
No | 'default' |
Session to use. |
recursive |
bool |
No | False |
If True, applies ownership change recursively. |
Examples:
# Change owner
ssh_change_owner(path='/var/www/html', owner='www-data')
# Change owner and group
ssh_change_owner(path='/var/www/html', owner='www-data', group='www-data', recursive=True)
๐ง ssh_find_files
Search for files and directories with flexible filters (equivalent to find).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
path |
str |
Yes | โ | Starting directory for the search. |
name |
str |
No | โ | Filename pattern (supports wildcards, e.g., '*.log', 'config*'). |
type |
str |
No | โ | Filter by type: 'f' for files only, 'd' for directories only. |
size |
str |
No | โ | Filter by size (e.g., '+100M' for files over 100MB, '-1k' for files under 1KB). |
modified_within |
str |
No | โ | Find files modified within a timeframe (e.g., '7' for 7 days, '1' for 1 day). |
session_name |
str |
No | 'default' |
Session to use. |
Examples:
# Find all .log files in /var/log
ssh_find_files(path='/var/log', name='*.log', type='f')
# Find large files over 500MB
ssh_find_files(path='/', size='+500M', type='f')
# Find recently modified config files
ssh_find_files(path='/etc', name='*.conf', modified_within='7')
# Find empty directories
ssh_find_files(path='/tmp', type='d')
๐ง ssh_disk_file_usage
Show disk usage for a specific file or directory (equivalent to du -sh).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
path |
str |
Yes | โ | Path to check. |
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_disk_file_usage(path='/var/log')
# Returns: "2.3G /var/log"
Category 4: Log & Search (5 tools)
Tools for searching through files, viewing logs, and performing text replacements.
๐ง ssh_search_in_files
Search for text patterns within files (equivalent to grep).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
pattern |
str |
Yes | โ | Text or regex pattern to search for. |
path |
str |
Yes | โ | File or directory path to search in. |
session_name |
str |
No | 'default' |
Session to use. |
case_insensitive |
bool |
No | False |
If True, performs case-insensitive matching. |
regex |
bool |
No | False |
If True, treats the pattern as a regular expression. |
Examples:
# Search for errors in a log file
ssh_search_in_files(pattern='ERROR', path='/var/log/app.log')
# Case-insensitive search across a directory
ssh_search_in_files(pattern='database', path='/etc/myapp/', case_insensitive=True)
# Regex search for IP addresses
ssh_search_in_files(pattern=r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', path='/var/log/auth.log', regex=True)
๐ง ssh_tail_file
View the last N lines of a file (equivalent to tail -n).
Ideal for checking recent log entries.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
path |
str |
Yes | โ | File path to tail. |
lines |
int |
No | 50 |
Number of lines to show from the end. |
session_name |
str |
No | 'default' |
Session to use. |
Example:
# View last 100 lines of syslog
ssh_tail_file(path='/var/log/syslog', lines=100)
๐ง ssh_head_file
View the first N lines of a file (equivalent to head -n).
Useful for inspecting file headers, CSV column names, or configuration file structures.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
path |
str |
Yes | โ | File path to read from. |
lines |
int |
No | 50 |
Number of lines to show from the beginning. |
session_name |
str |
No | 'default' |
Session to use. |
Example:
# View first 20 lines of a CSV file
ssh_head_file(path='/data/export.csv', lines=20)
๐ง ssh_search_logs
Search through system logs using journalctl or grep.
Provides a higher-level interface for log searching that works with both systemd journal and traditional log files.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
pattern |
str |
Yes | โ | Text pattern to search for in logs. |
log_path |
str |
No | โ | Specific log file to search. If omitted, searches the systemd journal. |
session_name |
str |
No | 'default' |
Session to use. |
since |
str |
No | โ | Time filter (e.g., '1 hour ago', 'today', '2024-01-15'). Only works with journalctl. |
Examples:
# Search systemd journal for SSH errors
ssh_search_logs(pattern='sshd', since='1 hour ago')
# Search a specific log file
ssh_search_logs(pattern='OutOfMemory', log_path='/var/log/app/error.log')
# Search for recent kernel errors
ssh_search_logs(pattern='error', since='today')
๐ง ssh_sed_replace
Find and replace text in a file using sed.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
file_path |
str |
Yes | โ | Path to the file to modify. |
find |
str |
Yes | โ | Text or pattern to find. |
replace |
str |
Yes | โ | Replacement text. |
session_name |
str |
No | 'default' |
Session to use. |
backup |
bool |
No | True |
If True, creates a backup of the original file (.bak extension). |
Examples:
# Update a port in a config file
ssh_sed_replace(
file_path='/etc/myapp/config.yml',
find='port: 3000',
replace='port: 8080'
)
# Replace without backup
ssh_sed_replace(
file_path='/tmp/test.txt',
find='old_value',
replace='new_value',
backup=False
)
Category 5: System Monitoring (8 tools)
Monitor system resources, processes, and performance metrics.
๐ง ssh_system_info
Get a comprehensive system summary.
Returns a consolidated overview of the entire system in one call.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_system_info()
Returns: Hostname, OS/distro, kernel version, architecture, CPU info, total/used memory, disk usage, uptime, load averages, and network interfaces.
๐ง ssh_disk_usage
Show disk space usage for all mounted filesystems (equivalent to df -h).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_disk_usage()
Returns: Formatted table with filesystem, size, used, available, use%, and mount point for each partition.
๐ง ssh_memory_usage
Show memory and swap usage (equivalent to free -h).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_memory_usage()
Returns: Total, used, free, shared, buff/cache, and available memory along with swap usage.
๐ง ssh_cpu_info
Get CPU details and current load.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_cpu_info()
Returns: CPU model, number of cores/threads, clock speed, architecture, and current load averages (1/5/15 minutes).
๐ง ssh_process_list
List running processes (equivalent to ps aux) with optional filtering and sorting.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
session_name |
str |
No | 'default' |
Session to use. |
filter_pattern |
str |
No | โ | Filter processes by name pattern (e.g., 'nginx', 'python'). |
sort_by |
str |
No | โ | Sort by 'cpu' or 'mem'. |
Examples:
# List all processes
ssh_process_list()
# Find all Python processes
ssh_process_list(filter_pattern='python')
# List processes sorted by memory usage
ssh_process_list(sort_by='mem')
๐ง ssh_top_processes
Show the top N processes by CPU or memory consumption.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
session_name |
str |
No | 'default' |
Session to use. |
count |
int |
No | 10 |
Number of top processes to show. |
sort_by |
str |
No | 'cpu' |
Sort by 'cpu' or 'mem'. |
Example:
# Top 5 memory-hungry processes
ssh_top_processes(count=5, sort_by='mem')
๐ง ssh_kill_process
Kill a process by its PID.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
pid |
int |
Yes | โ | Process ID to kill. |
session_name |
str |
No | 'default' |
Session to use. |
signal |
str |
No | 'TERM' |
Signal to send. Common values: 'TERM' (graceful), 'KILL' (force), 'HUP' (reload). |
Examples:
# Gracefully terminate a process
ssh_kill_process(pid=12345)
# Force kill a stuck process
ssh_kill_process(pid=12345, signal='KILL')
# Send HUP to reload config (e.g., nginx)
ssh_kill_process(pid=9876, signal='HUP')
๐ง ssh_system_load
Get current system load averages.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_system_load()
Returns: 1-minute, 5-minute, and 15-minute load averages along with the number of CPU cores for context.
Category 6: Network (5 tools)
Network diagnostics and information tools.
๐ง ssh_network_info
Show all network interfaces and their IP addresses.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_network_info()
Returns: Interface names, IPv4/IPv6 addresses, MAC addresses, and status (UP/DOWN).
๐ง ssh_open_ports
List all open/listening ports (equivalent to ss -tlnp).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_open_ports()
Returns: Protocol, local address, port, and the process/PID listening on each port.
๐ง ssh_check_port
Test if a specific port is reachable from the remote server.
Useful for verifying firewall rules, checking if a service is accessible, or testing connectivity between servers.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
host |
str |
Yes | โ | Target hostname or IP to test. |
port |
int |
Yes | โ | Port number to test. |
session_name |
str |
No | 'default' |
Session to use. |
Example:
# Check if database port is reachable
ssh_check_port(host='db.internal', port=5432)
# Check if external API is accessible
ssh_check_port(host='api.example.com', port=443)
๐ง ssh_ping
Ping a host from the remote server.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
target |
str |
Yes | โ | Hostname or IP to ping. |
count |
int |
No | 4 |
Number of ping packets to send. |
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_ping(target='8.8.8.8', count=3)
Returns: Ping statistics including round-trip times (min/avg/max) and packet loss percentage.
๐ง ssh_dns_lookup
Perform DNS lookup for a domain (equivalent to dig or nslookup).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
domain |
str |
Yes | โ | Domain name to look up. |
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_dns_lookup(domain='example.com')
Returns: DNS records including A, AAAA, MX, NS, and CNAME records (where available).
Category 7: Docker Operations (7 tools)
Manage Docker containers, images, and compose stacks on the remote host.
๐ง ssh_docker_ps
List Docker containers.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
session_name |
str |
No | 'default' |
Session to use. |
all |
bool |
No | False |
If True, shows all containers (including stopped). Default shows only running. |
Examples:
# List running containers
ssh_docker_ps()
# List all containers (including stopped)
ssh_docker_ps(all=True)
๐ง ssh_docker_logs
View logs from a Docker container.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
container |
str |
Yes | โ | Container name or ID. |
session_name |
str |
No | 'default' |
Session to use. |
lines |
int |
No | 100 |
Number of log lines to retrieve. |
Example:
ssh_docker_logs(container='nginx-proxy', lines=50)
๐ง ssh_docker_exec
Execute a command inside a running Docker container.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
container |
str |
Yes | โ | Container name or ID. |
command |
str |
Yes | โ | Command to execute inside the container. |
session_name |
str |
No | 'default' |
Session to use. |
Examples:
# Check nginx config inside container
ssh_docker_exec(container='nginx', command='nginx -t')
# List files in a container
ssh_docker_exec(container='myapp', command='ls -la /app')
# Check environment variables
ssh_docker_exec(container='myapp', command='env')
๐ง ssh_docker_images
List all Docker images on the remote host.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_docker_images()
Returns: Repository, tag, image ID, creation date, and size for each image.
๐ง ssh_docker_stats
Show real-time resource usage statistics for running containers.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_docker_stats()
Returns: CPU %, memory usage/limit, memory %, network I/O, and block I/O for each running container.
๐ง ssh_docker_compose
Run Docker Compose commands on a compose project.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
action |
str |
Yes | โ | Compose action: 'up', 'down', 'restart', 'ps', or 'logs'. |
path |
str |
Yes | โ | Path to the docker-compose.yml file or its parent directory. |
session_name |
str |
No | 'default' |
Session to use. |
Examples:
# Start services in detached mode
ssh_docker_compose(action='up', path='/opt/myapp/docker-compose.yml')
# Check running services
ssh_docker_compose(action='ps', path='/opt/myapp/')
# Restart all services
ssh_docker_compose(action='restart', path='/opt/myapp/')
# Bring everything down
ssh_docker_compose(action='down', path='/opt/myapp/')
# View compose logs
ssh_docker_compose(action='logs', path='/opt/myapp/')
๐ง ssh_docker_inspect
Inspect a Docker container's configuration and state.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
container |
str |
Yes | โ | Container name or ID. |
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_docker_inspect(container='redis-cache')
Returns: Detailed JSON output including container config, network settings, mount points, environment variables, and state information.
Category 8: Package Management (4 tools)
Install, remove, and manage system packages. Auto-detects the package manager on the remote system:
| Distro Family | Package Manager |
|---|---|
| Debian / Ubuntu | apt |
| RHEL / CentOS / Fedora | yum or dnf |
| Arch Linux | pacman |
๐ง ssh_install_package
Install a system package.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
package |
str |
Yes | โ | Package name to install (e.g., 'nginx', 'htop', 'git'). |
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_install_package(package='nginx')
# Auto-detects: runs "apt install -y nginx" on Ubuntu, "yum install -y nginx" on CentOS, etc.
๐ง ssh_remove_package
Remove/uninstall a system package.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
package |
str |
Yes | โ | Package name to remove. |
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_remove_package(package='apache2')
๐ง ssh_list_packages
List installed packages with optional filtering.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
filter |
str |
No | โ | Filter pattern to search for (e.g., 'python', 'lib*ssl*'). |
session_name |
str |
No | 'default' |
Session to use. |
Examples:
# List all installed packages
ssh_list_packages()
# List only Python-related packages
ssh_list_packages(filter='python')
๐ง ssh_check_updates
Check for available package updates.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_check_updates()
Returns: List of packages with available updates, including current and available versions.
Category 9: User Management (4 tools)
View and inspect user accounts and login history.
๐ง ssh_list_users
List all user accounts on the system.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_list_users()
Returns: Username, UID, GID, home directory, and shell for each user.
๐ง ssh_user_info
Get detailed information about a specific user.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
username |
str |
Yes | โ | Username to look up. |
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_user_info(username='deploy')
Returns: Username, UID, GID, groups (primary and supplementary), home directory, shell, account status, and last login.
๐ง ssh_whoami
Show the current authenticated user on the remote session.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_whoami()
Returns: The username of the currently authenticated SSH user.
๐ง ssh_last_logins
Show recent login history.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_last_logins()
Returns: Recent login records including username, terminal, source IP/hostname, and login/logout times.
Category 10: Cron Jobs (3 tools)
Manage scheduled tasks (cron jobs) on the remote server.
๐ง ssh_list_cron
List all cron jobs for the current user (or root).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_list_cron()
Returns: All crontab entries with their schedule expressions and commands.
๐ง ssh_add_cron
Add a new cron job.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
schedule |
str |
Yes | โ | Cron schedule expression (e.g., '0 2 * * *' for daily at 2 AM). |
command |
str |
Yes | โ | Command to execute on schedule. |
session_name |
str |
No | 'default' |
Session to use. |
Examples:
# Daily backup at 2 AM
ssh_add_cron(schedule='0 2 * * *', command='/opt/scripts/backup.sh >> /var/log/backup.log 2>&1')
# Every 5 minutes health check
ssh_add_cron(schedule='*/5 * * * *', command='curl -s http://localhost:8080/health > /dev/null')
# Weekly log rotation on Sunday at midnight
ssh_add_cron(schedule='0 0 * * 0', command='/usr/sbin/logrotate /etc/logrotate.conf')
Cron Schedule Quick Reference:
โโโโโโโโโโโโโโ minute (0 - 59)
โ โโโโโโโโโโโโโโ hour (0 - 23)
โ โ โโโโโโโโโโโโโโ day of month (1 - 31)
โ โ โ โโโโโโโโโโโโโโ month (1 - 12)
โ โ โ โ โโโโโโโโโโโโโโ day of week (0 - 7, where 0 and 7 = Sunday)
โ โ โ โ โ
* * * * * command
๐ง ssh_remove_cron
Remove a cron job matching a pattern.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
pattern |
str |
Yes | โ | Pattern to match against cron entries. All matching entries are removed. |
session_name |
str |
No | 'default' |
Session to use. |
Example:
# Remove the backup cron job
ssh_remove_cron(pattern='backup.sh')
Category 11: Archive & Compression (2 tools)
Create and extract compressed archives.
๐ง ssh_compress
Create a compressed archive (tar.gz or zip).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
source |
str |
Yes | โ | Path to file or directory to compress. |
destination |
str |
Yes | โ | Output archive path (e.g., /tmp/backup.tar.gz or /tmp/files.zip). |
session_name |
str |
No | 'default' |
Session to use. |
Examples:
# Create a tar.gz archive
ssh_compress(source='/var/www/html', destination='/backups/site-backup.tar.gz')
# Create a zip archive
ssh_compress(source='/home/admin/documents', destination='/tmp/documents.zip')
The archive format is automatically determined by the file extension of
destination.
๐ง ssh_extract
Extract a compressed archive.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
source |
str |
Yes | โ | Path to the archive file. |
destination |
str |
Yes | โ | Directory to extract into. |
session_name |
str |
No | 'default' |
Session to use. |
Examples:
# Extract a tar.gz
ssh_extract(source='/backups/site-backup.tar.gz', destination='/var/www/html')
# Extract a zip
ssh_extract(source='/tmp/release-v2.zip', destination='/opt/app')
Supports
.tar.gz,.tgz,.tar.bz2,.tar.xz,.zip, and.tarformats.
Category 12: Security & Audit (3 tools)
Service management and security auditing tools.
๐ง ssh_check_service
Check the status of a systemd service (equivalent to systemctl status).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
service |
str |
Yes | โ | Service name (e.g., 'nginx', 'sshd', 'docker'). |
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_check_service(service='nginx')
Returns: Service active/inactive status, enabled/disabled state, PID, memory usage, and recent log entries.
๐ง ssh_manage_service
Start, stop, restart, enable, or disable a systemd service.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
service |
str |
Yes | โ | Service name. |
action |
str |
Yes | โ | Action to perform: 'start', 'stop', 'restart', 'enable', or 'disable'. |
session_name |
str |
No | 'default' |
Session to use. |
Examples:
# Restart nginx after config change
ssh_manage_service(service='nginx', action='restart')
# Enable a service to start on boot
ssh_manage_service(service='docker', action='enable')
# Stop a service
ssh_manage_service(service='apache2', action='stop')
๐ง ssh_failed_logins
Show failed SSH login attempts (checks auth logs and/or lastb).
Useful for security auditing โ detect brute-force attempts, unauthorized access, and suspicious login activity.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
session_name |
str |
No | 'default' |
Session to use. |
Example:
ssh_failed_logins()
Returns: Recent failed login attempts with timestamp, username attempted, source IP address, and authentication method.
๐ Multi-Session Usage Examples
One of the most powerful features of this MCP server is the ability to manage multiple Linux servers simultaneously through named sessions.
Example: Managing Production + Staging
You: "Connect to my production server at prod.example.com and staging at staging.example.com"
โ AI calls: ssh_connect(host='prod.example.com', username='admin', password='...', session_name='prod')
โ AI calls: ssh_connect(host='staging.example.com', username='admin', password='...', session_name='staging')
You: "Show disk usage on both servers"
โ AI calls: ssh_disk_usage(session_name='prod')
โ AI calls: ssh_disk_usage(session_name='staging')
โ AI presents a comparison table of disk usage across both environments
Example: Rolling Deployment Across Multiple Servers
You: "Connect to all three web servers"
โ ssh_connect(host='web1.internal', session_name='web1')
โ ssh_connect(host='web2.internal', session_name='web2')
โ ssh_connect(host='web3.internal', session_name='web3')
You: "Deploy the latest version to each server one at a time"
โ For each server:
1. ssh_manage_service(service='nginx', action='stop', session_name='web1')
2. ssh_execute(command='cd /var/www && git pull origin main', session_name='web1')
3. ssh_manage_service(service='nginx', action='start', session_name='web1')
4. ssh_check_service(service='nginx', session_name='web1') # verify healthy
โ Repeat for web2, web3...
Example: Comparing Configurations Across Environments
You: "Compare the nginx config between prod and staging"
โ ssh_read_file(path='/etc/nginx/nginx.conf', session_name='prod')
โ ssh_read_file(path='/etc/nginx/nginx.conf', session_name='staging')
โ AI shows a diff of the two configurations
Session Management
You: "Show me all my active sessions"
โ ssh_list_sessions()
Result:
โโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโโโ
โ Session โ Host โ Username โ Uptime โ Commands โ
โโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโผโโโโโโโโโผโโโโโโโโโโโค
โ prod โ prod.example.com โ admin โ 45m โ 23 โ
โ staging โ stg.example.com โ admin โ 42m โ 18 โ
โ web1 โ web1.internal โ deploy โ 12m โ 8 โ
โโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโดโโโโโโโโโดโโโโโโโโโโโ
You: "Disconnect from all servers"
โ ssh_disconnect_all()
๐ก Security Best Practices
1. Use SSH Key Authentication in Production
Password-based authentication is convenient for development but less secure. For production servers:
ssh_connect(host='prod.example.com', username='deploy', key_path='C:\\Users\\pawan\\.ssh\\prod_key')
Generate a key pair if you don't have one:
ssh-keygen -t ed25519 -C "mcp-server"
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@remote-host
2. Credential Cache File Permissions
The credential cache at ~/.ssh-mcp-cache/credentials.json is created with restricted permissions (600 โ owner read/write only). Verify this:
ls -la ~/.ssh-mcp-cache/credentials.json
# Should show: -rw------- 1 user user ... credentials.json
3. Don't Commit Credentials to Git
Never commit mcp.json files containing passwords to version control.
Add to your .gitignore:
# MCP configuration with credentials
.cursor/mcp.json
mcp.json
# SSH MCP credential cache
.ssh-mcp-cache/
4. Use Environment Variables or Interactive Mode
Instead of hardcoding passwords in config files:
- Option A: Set environment variables in your shell profile (they won't be in any file checked into git)
- Option B: Omit the
envsection entirely and let the server prompt you in chat
5. Principle of Least Privilege
Create a dedicated SSH user for MCP operations with only the permissions needed:
# On the remote server
sudo useradd -m -s /bin/bash mcp-user
sudo usermod -aG docker mcp-user # if Docker access is needed
# Avoid giving root access unless absolutely necessary
6. Network Security
- Use a VPN or SSH bastion host for accessing production servers
- Configure firewall rules to restrict SSH access to known IP addresses
- Consider using fail2ban to block brute-force attempts
๐ง Troubleshooting
Server Not Loading in AI IDE
Symptom: The MCP server shows as disconnected or doesn't appear in the tools list.
Solutions:
Verify
uvis in your PATH:uv --versionIf not found, reinstall uv or add it to your system PATH.
Check the config file path: Ensure your
mcp.jsonis in the correct location for your IDE (see Configuring Your AI IDE).Validate JSON syntax: A single missing comma or bracket will break the config. Use a JSON validator.
Check the
--directorypath: Make sure the path inargspoints to the actual project directory containingserver.py.Restart the IDE: Some IDEs only read MCP configs on startup.
Connection Refused
Symptom: ssh_connect fails with "Connection refused."
Solutions:
- Verify the host is reachable:
ping your-host - Check SSH is running on the remote host:
sudo systemctl status sshd - Verify the port:
Test-NetConnection -ComputerName your-host -Port 22 - Check firewall rules on both the remote server and your local network.
Authentication Failed
Symptom: ssh_connect fails with "Authentication failed."
Solutions:
- Verify credentials manually:
ssh username@host - Check username/password: Ensure no typos, especially with special characters.
- SSH key permissions: Private key files must have restricted permissions:
chmod 600 ~/.ssh/id_rsa - Server allows password auth: Check
/etc/ssh/sshd_configon the remote host:PasswordAuthentication yes
Command Timeout
Symptom: Commands fail with a timeout error.
Solutions:
- Increase the timeout parameter:
ssh_execute(command='find / -name "*.log"', timeout=120) - Use background execution for long-running commands:
ssh_execute_background(command='tar czf /backup/full.tar.gz /') - Check network latency between your machine and the remote host.
Debugging with MCP Inspector
For any issue, the MCP Inspector provides detailed insight:
cd C:\AI_Workspaces\Anti_Workspace\linux-ssh-mcp
uv run mcp dev server.py
This opens a browser-based UI where you can:
- See all registered tools and their schemas
- Test individual tools with custom inputs
- View raw JSON requests and responses
- Check server logs for errors
Common Error Messages
| Error Message | Likely Cause | Fix |
|---|---|---|
No active session 'default' |
Not connected yet | Call ssh_connect first |
Session 'prod' already exists |
Duplicate session name | Use a different name or disconnect first |
Connection timed out |
Host unreachable or wrong port | Check host, port, and firewall |
Authentication failed |
Wrong credentials | Verify username/password/key |
Permission denied |
Insufficient privileges | Use sudo or connect as root |
Command not found |
Missing tool on remote host | Install the required package |
No such file or directory |
Invalid path | Verify the path exists on the remote server |
๐ License
This project is licensed under the MIT License.
MIT License
Copyright (c) 2025
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.