11# SSH MCP Server
22
3- A ** Model Context Protocol (MCP)** server that provides SSH remote command execution capabilities. It enables AI agents to discover, connect to, and execute commands on remote SSH hosts through a standardized MCP interface.
3+ [ ![ GitHub stars] ( https://img.shields.io/github/stars/B143KC47/ssh_mcp?style=flat-square )] ( https://github.com/B143KC47/ssh_mcp/stargazers )
4+ [ ![ License: MIT] ( https://img.shields.io/badge/license-MIT-green?style=flat-square )] ( LICENSE )
5+ [ ![ TypeScript] ( https://img.shields.io/badge/TypeScript-5.x-3178c6?style=flat-square&logo=typescript&logoColor=white )] ( https://www.typescriptlang.org/ )
6+ [ ![ MCP] ( https://img.shields.io/badge/MCP-compatible-6e56cf?style=flat-square )] ( https://modelcontextprotocol.io/ )
7+ [ ![ SSH] ( https://img.shields.io/badge/SSH-security--first-0f766e?style=flat-square )] ( https://www.openssh.com/ )
48
5- ## Features
9+ ** English ** | [ 中文 ] ( README.zh-CN.md )
610
7- - ** Dual-scope configuration** : Project-level (` ssh.config ` ) and user-level (` ~/.config/mcp-ssh/config ` ) SSH configs with automatic merging
8- - ** Connection pooling** : Reuse SSH connections across multiple commands with automatic idle cleanup
9- - ** Command security** : Built-in dangerous command blacklist + configurable per-host allow/deny lists
10- - ** Output management** : Automatic output truncation to prevent LLM context overflow
11- - ** Sensitive data protection** : Private keys never exposed in tool outputs; passwords via env vars only
12- - ** Standard SSH config syntax** : Uses OpenSSH config format — ` Host ` , ` HostName ` , ` User ` , ` Port ` , ` IdentityFile ` , etc.
11+ Secure SSH access for MCP clients. ` ssh_mcp ` lets Claude Desktop, VS Code Copilot, Augment, and other MCP-compatible agents run remote commands through a safety-first SSH proxy with OpenSSH config compatibility, connection pooling, and output guardrails.
1312
14- ## Quick Start
13+ ## Why developers pick this project
1514
16- ### 1. Install
15+ - ** Use the SSH config you already know** : standard OpenSSH fields like ` Host ` , ` HostName ` , ` User ` , ` Port ` , ` IdentityFile ` , and ` ProxyJump `
16+ - ** Safer than a raw shell bridge** : built-in dangerous command blocking, per-host allowlists/denylists, output caps, and secret redaction
17+ - ** Fast for multi-step agent sessions** : pooled SSH connections reduce reconnect overhead
18+ - ** Works with real MCP workflows** : designed for Claude Desktop, VS Code Copilot, Augment, and any MCP-compatible client
19+ - ** Flexible for teams** : merge project-level and user-level configs so shared hosts stay global while project overrides stay local
1720
18- ``` bash
19- npm install
20- npm run build
21- ```
21+ ## Great fit for
2222
23- ### 2. Configure SSH hosts
23+ - AI-assisted production troubleshooting
24+ - Safe observability and read-only operations on remote servers
25+ - DevOps and platform engineering copilots
26+ - Internal tooling that needs SSH access without handing an agent unlimited shell freedom
2427
25- Create a project-level config ( ` ssh.config ` in your project root):
28+ ## Quick start
2629
27- ``` sshconfig
28- Host my-server
29- HostName 192.168.1.100
30- User ubuntu
31- Port 22
32- IdentityFile ~/.ssh/id_rsa
33- # mcp-ssh:denylist = rm -rf,mkfs,dd,shutdown,reboot
34- ```
35-
36- Or initialize via the MCP tool:
30+ ### 1. Install and build
3731
32+ ``` bash
33+ npm install
34+ npm run build
3835```
39- Use tool: ssh_init_config with scope="project"
40- ```
4136
42- ### 3. Add to MCP client
37+ ### 2. Add the server to your MCP client
38+
39+ See the ready-to-copy examples in:
4340
44- #### Claude Desktop / Augment
41+ - ` examples/mcp-config.claude.example.json `
42+ - ` examples/mcp-config.vscode.example.json `
4543
46- Add to your MCP settings ( ` claude_desktop_config.json ` or equivalent) :
44+ Minimal Claude Desktop / Augment example :
4745
4846``` json
4947{
5048 "mcpServers" : {
5149 "ssh" : {
5250 "command" : " node" ,
53- "args" : [" path/to/ssh-mcp-server/dist/index.js" , " --project-root" , " /path/to/your/project" ],
51+ "args" : [
52+ " /absolute/path/to/ssh-mcp-server/dist/index.js" ,
53+ " --project-root" ,
54+ " /path/to/your/project"
55+ ],
5456 "env" : {}
5557 }
5658 }
5759}
5860```
5961
60- #### Using npx (development)
62+ Minimal VS Code MCP example:
6163
6264``` json
6365{
64- "mcpServers " : {
66+ "servers " : {
6567 "ssh" : {
66- "command" : " npx" ,
67- "args" : [" tsx" , " path/to/ssh-mcp-server/src/index.ts" , " --project-root" , " ." ]
68+ "command" : " node" ,
69+ "args" : [
70+ " /absolute/path/to/ssh-mcp-server/dist/index.js" ,
71+ " --project-root" ,
72+ " ${workspaceFolder}"
73+ ]
6874 }
6975 }
7076}
7177```
7278
73- ## Configuration
79+ ### 3. Configure SSH hosts
7480
75- ### Config file locations
81+ Copy ` examples/ssh.config.example ` to ` ssh.config ` in your project root, or initialize one through the MCP tool:
7682
77- | Scope | Path | Purpose |
78- | -------| ------| ---------|
79- | Project | ` <project-root>/ssh.config ` | Hosts specific to this project |
80- | User | ` ~/.config/mcp-ssh/config ` | Shared hosts across all projects |
81-
82- ** Merge rule** : Project-level settings override user-level settings for hosts with the same name.
83-
84- ### SSH config syntax
83+ ``` text
84+ Use tool: ssh_init_config with scope="project"
85+ ```
8586
86- Standard OpenSSH config syntax is supported :
87+ Minimal example :
8788
8889``` sshconfig
89- # Project-level ssh.config
90- Host prod-db
91- HostName db.prod.example.com
92- User deploy
90+ Host my-server
91+ HostName 192.168.1.100
92+ User ubuntu
9393 Port 22
94- IdentityFile ~/.ssh/deploy_key
95- ConnectTimeout 10
96- ServerAliveInterval 60
97- # mcp-ssh:denylist = DROP TABLE,rm -rf /,mkfs
98-
99- Host staging
100- HostName staging.example.com
101- User developer
102- IdentityFile ~/.ssh/id_ed25519
103- # mcp-ssh:allowlist = ls,cat,grep,find,ps,top,df,du,free,uptime
94+ IdentityFile ~/.ssh/id_rsa
95+ # mcp-ssh:denylist = rm -rf,mkfs,dd,shutdown,reboot
10496```
10597
98+ ### 4. Try a few prompts in your MCP client
99+
100+ - "List all configured SSH hosts."
101+ - "Test the SSH connection to ` my-server ` ."
102+ - "Run ` uptime && df -h ` on ` my-server ` ."
103+ - "Show me the merged SSH config for ` my-server ` ."
104+
105+ ## Core features
106+
107+ - ** Dual-scope configuration** : project-level (` ssh.config ` ) + user-level (` ~/.config/mcp-ssh/config ` ) with automatic merging
108+ - ** Connection pooling** : reuse SSH connections across commands with idle cleanup
109+ - ** Per-host security policy** : allowlists, denylists, max timeout, and max output size
110+ - ** Output management** : automatic truncation to protect LLM context windows
111+ - ** Sensitive data protection** : private keys and sensitive environment values are sanitized in output
112+ - ** OpenSSH compatibility** : keep using your normal host aliases and SSH habits
113+
114+ ## Configuration
115+
116+ ### Config file locations
117+
118+ | Scope | Path | Purpose |
119+ | -------| ------| ---------|
120+ | Project | ` <project-root>/ssh.config ` | Hosts specific to the current project |
121+ | User | ` ~/.config/mcp-ssh/config ` | Shared hosts across projects |
122+
123+ ** Merge rule** : project-level settings override user-level settings for hosts with the same name.
124+
106125### Security annotations
107126
108- Add security policies as comments within Host blocks :
127+ Add policies as comments inside a ` Host ` block :
109128
110129``` sshconfig
111130# mcp-ssh:denylist = cmd1,cmd2 # Block these command patterns
112- # mcp-ssh:allowlist = cmd1,cmd2 # Only allow these patterns (overrides denylist)
131+ # mcp-ssh:allowlist = cmd1,cmd2 # Only allow these command patterns
113132# mcp-ssh:maxTimeoutMs = 30000 # Max execution timeout for this host
114133# mcp-ssh:maxOutputChars = 5000 # Max output characters for this host
115134```
116135
117- ### Authentication
136+ ### Authentication order
118137
119- The server tries authentication methods in this order:
138+ 1 . ** Private key** from ` IdentityFile `
139+ 2 . ** SSH agent** via ` SSH_AUTH_SOCK ` (Unix) or Pageant (Windows)
140+ 3 . ** Password** via environment variable ` SSH_PASSWORD_<HOST> `
120141
121- 1 . ** Private key** — from ` IdentityFile ` in SSH config
122- 2 . ** SSH Agent** — ` SSH_AUTH_SOCK ` (Unix) or Pageant (Windows)
123- 3 . ** Password** — from environment variable ` SSH_PASSWORD_<HOST> ` (uppercase, special chars → ` _ ` )
142+ Example: for host ` my-server ` , set ` SSH_PASSWORD_MY_SERVER=secret ` .
124143
125- Example: For host ` my-server ` , set ` SSH_PASSWORD_MY_SERVER=secret ` .
144+ ## Why this is better than a plain SSH wrapper
126145
127- ## CLI Options
128-
129- ```
130- ssh-mcp-server [options]
131-
132- --project-root <path> Project root directory (for project-level ssh.config)
133- --user-config <path> Custom user config path (default: ~/.config/mcp-ssh/config)
134- --strict-host-key Enable strict host key checking
135- --no-strict-host-key Disable strict host key checking (default)
136- --timeout <ms> Default command timeout in ms (default: 60000)
137- --max-output <chars> Maximum output characters per stream (default: 10000)
138- --max-connections <n> Maximum concurrent SSH connections (default: 5)
139- --idle-timeout <ms> Connection idle timeout in ms (default: 600000)
140- ```
146+ | Plain remote exec bridge | SSH MCP Server |
147+ | ---| ---|
148+ | Often exposes a full shell with little policy control | Supports per-host allowlists / denylists |
149+ | Reconnects for every agent step | Reuses pooled connections |
150+ | Easy to overflow model context with huge outputs | Truncates output automatically |
151+ | Custom host definitions | Works with familiar OpenSSH config syntax |
152+ | Secrets may leak into logs | Sanitizes output and hides sensitive values |
141153
142- ## MCP Tools
154+ ## MCP tools
143155
144156| Tool | Description | Parameters |
145157| ------| -------------| ------------|
146158| ` ssh_list_hosts ` | List all available SSH hosts | — |
147159| ` ssh_exec ` | Execute a command on a remote host | ` host ` , ` command ` , ` timeout_ms? ` |
148- | ` ssh_init_config ` | Initialize SSH config file | ` scope ` (project/user) , ` project_root? ` , ` hosts? ` |
160+ | ` ssh_init_config ` | Initialize SSH config file | ` scope ` , ` project_root? ` , ` hosts? ` |
149161| ` ssh_get_config ` | Get config for a specific host | ` host ` |
150162| ` ssh_test_connection ` | Test connectivity to a host | ` host ` |
151- | ` ssh_disconnect ` | Disconnect session(s) | ` host? ` |
163+ | ` ssh_disconnect ` | Disconnect one host or all active sessions | ` host? ` |
152164
153- ## MCP Resources
165+ ## MCP resources
154166
155167| URI | Description |
156168| -----| -------------|
157169| ` ssh://hosts ` | JSON list of all configured SSH hosts |
158170
159- ## Security
160-
161- ### Built-in protections
171+ ## Security-first defaults
162172
163- - ** Command blacklist** : Dangerous commands blocked by default (` rm -rf / ` , ` mkfs ` , ` dd if= ` , ` shutdown ` , ` reboot ` , fork bombs, firewall flush, credential file reads)
164- - ** Output sanitization** : Private keys and sensitive env vars redacted from output
165- - ** No credential exposure** : Private key paths shown truncated; passwords never in tool results
166- - ** Connection limits** : Max concurrent connections (default: 5) with idle timeout
167- - ** Input sanitization** : Null bytes stripped from commands
173+ - Dangerous commands such as ` rm -rf / ` , ` mkfs ` , ` dd if= ` , ` shutdown ` , and ` reboot ` are blocked by default
174+ - Private key material and sensitive env values are redacted from outputs
175+ - Commands are sanitized before execution
176+ - Concurrent connection count and idle lifetime are limited
168177
169- ### Recommendations
178+ Recommended for production:
170179
171- 1 . Always use ` IdentityFile ` (key-based auth) over passwords
172- 2 . Use per-host ` # mcp-ssh:allowlist ` for production servers
180+ 1 . Prefer ` IdentityFile ` over password auth
181+ 2 . Use ` # mcp-ssh:allowlist ` for production hosts
1731823 . Add ` ssh.config ` to ` .gitignore ` if it contains sensitive hostnames
174- 4 . Enable ` --strict-host-key ` in production environments
175- 5 . Use SSH certificates or ` known_hosts ` pinning for host verification
183+ 4 . Enable ` --strict-host-key ` in production
184+ 5 . Use SSH certificates or pinned ` known_hosts ` entries when possible
176185
177- ## Architecture
186+ ## CLI options
178187
179- ```
180- ┌─────────────────────────────────────────────┐
181- │ MCP Client (Claude/Augment/IDE) │
182- │ ↕ JSON-RPC 2.0 over stdio │
183- ├─────────────────────────────────────────────┤
184- │ MCP Server Layer │
185- │ ├─ Tool handlers (ssh_exec, etc.) │
186- │ ├─ Resource handlers (ssh://hosts) │
187- │ └─ Logging notifications │
188- ├─────────────────────────────────────────────┤
189- │ Config Layer │
190- │ ├─ Parser (ssh-config lib) │
191- │ ├─ Merger (project + user, project wins) │
192- │ └─ Security policies (allowlist/denylist) │
193- ├─────────────────────────────────────────────┤
194- │ SSH Layer │
195- │ ├─ Connection Pool (ssh2 Client) │
196- │ ├─ Command Executor (exec channels) │
197- │ └─ Output truncation & sanitization │
198- └─────────────────────────────────────────────┘
188+ ``` text
189+ ssh-mcp-server [options]
190+
191+ --project-root <path> Project root directory (for project-level ssh.config)
192+ --user-config <path> Custom user config path (default: ~/.config/mcp-ssh/config)
193+ --strict-host-key Enable strict host key checking
194+ --no-strict-host-key Disable strict host key checking (default)
195+ --timeout <ms> Default command timeout in ms (default: 60000)
196+ --max-output <chars> Maximum output characters per stream (default: 10000)
197+ --max-connections <n> Maximum concurrent SSH connections (default: 5)
198+ --idle-timeout <ms> Connection idle timeout in ms (default: 600000)
199199```
200200
201201## Development
202202
203203``` bash
204- # Install deps
204+ # Install dependencies
205205npm install
206206
207207# Run in dev mode
@@ -210,13 +210,17 @@ npm run dev -- --project-root .
210210# Build
211211npm run build
212212
213- # Run built version
213+ # Run the built server
214214npm start -- --project-root .
215215
216216# Debug with MCP Inspector
217217npm run inspect
218218```
219219
220+ ## Contributing
221+
222+ Issues and pull requests are welcome. If you want support for more MCP clients, stronger security policies, or better SSH ergonomics, open an issue and share the workflow you want to enable.
223+
220224## License
221225
222- MIT
226+ MIT — see [ LICENSE ] ( LICENSE ) .
0 commit comments