Skip to main content
Glama
keywaysh

Keyway MCP Server

by keywaysh

keyway_generate

Generate secure secrets like passwords and API keys, storing them directly in a vault without exposing values in conversation.

Instructions

Generate a secure secret and store it directly in the vault. The value is never exposed in the conversation.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
nameYesSecret name - must be UPPERCASE_WITH_UNDERSCORES
typeNoType of secret to generate (default: "password")
lengthNoLength of the secret (default: 32, range: 8-256)
environmentNoEnvironment to store the secret in (default: "development")

Implementation Reference

  • The 'generate' function acts as the handler for the 'keyway_generate' tool, responsible for generating a secure secret, updating the vault, and returning the result.
    export async function generate(args: GenerateArgs): Promise<CallToolResult> {
      const { name, type = 'password', length = 32, environment = 'development' } = args;
    
      // Validate name
      if (!name) {
        return {
          content: [{ type: 'text', text: 'Error: Secret name is required' }],
          isError: true,
        };
      }
    
      if (!isValidSecretName(name)) {
        return {
          content: [
            {
              type: 'text',
              text: `Error: Invalid secret name "${name}". Must be UPPERCASE_WITH_UNDERSCORES (e.g., DATABASE_URL, API_KEY)`,
            },
          ],
          isError: true,
        };
      }
    
      // Validate type
      const validTypes: SecretType[] = ['password', 'uuid', 'api-key', 'jwt-secret', 'hex', 'base64'];
      if (!validTypes.includes(type)) {
        return {
          content: [
            {
              type: 'text',
              text: `Error: Invalid type "${type}". Valid types: ${validTypes.join(', ')}`,
            },
          ],
          isError: true,
        };
      }
    
      // Validate length
      if (length < 8 || length > 256) {
        return {
          content: [{ type: 'text', text: 'Error: Length must be between 8 and 256' }],
          isError: true,
        };
      }
    
      try {
        const token = await getToken();
        const repository = getRepository();
    
        // Generate the secret value
        const secretValue = generateSecret(type, length);
    
        // Pull existing secrets
        let existingSecrets: Record<string, string> = {};
        try {
          const content = await pullSecrets(repository, environment, token);
          existingSecrets = parseEnvContent(content);
        } catch {
          // Environment might not exist yet, that's OK
        }
    
        // Check if secret already exists
        const isUpdate = name in existingSecrets;
    
        // Add/update the secret
        existingSecrets[name] = secretValue;
    
        // Push to vault (API expects Record<string, string>)
        await pushSecrets(repository, environment, existingSecrets, token);
    
        const response = {
          success: true,
          action: isUpdate ? 'updated' : 'created',
          name,
          type,
          length: secretValue.length,
          preview: maskSecret(secretValue),
          environment,
          repository,
          message: `Secret "${name}" ${isUpdate ? 'updated' : 'created'} with a secure ${type} value. The actual value is stored in Keyway and was never exposed in this conversation.`,
        };
    
        return {
          content: [{ type: 'text', text: JSON.stringify(response, null, 2) }],
          isError: false,
        };
      } catch (error) {
        const message = error instanceof Error ? error.message : 'Unknown error';
        return {
          content: [{ type: 'text', text: `Error generating secret: ${message}` }],
          isError: true,
        };
      }
    }
  • The 'GenerateArgs' interface defines the input arguments for the 'keyway_generate' tool.
    interface GenerateArgs {
      name: string;
      type?: SecretType;
      length?: number;
      environment?: string;
    }
  • The 'generateSecret' helper function handles the logic for creating different types of secrets.
    function generateSecret(type: SecretType, length: number): string {
      switch (type) {
        case 'password':
          return generatePassword(length);
    
        case 'uuid':
          return randomUUID();
    
        case 'api-key':
          // Format: prefix_base62 (like sk_live_xxx or key_xxx)
          return `key_${randomString(length, CHARSET_ALPHANUMERIC)}`;
    
        case 'jwt-secret': {
          // 256-bit minimum for HS256
          const jwtLength = Math.max(length, 32);
          return randomBytes(jwtLength).toString('base64url');
        }
    
        case 'hex':
          return randomBytes(Math.ceil(length / 2))
            .toString('hex')
            .slice(0, length);
    
        case 'base64':
          return randomBytes(Math.ceil((length * 3) / 4))
            .toString('base64')
            .slice(0, length);
    
        default:
          return generatePassword(length);
      }
    }

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/keywaysh/keyway-mcp'

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