linux-ssh-mcp
Provides tools for managing Docker containers and images on remote Linux servers, including operations like listing containers, starting/stopping containers, pulling images, and more.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@linux-ssh-mcpcheck disk usage on web01"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
🐧 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
Related MCP server: SSH MCP Server
🌐 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 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 |
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 higherIf 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 --versionWhy 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-mcpStep 2: Install dependencies
uv syncThis single command will:
Create a virtual environment (
.venv/) if one doesn't existRead
pyproject.tomlfor dependency declarationsInstall 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.pyThis 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 |
| A unique name for this MCP server (you can change it) |
| The executable to run ( |
| Arguments passed to |
| 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.jsonThe 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 indicatorIf red, check the logs for error details
2. 🤖 Claude Desktop
Configuration File Location
OS | Path |
Windows |
|
macOS |
|
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.jsonConfiguration
{
"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.jsonAdd 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 chatConnection 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 outputFor Manual Testing / Debugging
# Open the MCP Inspector (browser-based tool debugger)
uv run mcp dev server.pyThe 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 |
| No | — | Hostname or IP address of the remote Linux server. If not set, you must provide it when calling |
| No |
| SSH port number. Only change this if your server uses a non-standard SSH port. |
| No |
| SSH username for authentication. |
| No | — | SSH password for password-based authentication. Mutually optional with |
| No | — | Absolute path to an SSH private key file (e.g., |
| No |
| 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.jsonInteractive 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 |
|
| Yes* | — | Hostname or IP address of the remote server. *Optional if |
|
| No |
| SSH username. |
|
| No | — | SSH password. Either |
|
| No | — | Path to SSH private key file. |
|
| No |
| SSH port number. |
|
| No |
| 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 |
|
| No |
| 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 |
|
| No |
| Name to identify these saved credentials. |
|
| Yes | — | Hostname or IP address. |
|
| No |
| SSH username. |
|
| No | — | SSH password. |
|
| No | — | Path to SSH private key. |
|
| No |
| 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 |
|
| Yes | — | The shell command to execute. |
|
| No |
| Session to execute on. |
|
| No |
| 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 |
|
| Yes | — | Multi-line bash script content. |
|
| No |
| Session to execute on. |
|
| No |
| 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 |
|
| Yes | — | The command to run in the background. |
|
| No |
| Path to redirect stdout/stderr. |
|
| No |
| 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 |
|
| No |
| Directory path to list. |
|
| No |
| Session to use. |
|
| No |
| 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 |
|
| Yes | — | Directory path to create. |
|
| No |
| 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 |
|
| Yes | — | File path to read. |
|
| No |
| Session to use. |
|
| 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 |
|
| Yes | — | File path to write to. |
|
| Yes | — | Content to write. |
|
| No |
| Session to use. |
|
| No |
| If |
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 |
|
| Yes | — | Path to delete. |
|
| No |
| Session to use. |
|
| No |
| If |
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 |
|
| Yes | — | Source path. |
|
| Yes | — | Destination path. |
|
| No |
| 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 |
|
| Yes | — | Source path. |
|
| Yes | — | Destination path. |
|
| No |
| Session to use. |
|
| No |
| If |
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 |
|
| Yes | — | Path to inspect. |
|
| No |
| 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 |
|
| Yes | — | Path to modify. |
|
| Yes | — | Permission string in octal format (e.g., |
|
| No |
| Session to use. |
|
| No |
| If |
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 |
|
| Yes | — | Path to modify. |
|
| Yes | — | New owner username. |
|
| No | — | New group name. If omitted, only the owner is changed. |
|
| No |
| Session to use. |
|
| No |
| If |
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 |
|
| Yes | — | Starting directory for the search. |
|
| No | — | Filename pattern (supports wildcards, e.g., |
|
| No | — | Filter by type: |
|
| No | — | Filter by size (e.g., |
|
| No | — | Find files modified within a timeframe (e.g., |
|
| No |
| 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 |
|
| Yes | — | Path to check. |
|
| No |
| 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 |
|
| Yes | — | Text or regex pattern to search for. |
|
| Yes | — | File or directory path to search in. |
|
| No |
| Session to use. |
|
| No |
| If |
|
| No |
| If |
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 |
|
| Yes | — | File path to tail. |
|
| No |
| Number of lines to show from the end. |
|
| No |
| 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 |
|
| Yes | — | File path to read from. |
|
| No |
| Number of lines to show from the beginning. |
|
| No |
| 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 |
|
| Yes | — | Text pattern to search for in logs. |
|
| No | — | Specific log file to search. If omitted, searches the systemd journal. |
|
| No |
| Session to use. |
|
| No | — | Time filter (e.g., |
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 |
|
| Yes | — | Path to the file to modify. |
|
| Yes | — | Text or pattern to find. |
|
| Yes | — | Replacement text. |
|
| No |
| Session to use. |
|
| No |
| If |
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 |
|
| No |
| 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 |
|
| No |
| 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 |
|
| No |
| 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 |
|
| No |
| 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 |
|
| No |
| Session to use. |
|
| No | — | Filter processes by name pattern (e.g., |
|
| No | — | Sort by |
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 |
|
| No |
| Session to use. |
|
| No |
| Number of top processes to show. |
|
| No |
| Sort by |
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 |
|
| Yes | — | Process ID to kill. |
|
| No |
| Session to use. |
|
| No |
| Signal to send. Common values: |
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 |
|
| No |
| 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 |
|
| No |
| 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 |
|
| No |
| 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 |
|
| Yes | — | Target hostname or IP to test. |
|
| Yes | — | Port number to test. |
|
| No |
| 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 |
|
| Yes | — | Hostname or IP to ping. |
|
| No |
| Number of ping packets to send. |
|
| No |
| 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 |
|
| Yes | — | Domain name to look up. |
|
| No |
| 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 |
|
| No |
| Session to use. |
|
| No |
| If |
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 |
|
| Yes | — | Container name or ID. |
|
| No |
| Session to use. |
|
| No |
| 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 |
|
| Yes | — | Container name or ID. |
|
| Yes | — | Command to execute inside the container. |
|
| No |
| 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 |
|
| No |
| 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 |
|
| No |
| 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 |
|
| Yes | — | Compose action: |
|
| Yes | — | Path to the |
|
| No |
| 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 |
|
| Yes | — | Container name or ID. |
|
| No |
| 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 |
|
RHEL / CentOS / Fedora |
|
Arch Linux |
|
🔧 ssh_install_package
Install a system package.
Parameter | Type | Required | Default | Description |
|
| Yes | — | Package name to install (e.g., |
|
| No |
| 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 |
|
| Yes | — | Package name to remove. |
|
| No |
| Session to use. |
Example:
ssh_remove_package(package='apache2')🔧 ssh_list_packages
List installed packages with optional filtering.
Parameter | Type | Required | Default | Description |
|
| No | — | Filter pattern to search for (e.g., |
|
| No |
| 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 |
|
| No |
| 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 |
|
| No |
| 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 |
|
| Yes | — | Username to look up. |
|
| No |
| 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 |
|
| No |
| 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 |
|
| No |
| 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 |
|
| No |
| 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 |
|
| Yes | — | Cron schedule expression (e.g., |
|
| Yes | — | Command to execute on schedule. |
|
| No |
| 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 |
|
| Yes | — | Pattern to match against cron entries. All matching entries are removed. |
|
| No |
| 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 |
|
| Yes | — | Path to file or directory to compress. |
|
| Yes | — | Output archive path (e.g., |
|
| No |
| 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 |
|
| Yes | — | Path to the archive file. |
|
| Yes | — | Directory to extract into. |
|
| No |
| 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 |
|
| Yes | — | Service name (e.g., |
|
| No |
| 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 |
|
| Yes | — | Service name. |
|
| Yes | — | Action to perform: |
|
| No |
| 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 |
|
| No |
| 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 environmentsExample: 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 configurationsSession 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-host2. 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.json3. 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 necessary6. 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-hostCheck SSH is running on the remote host:
sudo systemctl status sshdVerify the port:
Test-NetConnection -ComputerName your-host -Port 22Check 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@hostCheck username/password: Ensure no typos, especially with special characters.
SSH key permissions: Private key files must have restricted permissions:
chmod 600 ~/.ssh/id_rsaServer 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.pyThis 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 |
| Not connected yet | Call |
| Duplicate session name | Use a different name or disconnect first |
| Host unreachable or wrong port | Check host, port, and firewall |
| Wrong credentials | Verify username/password/key |
| Insufficient privileges | Use |
| Missing tool on remote host | Install the required package |
| 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.Built with ❤️ using FastMCP + Paramiko
If you find this useful, give it a ⭐!
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/Pawangunjkar/linux-ssh-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server