SSH MCP Server
SSH MCP Server lets you manage remote Linux servers through natural language in VS Code Copilot Chat. Instead of switching to a terminal and remembering SSH commands
README
<p align="center"> <img src="ssh-mcp-server-logo.png" alt="SSH MCP Server" width="200"> </p>
<p align="center"> <a href="https://www.python.org/downloads/"> <img src="https://img.shields.io/badge/python-3.11%2B-blue.svg" alt="Python 3.11+"> </a> <a href="https://opensource.org/licenses/MIT"> <img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"> </a> <a href="https://github.com/pycqa/pylint"> <img src="https://img.shields.io/badge/lint-pylint-green.svg" alt="Pylint"> </a> <a href="https://github.com/pyupio/safety"> <img src="https://img.shields.io/badge/security-safety-important.svg" alt="Safety Security Scan"> </a> <a href="https://github.com/pyupio/safety-action"> <img src="https://img.shields.io/badge/dependency%20security-passed-brightgreen.svg" alt="Dependency Security Check"> </a> </p>
<h1 align="center">SSH MCP Server</h1>
<p align="center"> <strong>Hardened SSH operations for VS Code Copilot Chat via the Model Context Protocol</strong> </p>
<p align="center"> <a href="#features">Features</a> • <a href="#quick-start">Quick Start</a> • <a href="#tools">Tools</a> • <a href="#configuration">Configuration</a> • <a href="#security">Security</a> • <a href="#testing">Testing</a> • <a href="#contributing">Contributing</a> </p>
What Is This?
SSH MCP Server lets you manage remote Linux servers through natural language in VS Code Copilot Chat. Instead of switching to a terminal and remembering SSH commands, you just ask:
"Check disk usage on production-web"
"Show me the last 200 lines of /var/log/nginx/error.log on staging"
"Download /var/log/syslog from web-server-01 for incident INC-2026-0309"
The server enforces strict security policies — no raw shell access, all commands go through pre-approved templates, parameters are regex-validated, secrets in output are auto-redacted, and privileged operations require an approval workflow.
Features
- 23 MCP tools — host discovery, session management, command execution (sync + background), file transfer, SFTP operations, SSH key management, certificate lifecycle, approval workflows
- Template-only execution — no raw shell; every command matches a registered template with regex-validated parameters
- 3-tier security model — read-only (Tier 0), controlled mutation with confirmation (Tier 1), privileged with approval workflow (Tier 2)
- Automatic secret redaction — AWS keys, bearer tokens, passwords, private keys are scrubbed from output
- Tamper-evident audit log — every operation is logged with hash-chain integrity verification
- Short-lived SSH certificates — issue and revoke certificates with TTL enforcement via a local CA
- Persistent SSH sessions — connection pooling with keepalive probes and configurable idle timeout
- Background command execution — run long-running template commands asynchronously with output polling
- Path traversal protection —
..sequences blocked in all path parameters and file transfers - Transfer policy — allowed paths, blocked extensions, size limits, mandatory justification for downloads
Quick Start
Prerequisites
- Python 3.11+
- VS Code with GitHub Copilot extension
- SSH access to at least one remote Linux host
Install
As vscode plugin
Follow instructions on link:
https://marketplace.visualstudio.com/items?itemName=bhayanak.ssh-mcp-server-secure
Python package: https://pypi.org/project/ssh-mcp-server-copilot/
Install from Source (for development / contributing)
git clone https://github.com/bhayanak/ssh-mcp-server.git
cd ssh-mcp-server
python -m venv .venv
source .venv/bin/activate # macOS/Linux
# .venv\Scripts\activate # Windows
pip install -e ".[dev]"
For local development, create .vscode/mcp.json pointing to the local source:
{
"servers": {
"ssh-mcp": {
"type": "stdio",
"command": "${workspaceFolder}/.venv/bin/python",
"args": ["-m", "ssh_mcp.server"],
"env": {
"SSH_MCP_CONFIG_DIR": "${workspaceFolder}/config",
"SSH_MCP_HOSTS_FILE": "${workspaceFolder}/config/hosts.json",
"SSH_MCP_TEMPLATES_FILE": "${workspaceFolder}/config/templates.json",
"SSH_MCP_AUDIT_LOG_DIR": "${workspaceFolder}/audit_logs",
"SSH_MCP_CERT_DATA_DIR": "${workspaceFolder}/cert_data",
"SSH_MCP_APPROVAL_DATA_DIR": "${workspaceFolder}/approval_data",
"SSH_MCP_SSH_KNOWN_HOSTS_FILE": "~/.ssh/known_hosts"
}
}
}
}
Configure Your Hosts
Edit the hosts file with your actual servers. If you used ssh-mcp-server-copilot init, edit ~/.ssh-mcp/hosts.json. If developing from source, edit config/hosts.json.
[
{
"host_id": "my-server",
"hostname": "192.168.1.10",
"port": 22,
"ssh_user": "deploy",
"labels": {"env": "production", "role": "web"},
"description": "Production web server",
"allowed_roles": ["operator", "admin"]
}
]
| Field | Required | Description |
|---|---|---|
host_id |
Yes | Unique identifier (alphanumeric, dots, dashes) |
hostname |
Yes | IP address or FQDN |
port |
No | SSH port (default: 22) |
ssh_user |
Yes* | Remote SSH username. If empty, uses your OS username |
labels |
No | Key-value tags for organization |
description |
No | Human-readable description |
allowed_roles |
No | Which roles can access this host (default: operator, admin) |
Set Up SSH Access
Your SSH key must be authorized on each host:
# Generate a key if you don't have one
ssh-keygen -t ed25519 -C "your-email@example.com"
# Copy to each host
ssh-copy-id -i ~/.ssh/id_ed25519.pub deploy@192.168.1.10
# Load into ssh-agent (required — the MCP server uses the agent)
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
# Verify access
ssh deploy@192.168.1.10 "echo OK"
Add host keys to known_hosts:
ssh-keyscan -H 192.168.1.10 >> ~/.ssh/known_hosts
Start Using
- Open the workspace in VS Code
- The MCP server auto-starts from
.vscode/mcp.json - Open Copilot Chat (Cmd+Shift+I / Ctrl+Shift+I)
- Switch to "Agent" mode (critical — only Agent mode can invoke MCP tools)
- Verify tools are loaded — click the tools icon in the chat input bar, you should see 23 tools from
ssh-mcp
Now just ask in natural language:
> List all my SSH hosts
> Check disk usage on my-server
> Show me the last 100 lines of /var/log/syslog on my-server
> What's the status of nginx on my-server?
Tools (23)
Tier 0 — Read-Only (No Confirmation)
| Tool | Description |
|---|---|
list_hosts |
List all configured SSH hosts with labels and metadata |
get_host_facts |
Get OS, uptime, kernel info from a host |
get_audit_logs |
View the tamper-evident audit trail |
list_templates |
List available command templates |
list_pending_approvals |
View pending approval requests |
Session Management
| Tool | Description |
|---|---|
ssh_connect |
Open a persistent SSH session (returns session_id for reuse) |
ssh_disconnect |
Close a persistent session |
ssh_list_sessions |
List active sessions and remaining connection slots |
ssh_session_ping |
Health-check a session (liveness, idle time, uptime) |
Tier 1 — Controlled Mutation (Confirmation Required)
| Tool | Description |
|---|---|
run_ssh_command |
Execute a template command on a host (supports session_id for persistent connections) |
transfer_file |
Download/upload files via SFTP with path and extension policies (supports session_id) |
Background Command Execution
| Tool | Description |
|---|---|
run_ssh_command_background |
Start a template command in the background (returns job_id) |
poll_background_job |
Read accumulated stdout/stderr of a background job (redacted) |
list_background_jobs |
List all background jobs (running + completed) |
cancel_background_job |
Cancel a running background job |
Enhanced SFTP
| Tool | Description |
|---|---|
sftp_list_directory |
List files in a remote directory (within allowed paths) |
sftp_delete |
Delete a remote file (within allowed paths, requires justification) |
Tier 2 — Privileged (Approval Required)
| Tool | Description |
|---|---|
add_ssh_key |
Register a public SSH key with TTL enforcement |
remove_ssh_key |
Revoke a registered SSH key |
issue_cert |
Issue a short-lived SSH certificate via the local CA |
revoke_cert |
Revoke a certificate and delete its PEM |
request_approval / approve_request |
Approval workflow for privileged ops |
Configuration
Command Templates
Templates define which commands can be executed. Edit config/templates.json:
[
{
"template_id": "disk_usage",
"description": "Show disk usage summary",
"command": "df -h",
"allowed_params": {},
"allowed_roles": ["developer", "operator", "admin"],
"timeout_seconds": 10,
"risk_level": "low"
},
{
"template_id": "tail_log",
"description": "Tail the last N lines of a log file",
"command": "tail -n {lines} {log_path}",
"allowed_params": {
"lines": "^[0-9]{1,5}$",
"log_path": "^/var/log/[a-zA-Z0-9_./-]+$"
},
"allowed_roles": ["operator", "admin"],
"timeout_seconds": 15,
"risk_level": "low"
}
]
Each parameter is validated against a regex pattern before substitution. Path traversal (..) is blocked automatically.
Environment Variables
All configuration is via environment variables with the SSH_MCP_ prefix:
| Variable | Default | Description |
|---|---|---|
SSH_MCP_CONFIG_DIR |
~/.ssh-mcp |
Base config directory (all other paths derive from this) |
SSH_MCP_HOSTS_FILE |
{config_dir}/hosts.json |
Path to hosts configuration |
SSH_MCP_TEMPLATES_FILE |
{config_dir}/templates.json |
Path to command templates |
SSH_MCP_AUDIT_LOG_DIR |
{config_dir}/audit_logs |
Audit log directory |
SSH_MCP_CERT_DATA_DIR |
{config_dir}/cert_data |
Certificate storage directory |
SSH_MCP_APPROVAL_DATA_DIR |
{config_dir}/approval_data |
Approval data directory |
SSH_MCP_MAX_SESSIONS |
10 |
Max simultaneous SSH sessions |
SSH_MCP_SESSION_IDLE_TIMEOUT |
300 |
Idle session timeout (seconds) |
SSH_MCP_KEEPALIVE_INTERVAL |
15 |
SSH keepalive interval (seconds) |
SSH_MCP_KEEPALIVE_COUNT_MAX |
3 |
Max failed keepalive probes before disconnect |
SSH_MCP_MAX_BACKGROUND_JOBS |
10 |
Max concurrent background jobs |
SSH_MCP_JOB_OUTPUT_MAX_BYTES |
1048576 |
Max output buffer per background job (1 MB) |
SSH_MCP_JOB_TTL_SECONDS |
3600 |
Background job auto-expiry (1 hour) |
SSH_MCP_SSH_KNOWN_HOSTS_FILE |
(none) | Path to SSH known_hosts file |
SSH_MCP_REQUIRE_TWO_PARTY_APPROVAL |
true |
Require different user as approver |
SSH_MCP_AUTH_TOKEN |
(none) | Bearer token (empty = dev mode) |
SSH_MCP_SSH_TIMEOUT_SECONDS |
30 |
SSH connection timeout |
Transfer Policy (Defaults)
| Setting | Default |
|---|---|
| Allowed paths | /tmp/*, /var/log/* |
| Blocked extensions | .exe, .sh, .bat, .ps1, .dll, .so |
| Max file size | 50 MB |
| Require justification for downloads | Yes |
Roles
| Role | Access |
|---|---|
developer |
Read-only tools, low-risk commands |
operator |
All Tier 0 + Tier 1 tools |
admin |
All tools including Tier 2 (key/cert management) |
auditor |
Audit log access |
Security
Design Principles
- No raw shell — all commands go through registered templates
- Parameter validation — every parameter is regex-validated before substitution
- Path traversal blocking —
..sequences rejected in all parameters and file paths - Secret redaction — AWS keys, bearer tokens, passwords, private keys automatically scrubbed from output
- Approval workflow — privileged operations (key/cert management) require explicit approval with HMAC-verified tokens
- Tamper-evident audit — hash-chained audit log for forensic analysis
- Strict host validation — paramiko
RejectPolicyby default (no auto-accepting unknown hosts) - TTL enforcement — SSH certificates and keys have configurable maximum lifetimes
Approval Workflow
Tier 2 operations follow a 3-step flow:
1. request_approval → returns request_id + one-time approval_token
2. approve_request → verifies HMAC token, marks approved
3. call the tool → pass approval_request_id, consumed after use
With REQUIRE_TWO_PARTY_APPROVAL=true (production), a different user must approve.
Audit Log Verification
python -c "
from ssh_mcp.audit import AuditLogger
from pathlib import Path
logger = AuditLogger(Path('audit_logs'))
ok, msg = logger.verify_chain()
print(f'Chain integrity: {ok} — {msg}')
"
Testing
Unit Tests
# Run all tests
pytest tests/ -v
# With coverage
pytest tests/ -v --cov=ssh_mcp
Runtime Directories (git-ignored, auto-created)
| Directory | Purpose |
|---|---|
audit_logs/ |
Tamper-evident audit log (audit.jsonl) |
cert_data/ |
CA keys, issued certificates, revocation list |
approval_data/ |
Pending and consumed approval requests |
CLI Reference
ssh-mcp-server-copilot --version # Print version
ssh-mcp-server-copilot init # Create ~/.ssh-mcp with default configs
ssh-mcp-server-copilot # Start MCP server (stdio transport)
ssh-mcp-server-copilot --config-dir PATH # Use custom config directory
ssh-mcp-server-copilot --config-dir PATH init # Init a custom config directory
Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Make your changes
- Run tests:
pytest tests/ -v - Lint:
ruff check src/ tests/ - Submit a pull request
License
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。