mcp-ssh-tool
The mcp-ssh-tool server enables autonomous SSH-based remote system management through natural language commands via MCP clients (e.g., GitHub Copilot, VS Code).
SSH Session Management
Open, close, list, and ping SSH sessions
Authenticate via password, SSH key (inline, path, or auto-discovery), or SSH agent
List and resolve hosts/aliases from
~/.ssh/configConnection pooling with TTL and LRU eviction
Command Execution
Run arbitrary commands (
proc_exec) with optional working directory, environment variables, and timeoutExecute commands with sudo privileges (
proc_sudo)
File System Operations (via SFTP or shell fallback)
Read, write, stat, list, create directories, remove, and rename/move files and directories
Configuration & Automation
Ensure packages are installed or removed (
ensure_package)Ensure services are started, stopped, restarted, enabled, or disabled (
ensure_service)Add or remove specific lines in config files (
ensure_lines_in_file)Apply unified diff patches to remote files (
patch_apply)
System Information & Metrics
Detect OS, distro, package manager, init system, and shell (
os_detect)Retrieve server metrics in JSON or Prometheus format
Additional Highlights
Automatic fallback to shell-based file ops for BusyBox/Dropbear (embedded) systems without SFTP
Sensitive data redaction in logs and configurable host key verification
Supports Linux, macOS, and Windows targets
Enables natural language SSH automation within GitHub Copilot, allowing for autonomous file operations and command execution on remote servers.
Supports the remote installation and management of the htop system monitoring tool via automated package management commands.
Provides comprehensive management of Linux-based systems, including process execution with sudo privileges, service control, and file system operations.
Facilitates SSH connectivity and remote command execution on macOS environments using POSIX shell wrappers.
Allows for the remote management of NGINX web servers, including configuration file editing and service state control.
Enables automated package management and system administration specifically tailored for Ubuntu server environments.
mcp-ssh-tool
A Model Context Protocol (MCP) SSH client server that provides autonomous SSH operations for GitHub Copilot and VS Code. Enable natural language SSH automation without manual prompts or GUI interactions.
Official MCP Registry entry: io.github.oaslananka/mcp-ssh-tool
Registry metadata: https://registry.modelcontextprotocol.io/v0.1/servers/io.github.oaslananka%2Fmcp-ssh-tool/versions/latest
Quick Start
Install
Global install (recommended):
npm install -g mcp-ssh-toolOne-off run:
npx mcp-ssh-tool
MCP Client Configuration (VS Code / Claude Desktop / others)
Add to your MCP configuration (mcp.json, .vscode/mcp.json, or the Claude Desktop MCP config):
{
"servers": {
"ssh-mcp": {
"type": "stdio",
"command": "mcp-ssh-tool",
"args": []
}
}
}Usage Examples
Once configured, you can use natural language with your MCP client:
SSH Connection: "Connect to server 192.168.1.100 as admin using SSH key"
File Operations: "Read the content of /etc/nginx/nginx.conf on the server"
Command Execution: "Run 'systemctl status nginx' on the remote server"
Package Management: "Install htop package on Ubuntu server"
Service Control: "Restart the nginx service"
Claude Desktop: "connect to my server and check disk usage"
Install a package/service stack: "install nginx on my remote server"
Read a config file: "read the file /etc/nginx/nginx.conf"
Restart a service: "restart the nginx service"
Browse logs: "list files in /var/log"
Available Tools
ssh_open_session- Establish SSH connection with various auth methodsssh_close_session- Close SSH sessionssh_list_sessions- List all active SSH sessionsssh_ping- Check if a session is alive and responsivessh_list_configured_hosts- List hosts from ~/.ssh/configssh_resolve_host- Resolve host alias from SSH configproc_exec- Execute commands remotely (with optional timeout)proc_sudo- Execute commands with sudo privilegesfs_read,fs_write,fs_list,fs_stat,fs_mkdirp,fs_rmrf,fs_rename- File system operationsensure_package- Package management withpresentandabsentstatesensure_service- Service control includingrestartedensure_lines_in_file- File line management withpresentandabsentstatespatch_apply- Apply patches to filesos_detect- System information detectionget_metrics- Server metrics in JSON or Prometheus formatproc_exec_stream- Streaming command execution with chunked outputfile_upload,file_download- SFTP file transfer helperstunnel_local_forward,tunnel_remote_forward,tunnel_close,tunnel_list- Tunnel management
Available Resources
mcp-ssh-tool://sessions/active- Active sessions as JSONmcp-ssh-tool://metrics/json- Metrics snapshot as JSONmcp-ssh-tool://metrics/prometheus- Prometheus metrics exportmcp-ssh-tool://ssh-config/hosts- Parsed local SSH host aliases
Overview
The SSH MCP Server acts as a bridge between GitHub Copilot and remote systems via SSH. It supports:
Non-interactive SSH operations - No prompts or GUI interactions
Multiple authentication methods - Password, SSH keys, or SSH agent
Session management - Automatic connection pooling with TTL and LRU eviction
File system operations - Read, write, list, and manage remote files via SFTP, with SSH-shell fallbacks for hosts that do not expose an SFTP subsystem
Process execution - Run commands and sudo operations remotely
High-level automation - Package management, service control, and configuration management
Security - Automatic redaction of sensitive data in logs
Architecture
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ GitHub Copilot │────│ SSH MCP Server │────│ Remote Systems │
│ / VS Code │ │ │ │ (via SSH) │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│ │ │
│ MCP stdio protocol │ Session management │ SSH + optional SFTP
│ │ LRU cache + TTL │
│ │ Auth strategies │Embedded / BusyBox Targets
Some embedded targets expose SSH command execution but do not ship an SFTP
subsystem, which is common with Dropbear- or BusyBox-based systems. In that
case ssh_open_session still succeeds and reports sftpAvailable: false.
Core file tools such as fs_read, fs_write, fs_stat, fs_list,
fs_mkdirp, fs_rmrf, and fs_rename automatically fall back to shell-based
implementations.
Installation
Prerequisites
Node.js ≥ 20 (LTS)
SSH access to target systems
SSH keys or credentials for authentication
Install from npm
npm install -g mcp-ssh-toolBuild from source
git clone https://github.com/oaslananka/mcp-ssh-tool.git
cd mcp-ssh-tool
npm install
npm run build
npm linkCLI Flags
--help/-h: Show usage and examples.--version/-v: Print version.--stdio: Force stdio mode (default).
Note: This is an MCP stdio server. The terminal is not an interactive shell; use an MCP client (Claude Desktop, VS Code MCP, etc.) or send JSON-RPC over stdio.
Platform Notes
Linux / macOS: Uses POSIX shell wrappers with safe quoting. Default temp directory:
/tmp.Windows targets: Requires OpenSSH server/agent; key discovery checks
C:\\Users\\<you>\\.ssh\\. Commands are wrapped for PowerShell-safe execution. Package/service helpers are intentionally disabled on Windows targets.Host keys: Host key checking is relaxed by default. Set
STRICT_HOST_KEY_CHECKING=trueand optionallyKNOWN_HOSTS_PATHto enforce verification.
ChatGPT Desktop Integration
Quick Setup
npm run setup:chatgptThis command automatically configures ChatGPT Desktop to use mcp-ssh-tool.
Manual Setup
Add to your ChatGPT Desktop MCP config:
macOS:
~/Library/Application Support/ChatGPT/mcp.jsonWindows:
%APPDATA%\ChatGPT\mcp.jsonLinux:
~/.config/chatgpt/mcp.json
{
"mcpServers": {
"ssh-mcp-server": {
"name": "ssh-mcp-server",
"command": "npx",
"args": ["-y", "mcp-ssh-tool"]
}
}
}For detailed usage, see docs/chatgpt-usage.md.
Codex Integration
Quick Setup
Install the package globally, then register it with Codex:
npm install -g mcp-ssh-tool
codex mcp add ssh-mcp -- mcp-ssh-toolIf you prefer not to install globally, you can register it through npx:
codex mcp add ssh-mcp -- npx -y mcp-ssh-toolVerification
Check that Codex can see the MCP server:
codex mcp list
codex mcp get ssh-mcpYou should see an enabled stdio server whose command is mcp-ssh-tool or npx.
Optional Security Hardening
To enforce host key verification in the Codex-managed server process:
codex mcp remove ssh-mcp
codex mcp add ssh-mcp \
--env STRICT_HOST_KEY_CHECKING=true \
--env KNOWN_HOSTS_PATH=/path/to/known_hosts \
-- mcp-ssh-toolAfter adding the server, restart Codex or open a fresh session, then try a simple tool call such as listing active sessions or opening an SSH connection.
VS Code Copilot Integration
User-level Configuration (Recommended)
Open VS Code and press Ctrl+Shift+P, then run "MCP: Open User Configuration".
Add to your mcp.json:
{
"servers": {
"ssh-mcp": {
"type": "stdio",
"command": "mcp-ssh-tool",
"args": []
}
}
}Workspace-level Configuration
Create .vscode/mcp.json in your workspace:
{
"servers": {
"ssh-mcp": {
"type": "stdio",
"command": "mcp-ssh-tool",
"args": []
}
}
}Verification
Restart VS Code
Open Copilot Chat
The SSH MCP tools should appear in the available tools list
Test with: "Connect to 192.168.1.100 as admin and run 'uname -a'"
Claude Desktop, Antigravity, and Other MCP Clients
Any MCP-compatible client that can launch a stdio server can use mcp-ssh-tool.
The exact settings screen or config file varies by client, but the process is the same:
Install the package:
npm install -g mcp-ssh-toolRegister a stdio MCP server that launches:
{
"servers": {
"ssh-mcp": {
"type": "stdio",
"command": "mcp-ssh-tool",
"args": []
}
}
}If the client uses an
mcpServers-style schema instead ofservers, use the equivalent entry:
{
"mcpServers": {
"ssh-mcp-server": {
"command": "npx",
"args": ["-y", "mcp-ssh-tool"]
}
}
}For Claude Desktop, use the same stdio command pattern above in its MCP configuration. For Antigravity or other MCP clients, use the client's own MCP settings UI or config format, but point it at the same executable command.
Usage Examples
Basic Connection and Command Execution
"Connect to 10.11.12.13 as deployer with password 'mypass' and run 'df -h'"File Operations
"Connect to server.example.com as admin, read /etc/nginx/nginx.conf and show me the server blocks"System Administration
"Connect to 192.168.1.50 as root, install htop package, start nginx service, and list /var/www contents"Configuration Management
"Connect to web-server as admin, add these lines to /etc/hosts:
192.168.1.10 db-server
192.168.1.20 cache-server
Then restart networking service"Ready-to-use Prompt Ideas
"connect to my server and check disk usage""install nginx on my remote server""read the file /etc/nginx/nginx.conf""restart the nginx service""list files in /var/log"Pro Tips
Multiple sessions: Open one session per host or environment and keep them alive with
ssh_list_sessionsandssh_pingwhen you are switching between production, staging, and development machines.SFTP fallback for BusyBox/Dropbear: On embedded systems that do not expose an SFTP subsystem,
ssh_open_sessioncan still succeed withsftpAvailable: false, and the corefs_*tools automatically fall back to shell-based implementations.Host key verification: Set
STRICT_HOST_KEY_CHECKING=truein the MCP server environment and optionallyKNOWN_HOSTS_PATHfor stricter production-grade SSH verification.
API Reference
Architecture
src/
├── container.ts - Dependency injection wiring
├── config.ts - ConfigManager (env + programmatic overrides)
├── index.ts - CLI entry point & graceful shutdown
├── mcp.ts - MCP server (thin: delegates to ToolRegistry)
├── tools/
│ ├── registry.ts - ToolRegistry (routes CallTool requests)
│ ├── types.ts - ToolProvider interface
│ ├── session.provider.ts
│ ├── process.provider.ts
│ ├── fs.provider.ts
│ ├── ensure.provider.ts
│ ├── system.provider.ts
│ ├── transfer.provider.ts
│ └── tunnel.provider.ts
├── session.ts - SessionManager (LRU cache + TTL)
├── resources.ts - MCP resources for sessions, metrics, and SSH hosts
├── telemetry.ts - Optional OpenTelemetry tracing
├── rate-limiter.ts - Sliding window rate limiter
├── metrics.ts - Prometheus-compatible metrics
├── safety.ts - Command safety warnings (non-blocking)
└── ... - fs-tools, process, ensure, detect, ...Adding a new tool group
Create
src/tools/<your-namespace>.provider.tsimplementingToolProviderRegister it in
src/tools/index.tsAdd unit tests to
test/unit/tools/<your-namespace>.provider.test.ts
No changes to mcp.ts are needed.
Session tools
ssh_open_session
{
"host": "example.com",
"username": "admin",
"port": 22,
"auth": "auto",
"password": "optional",
"privateKey": "optional-inline-key",
"privateKeyPath": "optional-path",
"passphrase": "optional",
"useAgent": false,
"readyTimeoutMs": 20000,
"ttlMs": 900000
}Returns:
{
"sessionId": "ssh-1645123456789-1",
"host": "example.com",
"username": "admin",
"expiresInMs": 900000
}ssh_close_session
{
"sessionId": "ssh-1645123456789-1"
}ssh_list_sessions, ssh_ping, ssh_list_configured_hosts, ssh_resolve_host
ssh_list_sessionsreturns active sessions with remaining TTL.ssh_pingchecks liveness and latency for a session.ssh_list_configured_hostsreads~/.ssh/config.ssh_resolve_hostexpands an SSH host alias into connection parameters.
Command tools
proc_exec
{
"sessionId": "ssh-1645123456789-1",
"command": "ls -la /home",
"cwd": "/tmp",
"env": {
"DEBUG": "1"
},
"timeoutMs": 30000
}proc_sudo
{
"sessionId": "ssh-1645123456789-1",
"command": "systemctl restart nginx",
"password": "sudo-password",
"cwd": "/etc",
"timeoutMs": 30000
}Both return:
{
"code": 0,
"stdout": "command output",
"stderr": "",
"durationMs": 245
}File tools
fs_read
{
"sessionId": "ssh-1645123456789-1",
"path": "/etc/hosts",
"encoding": "utf8"
}fs_write
{
"sessionId": "ssh-1645123456789-1",
"path": "/tmp/config.txt",
"data": "server_name example.com;\nlisten 80;",
"mode": 420
}fs_statreturnssize,mtime,mode, andtype.fs_listreturns{ "entries": [...], "nextToken": "optional" }.fs_mkdirpcreates directories recursively.fs_rmrfremoves files or directories recursively.fs_renamerenames or moves a path.
Configuration and automation tools
ensure_package
{
"sessionId": "ssh-1645123456789-1",
"name": "nginx",
"state": "present",
"sudoPassword": "optional"
}state supports present and absent.
ensure_service
{
"sessionId": "ssh-1645123456789-1",
"name": "nginx",
"state": "restarted",
"sudoPassword": "optional"
}state supports started, stopped, restarted, enabled, and disabled.
ensure_lines_in_file
{
"sessionId": "ssh-1645123456789-1",
"path": "/etc/hosts",
"lines": [
"192.168.1.10 db-server",
"192.168.1.20 cache-server"
],
"state": "present",
"createIfMissing": true,
"sudoPassword": "optional"
}state supports present and absent.
patch_apply
{
"sessionId": "ssh-1645123456789-1",
"path": "/etc/hosts",
"diff": "@@ -1 +1 @@\n-old\n+new"
}os_detect
Returns remote platform, distro, version, package manager, init system, shell, and temp directory.
get_metrics
Returns server metrics. Default output is JSON; optional { "format": "prometheus" } emits Prometheus text format.
Authentication
The server supports multiple authentication methods with automatic fallback:
Authentication Strategy Priority
Password (if provided)
SSH Key (inline → path → auto-discovery)
SSH Agent (if available)
SSH Key Auto-Discovery
The server automatically searches for SSH keys in:
~/.ssh/id_ed25519~/.ssh/id_rsa~/.ssh/id_ecdsa
Note: DSA keys (
id_dsa) are no longer supported due to security concerns.
Custom key directory: Set SSH_DEFAULT_KEY_DIR environment variable.
Examples
Password Authentication:
{
"host": "server.com",
"username": "admin",
"auth": "password",
"password": "secret"
}SSH Key (inline):
{
"host": "server.com",
"username": "admin",
"auth": "key",
"privateKey": "-----BEGIN PRIVATE KEY-----\n...",
"passphrase": "optional"
}SSH Key (file path):
{
"host": "server.com",
"username": "admin",
"auth": "key",
"privateKeyPath": "/home/user/.ssh/id_rsa"
}SSH Agent:
{
"host": "server.com",
"username": "admin",
"auth": "agent"
}Configuration
Environment Variables
Variable | Description | Default |
| Logging level ( |
|
| Log output format ( |
|
| Enable strict SSH host key verification |
|
| Custom |
|
| SSH key search directory |
|
| Maximum concurrent sessions |
|
| Session TTL in milliseconds |
|
| Default command timeout in milliseconds |
|
| Enable debug logging |
|
| Enable rate limiting ( |
|
| Legacy alias for strict host key verification |
|
Default Settings
Connection timeout: 20 seconds
Session TTL: 15 minutes
Max concurrent sessions: 20
Host key checking: Relaxed (disabled by default)
Error Codes
The server returns structured error codes for machine-readable error handling:
EAUTH - Authentication failed
ECONN - Connection error
ETIMEOUT - Operation timeout
ENOSUDO - Sudo operation failed
EPMGR - Package manager not found
EFS - File system operation failed
EPATCH - Patch application failed
EBADREQ - Invalid request parameters
Each error includes:
name: Error class namecode: Machine-readable error codemessage: Human-readable error messagehint: Optional suggestion for resolution
Security Features
Data Redaction
Sensitive data is automatically redacted from logs:
Passwords
Private keys
Passphrases
Sudo passwords
SSH agent socket paths
Connection Security
Configurable host key verification
Support for known_hosts files
Connection timeout enforcement
Automatic session cleanup
Session Management
TTL-based session expiration
LRU cache eviction
Graceful connection cleanup
No persistent credential storage
Additional Documentation
docs/configuration.md - environment variables, runtime modes, and example
.envsettingsdocs/security-model.md - redaction, host key verification, rate limiting, and safety guardrails
docs/troubleshooting.md - common setup, connection, and runtime issues
CONTRIBUTING.md - development workflow, integration tests, and Changesets release flow
Development
Setup
git clone https://github.com/oaslananka/mcp-ssh-tool.git
cd mcp-ssh-tool
npm installScripts
npm run build # Compile TypeScript
npm run dev # Watch mode compilation
npm run test # Run unit tests
npm run test:integration # Run integration tests (requires RUN_SSH_INTEGRATION=1)
npm run test:e2e # Run E2E tests (requires RUN_SSH_E2E=1)
npm run lint # Type-check (no emit)
npm run format # Run Prettier
npm run test:coverage
npm run licenses:check
npm run pack:check
npm run changeset
npm run docsTesting
Unit Tests:
npm testE2E Tests (optional):
RUN_SSH_E2E=1 npm run test:e2eIntegration Tests (optional):
RUN_SSH_INTEGRATION=1 npm run test:integrationLicense
MIT License
Copyright (c) 2025 Osman Aslan (oaslananka)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
E2E tests require a local Docker container or SSH server for testing.
Contributing
Follow TypeScript and ESLint rules
Add tests for new features
Update documentation
Ensure all tests pass
Use conventional commit messages
License
MIT License - see LICENSE file for details.
References
VS Code MCP Guide - VS Code Copilot extensibility
GitHub Copilot - GitHub Copilot documentation
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/oaslananka/mcp-ssh-tool'
If you have feedback or need assistance with the MCP directory API, please join our Discord server