Skip to content

Configuration

github-actions[bot] edited this page Aug 22, 2026 · 3 revisions

Configuration

ssh-mcp is configured with a TOML file. The schema has a top-level [defaults] section and one or more [[server]] entries. Each server inherits from [defaults], then from built-in defaults, and is validated at startup.

File location

Pass the config path with --config:

ssh-mcp --config ./ssh-mcp.toml

The install subcommand takes the same --config flag and embeds the path in the client entry it writes.

Full example

Only the fields listed in the [defaults] table below are inheritable. username, port, password, private_key, passphrase, agent, try_keyboard, and command_template are NOT inheritable and must be set on each [[server]] entry directly.

[defaults]
command_timeout     = "30s"
connection_timeout  = "30s"
sftp_timeout        = "5m"
shell_ready_timeout = "10s"
keepalive_interval  = "10s"
keepalive_count_max = 3
max_output_bytes    = 10485760
transport           = "exec"

[[server]]
name     = "web"
host     = "web.example.com"
username = "deploy"
port     = 22
private_key = "~/.ssh/id_ed25519"
whitelist = ["^systemctl status .*", "^journalctl .*", "^ls .*"]
allowed_remote_paths = ["/var/log", "/srv"]
allowed_local_paths = ["~/downloads"]

[[server]]
name     = "db"
host     = "db.example.com"
username = "postgres"
port     = 2222
password = "..."             # set directly; env var fallback does not apply in TOML mode
transport = "shell"
pty = true
pre_connect = true

[defaults]

Optional. Values set here apply to every server that does not override them. Only the fields listed below are inheritable; username, port, password, private_key, passphrase, agent, try_keyboard, and command_template are NOT inheritable and must be set on each [[server]] entry directly.

Field Type Default Description
command_timeout duration 30s Per-command timeout
connection_timeout duration 30s SSH connection timeout
sftp_timeout duration 5m SFTP operation timeout
shell_ready_timeout duration 10s Shell ready handshake timeout (shell transport)
keepalive_interval duration 10s Keepalive request interval
keepalive_count_max int 3 Failures before closing the connection
max_output_bytes int 10485760 Cap on captured stdout/stderr
transport string exec exec or shell
pty bool false Allocate a PTY for commands

[[server]]

One entry per remote server. Required fields: name, host, username, port (defaults to 22 if unset), and at least one auth method.

Field Type Default Description
name string required Unique server name used by connectionName
host string required Hostname or IP address
username string required SSH username
port int 22 SSH port (1-65535)
password string Password auth (or SSH_MCP_PASSWORD in CLI mode)
private_key string Path to a private key file
passphrase string Private key passphrase (or SSH_MCP_PASSPHRASE in CLI mode)
agent string Use the SSH agent — "env" (uses $SSH_AUTH_SOCK) or explicit socket path
try_keyboard bool false Try keyboard-interactive auth (2FA)
command_timeout duration 30s Per-command timeout (inheritable)
connection_timeout duration 30s SSH connection timeout (inheritable)
sftp_timeout duration 5m SFTP operation timeout (inheritable)
shell_ready_timeout duration 10s Shell ready handshake timeout (inheritable)
keepalive_interval duration 10s Keepalive interval (inheritable)
keepalive_count_max int 3 Failures before reconnect (inheritable)
max_output_bytes int 10485760 Output cap (inheritable)
transport string exec exec or shell (inheritable)
pty bool false Allocate a PTY (inheritable)
command_template string Wrap commands (must contain <command> or <quotedCommand>)
pre_connect bool false Connect at startup instead of lazily
whitelist []string Regex patterns a command must match
blacklist []string Regex patterns a command must not match
allowed_local_paths []string Local roots for SFTP uploads/downloads
allowed_remote_paths []string Remote roots for SFTP operations
proxy string SOCKS5, HTTP CONNECT, or HTTPS CONNECT proxy URL

Authentication

Auth methods are tried in this order: private key, agent, password, keyboard-interactive. Only configured methods are attempted. At least one method is required.

Sensitive values should be provided via environment variables instead of the config file:

Env var Used for
SSH_MCP_PASSWORD Password auth (fallback when password is empty)
SSH_MCP_PASSPHRASE Private key passphrase (fallback when passphrase is empty)
SSH_MCP_2FA_CODE 2FA code for keyboard-interactive auth

The SSH_MCP_PASSWORD and SSH_MCP_PASSPHRASE fallbacks apply only in single-server CLI mode (including MCPB, install, and snippet single-server entries). In TOML config mode, set password and passphrase directly in the config file — the env var fallback is not applied. SSH_MCP_2FA_CODE is read at auth time and works in all modes.

This is how MCPB and other launchers inject sensitive values without exposing them on the command line.

Command policy

whitelist and blacklist are lists of regular expressions. Before a command runs, it is checked against the policy:

  1. If a whitelist is configured, the command must match at least one whitelist pattern.
  2. If a blacklist is configured, the command must not match any blacklist pattern.

When both are set, the whitelist is checked first. When no whitelist is configured, all commands are allowed and a warning is logged at startup. Invalid regex patterns produce an error at startup naming the offending pattern and kind, so misconfigurations surface immediately.

The same policy also gates the individual probe commands used by the server-status tool, so a restrictive whitelist cannot be bypassed via status collection.

Path restrictions

allowed_local_paths and allowed_remote_paths confine SFTP transfers (uploads, downloads, directory sync, remote listings) to specific directories.

  • Local paths are resolved to absolute form and checked against the allowed roots. The current working directory is always included as the first local root. Symlinks are not expanded (to avoid Windows 8.3 short-name issues); filepath.Clean is used instead. Null bytes in a path are rejected outright.
  • Remote paths must be absolute POSIX paths. When allowed_remote_paths is empty, any absolute POSIX path is accepted and a warning is logged.

Transport modes

  • exec (default): each command runs in its own SSH session. Stateless.
  • shell: a persistent shell session per server. Commands are framed by random marker lines so output and exit code can be extracted. Preserves shell state across commands.

Duration format

Duration fields accept Go duration strings: 30s, 5m, 1h30m, etc.

Validation rules

At startup, each server is validated:

  • name must be unique across all servers.
  • host is required.
  • username is required (must be set directly on each server).
  • port must be in 1-65535.
  • At least one auth method must be configured.
  • transport must be exec or shell.
  • command_template, when set, must contain a <command> or <quotedCommand> placeholder.
  • pty is a tri-state field (*bool) so the distinction between "unset" and "explicitly false" is preserved during default inheritance.

SSH config alias resolution

In single-server mode, pass --ssh-config to resolve a host alias from your OpenSSH config:

ssh-mcp --host myalias --ssh-config ~/.ssh/config

Resolution fills in missing fields (HostName, User, Port, IdentityFile) from the matching Host block. It only runs when the host is not an IP address and does not contain a dot. First-match-wins semantics match OpenSSH. Include directives are followed recursively with cycle detection.

Hot-reload

When ssh-mcp is started with --config, the config file is watched for changes and reloaded automatically without restarting the server. This applies only to file-based config (the --config flag), not to single-server CLI mode.

How it works

  • The config file's modification time is polled every 2 seconds.
  • Polling is used instead of filesystem notifications because config files often live on network or cloud-synced filesystems where kernel-level notifications are unreliable.
  • When a change is detected, the file is reloaded and validated. If parsing or validation fails, the error is logged and the previous configuration is kept.
  • The reloaded configuration is applied atomically to the connection manager:
    • Servers that were removed have their connections closed.
    • Servers whose config changed in any way have their connections closed so the next operation reconnects with the new settings.
    • Servers whose config is unchanged keep their existing connections.
    • Command policies (whitelist/blacklist) are always rebuilt from the new config, so policy changes take effect immediately without reconnection.

What triggers a reload

Any change to the config file's modification time, including:

  • Adding or removing a [[server]] entry.
  • Changing any field on an existing server (host, port, auth method, whitelist, timeouts, etc.).
  • Editing the [defaults] section.

Limitations

  • The reload only affects file-based config. Single-server mode (--host and related CLI flags) does not support hot-reload.
  • If the config file is deleted or becomes unreadable, the watcher logs a warning and retries on the next poll cycle. The last successfully loaded configuration remains active.
  • The polling interval is 2 seconds, so there is a brief delay between saving the file and the change taking effect.

Clone this wiki locally