MCP SSH Session
This MCP server enables AI agents to establish and manage persistent SSH sessions for executing commands on remote systems.
Core Capabilities:
Execute commands on SSH hosts using persistent, reusable connections across multiple operations
Multi-host management - connect to and manage multiple remote hosts simultaneously
Session management - list active sessions, close individual sessions by host identifier, or terminate all sessions at once
Connection Features:
SSH config support - automatically reads
~/.ssh/configfor host aliases, hostnames, ports, users, and identity filesFlexible authentication - supports passwords, SSH keys, and explicit connection parameters
Automatic reconnection - detects and re-establishes dead connections
Thread-safe operations for concurrent usage
Specialized Support:
Network device handling - automatic enable mode management for routers and switches
Sudo support - automatic password handling for privileged commands on Unix/Linux systems
Enables persistent SSH connections to Linux systems for executing commands, managing services with sudo support, and performing system administration tasks remotely.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MCP SSH Session check disk usage on production server"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MCP SSH Session
Alternative version: mcp-ssh-tmux.
Uses tmux for improved persistence, observability, and a superior "LLM-as-Observer" approach.
An MCP (Model Context Protocol) server that enables AI agents to establish and manage persistent SSH sessions.
Features
Smart Command Execution: Never hangs the server - automatically transitions to async mode if timeout is reached
Persistent Sessions: SSH connections are reused across multiple command executions
Async Command Execution: Non-blocking execution for long-running commands
SSH Config Support: Automatically reads and uses settings from
~/.ssh/configMulti-host Support: Manage connections to multiple hosts simultaneously
Automatic Reconnection: Dead connections are detected and automatically re-established
Thread-safe: Safe for concurrent operations
Network Device Support: Automatic enable mode handling for routers and switches
Sudo Support: Automatic password handling for sudo commands on Unix/Linux hosts
File Operations: Safe helpers to read and write remote files over SFTP
Command Interruption: Send Ctrl+C to interrupt running commands
Related MCP server: SSH MCP Server
Installation
Using uvx
uvx mcp-ssh-sessionUsing Claude Code
Add to your ~/.claude.json:
{
"mcpServers": {
"ssh-session": {
"type": "stdio",
"command": "uvx",
"args": ["mcp-ssh-session"],
"env": {}
}
}
}Using MCP Inspector
npx @modelcontextprotocol/inspector uvx mcp-ssh-sessionDevelopment Installation
uv venv
source .venv/bin/activate
uv pip install -e .Usage
Available Tools
execute_command
Execute a command on an SSH host using a persistent session.
Smart Execution: Starts synchronously and waits for completion. If timeout is reached, automatically transitions to async mode and returns a command ID. Server never hangs!
Advanced Features:
Automatic timeout handling with async transition
Interactive command support (use
send_inputfor prompts)Command interruption capability (
interrupt_command_by_id)Session persistence across multiple commands
Using SSH config alias:
{
"host": "myserver",
"command": "uptime"
}Using explicit parameters:
{
"host": "example.com",
"username": "user",
"command": "ls -la",
"key_filename": "~/.ssh/id_rsa",
"port": 22
}Network device with enable mode:
{
"host": "router.example.com",
"username": "admin",
"password": "ssh_password",
"enable_password": "enable_password",
"command": "show running-config"
}Unix/Linux with sudo:
{
"host": "server.example.com",
"username": "user",
"sudo_password": "user_password",
"command": "systemctl restart nginx"
}list_sessions
List all active SSH sessions.
close_session
Close a specific SSH session.
{
"host": "myserver"
}close_all_sessions
Close all active SSH sessions.
execute_command_async
Execute a command asynchronously without blocking the server. Returns a command ID for tracking.
Use with companion tools:
get_command_status(command_id)- Check progress and retrieve outputinterrupt_command_by_id(command_id)- Send Ctrl+C to stop executionsend_input(command_id, text)- Provide input to interactive commands
{
"host": "myserver",
"command": "sleep 60 && echo 'Done'",
"timeout": 300
}get_command_status
Get the status and output of an async command.
{
"command_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}interrupt_command_by_id
Interrupt a running async command by sending Ctrl+C.
{
"command_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}list_running_commands
List all currently running async commands.
list_command_history
List recent command history (completed, failed, interrupted commands).
{
"limit": 50
}read_file
Read the contents of a remote file via SFTP, with optional sudo support.
Basic usage:
{
"host": "myserver",
"remote_path": "/etc/nginx/nginx.conf",
"max_bytes": 131072
}With passwordless sudo (NOPASSWD in sudoers):
{
"host": "myserver",
"remote_path": "/etc/shadow",
"use_sudo": true
}With sudo password:
{
"host": "myserver",
"remote_path": "/etc/shadow",
"sudo_password": "user_password"
}Attempts SFTP first for best performance
Falls back to
sudo catvia shell if permission denied anduse_sudo=trueorsudo_passwordprovidedSupports both passwordless sudo (NOPASSWD) and password-based sudo
Enforces a 2 MB maximum per request (configurable per call up to that limit)
Returns truncated notice when the content size exceeds the requested limit
write_file
Write text content to a remote file via SFTP, with optional sudo support.
Basic usage:
{
"host": "myserver",
"remote_path": "/tmp/app.env",
"content": "DEBUG=true\n",
"append": true,
"make_dirs": true
}With passwordless sudo (NOPASSWD in sudoers):
{
"host": "myserver",
"remote_path": "/etc/nginx/nginx.conf",
"content": "server { ... }",
"use_sudo": true,
"permissions": 420
}With sudo password:
{
"host": "myserver",
"remote_path": "/etc/nginx/nginx.conf",
"content": "server { ... }",
"sudo_password": "user_password",
"permissions": 420
}Uses SFTP when
use_sudo=falseand nosudo_passwordprovidedUses
sudo teevia shell whenuse_sudo=trueorsudo_passwordis providedSupports both passwordless sudo (NOPASSWD) and password-based sudo
Content larger than 2 MB is rejected for safety
Optional
appendmode to add to existing filesOptional
make_dirsflag will create missing parent directoriesSupports
permissionsto set octal file modes after write (e.g.,420for0644)Note: Shell fallback is slower than SFTP but enables writing to protected files
SSH Config Support
The server automatically reads ~/.ssh/config and supports:
Host aliases
Hostname mappings
Port configurations
User specifications
IdentityFile settings
Example ~/.ssh/config:
Host myserver
HostName example.com
User myuser
Port 2222
IdentityFile ~/.ssh/id_rsaThen simply use:
{
"host": "myserver",
"command": "uptime"
}Environment Variable Override System (Credential Hiding)
For production environments where AI agents should not have access to real credentials, you can use environment variables to override connection parameters. This allows agents to use simple aliases while real credentials are stored securely in the MCP server configuration.
Use case: Hide real hostnames, IPs, usernames, and passwords from AI agents while still allowing them to manage production servers.
Supported Environment Variables
Variable | Description |
| Real hostname or IP address |
| SSH port (default: 22) |
| SSH username |
| SSH password |
| Path to SSH private key file |
| Sudo password |
| Enable password for network devices (routers/switches) |
Example Configuration
Claude Desktop config (~/.claude.json):
{
"mcpServers": {
"ssh-session": {
"type": "stdio",
"command": "uvx",
"args": ["mcp-ssh-session"],
"env": {
"OVRD_prod_db_HOST": "192.168.1.100",
"OVRD_prod_db_USER": "admin",
"OVRD_prod_db_PASS": "secret_password",
"OVRD_prod_db_SUDO_PASS": "sudo_password"
}
}
}
}Agent uses the alias (knows nothing about real credentials):
{
"host": "prod_db",
"command": "systemctl status postgresql"
}System resolves to real credentials:
Host:
prod_db→192.168.1.100User: (from env) →
adminPassword: (from env) →
secret_password
Notes
Fully backward compatible - works without environment variables
The agent sees only the alias (
prod_db), not the real IPCredentials never appear in the AI context
Works with all tools:
execute_command,read_file,write_file, etc.
How It Works
Persistent Shell Sessions
Commands execute in persistent interactive shells that maintain state:
Current directory persists across commands (
cd /tmpstays in/tmp)Environment variables remain set
Shell history is maintained
Smart Command Completion Detection
Commands complete when either:
Prompt detected: Standard shell prompts (
$,#,>,%) at end of outputIdle timeout: No output for 2 seconds after receiving data
Why idle timeout? Custom themed prompts may not match standard patterns. The 2-second idle timeout ensures commands complete even with non-standard prompts.
Long-running commands: The idle timer resets every time new output arrives, so builds or scripts that output sporadically continue running until naturally complete or the overall timeout is reached.
Documentation
ASYNC_COMMANDS.md - Smart execution and async commands
License
Distributed under the MIT License. See LICENSE for details.
Available Tools
15 toolsclose_all_sessionsA
Close all active SSH sessions.
Inputs: no named parameters. Returns: result
close_sessionA
Close a specific SSH session.
The host parameter can be either a hostname/IP or an SSH config alias.
Args: host: Hostname, IP address, or SSH config alias username: SSH username (optional, will use SSH config or current user) port: SSH port (optional, will use SSH config or default 22)
Inputs: host (required), username, port. Returns: result
execute_commandA
Execute a command on an SSH host using a persistent session.
Starts synchronously and waits for completion. If the command doesn't complete within the timeout, it automatically transitions to async mode and returns a command ID for tracking.
The host parameter can be either a hostname/IP or an SSH config alias. If an SSH config alias is provided, configuration will be read from ~/.ssh/config.
For network devices (routers, switches), use enable_password to automatically enter privileged/enable mode before executing commands.
For Unix/Linux hosts requiring sudo, use sudo_password to automatically handle the sudo password prompt. The command will be automatically prefixed with 'sudo' if not already present.
Advanced Features:
Automatic timeout handling with async transition
Interactive command support with input capability
Command interruption (Ctrl+C) for stuck processes
Session persistence across multiple commands
Args: host: Hostname, IP address, or SSH config alias (e.g., "myserver") command: Command to execute username: SSH username (optional, will use SSH config or current user) password: Password (optional) key_filename: Path to SSH key file (optional, will use SSH config) port: SSH port (optional, will use SSH config or default 22) enable_password: Enable mode password for network devices (optional) enable_command: Command to enter enable mode (default: "enable") sudo_password: Password for sudo commands on Unix/Linux hosts (optional) timeout: Timeout in seconds for command execution (default: 30)
Inputs: host (required), command (required), username, password, +6 more. Returns: result
execute_command_asyncA
Execute a command asynchronously without blocking the server.
Returns a command ID that can be used to check status, retrieve output, or interrupt. Useful for long-running commands like 'sleep 60', monitoring tasks, or large operations.
Use with companion tools:
get_command_status(command_id) to check progress and retrieve output
interrupt_command_by_id(command_id) to send Ctrl+C and stop execution
send_input(command_id, text) to provide input to interactive commands
Args: host: Hostname, IP address, or SSH config alias command: Command to execute username: SSH username (optional) password: SSH password (optional) key_filename: Path to SSH key file (optional) port: SSH port (optional) timeout: Maximum execution time in seconds (default: 300)
Inputs: host (required), command (required), username, password, +3 more. Returns: result
get_command_statusA
Get the status and output of an async command.
Args: command_id: The command ID returned by execute_command_async
Inputs: command_id (required). Returns: result
interrupt_command_by_idA
Interrupt a running async command by sending Ctrl+C.
Args: command_id: The command ID returned by execute_command_async
Inputs: command_id (required). Returns: result
list_command_historyA
List recent command history (completed, failed, interrupted commands).
Args: limit: Maximum number of commands to return (default: 50)
Inputs: limit. Returns: result
list_running_commandsA
List all currently running async commands.
Inputs: no named parameters. Returns: result
list_sessionsA
List all active SSH sessions.
Inputs: no named parameters. Returns: result
read_fileA
Read a remote file over SSH.
Attempts to read using SFTP first. If permission is denied and use_sudo is True or sudo_password is provided, falls back to using 'sudo cat' via shell command.
Args: host: Hostname, IP address, or SSH config alias remote_path: Path to the remote file username: SSH username (optional) password: SSH password (optional) key_filename: Path to SSH key file (optional) port: SSH port (optional) encoding: Text encoding (default: utf-8) errors: Error handling for decoding (default: replace) max_bytes: Maximum bytes to read (default: 2MB) sudo_password: Password for sudo (optional, not needed if NOPASSWD configured) use_sudo: Use sudo for reading (tries passwordless if no sudo_password provided)
Inputs: host (required), remote_path (required), username, password, +7 more. Returns: result
read_screenA
Read the terminal screen state for a session.
Returns the current screen content from the terminal emulator, including cursor position. Only works when MCP_SSH_INTERACTIVE_MODE=1 is set.
Args: host: Hostname, IP address, or SSH config alias username: SSH username (optional, will use SSH config or current user) port: SSH port (optional, will use SSH config or default 22) max_lines: Maximum number of lines to return (default: 24)
Returns: JSON string with screen lines, cursor position, and dimensions
Inputs: host (required), username, port, max_lines. Returns: result
send_inputA
Send input to a running async command and return any new output.
Useful for interacting with commands that require user input, such as:
- Pagers (less, more): send 'q' to quit, space to page down
- Yes/no prompts: send 'y' or 'n'
- Interactive programs: send appropriate responses
Args:
command_id: The command ID to send input to
input_text: Text to send (e.g., 'q', 'y
', etc.)
Inputs: command_id (required), input_text (required). Returns: result
send_input_by_sessionA
Send input to the active shell for a session.
Useful for clearing stuck interactive states or sending input to the current shell.
Args:
host: Hostname, IP address, or SSH config alias
input_text: Text to send (e.g., 'q
' to quit pager, '' for Ctrl+C) username: SSH username (optional) port: SSH port (optional)
Inputs: host (required), input_text (required), username, port. Returns: result
send_keysA
Send special keys or key sequences to a session.
Supports special key tokens:
or : Send newline
or : Send escape key
: Send tab key
: Send Ctrl+C (interrupt)
: Send Ctrl+D (EOF)
: Send Ctrl+Z (suspend)
, , , : Arrow keys
: Space character
Regular text is sent as-is. Mix special keys with text: "helloworld"
Args: host: Hostname, IP address, or SSH config alias keys: Key sequence to send (e.g., "q", ":wq", "") username: SSH username (optional) port: SSH port (optional)
Returns: Success message
Inputs: host (required), keys (required), username, port. Returns: result
write_fileA
Write content to a remote file over SSH.
If use_sudo is True or sudo_password is provided, uses sudo via shell commands (tee). Otherwise, attempts to write using SFTP.
Args: host: Hostname, IP address, or SSH config alias remote_path: Path to the remote file content: Content to write username: SSH username (optional) password: SSH password (optional) key_filename: Path to SSH key file (optional) port: SSH port (optional) encoding: Text encoding (default: utf-8) errors: Error handling for encoding (default: strict) append: Append to file instead of overwriting (default: False) make_dirs: Create parent directories if they don't exist (default: False) permissions: Octal file permissions to set (e.g., 420 for 0644) max_bytes: Maximum bytes to write (default: 2MB) sudo_password: Password for sudo (optional, not needed if NOPASSWD configured) use_sudo: Use sudo for writing (tries passwordless if no sudo_password provided)
Inputs: host (required), remote_path (required), content (required), username, +11 more. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 15 tools
Tools are largely distinct across session management, command execution, file operations, and interactive features. Potential confusion between send_input, send_input_by_session, and send_keys is clarified by descriptions but still requires careful reading.
All tools follow a consistent verb_noun lowercase underscore pattern (e.g., execute_command, get_command_status, list_sessions). Compound verbs like close_all and send_input_by_session are still predictable and uniform.
15 tools cover the SSH domain comprehensively without being excessive. Each tool serves a specific need (sync/async commands, file transfer, interactive control, session management) and the count feels well-scoped.
Core SSH workflows are covered: command execution (sync and async), file reading/writing, session listing, and interactive input. Minor gaps include no explicit session creation tool (sessions are created implicitly) and no file deletion or rename operations.
Maintenance
Related MCP Connectors
Manage servers through SSH.
Work on your own computers from Claude or ChatGPT: run commands, edit and search files.
Let AI operate servers without SSH. Choose actions, approve risky changes, and audit every step.
Operate Linux, macOS and Windows from your LLM. Every action runs through an auditable allowlist.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI assistants to securely connect to and manage remote servers via SSH, supporting command execution, file transfers via SFTP, and multi-server management with both password and SSH key authentication.962 npm2MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to securely execute commands, transfer files, and manage port forwarding on remote servers via SSH.158 npm38Apache 2.0
- FlicenseNot gradedqualityDmaintenanceEnables AI to execute commands on remote hosts via SSH, supporting password and key authentication.-
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to securely execute commands on remote hosts via SSH and SFTP, with persistent shells, file transfers, screenshots, and an audit log.5MIT