ssh-tool
Model Context Protocol (MCP) SSH client server for remote automation
Installation
npx mcp-ssh-toolAsk AI about ssh-tool
Powered by Claude · Grounded in docs
I know everything about ssh-tool. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
mcp-ssh-tool
Production-grade MCP SSH automation for operators, developers, and AI clients. mcp-ssh-tool opens persistent SSH sessions and exposes safe, structured tools for command execution, file operations, transfers, tunnels, package/service management, metrics, resources, and guided prompts.
v2 is secure by default: strict host-key verification is on, root login is off, raw sudo is policy-gated, destructive commands and filesystem mutations are denied unless policy allows them, and remote HTTP starts on loopback only unless bearer auth and allowed origins are configured.
Why This Server
- Trust: central policy engine, structured audit events, redacted logs, strict host keys, and machine-readable errors.
- MCP quality: stdio for local clients, Streamable HTTP for remote clients, legacy SSE only behind an explicit compatibility flag.
- AI-friendly tools: stable output schemas,
structuredContent, annotations for read-only/destructive/idempotent behavior, resources, and curated prompts. - Operations: session TTL/eviction, command timeouts, transfer checksum verification, real SSH forwarding, Prometheus metrics, and OpenTelemetry hooks.
- Portability: SFTP first, POSIX/BusyBox-aware shell fallbacks for basic file operations, and explicit support boundaries.
Quick Start
Run without installing:
npx -y mcp-ssh-tool --version
Or install globally:
pnpm add --global mcp-ssh-tool
Add a stdio MCP server to your client:
{
"servers": {
"ssh-mcp": {
"type": "stdio",
"command": "mcp-ssh-tool",
"args": []
}
}
}
Use it from your MCP client:
Open a safe SSH session to prod-1 as deploy, inspect host capabilities, then show disk usage.
Requirements
- Node.js
22.22.2+or24.14.1+(LTS only) - SSH access to target hosts
- A populated
known_hostsfile for strict host verification, or an explicit per-session host-key policy
Transports
| Mode | Command | Use When |
|---|---|---|
| stdio | mcp-ssh-tool | Local desktop clients such as ChatGPT, Claude Desktop, VS Code, Cursor, or Codex. |
| Streamable HTTP | mcp-ssh-tool --transport=http --host 127.0.0.1 --port 3000 | Remote MCP clients, reverse proxies, or Inspector sessions. |
| legacy SSE | mcp-ssh-tool --transport=http --enable-legacy-sse | Temporary v1 compatibility only. Prefer Streamable HTTP. |
Non-loopback HTTP startup is refused unless both --bearer-token-file and allowed origins are configured.
Secure Defaults
| Area | v2 Default |
|---|---|
| Host keys | hostKeyPolicy=strict, knownHostsPath=~/.ssh/known_hosts |
| Root SSH login | denied |
Raw proc_sudo | denied unless allowRawSudo=true |
| Destructive commands | denied unless allowDestructiveCommands=true |
| Destructive fs operations | allowed only under policy prefixes, denied elsewhere |
| Local transfer paths | file_upload and file_download limited to OS temp unless policy allows more |
| HTTP bind | 127.0.0.1 |
| Legacy SSE | disabled |
| File reads | size-limited by SSH_MCP_MAX_FILE_SIZE |
Per-session policyMode: "explain" returns a plan/verdict without executing. Use it before mutations when an AI client needs to summarize risk.
Policy Example
Set SSH_MCP_POLICY_FILE=/etc/mcp-ssh-tool/policy.json:
{
"mode": "enforce",
"allowRootLogin": false,
"allowRawSudo": false,
"allowDestructiveCommands": false,
"allowDestructiveFs": false,
"allowedHosts": ["^prod-[0-9]+\\.example\\.com$"],
"commandAllow": ["^(uname|df|uptime|systemctl status)\\b"],
"commandDeny": ["rm\\s+-rf\\s+/", "shutdown", "reboot"],
"pathAllowPrefixes": ["/tmp", "/var/tmp", "/home/deploy"],
"pathDenyPrefixes": ["/etc/shadow", "/etc/sudoers", "/boot", "/dev", "/proc"],
"localPathAllowPrefixes": ["/var/tmp/mcp-ssh-tool"],
"localPathDenyPrefixes": []
}
Simple deploys can use environment overrides such as SSH_MCP_ALLOW_RAW_SUDO=true, SSH_MCP_ALLOWED_HOSTS=prod-1.example.com, SSH_MCP_PATH_ALLOW_PREFIXES=/tmp,/home/deploy, or SSH_MCP_LOCAL_PATH_ALLOW_PREFIXES=/var/tmp/mcp-ssh-tool.
Core Tools
ssh_open_session,ssh_close_session,ssh_list_sessions,ssh_ping,ssh_list_configured_hosts,ssh_resolve_hostproc_exec,proc_sudo,proc_exec_streamfs_read,fs_write,fs_list,fs_stat,fs_mkdirp,fs_rmrf,fs_renamefile_upload,file_downloadensure_package,ensure_service,ensure_lines_in_file,patch_applyos_detect,get_metricstunnel_local_forward,tunnel_remote_forward,tunnel_list,tunnel_close
All tools return text plus stable structuredContent. Tool metadata includes titles, output schemas, and annotations that disclose read-only, destructive, idempotent, and external side-effect behavior.
Resources And Prompts
Resources:
mcp-ssh-tool://sessions/activemcp-ssh-tool://metrics/jsonmcp-ssh-tool://metrics/prometheusmcp-ssh-tool://ssh-config/hostsmcp-ssh-tool://policy/effectivemcp-ssh-tool://audit/recentmcp-ssh-tool://capabilities/support-matrix
Prompts:
safe-connectinspect-host-capabilitiesplan-mutationmanaged-config-change
Support Matrix
| Target | Status |
|---|---|
| Linux | Full support. |
| macOS/BSD | Session, process, fs, and transfer supported; package/service helpers only where tested. |
| BusyBox/dropbear | Experimental for session, process, and basic fs fallbacks. |
| Windows SSH targets | Experimental for session, process, fs, and transfer; no proc_sudo or ensure_*. |
Client Examples
ChatGPT or Claude Desktop:
{
"mcpServers": {
"ssh-mcp": {
"command": "npx",
"args": ["-y", "mcp-ssh-tool"]
}
}
}
VS Code or Cursor:
{
"servers": {
"ssh-mcp": {
"type": "stdio",
"command": "mcp-ssh-tool"
}
}
}
MCP Inspector over HTTP:
printf '%s' 'super-secret-token' > .mcp-token
mcp-ssh-tool --transport=http --host 127.0.0.1 --port 3000 --bearer-token-file .mcp-token
Configuration
High-value environment variables:
| Variable | Default | Purpose |
|---|---|---|
SSH_MCP_POLICY_FILE | unset | Canonical JSON policy source. |
SSH_MCP_HOST_KEY_POLICY | strict | strict, accept-new, or insecure. |
SSH_MCP_KNOWN_HOSTS_PATH | ~/.ssh/known_hosts | Known-hosts file for strict verification. |
SSH_MCP_MAX_FILE_SIZE | 10485760 | Max bytes for fs_read. |
SSH_MCP_COMMAND_TIMEOUT | 30000 | Default command timeout. |
SSH_MCP_HTTP_HOST | 127.0.0.1 | Streamable HTTP bind host. |
SSH_MCP_HTTP_PORT / PORT | 3000 | Streamable HTTP port. |
SSH_MCP_HTTP_MAX_REQUEST_BODY_BYTES | 1048576 | Max JSON request bytes accepted by Streamable HTTP. |
SSH_MCP_LOCAL_PATH_ALLOW_PREFIXES | OS temp directory | Local transfer allow-list for file_upload and file_download. |
SSH_MCP_HTTP_BEARER_TOKEN_FILE | unset | Required for non-loopback HTTP. |
SSH_MCP_HTTP_ALLOWED_ORIGINS | loopback origins | Comma-separated allowed origins. |
Deprecated aliases STRICT_HOST_KEY_CHECKING and SSH_MCP_STRICT_HOST_KEY are still accepted for one v2 compatibility cycle. Prefer SSH_MCP_HOST_KEY_POLICY.
Development
Use the exact local runtime from .nvmrc / .node-version, then run:
pnpm install --frozen-lockfile
pnpm run check
Live SSH suites are opt-in:
RUN_SSH_INTEGRATION=1 pnpm run test:integration
RUN_SSH_E2E=1 pnpm run test:e2e
Local quality gates are layered:
pre-commit: formats staged files and lints staged TypeScript onlypre-push: runspnpm run check:pushtask hooks: runs tracked pnpm hooks plus.pre-commit-config.yamlhooks whenpre-commitis installed- manual/full parity:
task ciorpnpm run check
CI/CD Ownership
The organization repository https://github.com/oaslananka-lab/mcp-ssh-tool is the canonical source-of-truth. Automatic CI/CD, supply-chain security checks, trusted npm publishing, MCP Registry publishing, GitHub Releases, Docker image validation, SBOMs, attestations, and release decisions run only from the org repository.
The personal repository https://github.com/oaslananka/mcp-ssh-tool is a showcase mirror only. It must not contain publish workflows or require GitHub Actions for package or registry release authority. If the two repositories ever conflict, the org repository wins.
The npm package repository.url intentionally points at the org repository so npm provenance can verify that the published artifact came from the same GitHub Actions repository that built it.
The MCP Registry server name remains io.github.oaslananka/mcp-ssh-tool because it is already published and changing it would break existing users. Registry metadata points its repository/source at the org repository where the current official schema permits it.
See docs/ci-cd-topology.md for mirror, release, dry-run, and manual fallback guidance.
Documentation
- ARCHITECTURE.md
- SECURITY_DECISIONS.md
- MIGRATION.md
- docs/ci-cd-topology.md
- docs/development.md
- docs/release.md
- docs/publishing.md
- docs/npm-provenance.md
- docs/mcp-registry.md
- docs/chatgpt-app.md
- docs/doppler.md
- docs/operations.md
- docs/repository-operations.md
- docs/docker.md
- docs/client-configs.md
- docs/security/release-integrity.md
- docs/security/chatgpt-app-threat-model.md
- docs/security/ssh-threat-model.md
- docs/branch-protection.md
- docs/maintenance-policy.md
- docs/api-stability.md
- docs/threat-model.md
- docs/configuration.md
- docs/security-model.md
- docs/troubleshooting.md
- docs/enterprise-deployment.md
License
MIT License. See LICENSE.
