Multi-SSH MCP Server
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., "@Multi-SSH MCP ServerConnect to web-server and run 'df -h'"
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.
Multi-Server SSH MCP Server
A Python-based Model Context Protocol (MCP) server that enables Claude to connect to and manage multiple SSH servers through a unified interface. Built with FastMCP, it provides secure, on-demand connections with comprehensive server management capabilities.
Table of Contents
Related MCP server: DesktopCommanderPy
Features
Multiple Server Support: Define unlimited SSH servers in JSON configuration
On-Demand Connections: Connects only when needed, one server at a time
Flexible Authentication: Supports both password and SSH key authentication
Environment Variables: Secure credential storage using environment variables
File Transfer: Upload and download files via SFTP
Command Execution: Execute commands on any configured server
Structured Output Parsing: Automatic JSON parsing of command outputs using JC library
Connection Management: Easy connect/disconnect with status tracking
Security First: Credentials never stored in configuration files
Multiple Transports: Supports both stdio (Claude Desktop) and SSE/HTTP modes
Docker Ready: Full containerization with Docker and Docker Compose support
Quick Start
1. Clone and Install
git clone <repository-url>
cd multi-ssh-mcpInstall dependencies (see Installation section for more options):
pip install -r requirements.txt
# or using UV (recommended)
uv sync2. Create Configuration
Copy the example configuration and customize for your servers:
cp ssh_config_example.json servers.json
# Edit servers.json with your server details3. Run the MCP Server
# Using default config (servers.json)
python3 multi_ssh_mcp.py
# Using UV
uv run multi_ssh_mcp.py
# With custom config
python3 multi_ssh_mcp.py --config my_servers.jsonInstallation
System Requirements
Python 3.10 or higher (or Docker)
SSH access to target servers
SSH keys or passwords for authentication
Docker Installation (Recommended)
Using Docker simplifies deployment and ensures consistent environments:
# Clone the repository
git clone <repository-url>
cd multi-ssh-mcp
# Build the Docker image
./scripts/build.sh
# Copy and configure your servers
cp ssh_config_example.json config/servers.json
# Edit config/servers.json with your server detailsLocal Installation
Install from requirements.txt:
pip install -r requirements.txtOr install manually:
pip install fastmcp>=2.0.0 paramiko>=3.0.0 jc>=1.25.0Development Dependencies
For development and testing:
pip install -e .[dev]Usage
Command Line Options
# Use default config file (servers.json in current directory)
python3 multi_ssh_mcp.py
# Specify config file path as positional argument
python3 multi_ssh_mcp.py /path/to/my_servers.json
# Use --config flag
python3 multi_ssh_mcp.py --config /path/to/my_servers.json
python3 multi_ssh_mcp.py -c servers.jsonHelp
python3 multi_ssh_mcp.py --helpConfiguration
1. Create Configuration File
Create your SSH servers configuration file (e.g., my_servers.json) with your server definitions. See the example configuration for the structure.
2. Authentication Methods
Password Authentication:
{
"host": "example.com",
"username": "user",
"auth_method": "password",
"password": "${ENV:SERVER_PASSWORD}"
}SSH Key Authentication:
{
"host": "example.com",
"username": "user",
"auth_method": "key",
"private_key_path": "~/.ssh/id_rsa",
"key_passphrase": "${ENV:KEY_PASSPHRASE}"
}3. Environment Variables
Set environment variables for secure credential storage (when using ${ENV:VAR_NAME} in config):
export STAGING_PASSWORD="your_staging_password"
export PROD_KEY_PASSPHRASE="your_key_passphrase"
export BACKUP_PASSWORD="your_backup_password"Claude Desktop Integration
Configuration
Add this to your claude_desktop_config.json:
{
"mcpServers": {
"Multi-SSH MCP Server": {
"command": "uv",
"args": [
"run",
"--with",
"fastmcp,paramiko",
"python3",
"/path/to/multi-ssh-mcp/multi_ssh_mcp.py",
"/path/to/multi-ssh-mcp/servers.json"
]
}
}
}Alternative Configurations
Using Python directly (if dependencies are already installed):
{
"mcpServers": {
"Multi-SSH MCP Server": {
"command": "python3",
"args": [
"/path/to/multi-ssh-mcp/multi_ssh_mcp.py",
"/path/to/multi-ssh-mcp/servers.json"
]
}
}
}Using --config flag:
{
"mcpServers": {
"Multi-SSH MCP Server": {
"command": "uv",
"args": [
"run",
"--with",
"fastmcp,paramiko",
"python3",
"/path/to/multi-ssh-mcp/multi_ssh_mcp.py",
"--config",
"/path/to/multi-ssh-mcp/servers.json"
]
}
}
}Using default config location (servers.json in script directory):
{
"mcpServers": {
"Multi-SSH MCP Server": {
"command": "uv",
"args": [
"run",
"--with",
"fastmcp,paramiko",
"python3",
"/path/to/multi-ssh-mcp/multi_ssh_mcp.py"
]
}
}
}Note: Replace
/path/to/multi-ssh-mcp/with the actual absolute path to your cloned repository.
Docker Setup
The Multi-SSH MCP server can be run in Docker containers with support for both stdio (for Claude Desktop) and SSE/HTTP modes.
Quick Start with Docker
Build the Docker image:
./scripts/build.shRun in stdio mode (for Claude Desktop):
./scripts/run-docker.sh stdioRun in SSE/HTTP mode:
./scripts/run-docker.sh sse # Server will be available at http://localhost:8080
Docker Compose Options
# Run in stdio mode
docker-compose --profile stdio run --rm mcp-ssh-stdio
# Run in SSE/HTTP mode
docker-compose --profile sse up -d
# Run in development mode with hot reload
docker-compose --profile dev upClaude Desktop Configuration for Docker
Add this to your claude_desktop_config.json:
{
"mcpServers": {
"Multi-SSH MCP (Docker)": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-v", "/path/to/config:/config:ro",
"-v", "${HOME}/.ssh:/home/mcp/.ssh:ro",
"-e", "SSH_PASSWORD_PROD",
"-e", "SSH_PASSWORD_STAGING",
"multi-ssh-mcp:latest"
]
}
}
}Available Tools
Tool | Description |
list_servers | Lists all configured SSH servers with their details |
connect_server | Connects to a specific SSH server |
disconnect_server | Disconnects from the current SSH server |
execute_command | Executes commands with automatic output parsing (JC library) |
execute_batch_commands | Executes multiple commands concurrently on one server |
execute_command_on_multiple_servers | Executes the same command concurrently across multiple servers |
upload_file | Uploads files via SFTP with path validation |
download_file | Downloads files via SFTP with path validation |
get_current_connection | Shows current SSH connection status |
ping | Secure ping with count limits and source interface support |
traceroute | Traceroute with hop control and automatic parsing |
network_diagnostics | Run safe network commands (dig, nslookup, netstat, ss, ip) |
Core SSH Tools
list_servers(): Show all configured serversconnect_server(server_name): Connect to a specific serverdisconnect_server(): Close current connectionget_current_connection(): Check connection status
Command Execution
execute_command(command, server_name=None, parse_output=None): Run commands with JC parsingAuto-parses common commands (ls, ps, df, netstat, etc.)
Optional parse_output: None (auto), True (force), False (disable)
execute_batch_commands(server_name, commands, parse_output=None, max_workers=5): Run multiple commands in parallel on one serverUses isolated SSH sessions per command for safe concurrency
Returns per-command success/error, stdout/stderr, exit code, and summary stats
execute_command_on_multiple_servers(command, server_names=None, parse_output=None, max_workers=5): Run one command in parallel on many serversIf
server_namesis omitted, runs on all configured serversReturns per-server success/error, stdout/stderr, exit code, and summary stats
File Transfer
upload_file(local_path, remote_path, server_name=None): SFTP uploaddownload_file(remote_path, local_path, server_name=None): SFTP download
Network Diagnostics
ping(destination, server_name=None, count=5, source_interface=None): Test connectivitytraceroute(destination, server_name=None, max_hops=30, source_interface=None): Trace network pathnetwork_diagnostics(command_type, destination, server_name=None): Run network toolsSupported commands: nslookup, dig, netstat, ss, ip
Output Parsing with JC
The MCP server automatically parses command outputs into structured JSON format using the JC library. This makes it easier to analyze and process command results.
Automatic Parsing
Common commands like ls, ps, df, netstat, ifconfig, and many others are automatically parsed when executed.
Parsing Control
Use the parse_output parameter in execute_command:
None(default): Auto-parse supported commandsTrue: Force parsing attemptFalse: Disable parsing, return raw output only
Example
When running df -h, instead of raw text output, you'll receive structured JSON data with fields like filesystem, size, used, available, use_percent, and mount_point.
Usage Examples
List available servers:
"Show me all configured SSH servers"Connect and run commands:
"Connect to the production server and check disk usage" "Run 'ps aux | grep nginx' on web-server-1"File operations:
"Upload my local script.sh to /tmp/ on the staging server" "Download the nginx config from production server"Multi-server workflows:
"Check the system load on all web servers" "Deploy the config file to both staging and production"
Security Considerations
Built-in Security Features
Command Injection Prevention: All user inputs are sanitized and validated
Path Validation: File paths are checked for directory traversal attempts
Command Whitelisting: Only safe commands are allowed in execute_command
Argument Sanitization: Special characters and shell metacharacters are filtered
Network Input Validation: IP addresses and hostnames are validated
Best Practices
Store sensitive credentials in environment variables, not in the JSON config
Use SSH keys instead of passwords when possible
Limit SSH key permissions and use dedicated keys for automation
Keep your configuration file secure (proper file permissions)
Consider using SSH agent for key management
Security Restrictions
The following are blocked for security:
Command chaining (&&, ||, ;)
Shell redirections (>, <, |)
Command substitution ($(), ``)
Environment variable expansion (except for echo $VAR)
Directory traversal in file paths (..)
Troubleshooting
Connection Issues
Verify server hostnames and ports are correct
Check that SSH keys exist and have proper permissions (
chmod 600)Ensure environment variables are set correctly
Test SSH connections manually first:
ssh user@host
Authentication Failures
For key auth: verify the key path and passphrase
For password auth: check the password in environment variables
Ensure the SSH server accepts the authentication method
Configuration Problems
Validate JSON syntax in your config file
Check file permissions on config and key files
Verify the config file path is correct
Logging
The server logs connection attempts and errors. To see detailed logs, run with:
python3 multi_ssh_mcp.py 2>&1 | tee ssh_mcp.logEnvironment Variables
The MCP server supports the following environment variables:
Transport Configuration
MCP_TRANSPORT: Transport mode (stdioorsse, default:stdio)MCP_HOST: Host for SSE mode (default:0.0.0.0)MCP_PORT: Port for SSE mode (default:8080)MCP_CONFIG_PATH: Path to servers.json file (default:servers.json)
SSH Credentials
SSH_PASSWORD_<SERVER_NAME>: Password for specific serverSSH_KEY_PASSPHRASE: Passphrase for SSH keysAny custom variables referenced in your servers.json
Docker-specific
PYTHONUNBUFFERED: Set to1for immediate log output
SSE/HTTP Mode
The Multi-SSH MCP server supports Server-Sent Events (SSE) for HTTP-based communication, making it accessible from web applications and HTTP clients.
Running in SSE Mode
Using Docker:
./scripts/run-docker.sh sse # or docker-compose --profile sse up -dLocal Python:
MCP_TRANSPORT=sse MCP_PORT=8080 python multi_ssh_mcp.py
HTTP Endpoints
When running with MCP_TRANSPORT=sse, the server provides:
GET /sse- Server-Sent Events stream for real-time MCP messagesPOST /messages- Send commands to the MCP serverGET /health- Health check endpoint for monitoring
Client Integration
JavaScript/TypeScript Example:
// Connect to SSE endpoint
const eventSource = new EventSource('http://localhost:8080/sse');
// Handle incoming messages
eventSource.onmessage = (event) => {
const message = JSON.parse(event.data);
console.log('MCP Response:', message);
};
// Send MCP commands
async function sendCommand(method, params) {
const response = await fetch('http://localhost:8080/messages', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
method: method,
params: params,
id: Date.now()
})
});
return response.json();
}
// Example: List servers
sendCommand('list_servers', {});Python Client Example:
import requests
import sseclient
# Connect to SSE stream
response = requests.get('http://localhost:8080/sse', stream=True)
client = sseclient.SSEClient(response)
# Send command
def send_command(method, params=None):
return requests.post('http://localhost:8080/messages', json={
'jsonrpc': '2.0',
'method': method,
'params': params or {},
'id': 1
}).json()
# Example usage
servers = send_command('list_servers')
print(servers)Use Cases for SSE Mode
Web Applications: Build web UIs for SSH management
Microservices: Integrate SSH operations into HTTP-based architectures
Monitoring Systems: Stream real-time command outputs
API Gateways: Expose SSH functionality through REST APIs
License
MIT License - feel free to modify and use as needed.
This server cannot be installed
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/vignitin/multi-ssh-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server