ssh-mcp 1.4.0 → 1.5.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.md CHANGED
@@ -44,11 +44,13 @@
44
44
  - `exec`: Execute a shell command on the remote server
45
45
  - **Parameters:**
46
46
  - `command` (required): Shell command to execute on the remote SSH server
47
+ - `description` (optional): Optional description of what this command will do (appended as a comment)
47
48
  - **Timeout Configuration:**
48
49
 
49
50
  - `sudo-exec`: Execute a shell command with sudo elevation
50
51
  - **Parameters:**
51
52
  - `command` (required): Shell command to execute as root using sudo
53
+ - `description` (optional): Optional description of what this command will do (appended as a comment)
52
54
  - **Notes:**
53
55
  - Requires `--sudoPassword` to be set for password-protected sudo
54
56
  - Can be disabled by passing the `--disableSudo` flag at startup if sudo access is not needed or not available
package/build/index.js CHANGED
@@ -302,7 +302,7 @@ export class SSHConnectionManager {
302
302
  let connectionManager = null;
303
303
  const server = new McpServer({
304
304
  name: 'SSH MCP Server',
305
- version: '1.4.0',
305
+ version: '1.5.0',
306
306
  capabilities: {
307
307
  resources: {},
308
308
  tools: {},
@@ -310,7 +310,8 @@ const server = new McpServer({
310
310
  });
311
311
  server.tool("exec", "Execute a shell command on the remote SSH server and return the output.", {
312
312
  command: z.string().describe("Shell command to execute on the remote SSH server"),
313
- }, async ({ command }) => {
313
+ description: z.string().optional().describe("Optional description of what this command will do"),
314
+ }, async ({ command, description }) => {
314
315
  // Sanitize command input
315
316
  const sanitizedCommand = sanitizeCommand(command);
316
317
  try {
@@ -354,7 +355,11 @@ server.tool("exec", "Execute a shell command on the remote SSH server and return
354
355
  // Log but don't fail; fall back to non-elevated execution if elevation times out
355
356
  }
356
357
  }
357
- const result = await execSshCommandWithConnection(connectionManager, sanitizedCommand);
358
+ // Append description as comment if provided
359
+ const commandWithDescription = description
360
+ ? `${sanitizedCommand} # ${description.replace(/#/g, '\\#')}`
361
+ : sanitizedCommand;
362
+ const result = await execSshCommandWithConnection(connectionManager, commandWithDescription);
358
363
  return result;
359
364
  }
360
365
  catch (err) {
@@ -368,7 +373,8 @@ server.tool("exec", "Execute a shell command on the remote SSH server and return
368
373
  if (!DISABLE_SUDO) {
369
374
  server.tool("sudo-exec", "Execute a shell command on the remote SSH server using sudo. Will use sudo password if provided, otherwise assumes passwordless sudo.", {
370
375
  command: z.string().describe("Shell command to execute with sudo on the remote SSH server"),
371
- }, async ({ command }) => {
376
+ description: z.string().optional().describe("Optional description of what this command will do"),
377
+ }, async ({ command, description }) => {
372
378
  const sanitizedCommand = sanitizeCommand(command);
373
379
  try {
374
380
  if (!connectionManager) {
@@ -409,15 +415,19 @@ if (!DISABLE_SUDO) {
409
415
  }
410
416
  let wrapped;
411
417
  const sudoPassword = connectionManager.getSudoPassword();
418
+ // Append description as comment if provided
419
+ const commandWithDescription = description
420
+ ? `${sanitizedCommand} # ${description.replace(/#/g, '\\#')}`
421
+ : sanitizedCommand;
412
422
  if (!sudoPassword) {
413
423
  // No password provided, use -n to fail if sudo requires a password
414
- wrapped = `sudo -n sh -c '${sanitizedCommand.replace(/'/g, "'\\''")}'`;
424
+ wrapped = `sudo -n sh -c '${commandWithDescription.replace(/'/g, "'\\''")}'`;
415
425
  }
416
426
  else {
417
427
  // Password provided — pipe it into sudo using printf. This avoids complex
418
428
  // PTY/stdin handling on the SSH channel and is simpler and more reliable.
419
429
  const pwdEscaped = sudoPassword.replace(/'/g, "'\\''");
420
- wrapped = `printf '%s\\n' '${pwdEscaped}' | sudo -p "" -S sh -c '${sanitizedCommand.replace(/'/g, "'\\''")}'`;
430
+ wrapped = `printf '%s\\n' '${pwdEscaped}' | sudo -p "" -S sh -c '${commandWithDescription.replace(/'/g, "'\\''")}'`;
421
431
  }
422
432
  return await execSshCommandWithConnection(connectionManager, wrapped);
423
433
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ssh-mcp",
3
3
  "license": "MIT",
4
- "version": "1.4.0",
4
+ "version": "1.5.0",
5
5
  "description": "MCP server exposing SSH control for Linux and Windows systems via Model Context Protocol.",
6
6
  "type": "module",
7
7
  "bin": {