@jadchene/mcp-ssh-service 1.4.0 → 1.4.2
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.md +33 -5
- package/dist/tools/definitions.js +169 -4
- package/dist/tools/handlers.js +78 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -189,17 +189,31 @@ args = ["--config", "./config.json"]
|
|
|
189
189
|
* `cd`
|
|
190
190
|
* `execute_batch` [Auth Required if any sub-command is high-risk]
|
|
191
191
|
|
|
192
|
+
### System (9)
|
|
193
|
+
* `get_system_info`
|
|
194
|
+
* `hostname`
|
|
195
|
+
* `id`
|
|
196
|
+
* `uname`
|
|
197
|
+
* `uptime`
|
|
198
|
+
* `free`
|
|
199
|
+
* `env`
|
|
200
|
+
* `pwd`
|
|
201
|
+
* `cd`
|
|
202
|
+
|
|
192
203
|
### Shell & Basic (2)
|
|
193
204
|
* `execute_command` [Auth Required, single command only]
|
|
194
205
|
* `echo`
|
|
195
206
|
|
|
196
|
-
### File Management (
|
|
207
|
+
### File Management (18)
|
|
197
208
|
* `upload_file` [Auth Required]
|
|
198
209
|
* `download_file`
|
|
199
210
|
* `ll`
|
|
200
211
|
* `cat`
|
|
212
|
+
* `head`
|
|
201
213
|
* `tail`
|
|
214
|
+
* `sed`
|
|
202
215
|
* `grep`
|
|
216
|
+
* `grep_r`
|
|
203
217
|
* `edit_text_file` [Auth Required]
|
|
204
218
|
* `touch`
|
|
205
219
|
* `mkdir` [Auth Required]
|
|
@@ -218,12 +232,16 @@ args = ["--config", "./config.json"]
|
|
|
218
232
|
* `git_branch`
|
|
219
233
|
* `git_log`
|
|
220
234
|
|
|
221
|
-
### Docker & Compose (
|
|
235
|
+
### Docker & Compose (26)
|
|
222
236
|
* `docker_compose_up` [Auth Required]
|
|
223
237
|
* `docker_compose_down` [Auth Required]
|
|
224
238
|
* `docker_compose_stop` [Auth Required]
|
|
225
239
|
* `docker_compose_logs`
|
|
226
240
|
* `docker_compose_restart` [Auth Required]
|
|
241
|
+
* `docker_compose_pull` [Auth Required]
|
|
242
|
+
* `docker_compose_ps`
|
|
243
|
+
* `docker_compose_config`
|
|
244
|
+
* `docker_compose_exec` [Auth Required]
|
|
227
245
|
* `docker_ps`
|
|
228
246
|
* `docker_images`
|
|
229
247
|
* `docker_exec` [Auth Required]
|
|
@@ -240,13 +258,18 @@ args = ["--config", "./config.json"]
|
|
|
240
258
|
* `docker_logs`
|
|
241
259
|
* `docker_load` [Auth Required]
|
|
242
260
|
* `docker_save` [Auth Required]
|
|
261
|
+
* `docker_build` [Auth Required, supports `networkHost` for `--network=host`]
|
|
243
262
|
|
|
244
|
-
### Service & Network (
|
|
263
|
+
### Service & Network (18)
|
|
245
264
|
* `systemctl_status`
|
|
246
265
|
* `systemctl_restart` [Auth Required]
|
|
247
266
|
* `systemctl_start` [Auth Required]
|
|
248
267
|
* `systemctl_stop` [Auth Required]
|
|
268
|
+
* `systemctl_enable` [Auth Required]
|
|
269
|
+
* `systemctl_disable` [Auth Required]
|
|
249
270
|
* `ip_addr`
|
|
271
|
+
* `ip_route`
|
|
272
|
+
* `mount`
|
|
250
273
|
* `journalctl`
|
|
251
274
|
* `firewall_cmd` [Auth Required, structured actions only]
|
|
252
275
|
* `netstat` [uses `args: string[]`]
|
|
@@ -257,13 +280,18 @@ args = ["--config", "./config.json"]
|
|
|
257
280
|
* `dig`
|
|
258
281
|
* `curl_http` [Auth Required]
|
|
259
282
|
|
|
260
|
-
### Stats & Process (
|
|
283
|
+
### Stats & Process (19)
|
|
261
284
|
* `nvidia_smi`
|
|
262
285
|
* `ps`
|
|
263
286
|
* `pgrep`
|
|
264
287
|
* `kill_process` [Auth Required]
|
|
265
288
|
* `df_h`
|
|
289
|
+
* `df_inode`
|
|
266
290
|
* `du_sh`
|
|
291
|
+
* `which`
|
|
292
|
+
* `lsof`
|
|
293
|
+
* `file`
|
|
294
|
+
* `stat`
|
|
267
295
|
* `chmod` [Auth Required]
|
|
268
296
|
* `chown` [Auth Required]
|
|
269
297
|
* `ln` [Auth Required]
|
|
@@ -272,7 +300,7 @@ args = ["--config", "./config.json"]
|
|
|
272
300
|
* `zip` [Auth Required]
|
|
273
301
|
* `unzip` [Auth Required]
|
|
274
302
|
|
|
275
|
-
Total:
|
|
303
|
+
Total: 103 tools.
|
|
276
304
|
|
|
277
305
|
---
|
|
278
306
|
|
|
@@ -42,6 +42,36 @@ export const toolDefinitions = [
|
|
|
42
42
|
description: 'System health check: Returns current user, system uptime, kernel, and memory.',
|
|
43
43
|
inputSchema: baseParams()
|
|
44
44
|
},
|
|
45
|
+
{
|
|
46
|
+
name: 'hostname',
|
|
47
|
+
description: 'Show the current host name.',
|
|
48
|
+
inputSchema: baseParams(grepParam)
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'id',
|
|
52
|
+
description: 'Show current user identity and group information.',
|
|
53
|
+
inputSchema: baseParams(grepParam)
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: 'uname',
|
|
57
|
+
description: 'Show kernel and operating system information.',
|
|
58
|
+
inputSchema: baseParams({ all: { type: 'boolean' }, ...grepParam })
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'uptime',
|
|
62
|
+
description: 'Show system uptime and load averages.',
|
|
63
|
+
inputSchema: baseParams(grepParam)
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: 'free',
|
|
67
|
+
description: 'Show memory usage in megabytes.',
|
|
68
|
+
inputSchema: baseParams(grepParam)
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: 'env',
|
|
72
|
+
description: 'Show environment variables visible to the remote session.',
|
|
73
|
+
inputSchema: baseParams(grepParam)
|
|
74
|
+
},
|
|
45
75
|
{
|
|
46
76
|
name: 'pwd',
|
|
47
77
|
description: 'Current path: Returns the absolute path of the current directory on remote.',
|
|
@@ -108,23 +138,52 @@ export const toolDefinitions = [
|
|
|
108
138
|
{
|
|
109
139
|
name: 'll',
|
|
110
140
|
description: 'Directory listing: Lists files in a directory with detailed information.',
|
|
111
|
-
inputSchema: baseParams({ ...cwdParam, ...grepParam })
|
|
141
|
+
inputSchema: baseParams({ ...cwdParam, all: { type: 'boolean' }, ...grepParam })
|
|
112
142
|
},
|
|
113
143
|
{
|
|
114
144
|
name: 'cat',
|
|
115
145
|
description: 'File reading: Reads text file content.',
|
|
116
146
|
inputSchema: baseParams({ filePath: { type: 'string' }, ...grepParam }, ['filePath'])
|
|
117
147
|
},
|
|
148
|
+
{
|
|
149
|
+
name: 'head',
|
|
150
|
+
description: 'File preview: Reads the first N lines of a file.',
|
|
151
|
+
inputSchema: baseParams({ filePath: { type: 'string' }, lines: { type: 'number' }, ...grepParam }, ['filePath'])
|
|
152
|
+
},
|
|
118
153
|
{
|
|
119
154
|
name: 'tail',
|
|
120
155
|
description: 'Log inspection: Reads last N lines of a file.',
|
|
121
156
|
inputSchema: baseParams({ filePath: { type: 'string' }, lines: { type: 'number' }, ...grepParam }, ['filePath'])
|
|
122
157
|
},
|
|
158
|
+
{
|
|
159
|
+
name: 'sed',
|
|
160
|
+
description: 'Line range reading: Reads an inclusive line range from a text file.',
|
|
161
|
+
inputSchema: baseParams({
|
|
162
|
+
filePath: { type: 'string' },
|
|
163
|
+
startLine: { type: 'number' },
|
|
164
|
+
endLine: { type: 'number' },
|
|
165
|
+
...grepParam
|
|
166
|
+
}, ['filePath', 'startLine', 'endLine'])
|
|
167
|
+
},
|
|
123
168
|
{
|
|
124
169
|
name: 'grep',
|
|
125
170
|
description: 'Pattern search: Search for a regex pattern in a file.',
|
|
126
171
|
inputSchema: baseParams({ filePath: { type: 'string' }, pattern: { type: 'string' }, ignoreCase: { type: 'boolean' } }, ['filePath', 'pattern'])
|
|
127
172
|
},
|
|
173
|
+
{
|
|
174
|
+
name: 'grep_r',
|
|
175
|
+
description: 'Recursive pattern search: Search for a regex pattern across files under a directory tree.',
|
|
176
|
+
inputSchema: baseParams({
|
|
177
|
+
path: { type: 'string' },
|
|
178
|
+
pattern: { type: 'string' },
|
|
179
|
+
ignoreCase: { type: 'boolean' },
|
|
180
|
+
beforeContext: { type: 'number' },
|
|
181
|
+
afterContext: { type: 'number' },
|
|
182
|
+
context: { type: 'number' },
|
|
183
|
+
include: { type: 'array', items: { type: 'string' } },
|
|
184
|
+
excludeDir: { type: 'array', items: { type: 'string' } }
|
|
185
|
+
}, ['path', 'pattern'])
|
|
186
|
+
},
|
|
128
187
|
{
|
|
129
188
|
name: 'edit_text_file',
|
|
130
189
|
description: 'File creation/overwrite: Completely replaces file content. REQUIRES CONFIRMATION.',
|
|
@@ -172,7 +231,14 @@ export const toolDefinitions = [
|
|
|
172
231
|
{
|
|
173
232
|
name: 'find',
|
|
174
233
|
description: 'Search for files in a directory hierarchy.',
|
|
175
|
-
inputSchema: baseParams({
|
|
234
|
+
inputSchema: baseParams({
|
|
235
|
+
path: { type: 'string' },
|
|
236
|
+
name: { type: 'string' },
|
|
237
|
+
type: { type: 'string', enum: ['f', 'd', 'l'] },
|
|
238
|
+
maxDepth: { type: 'number' },
|
|
239
|
+
pathPattern: { type: 'string' },
|
|
240
|
+
...grepParam
|
|
241
|
+
}, ['path'])
|
|
176
242
|
},
|
|
177
243
|
// --- Git ---
|
|
178
244
|
{
|
|
@@ -231,6 +297,33 @@ export const toolDefinitions = [
|
|
|
231
297
|
description: 'Restart compose stack. REQUIRES CONFIRMATION.',
|
|
232
298
|
inputSchema: baseParams({ ...cwdParam, ...confirmationParams }, ['cwd'])
|
|
233
299
|
},
|
|
300
|
+
{
|
|
301
|
+
name: 'docker_compose_pull',
|
|
302
|
+
description: 'Pull images defined by the compose stack. REQUIRES CONFIRMATION.',
|
|
303
|
+
inputSchema: baseParams({ ...cwdParam, service: { type: 'string' }, ...confirmationParams }, ['cwd'])
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
name: 'docker_compose_ps',
|
|
307
|
+
description: 'List compose services and their current state.',
|
|
308
|
+
inputSchema: baseParams({ ...cwdParam, service: { type: 'string' }, ...grepParam }, ['cwd'])
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
name: 'docker_compose_config',
|
|
312
|
+
description: 'Render the fully resolved compose configuration for inspection.',
|
|
313
|
+
inputSchema: baseParams({ ...cwdParam, ...grepParam }, ['cwd'])
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
name: 'docker_compose_exec',
|
|
317
|
+
description: 'Run one process inside a compose service container without shell expansion. REQUIRES CONFIRMATION unless the final command is whitelisted.',
|
|
318
|
+
inputSchema: baseParams({
|
|
319
|
+
...cwdParam,
|
|
320
|
+
service: { type: 'string' },
|
|
321
|
+
command: { type: 'string' },
|
|
322
|
+
args: { type: 'array', items: { type: 'string' } },
|
|
323
|
+
user: { type: 'string' },
|
|
324
|
+
...confirmationParams
|
|
325
|
+
}, ['cwd', 'service', 'command'])
|
|
326
|
+
},
|
|
234
327
|
{
|
|
235
328
|
name: 'docker_ps',
|
|
236
329
|
description: 'List docker containers.',
|
|
@@ -311,6 +404,20 @@ export const toolDefinitions = [
|
|
|
311
404
|
description: 'Save one or more images to a tar archive. REQUIRES CONFIRMATION.',
|
|
312
405
|
inputSchema: baseParams({ image: { type: 'string' }, path: { type: 'string' }, ...confirmationParams }, ['image', 'path'])
|
|
313
406
|
},
|
|
407
|
+
{
|
|
408
|
+
name: 'docker_build',
|
|
409
|
+
description: 'Build a docker image from a build context. Supports options such as tag, dockerfile, build args, no-cache, and fixed host networking. REQUIRES CONFIRMATION unless the final command is whitelisted.',
|
|
410
|
+
inputSchema: baseParams({
|
|
411
|
+
...cwdParam,
|
|
412
|
+
context: { type: 'string' },
|
|
413
|
+
tag: { type: 'string' },
|
|
414
|
+
dockerfile: { type: 'string' },
|
|
415
|
+
buildArgs: { type: 'array', items: { type: 'string' } },
|
|
416
|
+
noCache: { type: 'boolean' },
|
|
417
|
+
networkHost: { type: 'boolean' },
|
|
418
|
+
...confirmationParams
|
|
419
|
+
}, ['context'])
|
|
420
|
+
},
|
|
314
421
|
// --- Service & Network (Requirements) ---
|
|
315
422
|
{
|
|
316
423
|
name: 'systemctl_status',
|
|
@@ -332,15 +439,43 @@ export const toolDefinitions = [
|
|
|
332
439
|
description: 'Stop system service. REQUIRES CONFIRMATION.',
|
|
333
440
|
inputSchema: baseParams({ service: { type: 'string' }, ...confirmationParams }, ['service'])
|
|
334
441
|
},
|
|
442
|
+
{
|
|
443
|
+
name: 'systemctl_enable',
|
|
444
|
+
description: 'Enable system service at boot. REQUIRES CONFIRMATION unless the final command is whitelisted.',
|
|
445
|
+
inputSchema: baseParams({ service: { type: 'string' }, ...confirmationParams }, ['service'])
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
name: 'systemctl_disable',
|
|
449
|
+
description: 'Disable system service at boot. REQUIRES CONFIRMATION unless the final command is whitelisted.',
|
|
450
|
+
inputSchema: baseParams({ service: { type: 'string' }, ...confirmationParams }, ['service'])
|
|
451
|
+
},
|
|
335
452
|
{
|
|
336
453
|
name: 'ip_addr',
|
|
337
454
|
description: 'Show network interface info.',
|
|
338
455
|
inputSchema: baseParams(grepParam)
|
|
339
456
|
},
|
|
457
|
+
{
|
|
458
|
+
name: 'ip_route',
|
|
459
|
+
description: 'Show routing table information.',
|
|
460
|
+
inputSchema: baseParams(grepParam)
|
|
461
|
+
},
|
|
462
|
+
{
|
|
463
|
+
name: 'mount',
|
|
464
|
+
description: 'Show mounted filesystems.',
|
|
465
|
+
inputSchema: baseParams(grepParam)
|
|
466
|
+
},
|
|
340
467
|
{
|
|
341
468
|
name: 'journalctl',
|
|
342
|
-
description: 'Read systemd journal logs with optional unit, since,
|
|
343
|
-
inputSchema: baseParams({
|
|
469
|
+
description: 'Read systemd journal logs with optional unit, since, until, priority, and follow filters.',
|
|
470
|
+
inputSchema: baseParams({
|
|
471
|
+
unit: { type: 'string' },
|
|
472
|
+
lines: { type: 'number' },
|
|
473
|
+
since: { type: 'string' },
|
|
474
|
+
until: { type: 'string' },
|
|
475
|
+
priority: { type: 'string' },
|
|
476
|
+
follow: { type: 'boolean' },
|
|
477
|
+
grep: { type: 'string' }
|
|
478
|
+
})
|
|
344
479
|
},
|
|
345
480
|
{
|
|
346
481
|
name: 'firewall_cmd',
|
|
@@ -415,11 +550,41 @@ export const toolDefinitions = [
|
|
|
415
550
|
description: 'System disk usage.',
|
|
416
551
|
inputSchema: baseParams(grepParam)
|
|
417
552
|
},
|
|
553
|
+
{
|
|
554
|
+
name: 'df_inode',
|
|
555
|
+
description: 'Filesystem inode usage.',
|
|
556
|
+
inputSchema: baseParams(grepParam)
|
|
557
|
+
},
|
|
418
558
|
{
|
|
419
559
|
name: 'du_sh',
|
|
420
560
|
description: 'Directory size estimation.',
|
|
421
561
|
inputSchema: baseParams({ path: { type: 'string' }, ...grepParam }, ['path'])
|
|
422
562
|
},
|
|
563
|
+
{
|
|
564
|
+
name: 'which',
|
|
565
|
+
description: 'Resolve the executable path of a command available on the remote host.',
|
|
566
|
+
inputSchema: baseParams({ commandName: { type: 'string' }, ...grepParam }, ['commandName'])
|
|
567
|
+
},
|
|
568
|
+
{
|
|
569
|
+
name: 'lsof',
|
|
570
|
+
description: 'Inspect open files, ports, and process-file relationships.',
|
|
571
|
+
inputSchema: baseParams({
|
|
572
|
+
path: { type: 'string' },
|
|
573
|
+
process: { type: 'string' },
|
|
574
|
+
port: { type: 'number' },
|
|
575
|
+
...grepParam
|
|
576
|
+
})
|
|
577
|
+
},
|
|
578
|
+
{
|
|
579
|
+
name: 'file',
|
|
580
|
+
description: 'Detect file type and encoding information.',
|
|
581
|
+
inputSchema: baseParams({ path: { type: 'string' }, ...grepParam }, ['path'])
|
|
582
|
+
},
|
|
583
|
+
{
|
|
584
|
+
name: 'stat',
|
|
585
|
+
description: 'File metadata inspection: Shows size, timestamps, mode bits, and related file details.',
|
|
586
|
+
inputSchema: baseParams({ filePath: { type: 'string' }, ...grepParam }, ['filePath'])
|
|
587
|
+
},
|
|
423
588
|
{
|
|
424
589
|
name: 'chmod',
|
|
425
590
|
description: 'Change file mode bits. REQUIRES CONFIRMATION unless the final command is whitelisted.',
|
package/dist/tools/handlers.js
CHANGED
|
@@ -17,8 +17,11 @@ const WRITE_TOOLS = [
|
|
|
17
17
|
'docker_compose_down',
|
|
18
18
|
'docker_compose_stop',
|
|
19
19
|
'docker_compose_restart',
|
|
20
|
+
'docker_compose_pull',
|
|
21
|
+
'docker_compose_exec',
|
|
20
22
|
'docker_exec',
|
|
21
23
|
'docker_pull',
|
|
24
|
+
'docker_build',
|
|
22
25
|
'docker_cp',
|
|
23
26
|
'docker_stop',
|
|
24
27
|
'docker_rm',
|
|
@@ -31,6 +34,8 @@ const WRITE_TOOLS = [
|
|
|
31
34
|
'systemctl_restart',
|
|
32
35
|
'systemctl_start',
|
|
33
36
|
'systemctl_stop',
|
|
37
|
+
'systemctl_enable',
|
|
38
|
+
'systemctl_disable',
|
|
34
39
|
'firewall_cmd',
|
|
35
40
|
'kill_process',
|
|
36
41
|
'chmod',
|
|
@@ -117,6 +122,14 @@ export class ToolHandlers {
|
|
|
117
122
|
this.validateShellToken(value, `${fieldName}[${index}]`);
|
|
118
123
|
}
|
|
119
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Validate positive line counts for text inspection helpers.
|
|
127
|
+
*/
|
|
128
|
+
validatePositiveInteger(value, fieldName) {
|
|
129
|
+
if (!Number.isInteger(value) || value <= 0) {
|
|
130
|
+
throw new Error(`${fieldName} must be a positive integer.`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
120
133
|
escapePerlEnvBase64(value) {
|
|
121
134
|
return Buffer.from(value).toString('base64');
|
|
122
135
|
}
|
|
@@ -212,11 +225,37 @@ export class ToolHandlers {
|
|
|
212
225
|
if ((name === 'netstat' || name === 'ss') && Array.isArray(params.args)) {
|
|
213
226
|
this.validateTokenArray(params.args, `${name}.args`);
|
|
214
227
|
}
|
|
228
|
+
if ((name === 'head' || name === 'tail') && params.lines !== undefined) {
|
|
229
|
+
this.validatePositiveInteger(params.lines, `${name}.lines`);
|
|
230
|
+
}
|
|
231
|
+
if (name === 'find' && params.maxDepth !== undefined) {
|
|
232
|
+
this.validatePositiveInteger(params.maxDepth, 'find.maxDepth');
|
|
233
|
+
}
|
|
234
|
+
if (name === 'sed') {
|
|
235
|
+
this.validatePositiveInteger(params.startLine, 'sed.startLine');
|
|
236
|
+
this.validatePositiveInteger(params.endLine, 'sed.endLine');
|
|
237
|
+
if (params.endLine < params.startLine) {
|
|
238
|
+
throw new Error(`sed.endLine must be greater than or equal to sed.startLine.`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
215
241
|
if (name === 'docker_exec' && Array.isArray(params.args)) {
|
|
216
242
|
for (const [index, arg] of params.args.entries()) {
|
|
217
243
|
this.validateShellFragment(arg, `docker_exec.args[${index}]`);
|
|
218
244
|
}
|
|
219
245
|
}
|
|
246
|
+
if (name === 'docker_compose_exec' && Array.isArray(params.args)) {
|
|
247
|
+
for (const [index, arg] of params.args.entries()) {
|
|
248
|
+
this.validateShellFragment(arg, `docker_compose_exec.args[${index}]`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (name === 'docker_build') {
|
|
252
|
+
if (params.tag) {
|
|
253
|
+
this.validateShellToken(params.tag, 'docker_build.tag');
|
|
254
|
+
}
|
|
255
|
+
for (const [index, buildArg] of (params.buildArgs || []).entries()) {
|
|
256
|
+
this.validateShellFragment(buildArg, `docker_build.buildArgs[${index}]`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
220
259
|
if ((name === 'tar_create' || name === 'zip') && Array.isArray(params.sourcePaths)) {
|
|
221
260
|
if (params.sourcePaths.length === 0) {
|
|
222
261
|
throw new Error(`${name}.sourcePaths must contain at least one path.`);
|
|
@@ -236,13 +275,29 @@ export class ToolHandlers {
|
|
|
236
275
|
getCommandForTool(name, params) {
|
|
237
276
|
switch (name) {
|
|
238
277
|
case 'get_system_info': return 'echo "USER: $(whoami)"; echo "UPTIME: $(uptime)"; echo "KERNEL: $(uname -a)"; echo "MEMORY:"; free -m';
|
|
278
|
+
case 'hostname': return 'hostname';
|
|
279
|
+
case 'id': return 'id';
|
|
280
|
+
case 'uname': return `uname ${params.all === false ? '-s' : '-a'}`;
|
|
281
|
+
case 'uptime': return 'uptime';
|
|
282
|
+
case 'free': return 'free -m';
|
|
283
|
+
case 'env': return 'env';
|
|
239
284
|
case 'check_dependencies': return `for cmd in ${params.commands.map((cmd) => this.shellEscape(cmd)).join(' ')}; do which "$cmd" || echo "$cmd not found"; done`;
|
|
240
285
|
case 'pwd': return 'pwd';
|
|
241
286
|
case 'cd': return `cd ${this.shellEscape(params.path)}`;
|
|
242
|
-
case 'll': return
|
|
287
|
+
case 'll': return `ls -l${params.all ? 'a' : ''}`;
|
|
243
288
|
case 'cat': return `cat ${this.shellEscape(params.filePath)}`;
|
|
289
|
+
case 'head': return `head -n ${params.lines || 40} ${this.shellEscape(params.filePath)}`;
|
|
244
290
|
case 'tail': return `tail -n ${params.lines || 50} ${this.shellEscape(params.filePath)}`;
|
|
291
|
+
case 'sed': return `sed -n '${params.startLine},${params.endLine}p' ${this.shellEscape(params.filePath)}`;
|
|
245
292
|
case 'grep': return `grep ${params.ignoreCase ? '-inE' : '-nE'} ${this.shellEscape(params.pattern)} ${this.shellEscape(params.filePath)}`;
|
|
293
|
+
case 'grep_r': {
|
|
294
|
+
const includeArgs = (params.include || []).map((value) => ` --include ${this.shellEscape(value)}`).join('');
|
|
295
|
+
const excludeDirArgs = (params.excludeDir || []).map((value) => ` --exclude-dir ${this.shellEscape(value)}`).join('');
|
|
296
|
+
const contextArgs = params.context !== undefined
|
|
297
|
+
? ` -C ${params.context}`
|
|
298
|
+
: `${params.beforeContext !== undefined ? ` -B ${params.beforeContext}` : ''}${params.afterContext !== undefined ? ` -A ${params.afterContext}` : ''}`;
|
|
299
|
+
return `grep ${params.ignoreCase ? '-RinE' : '-RnE'}${contextArgs}${includeArgs}${excludeDirArgs} ${this.shellEscape(params.pattern)} ${this.shellEscape(params.path)}`;
|
|
300
|
+
}
|
|
246
301
|
case 'edit_text_file':
|
|
247
302
|
const edB64 = Buffer.from(params.content).toString('base64');
|
|
248
303
|
return `printf '%s' ${this.shellEscape(edB64)} | base64 -d > ${this.shellEscape(params.filePath)}`;
|
|
@@ -265,7 +320,8 @@ export class ToolHandlers {
|
|
|
265
320
|
throw new Error(`RM_SAFE: Denied for restricted directory.`);
|
|
266
321
|
return `rm ${params.recursive ? '-rf' : '-f'} ${this.shellEscape(params.path)}`;
|
|
267
322
|
case 'echo': return `echo ${this.shellEscape(params.text)}`;
|
|
268
|
-
case 'find':
|
|
323
|
+
case 'find':
|
|
324
|
+
return `find ${this.shellEscape(params.path)}${params.maxDepth !== undefined ? ` -maxdepth ${params.maxDepth}` : ''}${params.type ? ` -type ${params.type}` : ''}${params.name ? ` -name ${this.shellEscape(params.name)}` : ''}${params.pathPattern ? ` -path ${this.shellEscape(params.pathPattern)}` : ''}`;
|
|
269
325
|
case 'git_status': return 'git status';
|
|
270
326
|
case 'git_fetch': return `git fetch ${params.all ? '--all ' : ''}${params.prune ? '--prune' : ''}`.trim();
|
|
271
327
|
case 'git_pull': return 'git pull --no-edit';
|
|
@@ -285,6 +341,11 @@ export class ToolHandlers {
|
|
|
285
341
|
case 'docker_compose_stop': return 'docker-compose stop';
|
|
286
342
|
case 'docker_compose_logs': return `docker-compose logs -n ${params.lines || 100}`;
|
|
287
343
|
case 'docker_compose_restart': return 'docker-compose restart';
|
|
344
|
+
case 'docker_compose_pull': return `docker-compose pull${params.service ? ` ${this.shellEscape(params.service)}` : ''}`;
|
|
345
|
+
case 'docker_compose_ps': return `docker-compose ps${params.service ? ` ${this.shellEscape(params.service)}` : ''}`;
|
|
346
|
+
case 'docker_compose_config': return 'docker-compose config';
|
|
347
|
+
case 'docker_compose_exec':
|
|
348
|
+
return `docker-compose exec -T${params.user ? ` --user ${this.shellEscape(params.user)}` : ''} ${this.shellEscape(params.service)} ${this.shellEscape(params.command)}${params.args?.length ? ` ${this.shellEscapeList(params.args)}` : ''}`;
|
|
288
349
|
case 'docker_ps': return 'docker ps';
|
|
289
350
|
case 'docker_images': return 'docker images';
|
|
290
351
|
case 'docker_exec':
|
|
@@ -304,13 +365,21 @@ export class ToolHandlers {
|
|
|
304
365
|
case 'docker_logs': return `docker logs -n ${params.lines || 100} ${this.shellEscape(params.container)}`;
|
|
305
366
|
case 'docker_load': return `docker load -i ${this.shellEscape(params.path)}`;
|
|
306
367
|
case 'docker_save': return `docker save -o ${this.shellEscape(params.path)} ${this.shellEscape(params.image)}`;
|
|
368
|
+
case 'docker_build': {
|
|
369
|
+
const buildArgs = (params.buildArgs || []).map((value) => ` --build-arg ${this.shellEscape(value)}`).join('');
|
|
370
|
+
return `docker build${params.tag ? ` -t ${this.shellEscape(params.tag)}` : ''}${params.dockerfile ? ` -f ${this.shellEscape(params.dockerfile)}` : ''}${params.noCache ? ' --no-cache' : ''}${params.networkHost ? ' --network=host' : ''}${buildArgs} ${this.shellEscape(params.context)}`;
|
|
371
|
+
}
|
|
307
372
|
case 'systemctl_status': return `systemctl status ${this.shellEscape(params.service)}`;
|
|
308
373
|
case 'systemctl_restart': return `systemctl restart ${this.shellEscape(params.service)}`;
|
|
309
374
|
case 'systemctl_start': return `systemctl start ${this.shellEscape(params.service)}`;
|
|
310
375
|
case 'systemctl_stop': return `systemctl stop ${this.shellEscape(params.service)}`;
|
|
376
|
+
case 'systemctl_enable': return `systemctl enable ${this.shellEscape(params.service)}`;
|
|
377
|
+
case 'systemctl_disable': return `systemctl disable ${this.shellEscape(params.service)}`;
|
|
311
378
|
case 'ip_addr': return 'ip addr';
|
|
379
|
+
case 'ip_route': return 'ip route';
|
|
380
|
+
case 'mount': return 'mount';
|
|
312
381
|
case 'journalctl':
|
|
313
|
-
return `journalctl --no-pager${params.unit ? ` -u ${this.shellEscape(params.unit)}` : ''}${params.priority ? ` -p ${this.shellEscape(params.priority)}` : ''}${params.since ? ` --since ${this.shellEscape(params.since)}` : ''} -n ${params.lines || 100}`;
|
|
382
|
+
return `journalctl --no-pager${params.unit ? ` -u ${this.shellEscape(params.unit)}` : ''}${params.priority ? ` -p ${this.shellEscape(params.priority)}` : ''}${params.since ? ` --since ${this.shellEscape(params.since)}` : ''}${params.until ? ` --until ${this.shellEscape(params.until)}` : ''}${params.follow ? ' -f' : ''} -n ${params.lines || 100}`;
|
|
314
383
|
case 'firewall_cmd':
|
|
315
384
|
return this.buildFirewallCommand(params);
|
|
316
385
|
case 'netstat':
|
|
@@ -336,7 +405,13 @@ export class ToolHandlers {
|
|
|
336
405
|
return common;
|
|
337
406
|
}
|
|
338
407
|
case 'df_h': return 'df -h';
|
|
408
|
+
case 'df_inode': return 'df -i';
|
|
339
409
|
case 'du_sh': return `du -sh ${this.shellEscape(params.path)}`;
|
|
410
|
+
case 'which': return `which ${this.shellEscape(params.commandName)}`;
|
|
411
|
+
case 'lsof':
|
|
412
|
+
return `lsof${params.path ? ` ${this.shellEscape(params.path)}` : ''}${params.process ? ` -c ${this.shellEscape(params.process)}` : ''}${params.port !== undefined ? ` -i :${params.port}` : ''}`;
|
|
413
|
+
case 'file': return `file ${this.shellEscape(params.path)}`;
|
|
414
|
+
case 'stat': return `stat ${this.shellEscape(params.filePath)}`;
|
|
340
415
|
case 'nvidia_smi': return 'nvidia-smi';
|
|
341
416
|
case 'ps': return 'ps aux';
|
|
342
417
|
case 'pgrep': return `pgrep ${params.fullCommand ? '-af ' : '-a '}${this.shellEscape(params.pattern)}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jadchene/mcp-ssh-service",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.2",
|
|
4
4
|
"description": "A production-ready, highly secure SSH MCP server featuring stateless connections, two-step operation confirmation, and comprehensive DevOps tool integration.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|