Skip to main content
Glama
vilasone455

SSH MCP Server

by vilasone455

secure_execute_command

Execute read-only shell commands on remote systems via SSH to retrieve output without modifying state.

Instructions

Run a read‑only shell command (i.e., one that does not mutate state) in an existing SSH session and return stdout/stderr/exitCode.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
connection_idYes
commandYesRead‑only shell command to execute (e.g., ls, cat).

Implementation Reference

  • The handler logic for the 'secure_execute_command' tool. Extracts arguments, validates connection and command, performs security check with isCommandDangerous, executes the command via wrapExec on the SSH client, and returns stdout, stderr, exitCode.
    if (name === "secure_execute_command") {
      const { connection_id, command } = args;
      if (!command?.trim()) throw new Error("Command cannot be empty.");
      const conn = connections.get(connection_id);
      if (!conn) throw new Error(`connection_id '${connection_id}' not found.`);
    
      // More refined security check - focus on actually dangerous operations
      if (isCommandDangerous(command)) {
        throw new Error("Command contains potentially dangerous operations and is not allowed.");
      }
    
      const { stdout, stderr, exitCode } = await wrapExec(conn.client, command);
      return {
        content: [
          {
            type: "text",
            text: JSON.stringify({ stdout, stderr, exitCode }, null, 2),
          },
        ],
      };
    
    }
  • The input schema definition for the 'secure_execute_command' tool, advertised in the ListTools response.
    {
      name: "secure_execute_command",
      description:
        "Run a **read‑only** shell command (i.e., one that does not mutate state) in an existing SSH session and return stdout/stderr/exitCode.",
      inputSchema: {
        type: "object",
        required: ["connection_id", "command"],
        properties: {
          connection_id: { type: "string" },
          command: { type: "string", description: "Read‑only shell command to execute (e.g., ls, cat)." },
        },
        additionalProperties: false,
      },
    },
  • src/index.ts:140-207 (registration)
    Registration of the tool via the ListToolsRequestSchema handler, which includes 'secure_execute_command' in the list of available tools.
    server.setRequestHandler(ListToolsRequestSchema, async () => ({
      tools: [
        {
          name: "get_available_connections",
          description:
            "List every SSH-capable machine this server knows about (but is NOT yet connected).",
          inputSchema: { type: "object", properties: {}, additionalProperties: false },
        },
        {
          name: "create_connection",
          description:
            "Open an SSH session to the given machine and track it in global state so subsequent tool calls can reuse it.",
          inputSchema: {
            type: "object",
            required: ["machine_id", "title"],
            properties: {
              machine_id: { type: "string", description: "ID from get_available_connections" },
              title: { type: "string", description: "Purpose of this session (displayed in UIs)" },
            },
            additionalProperties: false,
          },
        },
        {
          name: "get_connections",
          description: "Return every STILL-OPEN SSH session in global state.",
          inputSchema: { type: "object", properties: {}, additionalProperties: false },
        },
        {
          name: "execute_command",
          description:
            "Run a shell command in an existing SSH session and return stdout/stderr/exitCode.",
          inputSchema: {
            type: "object",
            required: ["connection_id", "command"],
            properties: {
              connection_id: { type: "string" },
              command: { type: "string", description: "Shell command to execute" },
            },
            additionalProperties: false,
          },
        },
        {
          name: "secure_execute_command",
          description:
            "Run a **read‑only** shell command (i.e., one that does not mutate state) in an existing SSH session and return stdout/stderr/exitCode.",
          inputSchema: {
            type: "object",
            required: ["connection_id", "command"],
            properties: {
              connection_id: { type: "string" },
              command: { type: "string", description: "Read‑only shell command to execute (e.g., ls, cat)." },
            },
            additionalProperties: false,
          },
        },
    
        {
          name: "close_connection",
          description: "Terminate an SSH session and remove it from global state.",
          inputSchema: {
            type: "object",
            required: ["connection_id"],
            properties: { connection_id: { type: "string" } },
            additionalProperties: false,
          },
        },
      ],
    }));
  • Helper function specifically used by secure_execute_command to validate if a command is safe (read-only) by checking against whitelisted read-only patterns and blacklisted dangerous regex patterns.
    function isCommandDangerous(command) {
      const cmd = command.trim().toLowerCase();
    
      // Allow common read-only systemctl operations
      if (/^systemctl\s+(status|show|list-units|list-unit-files|is-active|is-enabled|is-failed|cat|help)/.test(cmd)) {
        return false;
      }
    
      // Allow read-only git operations
      if (/^git\s+(status|log|show|diff|branch|remote|config\s+--list|ls-files|ls-remote)/.test(cmd)) {
        return false;
      }
    
      // Allow read-only package manager operations
      if (/^(apt|yum|dnf|pacman)\s+(list|search|show|info|query)/.test(cmd)) {
        return false;
      }
    
      // Allow read-only docker operations
      if (/^docker\s+(ps|images|inspect|logs|version|info|system\s+df|system\s+info)/.test(cmd)) {
        return false;
      }
    
      // Allow read-only kubectl operations
      if (/^kubectl\s+(get|describe|logs|explain|version|cluster-info|config\s+view)/.test(cmd)) {
        return false;
      }
    
      // Check for actually dangerous patterns
      const dangerousPatterns = [
        // File system destructive operations
        /\brm\s+(-[rf]*\s+)*(\/|\*|\$|~)/,  // rm with dangerous targets
        /\bmv\s+.*\s+(\/|\*)/,               // mv to dangerous locations
        /\bchmod\s+[0-7]*\s+(\/|~|\*)/,      // chmod on system locations
        /\bchown\s+.*\s+(\/|~|\*)/,          // chown on system locations
    
        // Output redirection that could overwrite files
        />[^|&]*\s*(\/|~|\*)/,               // Redirect to system locations
        /\bdd\s+.*of=/,                      // dd operations
        /\btruncate\s/,                      // truncate files
    
        // Process/service management (destructive)
        /\b(systemctl|service)\s+(stop|start|restart|disable|enable|mask|reload)/,
        /\b(kill|pkill|killall)\s/,
    
        // Package management (installation/removal)
        /\b(apt|yum|dnf|pacman)\s+(install|remove|update|upgrade|autoremove)/,
    
        // Network configuration
        /\b(iptables|ufw|firewall-cmd)\s/,
        /\bifconfig\s+.*\s+(up|down)/,
    
        // User/system modification
        /\b(useradd|userdel|usermod|passwd|su\s|sudo\s)/,
        /\bcrontab\s+-[er]/,
    
        // Dangerous git operations
        /\bgit\s+(push|pull|clone|reset\s+--hard|clean\s+-f|rm)/,
    
        // Container/orchestration destructive operations
        /\bdocker\s+(rm|rmi|kill|stop|exec|run|build|push|pull)/,
        /\bkubectl\s+(delete|apply|create|replace|patch|scale|rollout)/,
    
        // Text editors (could modify files)
        /\b(nano|vi|vim|emacs|code)\s/,
    
        // Archive operations that could overwrite
        /\b(tar|unzip|unrar)\s+.*-[xf]/,
    
        // System monitoring that could be used maliciously
        /\btcpdump\s/,
        /\bwireshark\s/,
    
        // Compilation (could create executables)
        /\b(gcc|g\+\+|make|cmake|javac|python\s+setup\.py\s+install)/,
    
        // Background processes
        /&\s*$/,                             // Commands ending with &
        /\bnohup\s/,
    
        // Pipes to dangerous commands
        /\|\s*(sh|bash|zsh|csh|tcsh|fish|python|perl|ruby|node)/,
      ];
    
      // Check against dangerous patterns
      return dangerousPatterns.some(pattern => pattern.test(cmd));
    }
  • Shared helper function to execute a command over SSH, capturing stdout, stderr, and exit code. Used by both execute_command and secure_execute_command.
    function wrapExec(client, command): any {
      return new Promise((resolve, reject) => {
        let stdout = "";
        let stderr = "";
        client.exec(command, (err, stream) => {
          if (err) return reject(err);
          stream
            .on("close", (code) => {
              resolve({ stdout, stderr, exitCode: code });
            })
            .on("data", (data) => {
              stdout += data.toString();
            })
            .stderr.on("data", (data) => {
              stderr += data.toString();
            });
        });
      });
    }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/vilasone455/ssh-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server