Skip to main content
Glama

ubuntu_ssl_certificate

Manage SSL certificates on Ubuntu servers using Let's Encrypt. Issue, renew, check status, or list certificates via SSH connection.

Instructions

Manage SSL certificates using Let's Encrypt on Ubuntu

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
connectionIdYesID of an active SSH connection
actionYesAction to perform (issue, renew, status, list)
domainNoDomain name for the certificate (required for issue and renew)
emailNoEmail address for Let's Encrypt notifications (required for issue)
webrootNoWeb root path for domain verification (default: /var/www/html)
sudoNoWhether to run the command with sudo (default: true)

Implementation Reference

  • The main handler function for the ubuntu_ssl_certificate tool. It manages SSL certificates using Certbot on Ubuntu servers via SSH, supporting actions: issue, renew, status, list. Installs Certbot if needed and executes appropriate certbot commands.
    async ubuntu_ssl_certificate(params) {
      const { connectionId, action, domain, email, webroot = '/var/www/html', sudo = true } = params;
      
      try {
        const conn = getConnection(connectionMap, connectionId);
        const sudoPrefix = sudo ? 'sudo ' : '';
        
        // Validate action
        const validActions = ['issue', 'renew', 'status', 'list'];
        if (!validActions.includes(action)) {
          throw new Error(`Invalid action: ${action}. Valid actions are: ${validActions.join(', ')}`);
        }
        
        // Check for required parameters
        if ((action === 'issue' || action === 'renew') && !domain) {
          throw new Error(`Domain name is required for ${action} action`);
        }
        if (action === 'issue' && !email) {
          throw new Error('Email address is required for issue action');
        }
        
        // Ensure certbot is installed
        const checkCertbot = await executeSSHCommand(conn, 'which certbot || echo "not-found"');
        if (checkCertbot.stdout === 'not-found') {
          const installCertbot = await executeSSHCommand(
            conn, 
            `${sudoPrefix}apt-get update && ${sudoPrefix}apt-get install -y certbot python3-certbot-nginx`
          );
          if (installCertbot.code !== 0) {
            throw new Error(`Failed to install certbot: ${installCertbot.stderr}`);
          }
        }
        
        let command = '';
        
        switch (action) {
          case 'issue':
            command = `${sudoPrefix}certbot certonly --webroot -w ${webroot} -d ${domain} --email ${email} --agree-tos --non-interactive`;
            break;
          case 'renew':
            command = domain 
              ? `${sudoPrefix}certbot renew --cert-name ${domain} --force-renewal` 
              : `${sudoPrefix}certbot renew`;
            break;
          case 'status':
            command = domain 
              ? `${sudoPrefix}certbot certificates -d ${domain}` 
              : `${sudoPrefix}certbot certificates`;
            break;
          case 'list':
            command = `${sudoPrefix}certbot certificates`;
            break;
        }
        
        const result = await executeSSHCommand(conn, command);
        
        return {
          content: [{
            type: 'text',
            text: `SSL certificate ${action} result:\n\n${result.stdout || result.stderr}`
          }]
        };
      } catch (error: any) {
        return {
          content: [{ type: 'text', text: `SSL certificate error: ${error.message}` }],
          isError: true
        };
      }
    },
  • Input schema definition for the ubuntu_ssl_certificate tool, defining parameters like connectionId, action, domain, email, etc.
    ubuntu_ssl_certificate: {
      description: 'Manage SSL certificates using Let\'s Encrypt on Ubuntu',
      inputSchema: {
        type: 'object',
        properties: {
          connectionId: {
            type: 'string',
            description: 'ID of an active SSH connection'
          },
          action: {
            type: 'string',
            description: 'Action to perform (issue, renew, status, list)'
          },
          domain: {
            type: 'string',
            description: 'Domain name for the certificate (required for issue and renew)'
          },
          email: {
            type: 'string',
            description: 'Email address for Let\'s Encrypt notifications (required for issue)'
          },
          webroot: {
            type: 'string',
            description: 'Web root path for domain verification (default: /var/www/html)'
          },
          sudo: {
            type: 'boolean',
            description: 'Whether to run the command with sudo (default: true)'
          }
        },
        required: ['connectionId', 'action']
      }
  • src/index.ts:294-296 (registration)
    Registration/dispatch logic in the main CallToolRequestSchema handler that routes calls to ubuntu_ssl_certificate via ubuntuToolHandlers.
    if (toolName.startsWith('ubuntu_') && ubuntuToolHandlers[toolName]) {
      return ubuntuToolHandlers[toolName](request.params.arguments);
    }
  • src/index.ts:179-179 (registration)
    Call to addUbuntuTools which sets up connectionMap and overrides ListToolsRequestSchema to include the tool schema.
    addUbuntuTools(this.server, this.connections);
  • Utility function executeSSHCommand used by the handler to run SSH commands safely with timeout and error handling.
    async function executeSSHCommand(conn: Client, command: string, timeout = 60000): Promise<{
      code: number;
      signal: string;
      stdout: string;
      stderr: string;
    }> {
      return new Promise((resolve, reject) => {
        // Set up timeout
        const timeoutId = setTimeout(() => {
          reject(new Error(`Command execution timed out after ${timeout}ms`));
        }, timeout);
        
        conn.exec(command, {}, (err: Error | undefined, stream: any) => {
          if (err) {
            clearTimeout(timeoutId);
            return reject(new Error(`Failed to execute command: ${err.message}`));
          }
          
          let stdout = '';
          let stderr = '';
          
          stream.on('close', (code: number, signal: string) => {
            clearTimeout(timeoutId);
            resolve({
              code,
              signal,
              stdout: stdout.trim(),
              stderr: stderr.trim()
            });
          });
          
          stream.on('data', (data: Buffer) => {
            stdout += data.toString();
          });
          
          stream.stderr.on('data', (data: Buffer) => {
            stderr += data.toString();
          });
        });
      });
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. While 'manage' implies both read and write operations, it doesn't specify critical behaviors like whether actions are destructive (e.g., 'issue' might overwrite existing certificates), authentication requirements beyond SSH, rate limits for Let's Encrypt, or what the tool outputs. This leaves significant gaps for a tool with multiple action types.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that states the core purpose without unnecessary words. It's appropriately sized and front-loaded, with every word earning its place by conveying essential information about the tool's domain and technology stack.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (multiple actions with different parameter requirements), lack of annotations, and absence of an output schema, the description is insufficient. It doesn't explain what the tool returns (e.g., certificate paths, status messages, error formats) or provide context about Let's Encrypt integration, making it incomplete for effective agent use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 100%, so all parameters are documented in the schema. The description adds no additional parameter semantics beyond what's in the schema (e.g., it doesn't explain the relationship between 'action' values and other parameters like 'domain' or 'email'). Since the schema does the heavy lifting, the baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose as managing SSL certificates using Let's Encrypt on Ubuntu, which includes both the verb ('manage') and resource ('SSL certificates'). It distinguishes itself from sibling tools like ubuntu_nginx_control or ubuntu_website_deployment by focusing specifically on SSL certificate operations, though it doesn't explicitly differentiate from all siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention prerequisites (e.g., needing an active SSH connection via ssh_connect first), nor does it explain when to choose this over other certificate management approaches or sibling tools like ubuntu_website_deployment that might handle certificates differently.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/mixelpixx/SSH-MCP'

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