ssh-mcp-server
Runs shell commands and moves files on remote machines over SSH, with command allow and deny lists
Run commands, move files and manage databases on many SSH servers, with per-server safety modes
By Jérémy Christillin (individual) TypeScript Local · stdio DevOps and monitoringDatabases
68 popularity score ★ 534 ↓ 2.9k/wk
Opens the app, which asks before it adds the server.
claude mcp add ssh-manager -- npx -y mcp-ssh-manager{
"mcpServers": {
"ssh-manager": {
"command": "npx",
"args": [
"-y",
"mcp-ssh-manager"
]
}
}
}{
"mcpServers": {
"ssh-manager": {
"command": "npx",
"args": [
"-y",
"mcp-ssh-manager"
]
}
}
}{
"servers": {
"ssh-manager": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"mcp-ssh-manager"
]
}
}
}[mcp_servers.ssh-manager]
command = "npx"
args = ["-y", "mcp-ssh-manager"]gemini mcp add --scope user ssh-manager npx -- -y mcp-ssh-managerOpens the app, which asks before it adds the server. Then replace each <NAME> in its settings with your value.
git clone https://github.com/bvisible/mcp-ssh-manager.git
cd mcp-ssh-manager
npm installclaude mcp add ssh-manager -- node '<ABSOLUTE_PATH_TO_CLONE>/src/index.js'{
"mcpServers": {
"ssh-manager": {
"command": "node",
"args": [
"<ABSOLUTE_PATH_TO_CLONE>/src/index.js"
]
}
}
}{
"mcpServers": {
"ssh-manager": {
"command": "node",
"args": [
"<ABSOLUTE_PATH_TO_CLONE>/src/index.js"
]
}
}
}{
"servers": {
"ssh-manager": {
"type": "stdio",
"command": "node",
"args": [
"<ABSOLUTE_PATH_TO_CLONE>/src/index.js"
]
}
}
}[mcp_servers.ssh-manager]
command = "node"
args = ["<ABSOLUTE_PATH_TO_CLONE>/src/index.js"]gemini mcp add --scope user ssh-manager node -- '<ABSOLUTE_PATH_TO_CLONE>/src/index.js'| Set together: config files | |
|---|---|
SSH_ENV_PATH |
Optional: Exact .env file to load. Hosts are set there as one block of SSH_SERVER_<NAME>_ variables per server. Without it the server tries SSH_MANAGER_ENV, then ~/.ssh-manager/.env, the working folder, your home folder and last the package folder. |
SSH_MANAGER_HOME |
Optional: Folder for the manager's own files, including the .env it looks for first. |
SSH_MANAGER_ENV |
Optional: Another way to point at a .env, honoured since 4.0. A missing file is skipped. |
SSH_CONFIG_PATH |
Optional: TOML file with host entries, read after the .env and the vault. |
| Set together: limits | |
MCP_SSH_DEFAULT_TIMEOUT |
Optional: Command timeout in ms. MCP_SSH_MAX_TIMEOUT caps what a call may ask for and is 300000 by default. |
MCP_SSH_MAX_OUTPUT_LENGTH |
Optional: Characters of command output returned before the rest is cut and counted. |
MCP_SSH_MAX_TIMEOUT |
Optional: Upper bound in ms on the timeout a single call may request. |
mcp-ssh-manager lets an agent work on your servers over SSH. You list the hosts in a .env or TOML file, and from then on the agent can run commands and move files on them. It also tails logs, opens tunnels and handles database dumps. Version 4.0 brings a control plane. It is optional and comes as a browser page or a desktop app, with an encrypted vault for credentials and a step where a person approves commands before they run on a given server. Skip it and nothing changes. Host keys are the exception: those are now checked.
| Runtime | Node.js 18+ |
|---|---|
| Runs on | macOS, Windows, Linux |
| Also |
|
The npm package needs Node 18 or newer. The desktop app, fetched with ssh-manager app, carries its own runtime. Each host is described by its own set of SSH_SERVER_<NAME>_ variables (host, user, key or password, port, mode) or by a TOML entry.
Command timeouts are advisory: the README says a command can keep running on the host after the timeout, and on Linux/macOS hosts a system timeout wrapper is used to stop it. Output is cut to 10000 characters and commands time out after 120 s by default (MCP_SSH_MAX_OUTPUT_LENGTH, MCP_SSH_DEFAULT_TIMEOUT), up to 5 minutes. ssh_monitor targets Linux hosts. Since 3.8.6 a changed host key is refused until cleared with ssh-keygen -R. The README calls the group tool ssh_group_execute in places; its real name is ssh_execute_group. The registry entry still describes 3.8.2.
People who already look after servers by SSH and want an agent for routine checks and deploys, with a lock on the hosts that matter.
11 only read, 22 change things, 4 can delete or overwrite. A ? marks an optional parameter.
ssh_list_serversssh_execute changesserver?: stringcommand?: stringcwd?: stringtimeout?: numberssh_execute_sudo changesserver?: stringcommand?: stringpassword?: stringcwd?: stringtimeout?: numberssh_execute_group changesgroup?: stringcommand?: stringstrategy?: enumdelay?: numberstopOnError?: booleancwd?: stringssh_group_manage changesaction?: enumname?: stringservers?: arraydescription?: stringstrategy?: enumdelay?: numberstopOnError?: booleanssh_upload changesserver?: stringlocalPath?: stringremotePath?: stringssh_download changesserver?: stringremotePath?: stringlocalPath?: stringssh_sync deletesserver?: stringsource?: stringdestination?: stringexclude?: arraydryRun?: booleandelete?: booleancompress?: booleanverbose?: booleanchecksum?: booleantimeout?: numberssh_deploy changesserver?: stringfiles?: arrayoptions?: objectssh_tailserver?: stringfile?: stringlines?: numberfollow?: booleangrep?: stringssh_monitorserver?: stringtype?: enuminterval?: numberduration?: numberssh_health_checkserver?: stringdetailed?: booleanssh_service_statusserver?: stringservices?: arrayssh_process_manager deletesserver?: stringaction?: enumpid?: numbersignal?: enumsortBy?: enumlimit?: numberfilter?: stringssh_alert_setup changesserver?: stringaction?: enumcpuThreshold?: numbermemoryThreshold?: numberdiskThreshold?: numberenabled?: booleanssh_session_start changesserver?: stringname?: stringssh_session_send changessession?: stringcommand?: stringtimeout?: numberssh_session_listserver?: stringssh_session_close changessession?: stringssh_tunnel_create changesserver?: stringtype?: enumlocalHost?: stringlocalPort?: numberremoteHost?: stringremotePort?: numberssh_tunnel_listserver?: stringssh_tunnel_close changestunnelId?: stringserver?: stringssh_connection_status changesaction?: enumserver?: stringssh_key_manage changesaction?: enumserver?: stringautoAccept?: booleanssh_historylimit?: numberserver?: stringsuccess?: booleansearch?: stringssh_backup_create changesserver?: stringtype?: enumname?: stringdatabase?: stringdbUser?: stringdbPassword?: stringdbHost?: stringdbPort?: numberpaths?: arrayexclude?: arraybackupDir?: stringretention?: numbercompress?: booleanssh_backup_listserver?: stringtype?: enumbackupDir?: stringssh_backup_restore deletesserver?: stringbackupId?: stringdatabase?: stringdbUser?: stringdbPassword?: stringdbHost?: stringdbPort?: numbertargetPath?: stringbackupDir?: stringssh_backup_schedule changesserver?: stringschedule?: stringtype?: enumname?: stringdatabase?: stringpaths?: arrayretention?: numberssh_db_dump changesserver?: stringtype?: enumdatabase?: stringoutputFile?: stringdbUser?: stringdbPassword?: stringdbHost?: stringdbPort?: numbercompress?: booleantables?: arrayssh_db_import deletesserver?: stringtype?: enumdatabase?: stringinputFile?: stringdbUser?: stringdbPassword?: stringdbHost?: stringdbPort?: numberdrop?: booleanssh_db_listserver?: stringtype?: enumdatabase?: stringdbUser?: stringdbPassword?: stringdbHost?: stringdbPort?: numberssh_db_queryserver?: stringtype?: enumdatabase?: stringquery?: stringcollection?: stringdbUser?: stringdbPassword?: stringdbHost?: stringdbPort?: numberssh_alias changesaction?: enumalias?: stringserver?: stringssh_command_alias changesaction?: enumalias?: stringcommand?: stringssh_hooks changesaction?: enumhook?: stringssh_profile changesaction?: enumprofile?: string