@pyrokine/mcp-ssh 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +353 -0
- package/README_zh.md +353 -0
- package/dist/file-ops.d.ts +78 -0
- package/dist/file-ops.js +572 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +804 -0
- package/dist/session-manager.d.ts +193 -0
- package/dist/session-manager.js +792 -0
- package/dist/types.d.ts +111 -0
- package/dist/types.js +4 -0
- package/package.json +43 -0
- package/src/file-ops.ts +730 -0
- package/src/index.ts +938 -0
- package/src/session-manager.ts +982 -0
- package/src/types.ts +133 -0
- package/tsconfig.json +16 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Pyrokine
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
# MCP-SSH
|
|
2
|
+
|
|
3
|
+
English | [中文](README_zh.md)
|
|
4
|
+
|
|
5
|
+
A comprehensive SSH MCP Server for AI assistants (Claude, Cursor, Windsurf, etc.)
|
|
6
|
+
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
[](https://nodejs.org/)
|
|
9
|
+
[](https://modelcontextprotocol.io/)
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- **Multiple Authentication**: Password, SSH key, SSH agent
|
|
14
|
+
- **Connection Management**: Connection pooling, keepalive, auto-reconnect
|
|
15
|
+
- **Session Persistence**: Sessions info saved for reconnection
|
|
16
|
+
- **Command Execution**:
|
|
17
|
+
- Basic exec with timeout
|
|
18
|
+
- PTY mode (for interactive commands like `top`, `htop`)
|
|
19
|
+
- `sudo` execution
|
|
20
|
+
- `su` (switch user) execution - *run commands as different user*
|
|
21
|
+
- Batch execution
|
|
22
|
+
- **Persistent PTY Sessions**: For long-running interactive commands (top, htop, tmux, vim, etc.)
|
|
23
|
+
- Output buffering with polling read
|
|
24
|
+
- Send keystrokes and commands
|
|
25
|
+
- Window resize support
|
|
26
|
+
- **File Operations**: Upload, download, read, write, list directory (via SFTP)
|
|
27
|
+
- **Smart Sync**: Directory sync with rsync (auto-fallback to SFTP if rsync unavailable)
|
|
28
|
+
- **Environment Configuration**: LANG, LC_ALL, custom env vars
|
|
29
|
+
- **Jump Host Support**: Connect through bastion hosts
|
|
30
|
+
|
|
31
|
+
## Compatible Clients
|
|
32
|
+
|
|
33
|
+
| Client | Status |
|
|
34
|
+
|--------|--------|
|
|
35
|
+
| Claude Code | ✅ |
|
|
36
|
+
| Claude Desktop | ✅ |
|
|
37
|
+
| Cursor | ✅ |
|
|
38
|
+
| Windsurf | ✅ |
|
|
39
|
+
| Continue.dev | ✅ |
|
|
40
|
+
| Cline | ✅ |
|
|
41
|
+
| Any MCP-compatible client | ✅ |
|
|
42
|
+
|
|
43
|
+
## Installation
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
git clone https://github.com/Pyrokine/claude-mcp-tools.git
|
|
47
|
+
cd claude-mcp-tools/ssh
|
|
48
|
+
npm install
|
|
49
|
+
npm run build
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Configuration
|
|
53
|
+
|
|
54
|
+
### Claude Code
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
claude mcp add ssh -- node /path/to/mcp-ssh/dist/index.js
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Claude Desktop / Other Clients
|
|
61
|
+
|
|
62
|
+
Add to your MCP settings (e.g., `~/.claude/settings.json` or client-specific config):
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{
|
|
66
|
+
"mcpServers": {
|
|
67
|
+
"ssh": {
|
|
68
|
+
"command": "node",
|
|
69
|
+
"args": ["/path/to/mcp-ssh/dist/index.js"]
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Available Tools (27 tools)
|
|
76
|
+
|
|
77
|
+
### Connection Management
|
|
78
|
+
|
|
79
|
+
| Tool | Description |
|
|
80
|
+
|------|-------------|
|
|
81
|
+
| `ssh_connect` | Establish SSH connection with keepalive |
|
|
82
|
+
| `ssh_disconnect` | Close connection |
|
|
83
|
+
| `ssh_list_sessions` | List active sessions |
|
|
84
|
+
| `ssh_reconnect` | Reconnect a disconnected session |
|
|
85
|
+
|
|
86
|
+
### Command Execution
|
|
87
|
+
|
|
88
|
+
| Tool | Description |
|
|
89
|
+
|------|-------------|
|
|
90
|
+
| `ssh_exec` | Execute command (supports PTY mode) |
|
|
91
|
+
| `ssh_exec_as_user` | Execute as different user (via `su`) |
|
|
92
|
+
| `ssh_exec_sudo` | Execute with `sudo` |
|
|
93
|
+
| `ssh_exec_batch` | Execute multiple commands sequentially |
|
|
94
|
+
| `ssh_quick_exec` | One-shot: connect, execute, disconnect |
|
|
95
|
+
|
|
96
|
+
### File Operations
|
|
97
|
+
|
|
98
|
+
| Tool | Description |
|
|
99
|
+
|------|-------------|
|
|
100
|
+
| `ssh_upload` | Upload local file to remote server |
|
|
101
|
+
| `ssh_download` | Download remote file to local |
|
|
102
|
+
| `ssh_read_file` | Read remote file content |
|
|
103
|
+
| `ssh_write_file` | Write content to remote file |
|
|
104
|
+
| `ssh_list_dir` | List remote directory contents |
|
|
105
|
+
| `ssh_file_info` | Get file/directory metadata |
|
|
106
|
+
| `ssh_mkdir` | Create remote directory |
|
|
107
|
+
| `ssh_sync` | Smart sync with rsync (fallback to SFTP) |
|
|
108
|
+
|
|
109
|
+
### PTY Sessions (Persistent Interactive Terminal)
|
|
110
|
+
|
|
111
|
+
| Tool | Description |
|
|
112
|
+
|------|-------------|
|
|
113
|
+
| `ssh_pty_start` | Start persistent PTY session (for top, htop, tmux, etc.) |
|
|
114
|
+
| `ssh_pty_write` | Send data to PTY (keystrokes, commands) |
|
|
115
|
+
| `ssh_pty_read` | Read PTY output (screen mode: current screen, raw mode: ANSI stream) |
|
|
116
|
+
| `ssh_pty_resize` | Resize PTY window |
|
|
117
|
+
| `ssh_pty_close` | Close PTY session |
|
|
118
|
+
| `ssh_pty_list` | List all PTY sessions |
|
|
119
|
+
|
|
120
|
+
### Port Forwarding
|
|
121
|
+
|
|
122
|
+
| Tool | Description |
|
|
123
|
+
|------|-------------|
|
|
124
|
+
| `ssh_forward_local` | Local port forwarding (ssh -L): access remote services |
|
|
125
|
+
| `ssh_forward_remote` | Remote port forwarding (ssh -R): expose local services |
|
|
126
|
+
| `ssh_forward_close` | Close port forwarding |
|
|
127
|
+
| `ssh_forward_list` | List all port forwards |
|
|
128
|
+
|
|
129
|
+
## Usage Examples
|
|
130
|
+
|
|
131
|
+
### Basic: Connect and Execute
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
1. ssh_connect(host="192.168.1.100", user="root", password="xxx", alias="myserver")
|
|
135
|
+
2. ssh_exec(alias="myserver", command="ls -la /home")
|
|
136
|
+
3. ssh_disconnect(alias="myserver")
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Switch User Execution (su)
|
|
140
|
+
|
|
141
|
+
Perfect for scenarios where you SSH as root but need to run commands as another user:
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
1. ssh_connect(host="192.168.1.100", user="root", password="xxx", alias="server")
|
|
145
|
+
2. ssh_exec_as_user(alias="server", command="whoami", targetUser="appuser")
|
|
146
|
+
// Output: appuser
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Interactive Commands (PTY mode)
|
|
150
|
+
|
|
151
|
+
For commands that need a terminal:
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
ssh_exec(alias="server", command="top -b -n 1", pty=true)
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### With Environment Variables
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
ssh_connect(
|
|
161
|
+
host="192.168.1.100",
|
|
162
|
+
user="root",
|
|
163
|
+
password="xxx",
|
|
164
|
+
env={"LANG": "en_US.UTF-8", "LC_ALL": "en_US.UTF-8"}
|
|
165
|
+
)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Quick One-shot Execution
|
|
169
|
+
|
|
170
|
+
No need to manage connections for single commands:
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
ssh_quick_exec(
|
|
174
|
+
host="192.168.1.100",
|
|
175
|
+
user="root",
|
|
176
|
+
password="xxx",
|
|
177
|
+
command="uptime"
|
|
178
|
+
)
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### File Operations
|
|
182
|
+
|
|
183
|
+
```
|
|
184
|
+
// Upload
|
|
185
|
+
ssh_upload(alias="server", localPath="/tmp/config.json", remotePath="/etc/app/config.json")
|
|
186
|
+
|
|
187
|
+
// Download
|
|
188
|
+
ssh_download(alias="server", remotePath="/var/log/app.log", localPath="/tmp/app.log")
|
|
189
|
+
|
|
190
|
+
// Read file content
|
|
191
|
+
ssh_read_file(alias="server", remotePath="/etc/hosts")
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Directory Sync (with rsync)
|
|
195
|
+
|
|
196
|
+
Smart sync automatically detects rsync availability and uses it for efficient incremental transfer:
|
|
197
|
+
|
|
198
|
+
```
|
|
199
|
+
// Sync local directory to remote (upload)
|
|
200
|
+
ssh_sync(
|
|
201
|
+
alias="server",
|
|
202
|
+
localPath="/local/project",
|
|
203
|
+
remotePath="/remote/project",
|
|
204
|
+
direction="upload"
|
|
205
|
+
)
|
|
206
|
+
// Returns: { method: "rsync", filesTransferred: 42, ... }
|
|
207
|
+
|
|
208
|
+
// Sync with exclude patterns
|
|
209
|
+
ssh_sync(
|
|
210
|
+
alias="server",
|
|
211
|
+
localPath="/local/project",
|
|
212
|
+
remotePath="/remote/project",
|
|
213
|
+
direction="upload",
|
|
214
|
+
exclude=["*.log", "node_modules", ".git"]
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
// Download from remote
|
|
218
|
+
ssh_sync(
|
|
219
|
+
alias="server",
|
|
220
|
+
localPath="/local/backup",
|
|
221
|
+
remotePath="/remote/data",
|
|
222
|
+
direction="download"
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
// Dry run (preview without actual transfer)
|
|
226
|
+
ssh_sync(..., dryRun=true)
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
If rsync is not available on remote or local, it automatically falls back to SFTP.
|
|
230
|
+
|
|
231
|
+
**Note**: rsync mode uses SSH key/agent authentication and disables strict host key checking (`StrictHostKeyChecking=no`) for convenience. If you require host key verification, use SFTP mode instead.
|
|
232
|
+
|
|
233
|
+
### Persistent PTY Sessions (top, tmux, etc.)
|
|
234
|
+
|
|
235
|
+
For interactive commands that continuously refresh or require ongoing interaction:
|
|
236
|
+
|
|
237
|
+
```
|
|
238
|
+
// 1. Start a PTY session with top
|
|
239
|
+
ssh_pty_start(alias="server", command="top", rows=24, cols=80)
|
|
240
|
+
// Returns: { "ptyId": "pty_1_1234567890" }
|
|
241
|
+
|
|
242
|
+
// 2. Read current output (polling)
|
|
243
|
+
ssh_pty_read(ptyId="pty_1_1234567890")
|
|
244
|
+
// Returns: { "data": "top - 10:30:15 up 5 days...", "active": true }
|
|
245
|
+
|
|
246
|
+
// 3. Send commands (e.g., quit top)
|
|
247
|
+
ssh_pty_write(ptyId="pty_1_1234567890", data="q")
|
|
248
|
+
|
|
249
|
+
// 4. Close when done
|
|
250
|
+
ssh_pty_close(ptyId="pty_1_1234567890")
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
tmux session example:
|
|
254
|
+
|
|
255
|
+
```
|
|
256
|
+
// Start tmux
|
|
257
|
+
ssh_pty_start(alias="server", command="tmux new -s work")
|
|
258
|
+
|
|
259
|
+
// Send commands in tmux
|
|
260
|
+
ssh_pty_write(ptyId="pty_1_xxx", data="ls -la\r")
|
|
261
|
+
|
|
262
|
+
// Read output
|
|
263
|
+
ssh_pty_read(ptyId="pty_1_xxx")
|
|
264
|
+
|
|
265
|
+
// Detach tmux (Ctrl+B, D)
|
|
266
|
+
ssh_pty_write(ptyId="pty_1_xxx", data="\x02d")
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Common control sequences:
|
|
270
|
+
- Enter: `\r` or `\n`
|
|
271
|
+
- Ctrl+C: `\x03`
|
|
272
|
+
- Ctrl+D: `\x04`
|
|
273
|
+
- Ctrl+Z: `\x1a`
|
|
274
|
+
- Arrow Up: `\x1b[A`
|
|
275
|
+
- Arrow Down: `\x1b[B`
|
|
276
|
+
|
|
277
|
+
### Port Forwarding
|
|
278
|
+
|
|
279
|
+
Access remote internal services or expose local services:
|
|
280
|
+
|
|
281
|
+
```
|
|
282
|
+
// Local forward: access remote MySQL (10.0.0.5:3306) via localhost:13306
|
|
283
|
+
ssh_forward_local(alias="server", localPort=13306, remoteHost="10.0.0.5", remotePort=3306)
|
|
284
|
+
|
|
285
|
+
// Remote forward: expose local dev server (3000) to remote port 8080
|
|
286
|
+
ssh_forward_remote(alias="server", remotePort=8080, localHost="127.0.0.1", localPort=3000)
|
|
287
|
+
|
|
288
|
+
// List all forwards
|
|
289
|
+
ssh_forward_list()
|
|
290
|
+
|
|
291
|
+
// Close forward
|
|
292
|
+
ssh_forward_close(forwardId="fwd_1_xxx")
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## Configuration Options
|
|
296
|
+
|
|
297
|
+
### Connection Options
|
|
298
|
+
|
|
299
|
+
| Option | Type | Default | Description |
|
|
300
|
+
|--------|------|---------|-------------|
|
|
301
|
+
| `host` | string | *required* | Server address |
|
|
302
|
+
| `user` | string | *required* | Username |
|
|
303
|
+
| `password` | string | - | Password authentication |
|
|
304
|
+
| `keyPath` | string | - | Path to SSH private key |
|
|
305
|
+
| `port` | number | 22 | SSH port |
|
|
306
|
+
| `alias` | string | auto-generated | Connection alias for reference |
|
|
307
|
+
| `env` | object | - | Environment variables |
|
|
308
|
+
| `keepaliveInterval` | number | 30000 | Keepalive interval in ms |
|
|
309
|
+
|
|
310
|
+
### Exec Options
|
|
311
|
+
|
|
312
|
+
| Option | Type | Default | Description |
|
|
313
|
+
|--------|------|---------|-------------|
|
|
314
|
+
| `timeout` | number | 30000 | Command timeout in ms |
|
|
315
|
+
| `cwd` | string | - | Working directory |
|
|
316
|
+
| `env` | object | - | Additional environment variables |
|
|
317
|
+
| `pty` | boolean | false | Enable PTY mode for interactive commands |
|
|
318
|
+
|
|
319
|
+
## Project Structure
|
|
320
|
+
|
|
321
|
+
```
|
|
322
|
+
mcp-ssh/
|
|
323
|
+
├── src/
|
|
324
|
+
│ ├── index.ts # MCP Server entry, tool definitions
|
|
325
|
+
│ ├── session-manager.ts # Connection pool, exec, keepalive
|
|
326
|
+
│ ├── file-ops.ts # SFTP file operations
|
|
327
|
+
│ └── types.ts # TypeScript type definitions
|
|
328
|
+
├── dist/ # Compiled JavaScript
|
|
329
|
+
├── package.json
|
|
330
|
+
├── tsconfig.json
|
|
331
|
+
└── README.md
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
## Roadmap
|
|
335
|
+
|
|
336
|
+
- [ ] Dynamic port forwarding (SOCKS proxy)
|
|
337
|
+
- [ ] SSH Agent forwarding
|
|
338
|
+
- [ ] Command history and audit logging
|
|
339
|
+
- [ ] Multi-host parallel execution
|
|
340
|
+
- [ ] SSH config file (~/.ssh/config) auto-discovery
|
|
341
|
+
|
|
342
|
+
## Contributing
|
|
343
|
+
|
|
344
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
345
|
+
|
|
346
|
+
## License
|
|
347
|
+
|
|
348
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
349
|
+
|
|
350
|
+
## Related Projects
|
|
351
|
+
|
|
352
|
+
- [Model Context Protocol](https://modelcontextprotocol.io/) - The MCP specification
|
|
353
|
+
- [MCP Servers](https://github.com/modelcontextprotocol/servers) - Official MCP server implementations
|