MCP server for managing persistent SSH sessions
Project description
MCP SSH Session
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/config - Multi-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
Installation
Using uvx
uvx mcp-ssh-session
Using 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-session
Development 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!
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.
{
"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_passwordprovided - Supports 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_passwordprovided - Uses
sudo teevia shell whenuse_sudo=trueorsudo_passwordis provided - Supports both passwordless sudo (NOPASSWD) and password-based sudo
- Content larger than 2 MB is rejected for safety
- Optional
appendmode to add to existing files - Optional
make_dirsflag will create missing parent directories - Supports
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_rsa
Then simply use:
{
"host": "myserver",
"command": "uptime"
}
Documentation
- ASYNC_COMMANDS.md - Smart execution and async commands
- CLAUDE.md - Detailed usage documentation
License
Distributed under the MIT License. See LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcp_ssh_session-0.1.3.tar.gz.
File metadata
- Download URL: mcp_ssh_session-0.1.3.tar.gz
- Upload date:
- Size: 106.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3ebd9aa0140dc773c6ce711b03214f50ac3de0531ca316b864faf173dbc0fd44
|
|
| MD5 |
6e76b0d7a008c12107edbf5433bd4157
|
|
| BLAKE2b-256 |
5db2fc5280eebf1838fc1662810f831b7148eaba49530ebcbe5b4355d5e3be76
|
Provenance
The following attestation bundles were made for mcp_ssh_session-0.1.3.tar.gz:
Publisher:
publish.yaml on devnullvoid/mcp-ssh-session
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_ssh_session-0.1.3.tar.gz -
Subject digest:
3ebd9aa0140dc773c6ce711b03214f50ac3de0531ca316b864faf173dbc0fd44 - Sigstore transparency entry: 703625957
- Sigstore integration time:
-
Permalink:
devnullvoid/mcp-ssh-session@57f9ae8a05733cb8c02801c6e58d056bef6d69b3 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/devnullvoid
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@57f9ae8a05733cb8c02801c6e58d056bef6d69b3 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file mcp_ssh_session-0.1.3-py3-none-any.whl.
File metadata
- Download URL: mcp_ssh_session-0.1.3-py3-none-any.whl
- Upload date:
- Size: 20.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3023be76ad973a238f6e5815e56262e93944086ec4335c2857cfa6a9f219aedf
|
|
| MD5 |
83271fcb8cbbd5578a48b5425b940f4e
|
|
| BLAKE2b-256 |
80f7147c17672d8a4cc8caf9b91643f97eab0cad3cf9f41d89b07ae7bc84d09b
|
Provenance
The following attestation bundles were made for mcp_ssh_session-0.1.3-py3-none-any.whl:
Publisher:
publish.yaml on devnullvoid/mcp-ssh-session
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_ssh_session-0.1.3-py3-none-any.whl -
Subject digest:
3023be76ad973a238f6e5815e56262e93944086ec4335c2857cfa6a9f219aedf - Sigstore transparency entry: 703626044
- Sigstore integration time:
-
Permalink:
devnullvoid/mcp-ssh-session@57f9ae8a05733cb8c02801c6e58d056bef6d69b3 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/devnullvoid
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@57f9ae8a05733cb8c02801c6e58d056bef6d69b3 -
Trigger Event:
workflow_dispatch
-
Statement type: