@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/README_zh.md ADDED
@@ -0,0 +1,353 @@
1
+ # MCP-SSH
2
+
3
+ [English](README.md) | 中文
4
+
5
+ 一个功能完善的 SSH MCP 服务器,适用于 AI 助手(Claude、Cursor、Windsurf 等)
6
+
7
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
8
+ [![Node](https://img.shields.io/badge/node-%3E%3D18-green.svg)](https://nodejs.org/)
9
+ [![MCP](https://img.shields.io/badge/MCP-compatible-purple.svg)](https://modelcontextprotocol.io/)
10
+
11
+ ## 功能特性
12
+
13
+ - **多种认证方式**:密码、SSH 密钥、SSH Agent
14
+ - **连接管理**:连接池复用、心跳保持、自动重连
15
+ - **会话持久化**:会话信息保存,支持重连
16
+ - **命令执行**:
17
+ - 基础执行(带超时)
18
+ - PTY 模式(用于 `top`、`htop` 等交互式命令)
19
+ - `sudo` 执行
20
+ - `su` 切换用户执行
21
+ - 批量执行
22
+ - **持久化 PTY 会话**:用于长时间运行的交互式命令(top、htop、tmux、vim 等)
23
+ - 输出缓冲区,支持轮询读取
24
+ - 发送按键和命令
25
+ - 窗口大小调整
26
+ - **文件操作**:上传、下载、读取、写入、目录列表(通过 SFTP)
27
+ - **智能同步**:目录同步,优先使用 rsync(无 rsync 时自动回退到 SFTP)
28
+ - **环境配置**:LANG、LC_ALL、自定义环境变量
29
+ - **跳板机支持**:通过堡垒机连接
30
+
31
+ ## 兼容客户端
32
+
33
+ | 客户端 | 状态 |
34
+ |--------|------|
35
+ | Claude Code | ✅ |
36
+ | Claude Desktop | ✅ |
37
+ | Cursor | ✅ |
38
+ | Windsurf | ✅ |
39
+ | Continue.dev | ✅ |
40
+ | Cline | ✅ |
41
+ | 其他 MCP 兼容客户端 | ✅ |
42
+
43
+ ## 安装
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
+ ## 配置
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 / 其他客户端
61
+
62
+ 添加到 MCP 配置文件(如 `~/.claude/settings.json` 或客户端特定配置):
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
+ ## 可用工具(27 个)
76
+
77
+ ### 连接管理
78
+
79
+ | 工具 | 描述 |
80
+ |------|------|
81
+ | `ssh_connect` | 建立 SSH 连接并保持心跳 |
82
+ | `ssh_disconnect` | 关闭连接 |
83
+ | `ssh_list_sessions` | 列出活跃会话 |
84
+ | `ssh_reconnect` | 重新连接断开的会话 |
85
+
86
+ ### 命令执行
87
+
88
+ | 工具 | 描述 |
89
+ |------|------|
90
+ | `ssh_exec` | 执行命令(支持 PTY 模式) |
91
+ | `ssh_exec_as_user` | 以其他用户身份执行(通过 `su`) |
92
+ | `ssh_exec_sudo` | 使用 `sudo` 执行 |
93
+ | `ssh_exec_batch` | 批量执行多条命令 |
94
+ | `ssh_quick_exec` | 一次性执行:连接、执行、断开 |
95
+
96
+ ### 文件操作
97
+
98
+ | 工具 | 描述 |
99
+ |------|------|
100
+ | `ssh_upload` | 上传本地文件到远程 |
101
+ | `ssh_download` | 从远程下载文件到本地 |
102
+ | `ssh_read_file` | 读取远程文件内容 |
103
+ | `ssh_write_file` | 写入内容到远程文件 |
104
+ | `ssh_list_dir` | 列出远程目录内容 |
105
+ | `ssh_file_info` | 获取文件/目录元数据 |
106
+ | `ssh_mkdir` | 创建远程目录 |
107
+ | `ssh_sync` | 智能同步(优先 rsync,回退 SFTP) |
108
+
109
+ ### PTY 会话(持久化交互式终端)
110
+
111
+ | 工具 | 描述 |
112
+ |------|------|
113
+ | `ssh_pty_start` | 启动持久化 PTY 会话(用于 top、htop、tmux 等) |
114
+ | `ssh_pty_write` | 向 PTY 发送数据(按键、命令) |
115
+ | `ssh_pty_read` | 读取 PTY 输出(screen 模式:当前屏幕,raw 模式:ANSI 流) |
116
+ | `ssh_pty_resize` | 调整 PTY 窗口大小 |
117
+ | `ssh_pty_close` | 关闭 PTY 会话 |
118
+ | `ssh_pty_list` | 列出所有 PTY 会话 |
119
+
120
+ ### 端口转发
121
+
122
+ | 工具 | 描述 |
123
+ |------|------|
124
+ | `ssh_forward_local` | 本地端口转发(ssh -L):访问远程服务 |
125
+ | `ssh_forward_remote` | 远程端口转发(ssh -R):暴露本地服务 |
126
+ | `ssh_forward_close` | 关闭端口转发 |
127
+ | `ssh_forward_list` | 列出所有端口转发 |
128
+
129
+ ## 使用示例
130
+
131
+ ### 基础:连接和执行
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
+ ### 切换用户执行(su)
140
+
141
+ 适用于 SSH 以 root 登录,但需要以其他用户执行命令的场景:
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
+ // 输出: appuser
147
+ ```
148
+
149
+ ### 交互式命令(PTY 模式)
150
+
151
+ 用于需要终端的命令:
152
+
153
+ ```
154
+ ssh_exec(alias="server", command="top -b -n 1", pty=true)
155
+ ```
156
+
157
+ ### 设置环境变量
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
+ ### 快速一次性执行
169
+
170
+ 无需管理连接,适用于单次命令:
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
+ ### 文件操作
182
+
183
+ ```
184
+ // 上传
185
+ ssh_upload(alias="server", localPath="/tmp/config.json", remotePath="/etc/app/config.json")
186
+
187
+ // 下载
188
+ ssh_download(alias="server", remotePath="/var/log/app.log", localPath="/tmp/app.log")
189
+
190
+ // 读取文件内容
191
+ ssh_read_file(alias="server", remotePath="/etc/hosts")
192
+ ```
193
+
194
+ ### 目录同步(rsync)
195
+
196
+ 智能同步会自动检测 rsync 可用性,使用 rsync 进行高效增量传输:
197
+
198
+ ```
199
+ // 同步本地目录到远程(上传)
200
+ ssh_sync(
201
+ alias="server",
202
+ localPath="/local/project",
203
+ remotePath="/remote/project",
204
+ direction="upload"
205
+ )
206
+ // 返回: { method: "rsync", filesTransferred: 42, ... }
207
+
208
+ // 带排除模式
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
+ // 从远程下载
218
+ ssh_sync(
219
+ alias="server",
220
+ localPath="/local/backup",
221
+ remotePath="/remote/data",
222
+ direction="download"
223
+ )
224
+
225
+ // 试运行(预览,不实际传输)
226
+ ssh_sync(..., dryRun=true)
227
+ ```
228
+
229
+ 如果远程或本地没有 rsync,会自动回退到 SFTP。
230
+
231
+ **注意**:rsync 模式使用 SSH 密钥/代理认证,并禁用严格主机密钥检查(`StrictHostKeyChecking=no`)以方便使用。如需主机密钥验证,请使用 SFTP 模式。
232
+
233
+ ### 持久化 PTY 会话(top、tmux 等)
234
+
235
+ 用于持续刷新或需要持续交互的命令:
236
+
237
+ ```
238
+ // 1. 启动 top 的 PTY 会话
239
+ ssh_pty_start(alias="server", command="top", rows=24, cols=80)
240
+ // 返回: { "ptyId": "pty_1_1234567890" }
241
+
242
+ // 2. 读取当前输出(轮询)
243
+ ssh_pty_read(ptyId="pty_1_1234567890")
244
+ // 返回: { "data": "top - 10:30:15 up 5 days...", "active": true }
245
+
246
+ // 3. 发送命令(如退出 top)
247
+ ssh_pty_write(ptyId="pty_1_1234567890", data="q")
248
+
249
+ // 4. 完成后关闭
250
+ ssh_pty_close(ptyId="pty_1_1234567890")
251
+ ```
252
+
253
+ tmux 会话示例:
254
+
255
+ ```
256
+ // 启动 tmux
257
+ ssh_pty_start(alias="server", command="tmux new -s work")
258
+
259
+ // 在 tmux 中发送命令
260
+ ssh_pty_write(ptyId="pty_1_xxx", data="ls -la\r")
261
+
262
+ // 读取输出
263
+ ssh_pty_read(ptyId="pty_1_xxx")
264
+
265
+ // 分离 tmux(Ctrl+B, D)
266
+ ssh_pty_write(ptyId="pty_1_xxx", data="\x02d")
267
+ ```
268
+
269
+ 常用控制序列:
270
+ - 回车: `\r` 或 `\n`
271
+ - Ctrl+C: `\x03`
272
+ - Ctrl+D: `\x04`
273
+ - Ctrl+Z: `\x1a`
274
+ - 上箭头: `\x1b[A`
275
+ - 下箭头: `\x1b[B`
276
+
277
+ ### 端口转发
278
+
279
+ 访问远程内网服务或暴露本地服务:
280
+
281
+ ```
282
+ // 本地转发:通过 localhost:13306 访问远程 MySQL (10.0.0.5:3306)
283
+ ssh_forward_local(alias="server", localPort=13306, remoteHost="10.0.0.5", remotePort=3306)
284
+
285
+ // 远程转发:将本地开发服务器 (3000) 暴露到远程端口 8080
286
+ ssh_forward_remote(alias="server", remotePort=8080, localHost="127.0.0.1", localPort=3000)
287
+
288
+ // 列出所有转发
289
+ ssh_forward_list()
290
+
291
+ // 关闭转发
292
+ ssh_forward_close(forwardId="fwd_1_xxx")
293
+ ```
294
+
295
+ ## 配置选项
296
+
297
+ ### 连接选项
298
+
299
+ | 选项 | 类型 | 默认值 | 描述 |
300
+ |------|------|--------|------|
301
+ | `host` | string | *必需* | 服务器地址 |
302
+ | `user` | string | *必需* | 用户名 |
303
+ | `password` | string | - | 密码认证 |
304
+ | `keyPath` | string | - | SSH 私钥路径 |
305
+ | `port` | number | 22 | SSH 端口 |
306
+ | `alias` | string | 自动生成 | 连接别名,用于后续引用 |
307
+ | `env` | object | - | 环境变量 |
308
+ | `keepaliveInterval` | number | 30000 | 心跳间隔(毫秒) |
309
+
310
+ ### 执行选项
311
+
312
+ | 选项 | 类型 | 默认值 | 描述 |
313
+ |------|------|--------|------|
314
+ | `timeout` | number | 30000 | 命令超时(毫秒) |
315
+ | `cwd` | string | - | 工作目录 |
316
+ | `env` | object | - | 额外环境变量 |
317
+ | `pty` | boolean | false | 启用 PTY 模式(用于交互式命令) |
318
+
319
+ ## 项目结构
320
+
321
+ ```
322
+ mcp-ssh/
323
+ ├── src/
324
+ │ ├── index.ts # MCP Server 入口,工具定义
325
+ │ ├── session-manager.ts # 连接池、执行、心跳
326
+ │ ├── file-ops.ts # SFTP 文件操作
327
+ │ └── types.ts # TypeScript 类型定义
328
+ ├── dist/ # 编译后的 JavaScript
329
+ ├── package.json
330
+ ├── tsconfig.json
331
+ └── README.md
332
+ ```
333
+
334
+ ## 路线图
335
+
336
+ - [ ] 动态端口转发(SOCKS 代理)
337
+ - [ ] SSH Agent 转发
338
+ - [ ] 命令历史和审计日志
339
+ - [ ] 多主机并行执行
340
+ - [ ] SSH 配置文件(~/.ssh/config)自动发现
341
+
342
+ ## 贡献
343
+
344
+ 欢迎贡献!请随时提交 Pull Request。
345
+
346
+ ## 许可证
347
+
348
+ MIT 许可证 - 详见 [LICENSE](LICENSE)。
349
+
350
+ ## 相关项目
351
+
352
+ - [Model Context Protocol](https://modelcontextprotocol.io/) - MCP 规范
353
+ - [MCP Servers](https://github.com/modelcontextprotocol/servers) - 官方 MCP 服务器实现
@@ -0,0 +1,78 @@
1
+ /**
2
+ * SSH File Operations - 文件操作
3
+ */
4
+ import { FileInfo, TransferProgress } from './types.js';
5
+ /**
6
+ * 上传文件
7
+ */
8
+ export declare function uploadFile(alias: string, localPath: string, remotePath: string, onProgress?: (progress: TransferProgress) => void): Promise<{
9
+ success: boolean;
10
+ size: number;
11
+ }>;
12
+ /**
13
+ * 下载文件
14
+ */
15
+ export declare function downloadFile(alias: string, remotePath: string, localPath: string, onProgress?: (progress: TransferProgress) => void): Promise<{
16
+ success: boolean;
17
+ size: number;
18
+ }>;
19
+ /**
20
+ * 读取远程文件内容
21
+ */
22
+ export declare function readFile(alias: string, remotePath: string, maxBytes?: number): Promise<{
23
+ content: string;
24
+ size: number;
25
+ truncated: boolean;
26
+ }>;
27
+ /**
28
+ * 写入远程文件
29
+ */
30
+ export declare function writeFile(alias: string, remotePath: string, content: string, append?: boolean): Promise<{
31
+ success: boolean;
32
+ size: number;
33
+ }>;
34
+ /**
35
+ * 列出目录内容
36
+ */
37
+ export declare function listDir(alias: string, remotePath: string, showHidden?: boolean): Promise<FileInfo[]>;
38
+ /**
39
+ * 获取文件信息
40
+ */
41
+ export declare function getFileInfo(alias: string, remotePath: string): Promise<FileInfo>;
42
+ /**
43
+ * 检查文件是否存在
44
+ */
45
+ export declare function fileExists(alias: string, remotePath: string): Promise<boolean>;
46
+ /**
47
+ * 创建目录
48
+ */
49
+ export declare function mkdir(alias: string, remotePath: string, recursive?: boolean): Promise<boolean>;
50
+ /**
51
+ * 删除文件
52
+ */
53
+ export declare function removeFile(alias: string, remotePath: string): Promise<boolean>;
54
+ /**
55
+ * 检查远程是否安装 rsync
56
+ */
57
+ export declare function checkRsync(alias: string): Promise<boolean>;
58
+ /**
59
+ * 智能文件同步(优先使用 rsync)
60
+ *
61
+ * @param alias SSH 连接别名
62
+ * @param localPath 本地路径
63
+ * @param remotePath 远程路径
64
+ * @param direction 同步方向:'upload' 或 'download'
65
+ * @param options 同步选项
66
+ */
67
+ export declare function syncFiles(alias: string, localPath: string, remotePath: string, direction: 'upload' | 'download', options?: {
68
+ delete?: boolean;
69
+ dryRun?: boolean;
70
+ exclude?: string[];
71
+ recursive?: boolean;
72
+ }): Promise<{
73
+ success: boolean;
74
+ method: 'rsync' | 'sftp';
75
+ filesTransferred?: number;
76
+ bytesTransferred?: number;
77
+ output?: string;
78
+ }>;