Content
# mcp-ssh-tool
[](https://www.npmjs.com/package/mcp-ssh-tool)
[](https://github.com/oaslananka-lab/mcp-ssh-tool/actions/workflows/ci.yml)
[](https://github.com/oaslananka-lab/mcp-ssh-tool/actions/workflows/security.yml)
[](https://registry.modelcontextprotocol.io/v0.1/servers/io.github.oaslananka%2Fmcp-ssh-tool/versions/latest)
[](https://opensource.org/licenses/MIT)
[](https://www.npmjs.com/package/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:
```bash
npx -y mcp-ssh-tool --version
```
Or install globally:
```bash
pnpm add --global mcp-ssh-tool
```
Add a stdio MCP server to your client:
```json
{
"servers": {
"ssh-mcp": {
"type": "stdio",
"command": "mcp-ssh-tool",
"args": []
}
}
}
```
Use it from your MCP client:
```text
Open a safe SSH session to prod-1 as deploy, inspect host capabilities, then show disk usage.
```
## Requirements
- Node.js `22.22.2+` or `24.14.1+` (LTS only)
- SSH access to target hosts
- A populated `known_hosts` file 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`:
```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_host`
- `proc_exec`, `proc_sudo`, `proc_exec_stream`
- `fs_read`, `fs_write`, `fs_list`, `fs_stat`, `fs_mkdirp`, `fs_rmrf`, `fs_rename`
- `file_upload`, `file_download`
- `ensure_package`, `ensure_service`, `ensure_lines_in_file`, `patch_apply`
- `os_detect`, `get_metrics`
- `tunnel_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/active`
- `mcp-ssh-tool://metrics/json`
- `mcp-ssh-tool://metrics/prometheus`
- `mcp-ssh-tool://ssh-config/hosts`
- `mcp-ssh-tool://policy/effective`
- `mcp-ssh-tool://audit/recent`
- `mcp-ssh-tool://capabilities/support-matrix`
Prompts:
- `safe-connect`
- `inspect-host-capabilities`
- `plan-mutation`
- `managed-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:
```json
{
"mcpServers": {
"ssh-mcp": {
"command": "npx",
"args": ["-y", "mcp-ssh-tool"]
}
}
}
```
VS Code or Cursor:
```json
{
"servers": {
"ssh-mcp": {
"type": "stdio",
"command": "mcp-ssh-tool"
}
}
}
```
MCP Inspector over HTTP:
```bash
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:
```bash
pnpm install --frozen-lockfile
pnpm run check
```
Live SSH suites are opt-in:
```bash
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 only
- `pre-push`: runs `pnpm run check:push`
- `task hooks`: runs tracked pnpm hooks plus `.pre-commit-config.yaml` hooks when `pre-commit` is installed
- manual/full parity: `task ci` or `pnpm 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](docs/ci-cd-topology.md) for mirror, release, dry-run, and manual fallback guidance.
## Documentation
- [ARCHITECTURE.md](ARCHITECTURE.md)
- [SECURITY_DECISIONS.md](SECURITY_DECISIONS.md)
- [MIGRATION.md](MIGRATION.md)
- [docs/ci-cd-topology.md](docs/ci-cd-topology.md)
- [docs/development.md](docs/development.md)
- [docs/release.md](docs/release.md)
- [docs/publishing.md](docs/publishing.md)
- [docs/npm-provenance.md](docs/npm-provenance.md)
- [docs/mcp-registry.md](docs/mcp-registry.md)
- [docs/chatgpt-app.md](docs/chatgpt-app.md)
- [docs/doppler.md](docs/doppler.md)
- [docs/operations.md](docs/operations.md)
- [docs/repository-operations.md](docs/repository-operations.md)
- [docs/docker.md](docs/docker.md)
- [docs/client-configs.md](docs/client-configs.md)
- [docs/security/release-integrity.md](docs/security/release-integrity.md)
- [docs/security/chatgpt-app-threat-model.md](docs/security/chatgpt-app-threat-model.md)
- [docs/security/ssh-threat-model.md](docs/security/ssh-threat-model.md)
- [docs/branch-protection.md](docs/branch-protection.md)
- [docs/maintenance-policy.md](docs/maintenance-policy.md)
- [docs/api-stability.md](docs/api-stability.md)
- [docs/threat-model.md](docs/threat-model.md)
- [docs/configuration.md](docs/configuration.md)
- [docs/security-model.md](docs/security-model.md)
- [docs/troubleshooting.md](docs/troubleshooting.md)
- [docs/enterprise-deployment.md](docs/enterprise-deployment.md)
## License
MIT License. See [LICENSE](LICENSE).
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
everything-claude-code
Complete Claude Code configuration collection - agents, skills, hooks,...
markitdown
MarkItDown-MCP is a lightweight server for converting URIs to Markdown.
cc-switch
All-in-One Assistant for Claude Code, Codex & Gemini CLI across platforms.
servers
Model Context Protocol Servers
servers
Model Context Protocol Servers
Time
A Model Context Protocol server for time and timezone conversions.