A tiny MCP server for SSH with persistent sessions.
This project is intentionally simple: it works, it fits my day-to-day workflow, and that is the main goal.
I wanted a lightweight SSH MCP setup that:
- keeps one SSH session alive across tool calls
- reads host credentials from a config file
- stays easy to understand and tweak
If you are looking for a big roadmap or tons of features, this is probably not that project. That said, contributions are welcome.
- Persistent SSH session: connection stays alive between
ssh_executecalls - Session state preserved:
cd, env vars, and shell state carry over - Config-driven hosts: no passing host/password/private key on every call
- Multiple hosts: switch by
hostName - Idle cleanup: sessions auto-disconnect after timeout
- Raw output option: inspect full terminal output with
showRaw
Main guide uses pnpm.
pnpm install
pnpm build
cp config.example.json config.jsonEdit config.json and add your hosts.
If you are still using npm, no judgment... but pnpm is faster and your SSD will thank you.
npm install
npm run build
cp config.example.json config.jsonExample:
{
"hosts": {
"my-server": {
"host": "192.168.1.100",
"port": 22,
"username": "admin",
"password": "your-password"
},
"dev-server": {
"host": "dev.example.com",
"username": "developer",
"privateKeyPath": "~/.ssh/id_rsa"
}
},
"settings": {
"sessionTimeoutMinutes": 10,
"commandTimeoutSeconds": 30,
"defaultPort": 22
}
}The server checks config paths in this order:
--config <path>or-c <path>SSH_MCP_CONFIG_PATH./config.json~/.ssh-mcp-server/config.json
passwordprivateKeyPath(supports~)passphrase(optional, for encrypted keys)
Add this to Cursor MCP settings:
{
"mcpServers": {
"simple-ssh": {
"command": "node",
"args": [
"/absolute/path/to/my-ssh-mcp-server/dist/index.js",
"--config",
"/absolute/path/to/my-ssh-mcp-server/config.json"
]
}
}
}Add to claude_desktop_config.json:
{
"mcpServers": {
"simple-ssh": {
"command": "node",
"args": [
"/absolute/path/to/my-ssh-mcp-server/dist/index.js",
"--config",
"/absolute/path/to/my-ssh-mcp-server/config.json"
]
}
}
}List configured hosts.
Connect to a host from config.
Parameters:
hostName(required)sessionId(optional)
Run a command in an existing session.
Parameters:
sessionId(required)command(required)timeout(optional, seconds)showRaw(optional, boolean; include raw terminal output)
List active sessions.
Disconnect a session.
Parameters:
sessionId(required)
ssh_list_hostsssh_connect({ hostName: "my-server" })ssh_execute({ sessionId: "...", command: "cd /var/log" })ssh_execute({ sessionId: "...", command: "ls -la" })ssh_disconnect({ sessionId: "..." })
pnpm dev
pnpm build
pnpm startnpm run dev
npm run build
npm startconfig.jsonhas secrets and is ignored by git- do not commit real credentials
- sessions auto-expire after idle timeout
This project is released under The Unlicense.