subpop/mcp_linux_ssh
If you are the rightful owner of mcp_linux_ssh and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
An MCP server that allows AI assistants to execute commands on remote Linux systems via SSH, providing a secure and efficient way to manage and troubleshoot systems.
MCP POSIX compatible system (Linux, BSD, macOS) SSH Server
An MCP (Model Context Protocol) server that enables AI assistants to run commands and access files on remote POSIX compatible system (Linux, BSD, macOS) systems via SSH. This server provides a secure way for AI models to perform system administration tasks, troubleshoot issues, execute commands, and read configuration files on remote POSIX compatible system (Linux, BSD, macOS) machines.
Example Use Cases
This MCP server enables LLMs to perform system administration tasks across remote infrastructure.
Issue Discovery
- Web performance → Check system resources (
top,free,df), examine web server logs, analyze network connections - Authentication failures → Investigate authentication logs (
/var/log/auth.log), check service status (systemctl status sshd), verify user accounts - Database timeouts → Examine database logs, check connection pools, analyze slow query logs, monitor system resources
Troubleshooting
- Comparative analysis: Check for differences between different web servers, databases, and load balancers
- Configuration analysis: Read and analyze config files (
nginx.conf,my.cnf, etc.) - Dependency tracking: Check systemd units, network connections, and process relationships
Operations
- Deployment verification: Verify services are running, configurations are correct, and applications are responding
- Incident response: Gather diagnostic information from multiple systems
- Documentation generation: Document system configurations, installed packages, and service dependencies
Features
- Tools:
- Local command execution for SSH troubleshooting
- Remote SSH command execution (standard user permissions)
- Remote SSH command execution with sudo support
- File copying with rsync (preserves attributes, creates backups)
- Patch application over SSH (apply diffs to remote files)
- Configurable timeouts: Per-command timeout settings to prevent blocking
- Public key discovery: List available public keys from
~/.sshdirectory - Authentication: Uses existing SSH configuration and keys
- User specification: Specify which user to run commands as
- Security: Leverages SSH's built-in security features
- System administrator persona: Built-in instructions for system administration tasks
- Error handling: Error messages for connection and execution issues
Prerequisites
- Rust toolchain (1.70 or later)
- SSH client installed on your system
- SSH access configured to your target Linux systems
- SSH keys set up for passwordless authentication (recommended)
Building
- Clone this repository:
git clone https://github.com/subpop/mcp_linux_ssh
cd mcp_linux_ssh
- Build the project:
cargo build --release
The compiled binary will be available at target/release/mcp_linux_ssh.
Setup Instructions
Claude Desktop
-
Build the project as described above
-
Edit your Claude Desktop configuration file:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
- macOS:
-
Add the MCP server configuration:
{
"mcpServers": {
"linux-ssh": {
"command": "/path/to/your/mcp_linux_ssh/target/release/mcp_linux_ssh",
"args": [],
"env": {
"RUST_LOG": "info"
}
}
}
}
- Restart Claude Desktop
Gemini (via MCP)
Gemini doesn't have native MCP support, but you can use it through compatible MCP clients or adapters. Follow the general MCP client setup pattern:
- Use an MCP-compatible client that supports Gemini
- Configure the server path:
/path/to/your/mcp_linux_ssh/target/release/mcp_linux_ssh - Set environment variables as needed
VSCode (via MCP Extension)
- Install an MCP extension for VSCode (such as the official MCP extension)
- Open VSCode settings (Cmd/Ctrl + ,)
- Search for "MCP" settings
- Add a new MCP server configuration:
- Name:
linux-ssh - Command:
/path/to/your/mcp_linux_ssh/target/release/mcp_linux_ssh - Args:
[] - Environment:
{"RUST_LOG": "info"}
- Name:
Cursor
- Build the project as described above
- Open Cursor settings
- Navigate to the MCP servers section
- Add a new server configuration:
{
"name": "linux-ssh",
"command": "/path/to/your/mcp_linux_ssh/target/release/mcp_linux_ssh",
"args": [],
"env": {
"RUST_LOG": "info"
}
}
Goose
- Build the project as described above
- Create or edit your Goose configuration file (
~/.config/goose/config.yamlor similar) - Add the MCP server configuration:
mcp_servers:
linux-ssh:
command: /path/to/your/mcp_linux_ssh/target/release/mcp_linux_ssh
args: []
env:
RUST_LOG: info
SSH Configuration
Before using this MCP server, ensure your SSH is properly configured:
1. SSH Key Setup
Generate an SSH key pair if you don't have one:
ssh-keygen -t ed25519 -C "your_email@example.com"
Copy your public key to the remote server:
ssh-copy-id user@remote-host
2. SSH Config File
Create or edit ~/.ssh/config to simplify connections:
Host myserver
HostName 192.168.1.100
User myuser
Port 22
IdentityFile ~/.ssh/id_ed25519
3. Test SSH Connection
Verify you can connect without a password:
ssh myserver whoami
4. Custom Identity Files
The MCP server supports specifying custom private key files through the private_key parameter. This is useful when:
- You have multiple SSH keys for different servers or environments
- You need to use a specific key that's not the default (
~/.ssh/id_ed25519) - You're managing multiple remote systems with different authentication requirements
Behavior:
- Default: Uses
~/.ssh/id_ed25519if noprivate_keyis specified - Tilde expansion: Supports
~for home directory (e.g.,~/.ssh/my_key) - Absolute paths: Supports full paths (e.g.,
/home/user/.ssh/production_key) - Relative paths: Supports relative paths from current working directory
Examples:
// Using default key (~/.ssh/id_ed25519)
{
"command": "ls",
"remote_host": "server1"
}
// Using custom key with tilde expansion
{
"command": "ls",
"remote_host": "server2",
"private_key": "~/.ssh/production_key"
}
// Using absolute path
{
"command": "ls",
"remote_host": "server3",
"private_key": "/opt/keys/deployment_key"
}
Security:
- Ensure private key files have correct permissions (600)
- Keep private keys secure and never share them
- Use different keys for different environments (dev/staging/production)
Usage
Once configured, you can use the following capabilities through your AI assistant:
Tools
Run (Local Command Execution)
Executes a command on the local system. This tool is primarily intended for troubleshooting SSH connectivity issues when remote commands fail.
Parameters:
command(required): The command to execute locallyargs(optional): Array of arguments to pass to the commandtimeout_seconds(optional): Timeout in seconds for command execution (default: 30, set to 0 to disable)
Examples:
{
"command": "ssh",
"args": ["-v", "user@remote-host", "echo", "test"]
}
{
"command": "ping",
"args": ["-c", "5", "google.com"],
"timeout_seconds": 10
}
SSH (Remote Command Execution)
Executes a command on a remote POSIX compatible system (Linux, BSD, macOS) system via SSH. This tool does not permit commands to be run with sudo.
Parameters:
command(required): The command to executeargs(optional): Array of arguments to pass to the commandremote_host(required): The hostname or IP address of the remote systemremote_user(optional): The username to connect as (defaults to current user)private_key(optional): Path to the private key file for authentication (defaults to~/.ssh/id_ed25519)timeout_seconds(optional): Timeout in seconds for command execution (default: 30, set to 0 to disable)
Examples:
{
"command": "ls",
"args": ["-la", "/home"],
"remote_host": "myserver",
"remote_user": "admin"
}
{
"command": "systemctl",
"args": ["status", "nginx"],
"remote_host": "webserver.example.com"
}
Using a custom private key:
{
"command": "ps",
"args": ["aux"],
"remote_host": "production-server",
"remote_user": "deploy",
"private_key": "~/.ssh/production_key"
}
SSH Sudo (Remote Command Execution with Sudo)
Executes a command on a remote POSIX compatible system (Linux, BSD, macOS) system via SSH. This tool permits commands to be run with sudo for administrative tasks.
Parameters:
command(required): The command to execute (can include sudo)args(optional): Array of arguments to pass to the commandremote_host(required): The hostname or IP address of the remote systemremote_user(optional): The username to connect as (defaults to current user)private_key(optional): Path to the private key file for authentication (defaults to~/.ssh/id_ed25519)timeout_seconds(optional): Timeout in seconds for command execution (default: 30, set to 0 to disable)
Examples:
{
"command": "sudo",
"args": ["systemctl", "restart", "nginx"],
"remote_host": "webserver.example.com",
"remote_user": "admin"
}
{
"command": "sudo",
"args": ["tail", "-f", "/var/log/syslog"],
"remote_host": "logserver",
"remote_user": "sysadmin"
}
Using a custom private key with sudo:
{
"command": "sudo",
"args": ["systemctl", "restart", "apache2"],
"remote_host": "web01.example.com",
"remote_user": "admin",
"private_key": "/home/user/.ssh/admin_key"
}
Copy_File (File Transfer with Rsync)
Copies a file from the local machine to a remote system using rsync. Preserves file attributes (permissions, timestamps, ownership) and creates backups of existing files on the remote system.
Parameters:
source(required): The path to the source file on the local machinedestination(required): The destination path on the remote machineremote_host(required): The hostname or IP address of the remote systemremote_user(optional): The username to connect as (defaults to current user)private_key(optional): Path to the private key file for authentication (defaults to~/.ssh/id_ed25519)timeout_seconds(optional): Timeout in seconds for the copy operation (default: 30, set to 0 to disable)
Features:
- Archive mode: Preserves permissions, timestamps, ownership, and other file attributes
- Automatic backups: If a file exists at the destination, a backup is created with a
~suffix - Secure transfer: Uses SSH for encrypted file transfer
Examples:
{
"source": "/home/user/config.yaml",
"destination": "/etc/myapp/config.yaml",
"remote_host": "webserver.example.com",
"remote_user": "deploy"
}
{
"source": "./build/app.jar",
"destination": "/opt/myapp/app.jar",
"remote_host": "production-server",
"remote_user": "deploy",
"private_key": "~/.ssh/deployment_key",
"timeout_seconds": 60
}
Using with absolute paths:
{
"source": "/var/www/html/index.html",
"destination": "/var/www/html/index.html",
"remote_host": "backup-server",
"private_key": "/opt/keys/backup_key"
}
Backup Behavior:
When copying to an existing file, rsync creates a backup with the original filename plus a ~ suffix:
- Original file:
/etc/myapp/config.yaml - Backup file:
/etc/myapp/config.yaml~ - New file:
/etc/myapp/config.yaml(updated)
Patch_File (Apply Patches to Remote Files)
Applies a patch/diff to a file on a remote system via SSH. The patch content is streamed through stdin over the SSH connection to the remote patch command.
Parameters:
patch(required): The patch/diff content to apply (unified diff format recommended)remote_file(required): The path to the file on the remote machine to patchremote_host(required): The hostname or IP address of the remote systemremote_user(optional): The username to connect as (defaults to current user)private_key(optional): Path to the private key file for authentication (defaults to~/.ssh/id_ed25519)timeout_seconds(optional): Timeout in seconds for the patch operation (default: 30, set to 0 to disable)options(optional): Additional SSH options to pass via-oflag (array of "key=value" strings)
Features:
- Stdin streaming: Patch content is securely streamed via SSH stdin
- Automatic strip detection: The
patchcommand automatically detects the appropriate-pstrip level - Unified diff support: Works best with unified diff format (
diff -uorgit diff) - Context preservation: Maintains file context for accurate patching
Examples:
Basic usage:
{
"patch": "--- config.yaml\n+++ config.yaml\n@@ -1,3 +1,3 @@\n-port: 8080\n+port: 9090\n",
"remote_file": "/etc/myapp/config.yaml",
"remote_host": "webserver.example.com",
"remote_user": "deploy"
}
Applying a Git diff:
{
"patch": "diff --git a/app.py b/app.py\nindex 1234567..abcdefg 100644\n--- a/app.py\n+++ b/app.py\n@@ -10,7 +10,7 @@ def main():\n- return 'Hello'\n+ return 'Hello, World!'\n",
"remote_file": "/opt/myapp/app.py",
"remote_host": "production-server",
"remote_user": "appuser",
"private_key": "~/.ssh/deployment_key"
}
With custom SSH options:
{
"patch": "--- nginx.conf\n+++ nginx.conf\n@@ -5,1 +5,1 @@\n-worker_processes 2;\n+worker_processes 4;\n",
"remote_file": "/etc/nginx/nginx.conf",
"remote_host": "192.168.1.100",
"remote_user": "root",
"options": ["StrictHostKeyChecking=no", "UserKnownHostsFile=/dev/null"]
}
Workflow:
- Generate a diff locally:
diff -u original.txt modified.txt > changes.patch - Read the patch content
- Use
Patch_Fileto apply it to the remote file - Verify the changes with
SSHtool (e.g.,cat /path/to/file)
Notes:
- The
patchcommand must be installed on the remote system - Ensure the file to be patched exists on the remote system
- If the patch fails to apply cleanly, check the output for conflicts
- The remote file path should be absolute or relative to the remote user's home directory
- For large patches or binary files, consider using
Copy_Fileinstead
Common Patch Formats:
- Unified diff (recommended):
diff -u old.txt new.txt - Git diff:
git diff file.txt - Context diff:
diff -c old.txt new.txt
Resources
This server exposes local system information as resources that can be read by the AI assistant.
public_keys
Lists all available public keys (.pub files) found in the user's ~/.ssh directory.
URI:
file:///public_keys
Returns: A comma-separated string of public key filenames.
Example Usage:
An AI assistant might read this resource to see which SSH keys are available for use in the SSH or SSH Sudo tools, especially when deciding which private_key to specify.
Example Return Value:
id_rsa.pub,id_ed25519.pub,work_key.pub
Timeout Configuration
All commands support configurable timeouts to prevent indefinite blocking.
- Default: 30 seconds
- Disable: Set
timeout_secondsto0 - Custom: Set any positive integer (seconds)
Examples
// Quick command
{
"command": "whoami",
"remote_host": "server1",
"timeout_seconds": 5
}
// Long operation
{
"command": "find",
"args": ["/", "-name", "*.log"],
"remote_host": "server1",
"timeout_seconds": 300
}
// No timeout (monitoring)
{
"command": "tail",
"args": ["-f", "/var/log/syslog"],
"remote_host": "server1",
"timeout_seconds": 0
}
Security Considerations
- SSH Key Security: Use strong SSH keys and keep private keys secure
- Limited Scope: Only grant access to systems you trust the AI to manage
- User Permissions: The remote user should have appropriate but limited permissions
- Monitoring: Consider logging SSH sessions for audit purposes
- Network Security: Ensure SSH is properly configured (disable password auth, use non-standard ports, etc.)
Troubleshooting
Connection Issues
- Permission Denied: Ensure SSH keys are properly set up and the user has access
- Host Key Verification Failed: Add the host to your known_hosts file:
ssh-keyscan -H remote-host >> ~/.ssh/known_hosts - Command Not Found: Ensure the command exists on the remote system and is in the PATH
Common SSH Issues
- Connection Timeout: Check network connectivity and SSH daemon status
- Authentication: Verify SSH key permissions (600 for private key, 644 for public key)
- Path Issues: Use absolute paths for commands when possible
Private Key Issues
-
Wrong Key Path: Ensure the
private_keyparameter points to the correct file:# Check if key exists ls -la ~/.ssh/id_ed25519 # Verify key permissions chmod 600 ~/.ssh/id_ed25519 -
Key Not Added to Agent: If using SSH agent, ensure your key is loaded:
ssh-add ~/.ssh/id_ed25519 ssh-add -l # List loaded keys -
Multiple Keys: When using multiple keys, specify the correct one:
{ "command": "whoami", "remote_host": "server", "private_key": "~/.ssh/specific_key" } -
Key Format Issues: Ensure your private key is in the correct format (OpenSSH format preferred)
Development
To modify or extend this server:
- Edit the source code in
src/lib.rs - Add new tools by implementing functions with the
#[tool]attribute - Rebuild with
cargo build --release - Restart your MCP client to pick up changes
Logging
The server automatically logs all tool calls to ~/.local/state/mcp_linux_ssh/tool_calls.jsonl (following XDG Base Directory specification) for debugging and audit purposes. Logs are rotated daily.
Contributing
Contributions are welcome! Please ensure:
- Code is properly formatted (
cargo fmt) - All tests pass (
cargo test) - Security best practices are followed
License
See file for details.