frah/ssh-mcp
If you are the rightful owner of ssh-mcp 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 Model Context Protocol (MCP) server that provides secure SSH control for Linux and Windows servers.
SSH MCP Server
A Model Context Protocol (MCP) server that provides secure SSH control for Linux and Windows servers. Execute remote shell commands, transfer files, and manage multiple server connections through a standardized MCP interface.
Features
- Multiple Authentication Methods: Password and SSH key authentication
- Multi-hop SSH Support: Connect through multiple jump hosts/bastions
- File Operations: Upload and download files via SFTP
- Security Controls: Command whitelist/blacklist configuration
- Connection Pooling: Efficient connection management and reuse
- TypeScript: Full type safety and modern JavaScript features
- Bun Runtime: Fast execution and built-in TypeScript support
Installation
Prerequisites
- Bun runtime installed
- Node.js 18+ (for compatibility)
Quick Start (using bunx)
Run directly without installation:
# Generate example config file
bunx @frah/ssh-mcp --example-config > config.json
# Run with default config (./config.json)
bunx @frah/ssh-mcp
# Run with custom config file
bunx @frah/ssh-mcp --config /path/to/your/config.json
# Show help
bunx @frah/ssh-mcp --help
Local Setup
- Clone the repository:
git clone https://github.com/frah/ssh-mcp.git
cd ssh-mcp
- Install dependencies:
bun install
- Copy and configure the example config:
cp config.example.json config.json
# Edit config.json with your server details
Configuration
Create a config.json file based on the provided example:
{
"connections": [
{
"id": "dev-server",
"host": "192.168.1.100",
"port": 22,
"username": "developer",
"password": "your-password",
"description": "Development environment server",
"commandWhitelist": ["^ls", "^cat", "^grep"],
"timeout": 30000
},
{
"id": "prod-server",
"host": "prod.example.com",
"username": "admin",
"privateKeyPath": "/path/to/key",
"commandBlacklist": ["^rm", "^dd"]
}
],
"globalSettings": {
"maxConnections": 10,
"defaultTimeout": 30000,
"idleTimeout": 60000
}
}
Connection Configuration Options
id: Unique identifier for the connectionhost: Server hostname or IP addressport: SSH port (default: 22)username: SSH usernamepassword: Password authentication (optional)privateKey: Private key content as string (optional)privateKeyPath: Path to private key file (optional)passphrase: Private key passphrase (optional)description: Human-readable description of the connection (optional)proxy: Array of proxy configurations for multi-hop connectionscommandWhitelist: Regex patterns for allowed commandscommandBlacklist: Regex patterns for blocked commandstimeout: Command execution timeout in milliseconds
Global Settings Options
defaultTimeout: Default command execution timeout in millisecondsmaxConnections: Maximum number of concurrent SSH connectionsidleTimeout: SSH connection idle timeout in milliseconds (default: 60000)commandWhitelist: Global regex patterns for allowed commandscommandBlacklist: Global regex patterns for blocked commands
Multi-hop SSH Configuration
For connections through bastion hosts:
{
"id": "internal-server",
"host": "10.0.1.50",
"username": "app-user",
"privateKeyPath": "/path/to/key",
"proxy": [
{
"host": "bastion.example.com",
"username": "bastion-user",
"privateKeyPath": "/path/to/bastion/key"
}
]
}
Usage
Running the Server
Using bunx (No Installation Required)
# Run with default config (./config.json)
bunx @frah/ssh-mcp
# Run with custom config file
bunx @frah/ssh-mcp --config /path/to/your/config.json
From Source
Start the MCP server (Bun natively supports TypeScript):
bun run dev
# or directly
bun src/index.ts
Production Build
For production deployment with Node.js:
bun run build
node dist/index.js
Command Line Options
-c, --config <path>: Specify path to configuration file (default:./config.json)-h, --help: Show help message-v, --version: Show version number--example-config: Output example configuration JSON to stdout
Examples:
ssh-mcp # Start with default config
ssh-mcp --config /etc/ssh-mcp/config.json # Use custom config path
ssh-mcp --example-config > config.json # Generate config file
ssh-mcp --help # Show help information
ssh-mcp --version # Show version
Available MCP Tools
1. ssh_execute
Execute commands on remote servers.
Parameters:
connectionId(string): Connection ID from configcommand(string): Command to executetimeout(number, optional): Timeout in milliseconds
Example:
{
"tool": "ssh_execute",
"arguments": {
"connectionId": "dev-server",
"command": "ls -la /var/log",
"timeout": 5000
}
}
2. ssh_upload
Upload files to remote server via SFTP.
Parameters:
connectionId(string): Connection ID from configlocalPath(string): Local file pathremotePath(string): Remote destination path
Example:
{
"tool": "ssh_upload",
"arguments": {
"connectionId": "dev-server",
"localPath": "/local/file.txt",
"remotePath": "/remote/file.txt"
}
}
3. ssh_download
Download files from remote server via SFTP.
Parameters:
connectionId(string): Connection ID from configremotePath(string): Remote file pathlocalPath(string): Local destination path
Example:
{
"tool": "ssh_download",
"arguments": {
"connectionId": "dev-server",
"remotePath": "/remote/log.txt",
"localPath": "/local/log.txt"
}
}
4. ssh_list_servers
List all configured SSH server definitions.
Parameters: None
Returns: Array of server configurations with:
id: Connection identifierhost: Server hostnameport: SSH port numberusername: SSH usernamedescription: Human-readable description (if configured)
Example:
{
"tool": "ssh_list_servers",
"arguments": {}
}
Response Example:
[
{
"id": "dev-server",
"host": "192.168.1.100",
"port": 22,
"username": "developer",
"description": "Development environment server"
},
{
"id": "prod-server",
"host": "prod.example.com",
"port": 22,
"username": "admin",
"description": ""
}
]
Security Features
Command Filtering
The server supports both whitelist and blacklist patterns for commands:
- Whitelist: Only commands matching these patterns are allowed
- Blacklist: Commands matching these patterns are blocked
- Patterns are evaluated as regular expressions
- Connection-specific rules override global rules
Built-in Dangerous Command Protection
The following dangerous commands are always blocked:
rm -rf /and variants- Disk formatting commands
- Fork bombs
- Direct disk write operations
Path Sanitization
All file paths are automatically sanitized to prevent directory traversal attacks.
Claude Code Integration
To use this MCP server with Claude Code, follow these steps:
1. Configure Claude Code
Add the MCP server to your Claude Code configuration file:
Configuration File Location:
Option A: Global Configuration
- Linux/macOS:
~/.claude.json - Windows:
%USERPROFILE%\.claude.json
Option B: Project-Specific Configuration
Create .claude/settings.local.json in your project directory.
Configuration Example:
Using bunx (Recommended - No Installation Required):
{
"mcpServers": {
"ssh-mcp": {
"command": "bunx",
"args": ["@frah/ssh-mcp", "--config", "/absolute/path/to/your/config.json"]
}
}
}
Using Local Installation:
{
"mcpServers": {
"ssh-mcp": {
"command": "bun",
"args": ["run", "/absolute/path/to/ssh-mcp/src/index.ts", "--config", "/absolute/path/to/your/config.json"]
}
}
}
Example for Windows:
{
"mcpServers": {
"ssh-mcp": {
"command": "bunx",
"args": ["@frah/ssh-mcp", "--config", "C:\\Users\\YourName\\ssh-mcp-config.json"]
}
}
}
Important Notes:
- When using
bunx, you only need to specify the config file path - The config file path in
--configmust be absolute, not relative - bunx will automatically download and run the latest version of ssh-mcp
2. Create Configuration File
Ensure you have a config.json file in the ssh-mcp directory:
cd /absolute/path/to/ssh-mcp
cp config.example.json config.json
# Edit config.json with your server details
3. Verify Configuration
You can verify the MCP server is properly configured by running:
# Test the server directly
bun run /absolute/path/to/ssh-mcp/src/index.ts
# Or inside Claude Code, use the slash command
/mcp
If the server starts successfully, you should see log messages indicating the server is running.
4. Restart Claude Code
After configuring the MCP server, restart Claude Code to load the new configuration.
5. Usage in Claude Code
Once configured, you can use the SSH tools in Claude Code conversations:
Example commands:
- "Show me the list of available SSH servers"
- "Execute
ls -laon my development server" - "Upload the local file
app.logto/var/log/app.logon production" - "Download
/etc/nginx/nginx.conffrom the web server to my local machine"
With the ssh_list_servers tool, Claude can automatically discover available connections and select the appropriate server based on your natural language description.
Alternative: Using Node.js
If you prefer to use Node.js instead of Bun, you need to first build the project:
bun run build
Then configure it as:
{
"mcpServers": {
"ssh-mcp": {
"command": "node",
"args": ["/absolute/path/to/ssh-mcp/dist/index.js", "--config", "/absolute/path/to/your/config.json"]
}
}
}
Notes:
- Replace
/absolute/path/to/ssh-mcpwith the full absolute path to your ssh-mcp directory - Make sure Node.js 18+ is installed and run
bun installto install dependencies - The
--configparameter is optional if your config.json is in the ssh-mcp directory
Environment Variables
LOG_LEVEL: Set logging level (debug, info, warn, error)LOG_FILE: Path to log file (optional)
Example:
LOG_LEVEL=debug LOG_FILE=ssh-mcp.log bun run dev
Development
Project Structure
ssh-mcp/
├── src/
│ ├── index.ts # MCP server entry point
│ ├── ssh/
│ │ └── connection.ts # SSH connection management
│ ├── tools/
│ │ ├── execute.ts # Command execution
│ │ └── file.ts # File operations
│ ├── security/
│ │ └── validator.ts # Security validation
│ ├── config/
│ │ └── manager.ts # Configuration management
│ └── utils/
│ └── logger.ts # Logging utilities
├── tests/ # Test files
├── config.example.json # Example configuration
└── package.json
Running Tests
bun test
Type Checking
bun run lint
Troubleshooting
MCP Configuration Issues
-
"No MCP servers configured":
- Check file path in configuration is absolute, not relative
- Verify
.claude.jsonfile location and JSON syntax - Make sure Bun is installed and in PATH
-
Server not starting:
- Test the command manually:
bun run /full/path/to/ssh-mcp/src/index.ts - Check for TypeScript compilation errors
- Verify all dependencies are installed:
bun install
- Test the command manually:
Connection Issues
- Authentication Failed: Check username/password or key file permissions
- Connection Timeout: Verify network connectivity and firewall rules
- Key Permission Error: Ensure private key has 600 permissions
Command Execution Issues
- Command Blocked: Check whitelist/blacklist configuration
- Timeout Error: Increase timeout value in config or command
- Permission Denied: Verify user has necessary permissions on remote server
Debug Mode
Enable debug logging for troubleshooting:
LOG_LEVEL=debug bun run dev
License
MIT