Skip to main content
Glama
dj-pearson

Supabase Coolify MCP Server

by dj-pearson
deployment-tools.ts7.7 kB
/** * Supabase deployment tools for Coolify */ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { CoolifyClient } from '../coolify-client.js'; import { SupabaseManager } from '../supabase-client.js'; import { SupabaseDeploymentConfig } from '../types.js'; export function registerDeploymentTools( server: Server, coolify: CoolifyClient, supabase: SupabaseManager, toolHandlers: Map<string, (args: any) => Promise<any>> ) { /** * Deploy a complete Supabase instance on Coolify */ toolHandlers.set( 'deploy_supabase_to_coolify', async (args: { name: string; config?: SupabaseDeploymentConfig }) => { const { name, config = {} } = args; try { // Step 1: Create the main Supabase application const appResult = await coolify.createApplication({ name: `${name}-supabase`, description: 'Self-hosted Supabase instance', build_pack: 'docker', git_repository: 'https://github.com/supabase/supabase', git_branch: 'master', }); if (!appResult.success || !appResult.data) { return { success: false, error: 'Failed to create Supabase application', }; } const appUuid = appResult.data.uuid; // Step 2: Configure environment variables const envVars: Record<string, string> = { POSTGRES_VERSION: config.postgres_version || '15', POSTGRES_PASSWORD: generateSecurePassword(), JWT_SECRET: generateSecurePassword(64), ANON_KEY: generateSupabaseKey('anon'), SERVICE_ROLE_KEY: generateSupabaseKey('service_role'), SITE_URL: config.custom_domain || process.env.SUPABASE_URL || `https://${name}.coolify.app`, ENABLE_REALTIME: config.enable_realtime !== false ? 'true' : 'false', ENABLE_STORAGE: config.enable_storage !== false ? 'true' : 'false', ENABLE_AUTH: config.enable_auth !== false ? 'true' : 'false', ENABLE_REST: config.enable_rest !== false ? 'true' : 'false', ENABLE_GRAPHQL: config.enable_graphql !== false ? 'true' : 'false', ...config.environment_variables, }; const envResult = await coolify.updateApplicationEnv(appUuid, envVars); if (!envResult.success) { return { success: false, error: 'Failed to configure environment variables', }; } // Step 3: Deploy the application const deployResult = await coolify.deployApplication(appUuid); if (!deployResult.success) { return { success: false, error: 'Failed to deploy Supabase', }; } return { success: true, data: { uuid: appUuid, name, status: 'deploying', credentials: { postgres_password: envVars.POSTGRES_PASSWORD, jwt_secret: envVars.JWT_SECRET, anon_key: envVars.ANON_KEY, service_role_key: envVars.SERVICE_ROLE_KEY, }, }, message: 'Supabase deployment started successfully. Save the credentials securely!', }; } catch (error) { return { success: false, error: `Deployment failed: ${error instanceof Error ? error.message : 'Unknown error'}`, }; } } ); /** * Update an existing Supabase deployment */ toolHandlers.set( 'update_supabase_deployment', async (args: { uuid: string; config: Partial<SupabaseDeploymentConfig> }) => { const { uuid, config } = args; try { // Get current application const appResult = await coolify.getApplication(uuid); if (!appResult.success || !appResult.data) { return { success: false, error: 'Application not found', }; } // Update environment variables const currentEnv = appResult.data.environment || {}; const updatedEnv: Record<string, string> = { ...currentEnv, }; if (config.postgres_version) { updatedEnv.POSTGRES_VERSION = config.postgres_version; } if (config.enable_realtime !== undefined) { updatedEnv.ENABLE_REALTIME = config.enable_realtime ? 'true' : 'false'; } if (config.enable_storage !== undefined) { updatedEnv.ENABLE_STORAGE = config.enable_storage ? 'true' : 'false'; } if (config.enable_auth !== undefined) { updatedEnv.ENABLE_AUTH = config.enable_auth ? 'true' : 'false'; } if (config.enable_rest !== undefined) { updatedEnv.ENABLE_REST = config.enable_rest ? 'true' : 'false'; } if (config.enable_graphql !== undefined) { updatedEnv.ENABLE_GRAPHQL = config.enable_graphql ? 'true' : 'false'; } if (config.custom_domain) { updatedEnv.SITE_URL = config.custom_domain; } if (config.environment_variables) { Object.assign(updatedEnv, config.environment_variables); } const envResult = await coolify.updateApplicationEnv(uuid, updatedEnv); if (!envResult.success) { return { success: false, error: 'Failed to update configuration', }; } // Restart to apply changes const restartResult = await coolify.restartApplication(uuid); if (!restartResult.success) { return { success: false, error: 'Failed to restart application', }; } return { success: true, message: 'Supabase deployment updated successfully', }; } catch (error) { return { success: false, error: `Update failed: ${error instanceof Error ? error.message : 'Unknown error'}`, }; } } ); /** * Get deployment status */ toolHandlers.set('get_deployment_status', async (args: { uuid: string }) => { const { uuid } = args; try { // Get application details const appResult = await coolify.getApplication(uuid); if (!appResult.success || !appResult.data) { return { success: false, error: 'Application not found', }; } // Check Supabase health const healthResult = await supabase.checkHealth(); return { success: true, data: { application: appResult.data, health: healthResult.success ? healthResult.data : [], status: appResult.data.status, }, }; } catch (error) { return { success: false, error: `Status check failed: ${error instanceof Error ? error.message : 'Unknown error'}`, }; } }); } /** * Generate a secure random password */ function generateSecurePassword(length: number = 32): string { const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*'; let password = ''; const array = new Uint8Array(length); crypto.getRandomValues(array); for (let i = 0; i < length; i++) { password += charset[array[i] % charset.length]; } return password; } /** * Generate a Supabase API key (simplified version) * In production, this should use proper JWT generation */ function generateSupabaseKey(role: string): string { // This is a simplified placeholder. In production, you should: // 1. Use a proper JWT library // 2. Sign with the JWT_SECRET // 3. Include proper claims return `eyJ${Buffer.from(role).toString('base64')}.${generateSecurePassword(32)}`; }

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/dj-pearson/supabase-coolify-mcp-server'

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