-
Notifications
You must be signed in to change notification settings - Fork 0
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.
Pass the config path with --config:
ssh-mcp --config ./ssh-mcp.tomlThe install subcommand takes the same --config flag and embeds the
path in the client entry it writes.
[defaults]
username = "deploy"
port = 22
private_key = "~/.ssh/id_ed25519"
timeout = "30s"
keepalive_interval = "30s"
keepalive_count_max = 3
max_output_bytes = 1048576
transport = "exec"
[[server]]
name = "web"
host = "web.example.com"
whitelist = ["^systemctl status .*", "^journalctl .*", "^ls .*"]
allowed_remote_paths = ["/var/log", "/srv"]
allowed_local_paths = ["~/downloads"]
[[server]]
name = "db"
host = "db.example.com"
username = "postgres" # overrides defaults.username
port = 2222 # overrides defaults.port
password = "..." # or use SSH_MCP_PASSWORD
transport = "shell"
pty = true
pre_connect = trueOptional. Values set here apply to every server that does not override them.
| Field | Type | Default | Description |
|---|---|---|---|
username |
string | – | SSH username |
port |
int | 22 | SSH port (1-65535) |
password |
string | – | Password auth (or SSH_MCP_PASSWORD) |
private_key |
string | – | Path to a private key file |
passphrase |
string | – | Private key passphrase (or SSH_MCP_PASSPHRASE) |
agent |
bool | false | Use the SSH agent (SSH_AUTH_SOCK) |
try_keyboard |
bool | false | Try keyboard-interactive auth (2FA) |
timeout |
duration | 30s |
Per-command timeout |
keepalive_interval |
duration | 30s |
Keepalive request interval |
keepalive_count_max |
int | 3 | Failures before closing the connection |
max_output_bytes |
int | 1048576 | Cap on captured stdout/stderr |
transport |
string | exec |
exec or shell
|
pty |
bool | false | Allocate a PTY for commands |
command_template |
string | – | Wrap commands (must contain <command> or <quotedCommand>) |
One entry per remote server. Required fields: name, host,
username, port (or inherited from defaults), 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 (inheritable) |
port |
int | 22 | SSH port (inheritable) |
password |
string | – | Password auth (or SSH_MCP_PASSWORD) |
private_key |
string | – | Path to a private key file |
passphrase |
string | – | Private key passphrase (or SSH_MCP_PASSPHRASE) |
agent |
bool | false | Use the SSH agent |
try_keyboard |
bool | false | Try keyboard-interactive auth (2FA) |
timeout |
duration | 30s |
Per-command timeout |
keepalive_interval |
duration | 30s |
Keepalive interval |
keepalive_count_max |
int | 3 | Failures before reconnect |
max_output_bytes |
int | 1048576 | Output cap |
transport |
string | exec |
exec or shell
|
pty |
bool | false | Allocate a PTY |
command_template |
string | – | Wrap commands |
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_url |
string | – | SOCKS5 or HTTP CONNECT proxy URL |
ssh_config |
string | – | Path to an OpenSSH config for alias resolution |
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 |
This is how MCPB and other launchers inject sensitive values without exposing them on the command line.
whitelist and blacklist are lists of regular expressions. Before a
command runs, it is checked against the policy:
- If a whitelist is configured, the command must match at least one whitelist pattern.
- 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.
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.Cleanis used instead. Null bytes in a path are rejected outright. - Remote paths must be absolute POSIX paths. When
allowed_remote_pathsis empty, any absolute POSIX path is accepted and a warning is logged.
-
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 fields accept Go duration strings: 30s, 5m, 1h30m, etc.
At startup, each server is validated:
-
namemust be unique across all servers. -
hostis required. -
usernameis required (directly or via defaults). -
portmust be in 1-65535. - At least one auth method must be configured.
-
transportmust beexecorshell. -
command_template, when set, must contain a<command>or<quotedCommand>placeholder. -
ptyis a tri-state field (*bool) so the distinction between "unset" and "explicitly false" is preserved during default inheritance.
In single-server mode, pass --ssh-config to resolve a host alias from
your OpenSSH config:
ssh-mcp --host myalias --ssh-config ~/.ssh/configResolution 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.