Enhanced MCP SSH Agent - Batch execution, host grouping, file sync, retry & rate limiting
npm install @laomeifun/mcp-ssh~/.ssh/config and ~/.ssh/known_hosts files and executes commands using native SSH tools for maximum reliability.
mcp-ssh-*.dxt file from the GitHub releases page
.dxt file to install it in Claude Desktop
bash
npx @laomeifun/mcp-ssh
`
$3
By default, the server reads your SSH hosts from ~/.ssh/config. If you maintain a project-specific SSH config (recommended when you have many servers), you can point MCP SSH Agent at that file.
Option A: CLI flag (highest priority)
`bash
npx @laomeifun/mcp-ssh --ssh-config /path/to/your/ssh_config
`
Option B: Environment variable
`bash
SSH_CONFIG_PATH=/path/to/your/ssh_config npx @laomeifun/mcp-ssh
`
$3
Automatic Retry: Network failures (timeout, connection reset, etc.) are automatically retried with exponential backoff (default: 2 retries).
Rate Limiting: Built-in token bucket rate limiter prevents overwhelming servers (default: 10 requests/sec, burst 20). Configure via environment variables:
`bash
SSH_RATE_LIMIT=5 SSH_RATE_BURST=10 npx @laomeifun/mcp-ssh
`
$3
When you manage many servers, you can run the same command across multiple hosts and get aggregated results via the MCP tool:
- Tool: runBatchCommand
- Args: hosts: string[], command: string, optional concurrency, timeoutMs
$3
To keep your SSH config fully standard and portable, grouping is implemented via a separate JSON file (no non-standard SSH directives required).
- Default groups file path:
- Override with:
- --ssh-groups /path/to/groups.json
- SSH_GROUPS_PATH=/path/to/groups.json
Example groups file:
`json
{
"web-servers": ["web1", "web2"],
"db-servers": ["db1"]
}
`
Related tools:
- listHostGroups
- runGroupCommand (args: group, command, optional concurrency, timeoutMs)
$3
Distribute local files or directories to multiple remote servers in one command.
Tools:
- syncFile - Sync to a list of hosts
- Args: localPath, remotePath, hosts: string[]
- Optional: useRsync (default: false), delete (rsync only), concurrency, timeoutMs
- syncFileToGroup - Sync to all hosts in a named group
- Args: localPath, remotePath, group
- Optional: same as above
Examples:
`
Distribute a config file to web servers
syncFile("/local/nginx.conf", "/etc/nginx/nginx.conf", ["web1", "web2"])
Use rsync for a directory with delete
syncFileToGroup("/local/app/", "/opt/app/", "web-servers", { useRsync: true, delete: true })
`
#### Manual Claude Desktop Configuration
To use this MCP server with Claude Desktop using manual configuration, add the following to your MCP settings file:
On macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
On Windows: %APPDATA%/Claude/claude_desktop_config.json
`json
{
"mcpServers": {
"mcp-ssh": {
"command": "npx",
"args": [
"@laomeifun/mcp-ssh",
"--ssh-config",
"/path/to/your/ssh_config",
"--ssh-groups",
"/path/to/your/ssh_config.groups.json"
]
}
}
}
`
After adding this configuration, restart Claude Desktop. The SSH tools will be available for use in your conversations with Claude.
#### Global Installation
`bash
npm install -g @laomeifun/mcp-ssh
`
#### Local Development
`bash
git clone https://github.com/aiondadotcom/mcp-ssh.git
cd mcp-ssh
npm install
npm start
`
Example Usage
!MCP SSH Agent Example
The screenshot above shows the MCP SSH Agent in action, demonstrating how it integrates with MCP-compatible clients to provide seamless SSH operations.
$3
!Claude MCP Integration
This screenshot demonstrates the MCP SSH Agent integrated with Claude, showing how the AI assistant can directly manage SSH connections and execute remote commands through the MCP protocol.
Key Features
- Reliable SSH: Uses native ssh/scp commands instead of JavaScript SSH libraries
- Automatic Discovery: Finds hosts from SSH config and known_hosts files
- Full SSH Support: Works with SSH agents, keys, and all authentication methods
- File Operations: Upload and download files using scp
- Batch Commands: Execute multiple commands in sequence
- Error Handling: Comprehensive error reporting with timeouts
Functions
The agent provides the following MCP tools:
1. listKnownHosts() - Lists all known SSH hosts, prioritizing entries from ~/.ssh/config first, then additional hosts from ~/.ssh/known_hosts
2. runRemoteCommand(hostAlias, command) - Executes a command on a remote host using ssh
3. getHostInfo(hostAlias) - Returns detailed configuration for a specific host
4. checkConnectivity(hostAlias) - Tests SSH connectivity to a host
5. uploadFile(hostAlias, localPath, remotePath) - Uploads a file to the remote host using scp
6. downloadFile(hostAlias, remotePath, localPath) - Downloads a file from the remote host using scp
7. runCommandBatch(hostAlias, commands) - Executes multiple commands sequentially
Configuration Examples
$3
Here's how your Claude Desktop configuration should look:
`json
{
"mcpServers": {
"mcp-ssh": {
"command": "npx",
"args": ["@laomeifun/mcp-ssh"]
}
}
}
`
$3
If you prefer to run the server manually or integrate it with other MCP clients:
`json
{
"servers": {
"mcp-ssh": {
"command": "npx",
"args": ["@laomeifun/mcp-ssh"]
}
}
}
`
Requirements
- Node.js 18 or higher
- SSH client installed (ssh and scp commands available)
- SSH configuration files (~/.ssh/config and ~/.ssh/known_hosts)
Usage with Claude Desktop
Once configured, you can ask Claude to help you with SSH operations like:
- "List all my SSH hosts"
- "Check connectivity to my production server"
- "Run a command on my web server"
- "Upload this file to my remote server"
- "Download logs from my application server"
Claude will use the MCP SSH tools to perform these operations safely and efficiently.
Usage
The agent runs as a Model Context Protocol server over STDIO. When installed via npm, you can use it directly:
`bash
Run via npx (recommended)
npx @laomeifun/mcp-ssh
Or if installed globally
mcp-ssh
For development - run with debug output
npm start
`
The server communicates via clean JSON over STDIO, making it perfect for MCP clients like Claude Desktop.
Advanced Configuration
$3
- MCP_SILENT=true - Disable debug output (automatically set when used as MCP server)
$3
The agent reads from standard SSH configuration files:
- ~/.ssh/config - SSH client configuration (supports Include directives)
- ~/.ssh/known_hosts - Known host keys
Make sure your SSH keys are properly configured and accessible via SSH agent or key files.
#### Include Directive Support
The MCP SSH Agent fully supports SSH Include directives to organize your configuration across multiple files. However, there's an important SSH bug to be aware of:
⚠️ SSH Include Directive Bug Warning
SSH has a configuration parsing bug where Include statements must be placed at the beginning of your ~/.ssh/config file to work correctly. If placed at the end, SSH will read them but won't properly apply the included configurations.
✅ Correct placement (at the beginning):
`ssh-config
~/.ssh/config
Include ~/.ssh/config.d/*
Include ~/.ssh/work-hosts
Global settings
ServerAliveInterval 55
Host definitions
Host myserver
HostName example.com
`
❌ Incorrect placement (at the end) - won't work:
`ssh-config
~/.ssh/config
Global settings
ServerAliveInterval 55
Host definitions
Host myserver
HostName example.com
These Include statements won't work properly due to SSH bug:
Include ~/.ssh/config.d/*
Include ~/.ssh/work-hosts
`
The MCP SSH Agent correctly processes Include directives regardless of their placement in the file, so you'll get full host discovery even if SSH itself has issues with your configuration.
#### Example ~/.ssh/config
Here's an example SSH configuration file that demonstrates various connection scenarios including Include directives:
`ssh-config
Include directives must be at the beginning due to SSH bug
Include ~/.ssh/config.d/*
Include ~/.ssh/work-servers
Global settings - keep connections alive
ServerAliveInterval 55
Production server with jump host
Host prod
Hostname 203.0.113.10
Port 22022
User deploy
IdentityFile ~/.ssh/id_prod_rsa
Root access to production (separate entry)
Host root@prod
Hostname 203.0.113.10
Port 22022
User root
IdentityFile ~/.ssh/id_prod_rsa
Archive server accessed through production jump host
Host archive
Hostname 2001:db8:1f0:cafe::1
Port 22077
User archive-user
ProxyJump prod
Web servers with specific configurations
Host web1.example.com
Hostname 198.51.100.15
Port 22022
User root
IdentityFile ~/.ssh/id_ed25519
Host web2.example.com
Hostname 198.51.100.25
Port 22022
User root
IdentityFile ~/.ssh/id_ed25519
Database server with custom key
Host database
Hostname 203.0.113.50
Port 22077
User dbadmin
IdentityFile ~/.ssh/id_database_rsa
IdentitiesOnly yes
Mail servers
Host mail1
Hostname 198.51.100.88
Port 22078
User mailuser
Host root@mail1
Hostname 198.51.100.88
Port 22078
User root
Monitoring server
Host monitor
Hostname 203.0.113.100
Port 22077
User monitoring
IdentityFile ~/.ssh/id_monitor_ed25519
IdentitiesOnly yes
Load balancers
Host lb-a
Hostname 198.51.100.200
Port 22077
User root
Host lb-b
Hostname 198.51.100.201
Port 22077
User root
`
This configuration demonstrates:
- Global settings: ServerAliveInterval to keep connections alive
- Custom ports: Non-standard SSH ports for security
- Multiple users: Different user accounts for the same host (e.g., prod and root@prod)
- Jump hosts: Using ProxyJump to access servers through bastion hosts
- IPv6 addresses: Modern networking support
- Identity files: Specific SSH keys for different servers
- Security options: IdentitiesOnly yes to use only specified keys
#### How MCP SSH Agent Uses Your Configuration
The MCP SSH agent automatically discovers and uses your SSH configuration:
1. Host Discovery: All hosts from ~/.ssh/config are automatically available
2. Native SSH: Uses your system's ssh command, so all config options work
3. Authentication: Respects your SSH agent, key files, and authentication settings
4. Jump Hosts: Supports complex proxy chains and bastion host setups
5. Port Forwarding: Can work with custom ports and connection options
Example Usage with Claude Desktop:
- "List my SSH hosts" → Shows all configured hosts including prod, archive, web1.example.com, etc.
- "Connect to archive server" → Uses the ProxyJump configuration automatically
- "Run 'df -h' on web1.example.com" → Connects with the correct user, port, and key
- "Upload file to database server" → Uses the specific identity file and port configuration
Troubleshooting
$3
1. Command not found: Ensure ssh and scp are installed and in your PATH
2. Permission denied: Check SSH key permissions and SSH agent
3. Host not found: Verify host exists in ~/.ssh/config or ~/.ssh/known_hosts
4. Connection timeout: Check network connectivity and firewall settings
$3
Run with debug output to see detailed operation logs:
`bash
Enable debug mode
MCP_SILENT=false npx @laomeifun/mcp-ssh
`
SSH Key Setup Guide
For the MCP SSH Agent to work properly, you need to set up SSH key authentication. Here's a complete guide:
$3
Generate a new SSH key pair (use Ed25519 for better security):
`bash
Generate Ed25519 key (recommended)
ssh-keygen -t ed25519 -C "your-email@example.com"
Or generate RSA key (if Ed25519 is not supported)
ssh-keygen -t rsa -b 4096 -C "your-email@example.com"
`
Important: When prompted for a passphrase, leave it empty (press Enter). The MCP SSH Agent cannot handle password-protected keys as it runs non-interactively.
`
Enter passphrase (empty for no passphrase): [Press Enter]
Enter same passphrase again: [Press Enter]
`
This creates two files:
- ~/.ssh/id_ed25519 (private key) - Keep this secret!
- ~/.ssh/id_ed25519.pub (public key) - This gets copied to servers
$3
Copy your public key to the remote server's authorized_keys file:
`bash
Method 1: Using ssh-copy-id (easiest)
ssh-copy-id user@hostname
Method 2: Manual copy
cat ~/.ssh/id_ed25519.pub | ssh user@hostname "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
Method 3: Copy and paste manually
cat ~/.ssh/id_ed25519.pub
Then SSH to the server and paste into ~/.ssh/authorized_keys
`
$3
To enable secure key-only authentication on your SSH servers, edit /etc/ssh/sshd_config:
`bash
Edit SSH daemon configuration
sudo nano /etc/ssh/sshd_config
`
Add or modify these settings:
`ssh-config
Enable public key authentication
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
Disable password authentication (security best practice)
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no
Root login options (choose one):
Option 1: Allow root login with SSH keys only (recommended for admin access)
PermitRootLogin prohibit-password
Option 2: Completely disable root login (most secure, but less flexible)
PermitRootLogin no
Optional: Restrict SSH to specific users
AllowUsers deploy root admin
Optional: Change default port for security
Port 22022
`
After editing, restart the SSH service:
`bash
On Ubuntu/Debian
sudo systemctl restart ssh
On CentOS/RHEL/Fedora
sudo systemctl restart sshd
On macOS
sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist
sudo launchctl load /System/Library/LaunchDaemons/ssh.plist
`
$3
SSH is very strict about file permissions. Set them correctly:
On your local machine:
`bash
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
chmod 644 ~/.ssh/config
chmod 644 ~/.ssh/known_hosts
`
On the remote server:
`bash
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
`
$3
Test your connection before using with MCP SSH Agent:
`bash
Test connection
ssh -i ~/.ssh/id_ed25519 user@hostname
Test with verbose output for debugging
ssh -v -i ~/.ssh/id_ed25519 user@hostname
Test specific configuration
ssh -F ~/.ssh/config hostname
`
$3
You can create different keys for different servers:
`bash
Create specific keys
ssh-keygen -t ed25519 -f ~/.ssh/id_production -C "production-server"
ssh-keygen -t ed25519 -f ~/.ssh/id_staging -C "staging-server"
`
Then configure them in ~/.ssh/config:
`ssh-config
Host production
Hostname prod.example.com
User deploy
IdentityFile ~/.ssh/id_production
IdentitiesOnly yes
Host staging
Hostname staging.example.com
User deploy
IdentityFile ~/.ssh/id_staging
IdentitiesOnly yes
`
Security Best Practices
$3
- Never use password-protected keys with MCP SSH Agent
- Never share private keys - they should stay on your machine only
- Use Ed25519 keys when possible (more secure than RSA)
- Create separate keys for different environments/purposes
- Regularly rotate keys (every 6-12 months)
$3
- Disable password authentication completely
- Use non-standard SSH ports to reduce automated attacks
- Limit SSH access to specific users with AllowUsers
- Choose appropriate root login policy:
- PermitRootLogin prohibit-password - Allows root access with SSH keys only (recommended for admin tasks)
- PermitRootLogin no - Completely disables root login (most secure, but requires sudo access)
- Enable SSH key-only authentication for all accounts
- Consider using jump hosts for additional security layers
$3
- Use VPN or bastion hosts for production servers
- Implement fail2ban to block brute force attempts
- Monitor SSH logs regularly
- Use SSH key forwarding carefully (disable when not needed)
Building Desktop Extensions
For developers who want to build DXT packages locally:
$3
- Node.js 18 or higher
- npm
$3
`bash
Install dependencies
npm install
Build the DXT package
npm run build:dxt
`
This creates a .dxt file in the build/ directory that can be installed in Claude Desktop.
$3
To publish a new DXT release:
`bash
Build the DXT package
npm run build:dxt
Create a GitHub release with the DXT file
gh release create v1.0.3 build/mcp-ssh-1.0.3.dxt --title "Release v1.0.3" --notes "MCP SSH Agent v1.0.3"
`
The DXT file will be available as a release asset for users to download and install.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT License - see LICENSE file for details.
Project Structure
`
mcp-ssh/
├── server-simple.mjs # Main MCP server implementation
├── manifest.json # DXT package manifest
├── package.json # Dependencies and scripts
├── README.md # Documentation
├── LICENSE # MIT License
├── CHANGELOG.md # Release history
├── PUBLISHING.md # Publishing instructions
├── start.sh # Development startup script
├── start-silent.sh # Silent startup script
├── scripts/
│ └── build-dxt.sh # DXT package build script
├── doc/
│ ├── example.png # Usage example screenshot
│ └── Claude.png # Claude Desktop integration example
├── src/ # TypeScript source files (development)
│ ├── ssh-client.ts # SSH operations implementation
│ ├── ssh-config-parser.ts # SSH configuration parsing
│ └── types.ts # Type definitions
└── tsconfig.json # TypeScript configuration
``