@jadchene/mcp-ssh-service 1.4.1 → 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 CHANGED
@@ -189,11 +189,22 @@ 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 (17)
207
+ ### File Management (18)
197
208
  * `upload_file` [Auth Required]
198
209
  * `download_file`
199
210
  * `ll`
@@ -202,6 +213,7 @@ args = ["--config", "./config.json"]
202
213
  * `tail`
203
214
  * `sed`
204
215
  * `grep`
216
+ * `grep_r`
205
217
  * `edit_text_file` [Auth Required]
206
218
  * `touch`
207
219
  * `mkdir` [Auth Required]
@@ -220,12 +232,16 @@ args = ["--config", "./config.json"]
220
232
  * `git_branch`
221
233
  * `git_log`
222
234
 
223
- ### Docker & Compose (21)
235
+ ### Docker & Compose (26)
224
236
  * `docker_compose_up` [Auth Required]
225
237
  * `docker_compose_down` [Auth Required]
226
238
  * `docker_compose_stop` [Auth Required]
227
239
  * `docker_compose_logs`
228
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]
229
245
  * `docker_ps`
230
246
  * `docker_images`
231
247
  * `docker_exec` [Auth Required]
@@ -242,13 +258,18 @@ args = ["--config", "./config.json"]
242
258
  * `docker_logs`
243
259
  * `docker_load` [Auth Required]
244
260
  * `docker_save` [Auth Required]
261
+ * `docker_build` [Auth Required, supports `networkHost` for `--network=host`]
245
262
 
246
- ### Service & Network (14)
263
+ ### Service & Network (18)
247
264
  * `systemctl_status`
248
265
  * `systemctl_restart` [Auth Required]
249
266
  * `systemctl_start` [Auth Required]
250
267
  * `systemctl_stop` [Auth Required]
268
+ * `systemctl_enable` [Auth Required]
269
+ * `systemctl_disable` [Auth Required]
251
270
  * `ip_addr`
271
+ * `ip_route`
272
+ * `mount`
252
273
  * `journalctl`
253
274
  * `firewall_cmd` [Auth Required, structured actions only]
254
275
  * `netstat` [uses `args: string[]`]
@@ -259,13 +280,18 @@ args = ["--config", "./config.json"]
259
280
  * `dig`
260
281
  * `curl_http` [Auth Required]
261
282
 
262
- ### Stats & Process (13)
283
+ ### Stats & Process (19)
263
284
  * `nvidia_smi`
264
285
  * `ps`
265
286
  * `pgrep`
266
287
  * `kill_process` [Auth Required]
267
288
  * `df_h`
289
+ * `df_inode`
268
290
  * `du_sh`
291
+ * `which`
292
+ * `lsof`
293
+ * `file`
294
+ * `stat`
269
295
  * `chmod` [Auth Required]
270
296
  * `chown` [Auth Required]
271
297
  * `ln` [Auth Required]
@@ -274,7 +300,7 @@ args = ["--config", "./config.json"]
274
300
  * `zip` [Auth Required]
275
301
  * `unzip` [Auth Required]
276
302
 
277
- Total: 81 tools.
303
+ Total: 103 tools.
278
304
 
279
305
  ---
280
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,7 +138,7 @@ 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',
@@ -140,6 +170,20 @@ export const toolDefinitions = [
140
170
  description: 'Pattern search: Search for a regex pattern in a file.',
141
171
  inputSchema: baseParams({ filePath: { type: 'string' }, pattern: { type: 'string' }, ignoreCase: { type: 'boolean' } }, ['filePath', 'pattern'])
142
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
+ },
143
187
  {
144
188
  name: 'edit_text_file',
145
189
  description: 'File creation/overwrite: Completely replaces file content. REQUIRES CONFIRMATION.',
@@ -187,7 +231,14 @@ export const toolDefinitions = [
187
231
  {
188
232
  name: 'find',
189
233
  description: 'Search for files in a directory hierarchy.',
190
- inputSchema: baseParams({ path: { type: 'string' }, name: { type: 'string' }, ...grepParam }, ['path'])
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'])
191
242
  },
192
243
  // --- Git ---
193
244
  {
@@ -246,6 +297,33 @@ export const toolDefinitions = [
246
297
  description: 'Restart compose stack. REQUIRES CONFIRMATION.',
247
298
  inputSchema: baseParams({ ...cwdParam, ...confirmationParams }, ['cwd'])
248
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
+ },
249
327
  {
250
328
  name: 'docker_ps',
251
329
  description: 'List docker containers.',
@@ -326,6 +404,20 @@ export const toolDefinitions = [
326
404
  description: 'Save one or more images to a tar archive. REQUIRES CONFIRMATION.',
327
405
  inputSchema: baseParams({ image: { type: 'string' }, path: { type: 'string' }, ...confirmationParams }, ['image', 'path'])
328
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
+ },
329
421
  // --- Service & Network (Requirements) ---
330
422
  {
331
423
  name: 'systemctl_status',
@@ -347,15 +439,43 @@ export const toolDefinitions = [
347
439
  description: 'Stop system service. REQUIRES CONFIRMATION.',
348
440
  inputSchema: baseParams({ service: { type: 'string' }, ...confirmationParams }, ['service'])
349
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
+ },
350
452
  {
351
453
  name: 'ip_addr',
352
454
  description: 'Show network interface info.',
353
455
  inputSchema: baseParams(grepParam)
354
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
+ },
355
467
  {
356
468
  name: 'journalctl',
357
- description: 'Read systemd journal logs with optional unit, since, and priority filters.',
358
- inputSchema: baseParams({ unit: { type: 'string' }, lines: { type: 'number' }, since: { type: 'string' }, priority: { type: 'string' }, grep: { type: 'string' } })
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
+ })
359
479
  },
360
480
  {
361
481
  name: 'firewall_cmd',
@@ -430,11 +550,41 @@ export const toolDefinitions = [
430
550
  description: 'System disk usage.',
431
551
  inputSchema: baseParams(grepParam)
432
552
  },
553
+ {
554
+ name: 'df_inode',
555
+ description: 'Filesystem inode usage.',
556
+ inputSchema: baseParams(grepParam)
557
+ },
433
558
  {
434
559
  name: 'du_sh',
435
560
  description: 'Directory size estimation.',
436
561
  inputSchema: baseParams({ path: { type: 'string' }, ...grepParam }, ['path'])
437
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
+ },
438
588
  {
439
589
  name: 'chmod',
440
590
  description: 'Change file mode bits. REQUIRES CONFIRMATION unless the final command is whitelisted.',
@@ -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',
@@ -223,6 +228,9 @@ export class ToolHandlers {
223
228
  if ((name === 'head' || name === 'tail') && params.lines !== undefined) {
224
229
  this.validatePositiveInteger(params.lines, `${name}.lines`);
225
230
  }
231
+ if (name === 'find' && params.maxDepth !== undefined) {
232
+ this.validatePositiveInteger(params.maxDepth, 'find.maxDepth');
233
+ }
226
234
  if (name === 'sed') {
227
235
  this.validatePositiveInteger(params.startLine, 'sed.startLine');
228
236
  this.validatePositiveInteger(params.endLine, 'sed.endLine');
@@ -235,6 +243,19 @@ export class ToolHandlers {
235
243
  this.validateShellFragment(arg, `docker_exec.args[${index}]`);
236
244
  }
237
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
+ }
238
259
  if ((name === 'tar_create' || name === 'zip') && Array.isArray(params.sourcePaths)) {
239
260
  if (params.sourcePaths.length === 0) {
240
261
  throw new Error(`${name}.sourcePaths must contain at least one path.`);
@@ -254,15 +275,29 @@ export class ToolHandlers {
254
275
  getCommandForTool(name, params) {
255
276
  switch (name) {
256
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';
257
284
  case 'check_dependencies': return `for cmd in ${params.commands.map((cmd) => this.shellEscape(cmd)).join(' ')}; do which "$cmd" || echo "$cmd not found"; done`;
258
285
  case 'pwd': return 'pwd';
259
286
  case 'cd': return `cd ${this.shellEscape(params.path)}`;
260
- case 'll': return 'ls -l';
287
+ case 'll': return `ls -l${params.all ? 'a' : ''}`;
261
288
  case 'cat': return `cat ${this.shellEscape(params.filePath)}`;
262
289
  case 'head': return `head -n ${params.lines || 40} ${this.shellEscape(params.filePath)}`;
263
290
  case 'tail': return `tail -n ${params.lines || 50} ${this.shellEscape(params.filePath)}`;
264
291
  case 'sed': return `sed -n '${params.startLine},${params.endLine}p' ${this.shellEscape(params.filePath)}`;
265
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
+ }
266
301
  case 'edit_text_file':
267
302
  const edB64 = Buffer.from(params.content).toString('base64');
268
303
  return `printf '%s' ${this.shellEscape(edB64)} | base64 -d > ${this.shellEscape(params.filePath)}`;
@@ -285,7 +320,8 @@ export class ToolHandlers {
285
320
  throw new Error(`RM_SAFE: Denied for restricted directory.`);
286
321
  return `rm ${params.recursive ? '-rf' : '-f'} ${this.shellEscape(params.path)}`;
287
322
  case 'echo': return `echo ${this.shellEscape(params.text)}`;
288
- case 'find': return `find ${this.shellEscape(params.path)} -name ${this.shellEscape(params.name)}`;
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)}` : ''}`;
289
325
  case 'git_status': return 'git status';
290
326
  case 'git_fetch': return `git fetch ${params.all ? '--all ' : ''}${params.prune ? '--prune' : ''}`.trim();
291
327
  case 'git_pull': return 'git pull --no-edit';
@@ -305,6 +341,11 @@ export class ToolHandlers {
305
341
  case 'docker_compose_stop': return 'docker-compose stop';
306
342
  case 'docker_compose_logs': return `docker-compose logs -n ${params.lines || 100}`;
307
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)}` : ''}`;
308
349
  case 'docker_ps': return 'docker ps';
309
350
  case 'docker_images': return 'docker images';
310
351
  case 'docker_exec':
@@ -324,13 +365,21 @@ export class ToolHandlers {
324
365
  case 'docker_logs': return `docker logs -n ${params.lines || 100} ${this.shellEscape(params.container)}`;
325
366
  case 'docker_load': return `docker load -i ${this.shellEscape(params.path)}`;
326
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
+ }
327
372
  case 'systemctl_status': return `systemctl status ${this.shellEscape(params.service)}`;
328
373
  case 'systemctl_restart': return `systemctl restart ${this.shellEscape(params.service)}`;
329
374
  case 'systemctl_start': return `systemctl start ${this.shellEscape(params.service)}`;
330
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)}`;
331
378
  case 'ip_addr': return 'ip addr';
379
+ case 'ip_route': return 'ip route';
380
+ case 'mount': return 'mount';
332
381
  case 'journalctl':
333
- 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}`;
334
383
  case 'firewall_cmd':
335
384
  return this.buildFirewallCommand(params);
336
385
  case 'netstat':
@@ -356,7 +405,13 @@ export class ToolHandlers {
356
405
  return common;
357
406
  }
358
407
  case 'df_h': return 'df -h';
408
+ case 'df_inode': return 'df -i';
359
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)}`;
360
415
  case 'nvidia_smi': return 'nvidia-smi';
361
416
  case 'ps': return 'ps aux';
362
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.1",
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",