kunwarmahen/ssh-mcp-server
If you are the rightful owner of ssh-mcp-server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
A secure Model Context Protocol (MCP) server that enables remote SSH command execution with strict read-only enforcement.
SSH Read-Only MCP Server
A secure Model Context Protocol (MCP) server that enables remote SSH command execution with strict read-only enforcement. Perfect for safely delegating SSH access to Claude while preventing accidental or malicious write operations.
Features
✅ Read-Only Command Enforcement – Only allows safe, read-only commands
✅ SSH Connection Pooling – Support multiple simultaneous connections
✅ Command Validation – Blocks dangerous patterns and write operations
✅ Multicast Discovery – Auto-announces on network for easy discovery
✅ Flexible Transport – Stdio, HTTP, or Streamable-HTTP modes
✅ Comprehensive Logging – Full audit trail in ssh_mcp.log
✅ Environment Configuration – Fully configurable via .env
Installation
Prerequisites
- Python 3.8+
uvpackage manager
Setup
# Clone or create project directory
mkdir ssh-mcp-server
cd ssh-mcp-server
# Initialize uv project (if needed)
uv init
# Install dependencies
uv pip install fastmcp paramiko python-dotenv
Or use pyproject.toml:
[project]
name = "ssh-mcp-server"
version = "0.1.0"
dependencies = [
"fastmcp>=0.1.0",
"paramiko>=3.0.0",
"python-dotenv>=1.0.0",
]
Then install:
uv sync
Configuration
Create a .env file in the project root:
# Transport mode: stdio (default), http, or streamable-http
MCP_TRANSPORT=stdio
# Server identification
MCP_SERVER_NAME=SSH Read-Only MCP Server
# HTTP mode settings (if using http/streamable-http)
MCP_HOST=0.0.0.0
MCP_PORT=3000
# Multicast discovery
MCP_ENABLE_BROADCAST=true
MCP_BROADCAST_INTERVAL=30
Environment Variables
| Variable | Default | Description |
|---|---|---|
MCP_TRANSPORT | stdio | Communication transport: stdio, http, or streamable-http |
MCP_SERVER_NAME | SSH Read-Only MCP Server | Display name for the server |
MCP_HOST | 0.0.0.0 | Bind address for HTTP mode |
MCP_PORT | 3000 | Port for HTTP mode |
MCP_ENABLE_BROADCAST | true | Enable multicast discovery announcements |
MCP_BROADCAST_INTERVAL | 30 | Seconds between broadcast announcements |
Usage
Start the Server
Stdio mode (default):
uv run ssh_readonly_fastmcp_mcast.py
HTTP mode with multicast discovery:
MCP_TRANSPORT=http MCP_PORT=3000 uv run ssh_readonly_fastmcp_mcast.py
HTTP mode without broadcasting:
MCP_ENABLE_BROADCAST=false MCP_TRANSPORT=http MCP_PORT=3000 uv run ssh_readonly_fastmcp_mcast.py
Available Tools
1. ssh_connect
Establish an SSH connection to a remote machine.
Parameters:
host(required) – Remote host IP or hostnameusername(required) – SSH usernameport(optional, default: 22) – SSH portkey_filename(optional) – Path to private key file (recommended)password(optional) – SSH password (fallback)
Example:
Connect to 192.168.1.100 as user 'admin' with private key
host: 192.168.1.100
username: admin
key_filename: /home/user/.ssh/id_rsa
2. ssh_execute
Execute a read-only command on the connected remote machine.
Parameters:
host(required) – Remote host (must be connected first)username(required) – SSH usernamecommand(required) – Read-only command to executeport(optional, default: 22) – SSH port
Example:
Run 'ls -la /home' on connected server
host: 192.168.1.100
username: admin
command: ls -la /home
3. ssh_disconnect
Close an SSH connection.
Parameters:
host(required) – Remote hostusername(required) – SSH usernameport(optional, default: 22) – SSH port
4. ssh_list_connections
View all active SSH connections.
Parameters: None
5. ssh_get_allowed_commands
Retrieve the list of allowed read-only commands.
Parameters: None
Allowed Commands
The server permits the following read-only operations:
- File operations:
cat,ls,file,head,tail,find,locate - System info:
ps,top,df,du,free,uname,hostname,uptime - Network:
netstat,ss,ifconfig,ip,curl,wget,dig,nslookup,ping,traceroute - Process management:
lsof,systemctl,service - Text processing:
grep,awk,sed,wc - And many more read-only utilities
Blocked operations: rm, mv, cp, chmod, chown, mkdir, touch, kill, shutdown, reboot, sudo, and any write/modify commands.
Multicast Discovery
When running in HTTP mode with broadcasting enabled, the server announces itself on the multicast group:
- Address:
239.255.255.250 - Port:
5353 - Interval: Configurable (default: 30 seconds)
Discovery announcement includes:
- Server UUID
- Server name
- Local IP and port
- Transport type
- Protocol version
Logging
All activity is logged to ssh_mcp.log:
2025-10-17 10:30:45,123 [INFO] ssh_mcp - Starting MCP server with transport=http
2025-10-17 10:30:46,456 [INFO] ssh_mcp - Starting multicast broadcaster on 239.255.255.250:5353
2025-10-17 10:30:47,789 [INFO] ssh_mcp - Successfully connected to admin@192.168.1.100:22
Security Considerations
🔒 Read-Only Enforcement:
- Only whitelisted commands are allowed
- Dangerous patterns (pipes, redirects, subshells) are blocked
- Write operations are prevented at the command level
⏱️ Timeouts:
- 30-second execution timeout per command
- Prevents hanging commands from blocking the server
🔐 Authentication:
- SSH key authentication recommended over passwords
- Passwords stored in memory only, never persisted
📋 Audit Trail:
- All connections and commands are logged
- Review
ssh_mcp.logfor security audits
Troubleshooting
Connection Refused
Error: Connection failed: [Errno 111] Connection refused
- Verify the remote host is reachable:
ping <host> - Check SSH is running on the remote machine
- Verify port number (default 22)
Authentication Failed
Error: Connection failed: Authentication failed
- Verify username is correct
- For key auth: check key file path and permissions (
chmod 600) - For password auth: verify credentials
- Ensure SSH public key is authorized on remote (
~/.ssh/authorized_keys)
Command Not Allowed
Error: Command not allowed for security reasons
- The command contains a blocked pattern or is not in the allowed list
- Use
ssh_get_allowed_commandsto see permitted commands - For write operations, use SSH directly instead
Broadcast Not Working
- Verify
MCP_ENABLE_BROADCAST=true - Check network supports multicast (most corporate networks block it)
- Verify firewall allows UDP on port 5353
- Check
ssh_mcp.logfor broadcast errors
Development
Running in Debug Mode
DEBUG=true uv run ssh_readonly_fastmcp_mcast.py
Testing
# Test connection
uv run -c "from ssh_readonly_fastmcp_mcast import is_command_safe; print(is_command_safe('ls -la'))"
# Should print: True
# Test blocked command
uv run -c "from ssh_readonly_fastmcp_mcast import is_command_safe; print(is_command_safe('rm -rf /'))"
# Should print: False
Project Structure
ssh-mcp-server/
├── ssh_readonly_fastmcp_mcast.py # Main server implementation
├── .env # Configuration file
├── .env.example # Configuration template
├── ssh_mcp.log # Server logs (auto-generated)
├── pyproject.toml # Project metadata
└── README.md # This file
API Response Format
All tools return consistent JSON responses:
Success:
{
"status": "success",
"host": "192.168.1.100",
"command": "ls -la /home",
"exit_code": 0,
"output": "total 24\ndrwxr-xr-x 3 root root 4096...",
"error": null
}
Error:
{
"status": "error",
"message": "Command not allowed for security reasons",
"reason": "Only read-only commands are permitted"
}
License
MIT
Contributing
Contributions welcome! Please ensure:
- All changes maintain read-only enforcement
- Code is logged appropriately
- Tests pass for security validations
Support
For issues or questions:
- Check
ssh_mcp.logfor error details - Review the Troubleshooting section
- Verify environment configuration
- Check network connectivity to remote hosts