README
¶
$$$$$$\ $$$$$$\ $$\ $$\ $$\ $$\ $$$$$$\ $$$$$$$\
$$ __$$\ $$ __$$\ $$ | $$ |$$$\ $$$ |$$ __$$\ $$ __$$\
$$ / \__|$$ / \__|$$ | $$ |$$$$\ $$$$ |$$ / \__|$$ | $$ |
\$$$$$$\ \$$$$$$\ $$$$$$$$ |$$\$$\$$ $$ |$$ | $$$$$$$ |
\____$$\ \____$$\ $$ __$$ |$$ \$$$ $$ |$$ | $$ ____/
$$\ $$ |$$\ $$ |$$ | $$ |$$ |\$ /$$ |$$ | $$\ $$ |
\$$$$$$ |\$$$$$$ |$$ | $$ |$$ | \_/ $$ |\$$$$$$ |$$ |
\______/ \______/ \__| \__|\__| \__| \______/ \__|
Secure SSH & SFTP Client with MCP Protocol Support
SSHMCP
sshx provides a barrier-free SSH command-line client while implementing the MCP (Model Context Protocol) interface, enabling AI assistants to easily invoke remote SSH/SFTP functionality.
Project Structure
cmd/sshx: Main binary entry point, responsible for command-line argument parsing, MCP mode startup, and password management features.internal/sshclient: Core SSH/SFTP/script execution logic, command security validation, and connection pool wrapper.internal/mcp: MCP stdio server implementation, exposing SSH/SFTP/script tools to external tools (e.g., AI assistants).
Key Features
- Cross-platform SSH/SFTP operations (supports sudo auto-fill).
- Password management (Keychain / Secret Service / Credential Manager).
- MCP stdio mode for AI assistant integration.
- Connection pooling, script execution, and command security validation.
Installation
Quick Install with Go (Recommended for Go Users)
If you have Go 1.21+ installed, you can use Go's built-in tools:
Run directly without installation (like npx)
# Run the latest version
go run github.com/talkincode/sshmcp/cmd/sshx@latest --help
# Run specific version
go run github.com/talkincode/sshmcp/cmd/sshx@v0.0.6 -h=192.168.1.100 "uptime"
Install globally
# Install latest version to $GOPATH/bin
go install github.com/talkincode/sshmcp/cmd/sshx@latest
# Then use it anywhere
sshx --help
sshx -h=192.168.1.100 "uptime"
Note: Make sure $GOPATH/bin (typically ~/go/bin) is in your PATH.
One-Line Installation Script
Linux / macOS
curl -fsSL https://raw.githubusercontent.com/talkincode/sshmcp/main/install.sh | bash
Or download and run:
wget https://raw.githubusercontent.com/talkincode/sshmcp/main/install.sh
chmod +x install.sh
./install.sh
Install specific version:
./install.sh v0.0.2
Windows
Open PowerShell as Administrator and run:
irm https://raw.githubusercontent.com/talkincode/sshmcp/main/install.ps1 | iex
Or download and run:
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/talkincode/sshmcp/main/install.ps1" -OutFile "install.ps1"
.\install.ps1
Install specific version:
.\install.ps1 -Version v0.0.2
Manual Installation
Download pre-built binaries from Releases:
Linux / macOS:
# Download and extract (replace <platform>-<arch> with your system)
tar -xzf sshx-<platform>-<arch>.tar.gz
# Move to system path
sudo mv sshx /usr/local/bin/
# Make executable
sudo chmod +x /usr/local/bin/sshx
# Verify installation
sshx --help
Windows:
- Download
sshx-windows-amd64.zip - Extract the archive
- Move
sshx.exeto a directory in your PATH (e.g.,C:\Program Files\sshx) - Or add the extracted directory to your system PATH
Build from Source
# Clone repository
git clone https://github.com/talkincode/sshmcp.git
cd sshmcp
# Build command-line tool
go build -o bin/sshx ./cmd/sshx
# Install to system (optional)
make install
Quick Start
# Execute remote command
sshx -h=192.168.1.100 -u=root "uptime"
# Save password for easier access (interactive input)
sshx --password-set=root
# Or set password for specific host
sshx --password-set=192.168.1.100-root
# Execute command without password flag (uses saved password)
sshx -h=192.168.1.100 -u=root "df -h"
# Start MCP stdio mode
sshx mcp-stdio
Password Management
sshx provides secure password storage using the operating system's native credential manager, eliminating the need to enter passwords repeatedly or store them in plaintext.
Supported Platforms
- macOS: Uses Keychain Access
- Linux: Uses Secret Service (GNOME Keyring / KDE Wallet)
- Windows: Uses Credential Manager
Password Commands
Save Password
# Save default sudo password (interactive input, recommended)
sshx --password-set=master
# Save password for specific user
sshx --password-set=root
# Save password for specific host+user combination
sshx --password-set=192.168.1.100-root
# Set password inline (not recommended, insecure)
sshx --password-set=master:yourpassword
You will be prompted to enter the password securely (input is hidden).
Check Saved Password
# Check if password exists
sshx --password-check=master
sshx --password-check=root
# Output example:
# ✓ Password exists for key: master
List Saved Passwords
# List common password keys
sshx --password-list
# Output example:
# Checking password keys in system keyring...
# Service: sshx
#
# Common keys:
# ✓ master (exists)
# ✓ root (exists)
# sudo (not set)
Get Password
# Get stored password (for debugging)
sshx --password-get=master
# Output example:
# ✓ Password retrieved from system keyring
# Service: sshx
# Key: master
#
# Password: yourpassword
Delete Password
# Delete password
sshx --password-delete=master
sshx --password-delete=root
# Confirmation message:
# ✓ Password deleted from system keyring
# Service: sshx
# Key: master
Using Stored Passwords
Once a password is saved, sudo commands will automatically retrieve the password from system keyring:
# 1. First save sudo password
sshx --password-set=master
# 2. Execute sudo commands (automatically uses stored password)
sshx -h=192.168.1.100 -u=root "sudo systemctl status nginx"
sshx -h=192.168.1.100 -u=root "sudo reboot"
# 3. Multi-server scenario: save different passwords for different servers
sshx --password-set=server-A
sshx --password-set=server-B
sshx --password-set=server-C
# 4. Use -pk parameter to specify sudo password key temporarily
sshx -h=192.168.1.100 -pk=server-A "sudo systemctl restart nginx"
sshx -h=192.168.1.101 -pk=server-B "sudo systemctl restart nginx"
sshx -h=192.168.1.102 -pk=server-C "sudo systemctl restart nginx"
Password Key Names
- master: Default sudo password key name, used for sudo commands
- root: Password for root user
- Custom keys: You can use any key name, e.g.,
server-A,server-B,prod-db, etc.
Best Practices for Multi-Server Password Management
If you manage multiple servers with the same username but different passwords, use this strategy:
# Scenario: Manage 3 servers, all with root user but different passwords
# 1. Save password for each server (use meaningful key names)
sshx --password-set=prod-web # Production web server
sshx --password-set=prod-db # Production database server
sshx --password-set=dev-server # Development server
# 2. Execute commands using -pk parameter to specify password key
sshx -h=192.168.1.10 -u=root -pk=prod-web "sudo systemctl status nginx"
sshx -h=192.168.1.20 -u=root -pk=prod-db "sudo systemctl status mysql"
sshx -h=192.168.1.30 -u=root -pk=dev-server "sudo docker ps"
# 3. You can also use aliases to simplify commands (add to ~/.zshrc or ~/.bashrc)
alias ssh-prod-web='sshx -h=192.168.1.10 -u=root -pk=prod-web'
alias ssh-prod-db='sshx -h=192.168.1.20 -u=root -pk=prod-db'
alias ssh-dev='sshx -h=192.168.1.30 -u=root -pk=dev-server'
# Then use simply:
ssh-prod-web "sudo systemctl restart nginx"
ssh-prod-db "sudo systemctl restart mysql"
ssh-dev "sudo docker-compose up -d"
Environment Variables
You can customize the sudo password key name via environment variable (but using -pk parameter is more flexible):
# Use environment variable (can only specify one at a time, needs constant modification)
export SSH_SUDO_KEY=my-sudo-password
sshx --password-set=my-sudo-password
sshx -h=192.168.1.100 "sudo ls -la /root"
# Recommended: Use -pk parameter, more flexible, no need to modify environment variables
sshx -h=192.168.1.100 -pk=server-A "sudo ls -la /root"
sshx -h=192.168.1.101 -pk=server-B "sudo ls -la /root"
Security Notes
- ✅ Passwords are stored using OS-native encryption
- ✅ Passwords are never stored in plaintext
- ✅ Each host+user combination has a separate password entry
- ✅ Password input is hidden during entry
- ⚠️ Requires OS credential manager to be available
- ⚠️ On Linux, requires Secret Service daemon running (usually automatic with desktop environments)
Environment Variables
You can use environment variables to avoid typing credentials repeatedly:
# Set in .env file or export in shell
export SSH_HOST=192.168.1.100
export SSH_USER=root
export SSH_PORT=22
export SUDO_PASSWORD=your_sudo_password
# Then run commands without flags
./bin/sshx "uptime"
Example Workflow
# 1. Save sudo password (interactive input)
sshx --password-set=master
# Enter password for key 'master': ******
# 2. Verify it's saved
sshx --password-check=master
# ✓ Password exists for key: master
# 3. Use for SSH commands (sudo automatically uses stored password)
sshx -h=192.168.1.100 -u=root "sudo systemctl status docker"
sshx -h=192.168.1.100 -u=root "sudo df -h"
# 4. Use for SFTP operations
sshx -h=192.168.1.100 -u=root --upload=local.txt --to=/tmp/remote.txt
sshx -h=192.168.1.100 -u=root --download=/etc/hosts --to=./hosts.txt
# 5. List all saved password keys
sshx --password-list
# Common keys:
# ✓ master (exists)
# root (not set)
# 6. When done, optionally delete the password
sshx --password-delete=master
# ✓ Password deleted from system keyring
Troubleshooting
"sshx: command not found"
Solution:
- Ensure
/usr/local/bin(or your installation directory) is in your PATH - Restart your terminal after installation
- Or run with full path:
/usr/local/bin/sshx
macOS Security Warning
macOS may block the binary on first run:
sudo xattr -rd com.apple.quarantine /usr/local/bin/sshx
Or go to System Preferences → Security & Privacy → Click "Allow Anyway"
Windows SmartScreen Warning
Click "More info" and then "Run anyway" if Windows Defender SmartScreen shows a warning.
Permission Denied
# Make sure the binary has execute permissions
sudo chmod +x /usr/local/bin/sshx
Development
# Run tests
go test ./...
# Format code
gofmt -w .
# Build for all platforms
make build-all
# Run linter
make lint
The lint target requires
golangci-lintv2.6.1 or newer. Install it withgo install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.6.1.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Documentation • Issues • Discussions • Releases
Made with ❤️ by talkincode