ssh-mcp-server

repository·main·Indexed 20 days ago

https://github.com/classfang/ssh-mcp-server

An MCP (Model Context Protocol) server that enables AI assistants to execute remote SSH commands and manage files. It provides a secure bridge between AI models and remote infrastructure, supporting password and private key authentication, SOCKS proxies, and dual transport modes (exec and shell). Key features include command whitelisting/blacklisting, bidirectional file transfers via SFTP, and support for multiple SSH connections and jump hosts.

Tokens
16.3K
Snippets
35
Records
55
Agent score
66%

What's inside ssh-mcp-server

  1. Overview of ssh-mcp-server

    main

    ssh-mcp-server is an MCP (Model Context Protocol) server that enables AI assistants to execute remote SSH commands through a standardized interface. It acts as a bridge, allowing AI models to interact with remote servers securely without exposing raw SSH credentials to the model itself.

    Key capabilities include:

    • Secure Connections: Supports password and private key authentication (including passphrased keys).
    • Command Control: Uses blacklists and whitelists to restrict the range of executable commands.
    • Dual Transport Modes: Supports both exec and shell transports, making it compatible with direct connections and jump hosts/bastion servers.
    • File Transfer: Supports bidirectional file transfers (uploading local files to the server and downloading files from the server).
    • Credential Isolation: SSH credentials are managed locally and never shared with the AI model.
    • Zero-Install Execution: Can be run directly via npx.
  2. Wrap commands with a Command Template

    main

    Use --command-template to wrap every executed command. This is useful for su, sudo, running inside containers, or jumping through hosts.

    Placeholders:

    • <quotedCommand>: Use this when the command is passed as a shell argument (recommended for most cases).
    • <command>: Use this for raw insertion.

    The template is applied after the working-directory cd is prepended. The resulting chain is cd ... && <template>.

    {
      "mcpServers": {
        "ssh-mcp-server": {
          "command": "npx",
          "args": [
            "-y",
            "@fangjunjie/ssh-mcp-server",
            "--host", "10.0.0.1",
            "--port", "22",
            "--username", "deploy",
            "--password", "xxx",
            "--command-template", "su root -c <quotedCommand>"
          ]
        }
      }
    }
  3. Authentication methods for ssh-mcp-server

    main

    When configuring ssh-mcp-server, you can choose from several authentication modes:

    • password: Uses a username and password via --username and --password.
    • privateKey: Uses a username and a private key file via --username and --privateKey. If the key is encrypted, provide the --passphrase.
    • ssh-config: Reuses existing aliases from your ~/.ssh/config. You only need to provide --host <alias> and optionally --ssh-config-file.
    • ssh-agent: Uses an existing SSH agent by pointing to the socket via --agent.
    • 2fa: For multi-factor authentication requiring password + private key + keyboard interaction. Append the --try-keyboard flag.
  4. Configure Multiple SSH Connections

    main

    To manage multiple SSH targets within a single MCP server, assign each connection a name. You can then select the target by passing connectionName in your tool calls.

    There are three ways to configure multiple connections:

    Create a JSON file (e.g., ssh-config.json) containing an array of connection objects or a single object where keys are connection names.

    Array Format Example:

    [
      { "name": "dev", "host": "1.2.3.4", "port": 22, "username": "alice", "password": "pwd" },
      { "name": "prod", "host": "5.6.7.8", "port": 22, "username": "bob", "password": "pwd" }
    ]

    Object Format Example:

    {
      "dev": { "host": "1.2.3.4", "port": 22, "username": "alice", "password": "pwd" },
      "prod": { "host": "5.6.7.8", "port": 22, "username": "bob", "password": "pwd" }
    }

    Then, start the server using the --config-file argument:

    {
      "mcpServers": {
        "ssh-mcp-server": {
          "command": "npx",
          "args": [
            "-y",
            "@fangjunjie/ssh-mcp-server",
            "--config-file", "ssh-config.json"
          ]
        }
      }
    }

    2. Using JSON strings with --ssh

    Pass multiple --ssh arguments, each containing a JSON string representing a connection.

    3. Legacy Comma-Separated Format (Backward Compatible)

    Use the format name=dev,host=1.2.3.4,port=22,user=alice,password=xxx. Warning: This format may fail if passwords contain special characters like =, ,, {, or }.

    // Example tool call to a specific connection
    {
      "tool": "execute-command",
      "params": {
        "cmdString": "ls -al",
        "connectionName": "prod"
      }
    }
  5. Wrap commands with commandTemplate

    main

    The --command-template option wraps every executed command in a template. This is useful for switching users (su), running commands inside containers, or routing through jump hosts.

    Template Placeholders:

    • <quotedCommand>: Use this when the command will be passed as a shell argument (it will be quoted).
    • <command>: Use this when the command should be inserted as-is.

    Lifecycle Note: The template is applied after the directory cd command is concatenated. The resulting command structure is cd ... && <template>.

    Examples:

    • su root -c <quotedCommand>
    • sudo bash -c <quotedCommand>
    • docker exec -i mycontainer sh -c <quotedCommand>
    • ssh jumphost <quotedCommand>
    {
      "mcpServers": {
        "ssh-mcp-server": {
          "command": "npx",
          "args": [
            "-y",
            "@fangjunjie/ssh-mcp-server",
            "--host", "10.0.0.1",
            "--port", "22",
            "--username", "deploy",
            "--password", "xxx",
            "--command-template", "su root -c <quotedCommand>"
          ]
        }
      }
    }
  6. Manage Multiple SSH Connections

    main

    To expose multiple SSH targets through a single MCP server, use one of the following methods and specify the target via connectionName in your tool calls.

    Create a JSON file containing an array or object of connection definitions and pass it via --config-file.

    Array Format Example:

    [
      {
        "name": "dev",
        "host": "1.2.3.4",
        "port": 22,
        "username": "alice",
        "password": "pwd"
      }
    ]

    Method 2: Using --ssh parameter

    Pass JSON-formatted strings directly for each connection:

    {
      "args": [
        "-y",
        "@fangjunjie/ssh-mcp-server",
        "--ssh", "{\"name\":\"dev\",\"host\":\"1.2.3.4\"}"
      ]
    }

    Method 3: Legacy Comma-Separated Format

    npx @fangjunjie/ssh-mcp-server --ssh "name=dev,host=1.2.3.4,user=alice,password=xxx"

    Calling a specific connection: In your MCP tool call, provide the connectionName parameter:

    {
      "tool": "execute-command",
      "params": {
        "cmdString": "ls -al",
        "connectionName": "prod"
      }
    }
    {
      "mcpServers": {
        "ssh-mcp-server": {
          "command": "npx",
          "args": [
            "-y",
            "@fangjunjie/ssh-mcp-server",
            "--config-file", "ssh-config.json"
          ]
        }
      }
    }
  7. Use transportMode: shell for Bastion/Jump Hosts

    main

    The default --transport-mode is exec. You should switch to shell mode if:

    • SSH login succeeds, but exec command execution fails.
    • The remote host requires waiting for login banners, profiles, or environment initialization before commands can run.
    • The connection target is a bastion host or a device that only exposes an interactive shell.

    Comparison:

    • exec mode: Supports execute-command, upload, and download.
    • shell mode: Commands are executed serially through a persistent shell session with an internal command queue. Note: upload and download are NOT supported in shell mode because SFTP is disabled.

    You can configure --shell-ready-timeout (default 10000ms) to detect when the shell is ready.

    {
      "mcpServers": {
        "ssh-mcp-server": {
          "command": "npx",
          "args": [
            "-y",
            "@fangjunjie/ssh-mcp-server",
            "--host", "bastion.example.com",
            "--port", "22",
            "--username", "ops",
            "--password", "pwd123456",
            "--transport-mode", "shell",
            "--shell-ready-timeout", "15000"
          ]
        }
      }
    }
  8. Restrict commands with Whitelist and Blacklist

    main

    For security (especially in production), use --whitelist and --blacklist to restrict which commands the server can execute. Both arguments accept comma-separated regular expressions.

    Rules:

    • If both are provided, a command must pass the whitelist check and the blacklist check to run.
    • Whitelist example (read-only): ^ls( .*)?,^cat .*,^df.*
    • Blacklist example (destructive): ^rm .*,^shutdown.*,^reboot.*
    {
      "mcpServers": {
        "ssh-mcp-server": {
          "command": "npx",
          "args": [
            "-y",
            "@fangjunjie/ssh-mcp-server",
            "--host", "192.168.1.1",
            "--port", "22",
            "--username", "root",
            "--password", "pwd123456",
            "--whitelist", "^ls( .*)?,^cat .*,^df.*"
          ]
        }
      }
    }
  9. Use Shell Transport Mode for Bastions and Jump Hosts

    main

    By default, the server uses exec transport mode. Switch to shell mode using --transport-mode shell if:

    • exec fails despite successful login.
    • The remote side requires shell startup scripts or environment initialization.
    • The target is a bastion, jump host, or network device that only exposes an interactive shell.

    Important Differences:

    • exec mode: Supports execute-command, upload, and download (via SFTP).
    • shell mode: Runs commands through a persistent shell session. It does not support upload or download because SFTP is unavailable.

    Configuration: Use --shell-ready-timeout to adjust the readiness probe (default 10000ms).

    {
      "mcpServers": {
        "ssh-mcp-server": {
          "command": "npx",
          "args": [
            "-y",
            "@fangjunjie/ssh-mcp-server",
            "--host", "bastion.example.com",
            "--port", "22",
            "--username", "ops",
            "--password", "pwd123456",
            "--transport-mode", "shell",
            "--shell-ready-timeout", "15000"
          ]
        }
      }
    }
  10. Reuse ~/.ssh/config for connections

    main

    If you have host aliases defined in your ~/.ssh/config, you can simply pass the host alias to --host. The server will automatically read the HostName, Port, User, and IdentityFile from your config.

    Custom SSH Config Path: Use --ssh-config-file to specify a non-standard configuration file.

    Note: Command-line parameters (like --port) take precedence over values found in the SSH config.

    {
      "mcpServers": {
        "ssh-mcp-server": {
          "command": "npx",
          "args": [
            "-y",
            "@fangjunjie/ssh-mcp-server",
            "--host", "myserver",
            "--ssh-config-file", "/path/to/custom/ssh_config"
          ]
        }
      }
    }
  11. Handle Multi-Factor Authentication (2FA/MFA)

    main

    To support servers requiring 2FA (e.g., password + private key + code), enable --try-keyboard.

    Authentication Flow:

    1. Private key (if provided).
    2. Password (if provided).
    3. Keyboard-interactive for the 2FA code.

    Providing the Code: Set the SSH_MCP_2FA_CODE environment variable in the server environment before connecting.

    {
      "mcpServers": {
        "ssh-mcp-server": {
          "command": "npx",
          "args": [
            "-y",
            "@fangjunjie/ssh-mcp-server",
            "--host", "example.com",
            "--port", "22",
            "--username", "user",
            "--password", "your_password",
            "--privateKey", "/path/to/key",
            "--try-keyboard"
          ]
        }
      }
    }
  12. Security best practices for ssh-mcp-server

    main

    Because ssh-mcp-server provides powerful capabilities to execute commands and transfer files on remote servers, follow these security guidelines to mitigate risks:

    • Restrict Commands: Use the --whitelist option to limit the set of executable commands. Without a whitelist, any command can be executed on the remote server.
    • Protect Private Keys: The server reads SSH private keys into memory. Ensure the host running the server is secure and not exposed to untrusted networks.
    • Mitigate DoS: The server lacks built-in rate limiting. Run it behind a firewall or reverse proxy with rate-limiting capabilities to prevent Denial of Service attacks via connection flooding or large file transfers.
    • Path Traversal & Scoping:
      • Local Filesystem: The server has built-in protection against path traversal, but it defaults to restricting access to the current working directory. Use --allowed-local-paths or the allowedLocalPaths configuration key to expand this scope only when necessary.
      • Remote Filesystem: SFTP upload and download commands accept absolute POSIX paths. If allowedRemotePaths (or --allowed-remote-paths) is not configured, any remote path is allowed (a warning will be printed at startup). Strongly recommended: Explicitly configure an allowedRemotePaths whitelist to prevent models from reading or writing sensitive files like ~/.ssh/authorized_keys or /etc/sshd_config via prompt injection.