ssh-mcp-devops 2.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SSH-MCP Team
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,205 @@
1
+ # SSH-MCP Server - AI 运维工具
2
+
3
+ 基于 Node.js 实现的 SSH MCP 服务器,支持 AI 自动化运维操作。
4
+
5
+ ## 功能特性
6
+
7
+ ✅ SSH 远程连接管理
8
+ ✅ 命令执行(带安全检查)
9
+ ✅ 危险操作二次确认
10
+ ✅ 文件上传/下载
11
+ ✅ 自动化项目部署
12
+ ✅ 操作审计日志
13
+
14
+ ## 快速开始
15
+
16
+ ### 自动配置(推荐)
17
+
18
+ 运行配置向导:
19
+
20
+ **Windows:**
21
+ ```bash
22
+ setup.bat
23
+ ```
24
+
25
+ **Linux/Mac:**
26
+ ```bash
27
+ chmod +x setup.sh
28
+ ./setup.sh
29
+ ```
30
+
31
+ ### 手动配置
32
+
33
+ 详细步骤请查看 [QUICKSTART.md](QUICKSTART.md) 或 [SETUP.md](SETUP.md)
34
+
35
+ ### 1. 安装依赖
36
+
37
+ ```bash
38
+ npm install
39
+ ```
40
+
41
+ ### 2. 配置 MCP
42
+
43
+ 在 Kiro 中配置 MCP 服务器,编辑 `.kiro/settings/mcp.json`:
44
+
45
+ ```json
46
+ {
47
+ "mcpServers": {
48
+ "ssh-mcp": {
49
+ "command": "node",
50
+ "args": ["index.js"],
51
+ "disabled": false,
52
+ "autoApprove": ["ssh_audit_log"],
53
+ "env": {
54
+ "SSH_HOST": "192.168.1.100",
55
+ "SSH_PORT": "22",
56
+ "SSH_USERNAME": "ubuntu",
57
+ "SSH_PASSWORD": "your-password",
58
+ "SSH_PRIVATE_KEY_PATH": ""
59
+ }
60
+ }
61
+ }
62
+ }
63
+ ```
64
+
65
+ **配置说明:**
66
+ - `SSH_HOST`: SSH 服务器地址(必填)
67
+ - `SSH_PORT`: SSH 端口(默认 22)
68
+ - `SSH_USERNAME`: 登录用户名(必填)
69
+ - `SSH_PASSWORD`: 登录密码(密码认证时使用)
70
+ - `SSH_PRIVATE_KEY_PATH`: 私钥文件路径(密钥认证时使用,如 `~/.ssh/id_rsa`)
71
+
72
+ **认证方式:**
73
+ - 密码认证:填写 `SSH_PASSWORD`
74
+ - 密钥认证:填写 `SSH_PRIVATE_KEY_PATH`(推荐,更安全)
75
+
76
+ 配置完成后,MCP 服务器启动时会自动连接到指定的 SSH 服务器。
77
+
78
+ ### 3. 使用示例
79
+
80
+ #### 连接到服务器
81
+
82
+ ```
83
+ 请连接到我的服务器:
84
+ - 主机: 192.168.1.100
85
+ - 用户名: ubuntu
86
+ - 密码: mypassword
87
+ ```
88
+
89
+ #### 执行命令
90
+
91
+ ```
92
+ 在服务器上执行: ls -la /var/www
93
+ ```
94
+
95
+ #### 部署项目
96
+
97
+ ```
98
+ 帮我部署项目:
99
+ - 本地路径: ./my-app
100
+ - 远程路径: /var/www/my-app
101
+ - 部署脚本: npm install && npm run build && pm2 restart my-app
102
+ ```
103
+
104
+ ## 工具列表
105
+
106
+ ### ssh_connect
107
+ 连接到远程 SSH 服务器
108
+
109
+ 参数:
110
+ - `host`: 服务器地址
111
+ - `port`: SSH 端口(默认 22)
112
+ - `username`: 用户名
113
+ - `password`: 密码(可选)
114
+ - `privateKey`: 私钥路径(可选)
115
+
116
+ ### ssh_exec
117
+ 执行远程命令(危险命令需要确认)
118
+
119
+ 参数:
120
+ - `command`: 要执行的命令
121
+ - `confirm`: 确认执行危险操作(默认 false)
122
+
123
+ ### ssh_upload
124
+ 上传文件到远程服务器
125
+
126
+ 参数:
127
+ - `localPath`: 本地文件路径
128
+ - `remotePath`: 远程目标路径
129
+
130
+ ### ssh_download
131
+ 从远程服务器下载文件
132
+
133
+ 参数:
134
+ - `remotePath`: 远程文件路径
135
+ - `localPath`: 本地保存路径
136
+
137
+ ### ssh_deploy
138
+ 自动部署项目
139
+
140
+ 参数:
141
+ - `projectPath`: 本地项目路径
142
+ - `remotePath`: 远程部署路径
143
+ - `deployScript`: 部署脚本(默认: npm install && npm run build && pm2 restart app)
144
+
145
+ ### ssh_audit_log
146
+ 查看操作审计日志
147
+
148
+ 参数:
149
+ - `limit`: 返回日志条数(默认 50)
150
+
151
+ ## 安全特性
152
+
153
+ ### 危险命令检测
154
+
155
+ 系统会自动检测以下危险操作:
156
+ - `rm -rf /` - 删除根目录
157
+ - `rm -rf` - 强制递归删除
158
+ - `dd if=...of=/dev/...` - 磁盘写入
159
+ - `mkfs` - 格式化文件系统
160
+ - `shutdown/reboot` - 系统关机/重启
161
+ - `iptables -F` - 清空防火墙规则
162
+ - 等等...
163
+
164
+ 危险命令需要设置 `confirm: true` 才能执行。
165
+
166
+ ### 操作审计
167
+
168
+ 所有操作都会记录到 `ssh-mcp-audit.log` 文件中,包括:
169
+ - 时间戳
170
+ - 操作类型
171
+ - 目标对象
172
+ - 执行状态
173
+ - 风险级别
174
+
175
+ ## 开发
176
+
177
+ ```bash
178
+ # 开发模式(自动重启)
179
+ npm run dev
180
+
181
+ # 生产模式
182
+ npm start
183
+ ```
184
+
185
+ ## 许可证
186
+
187
+ MIT
188
+
189
+ ---
190
+
191
+ ## 📚 完整文档
192
+
193
+ - [QUICKSTART.md](QUICKSTART.md) - 快速开始指南
194
+ - [SETUP.md](SETUP.md) - 详细配置指南
195
+ - [example-usage.md](example-usage.md) - 使用示例
196
+ - [PROJECT-STRUCTURE.md](PROJECT-STRUCTURE.md) - 项目结构说明
197
+ - [CHECKLIST.md](CHECKLIST.md) - 配置检查清单
198
+
199
+ ## 🤝 贡献
200
+
201
+ 欢迎提交 Issue 和 Pull Request!
202
+
203
+ ## 📧 支持
204
+
205
+ 如有问题,请查看文档或提交 Issue。
@@ -0,0 +1,60 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+
4
+ export class AuditLogger {
5
+ constructor() {
6
+ this.logFile = 'ssh-mcp-audit.log';
7
+ this.logs = [];
8
+ this.loadLogs();
9
+ }
10
+
11
+ async loadLogs() {
12
+ try {
13
+ const data = await fs.readFile(this.logFile, 'utf-8');
14
+ this.logs = data.split('\n').filter(Boolean).map(line => JSON.parse(line));
15
+ } catch (error) {
16
+ // 文件不存在,创建新的
17
+ this.logs = [];
18
+ }
19
+ }
20
+
21
+ log(action, target, status, metadata = {}) {
22
+ const entry = {
23
+ timestamp: new Date().toISOString(),
24
+ action,
25
+ target,
26
+ status,
27
+ metadata,
28
+ };
29
+
30
+ this.logs.push(entry);
31
+
32
+ // 异步写入文件
33
+ fs.appendFile(this.logFile, JSON.stringify(entry) + '\n').catch(console.error);
34
+
35
+ // 保持最近1000条记录
36
+ if (this.logs.length > 1000) {
37
+ this.logs = this.logs.slice(-1000);
38
+ }
39
+
40
+ return entry;
41
+ }
42
+
43
+ getLogs(limit = 50) {
44
+ return this.logs.slice(-limit).reverse();
45
+ }
46
+
47
+ getLogsByAction(action, limit = 50) {
48
+ return this.logs
49
+ .filter(log => log.action === action)
50
+ .slice(-limit)
51
+ .reverse();
52
+ }
53
+
54
+ getLogsByStatus(status, limit = 50) {
55
+ return this.logs
56
+ .filter(log => log.status === status)
57
+ .slice(-limit)
58
+ .reverse();
59
+ }
60
+ }
@@ -0,0 +1,116 @@
1
+ export class DockerManager {
2
+ constructor(sshManager) {
3
+ this.ssh = sshManager;
4
+ }
5
+
6
+ async listContainers(all = true) {
7
+ const flag = all ? '-a' : '';
8
+ const output = await this.ssh.execCommand(`docker ps ${flag} --format "{{.ID}}|{{.Names}}|{{.Image}}|{{.Status}}|{{.Ports}}"`);
9
+
10
+ const containers = output.trim().split('\n').filter(Boolean).map(line => {
11
+ const [id, name, image, status, ports] = line.split('|');
12
+ return { id, name, image, status, ports };
13
+ });
14
+
15
+ return containers;
16
+ }
17
+
18
+ async listImages() {
19
+ const output = await this.ssh.execCommand('docker images --format "{{.Repository}}:{{.Tag}}|{{.ID}}|{{.Size}}"');
20
+
21
+ const images = output.trim().split('\n').filter(Boolean).map(line => {
22
+ const [name, id, size] = line.split('|');
23
+ return { name, id, size };
24
+ });
25
+
26
+ return images;
27
+ }
28
+
29
+ async startContainer(nameOrId) {
30
+ const output = await this.ssh.execCommand(`docker start ${nameOrId}`);
31
+ return `✅ 容器已启动: ${nameOrId}\n${output}`;
32
+ }
33
+
34
+ async stopContainer(nameOrId) {
35
+ const output = await this.ssh.execCommand(`docker stop ${nameOrId}`);
36
+ return `✅ 容器已停止: ${nameOrId}\n${output}`;
37
+ }
38
+
39
+ async restartContainer(nameOrId) {
40
+ const output = await this.ssh.execCommand(`docker restart ${nameOrId}`);
41
+ return `✅ 容器已重启: ${nameOrId}\n${output}`;
42
+ }
43
+
44
+ async removeContainer(nameOrId, force = false) {
45
+ const flag = force ? '-f' : '';
46
+ const output = await this.ssh.execCommand(`docker rm ${flag} ${nameOrId}`);
47
+ return `✅ 容器已删除: ${nameOrId}\n${output}`;
48
+ }
49
+
50
+ async getContainerLogs(nameOrId, lines = 100) {
51
+ const output = await this.ssh.execCommand(`docker logs --tail ${lines} ${nameOrId}`);
52
+ return output;
53
+ }
54
+
55
+ async getContainerStats(nameOrId) {
56
+ const output = await this.ssh.execCommand(`docker stats ${nameOrId} --no-stream --format "{{.Container}}|{{.CPUPerc}}|{{.MemUsage}}|{{.NetIO}}|{{.BlockIO}}"`);
57
+
58
+ const [container, cpu, memory, network, blockIO] = output.trim().split('|');
59
+ return { container, cpu, memory, network, blockIO };
60
+ }
61
+
62
+ async inspectContainer(nameOrId) {
63
+ const output = await this.ssh.execCommand(`docker inspect ${nameOrId}`);
64
+ return JSON.parse(output);
65
+ }
66
+
67
+ async execInContainer(nameOrId, command) {
68
+ const output = await this.ssh.execCommand(`docker exec ${nameOrId} ${command}`);
69
+ return output;
70
+ }
71
+
72
+ async pullImage(imageName) {
73
+ const output = await this.ssh.execCommand(`docker pull ${imageName}`, { timeout: 600000 });
74
+ return `✅ 镜像拉取完成: ${imageName}\n${output}`;
75
+ }
76
+
77
+ async removeImage(imageNameOrId, force = false) {
78
+ const flag = force ? '-f' : '';
79
+ const output = await this.ssh.execCommand(`docker rmi ${flag} ${imageNameOrId}`);
80
+ return `✅ 镜像已删除: ${imageNameOrId}\n${output}`;
81
+ }
82
+
83
+ async pruneSystem() {
84
+ const output = await this.ssh.execCommand('docker system prune -af --volumes');
85
+ return `✅ 系统清理完成\n${output}`;
86
+ }
87
+
88
+ async getDockerInfo() {
89
+ const output = await this.ssh.execCommand('docker info --format "{{.ServerVersion}}|{{.Containers}}|{{.ContainersRunning}}|{{.Images}}|{{.Driver}}"');
90
+
91
+ const [version, containers, running, images, driver] = output.trim().split('|');
92
+ return {
93
+ version,
94
+ totalContainers: containers,
95
+ runningContainers: running,
96
+ totalImages: images,
97
+ storageDriver: driver,
98
+ };
99
+ }
100
+
101
+ async composeUp(composePath, detached = true) {
102
+ const flag = detached ? '-d' : '';
103
+ const output = await this.ssh.execCommand(`cd ${composePath} && docker-compose up ${flag}`, { timeout: 600000 });
104
+ return `✅ Docker Compose 启动完成\n${output}`;
105
+ }
106
+
107
+ async composeDown(composePath) {
108
+ const output = await this.ssh.execCommand(`cd ${composePath} && docker-compose down`);
109
+ return `✅ Docker Compose 停止完成\n${output}`;
110
+ }
111
+
112
+ async composeRestart(composePath) {
113
+ const output = await this.ssh.execCommand(`cd ${composePath} && docker-compose restart`);
114
+ return `✅ Docker Compose 重启完成\n${output}`;
115
+ }
116
+ }