Skip to main content
Glama
mcp-server.ts17.3 kB
/** * Coolify MCP Server * Model Context Protocol server for Coolify API * * Tools focused on debugging, management, and deployment: * - Servers: list, get, validate, resources, domains * - Projects: CRUD * - Environments: CRUD * - Applications: list, get, update, delete, start/stop/restart, logs, env vars, deploy (private-gh, private-key) * - Databases: list, get, start/stop/restart * - Services: list, get, update, start/stop/restart, env vars * - Deployments: list, get, deploy * * Note: @ts-nocheck is required because the MCP SDK's tool() method causes * TypeScript type instantiation depth errors with 40+ zod-typed tools. * The client and types are still fully type-checked. */ /* eslint-disable @typescript-eslint/ban-ts-comment */ // @ts-nocheck import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js'; import { z } from 'zod'; import { CoolifyClient } from './coolify-client.js'; import type { CoolifyConfig } from '../types/coolify.js'; const VERSION = '0.3.1'; /** Wrap tool handler with consistent error handling */ function wrapHandler<T>( fn: () => Promise<T>, ): Promise<{ content: Array<{ type: 'text'; text: string }> }> { return fn() .then((result) => ({ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }], })) .catch((error) => ({ content: [ { type: 'text' as const, text: `Error: ${error instanceof Error ? error.message : String(error)}`, }, ], })); } /** * Coolify MCP Server */ export class CoolifyMcpServer extends McpServer { private readonly client: CoolifyClient; constructor(config: CoolifyConfig) { super({ name: 'coolify', version: VERSION, capabilities: { tools: {} }, }); this.client = new CoolifyClient(config); this.registerTools(); } async connect(transport: Transport): Promise<void> { await super.connect(transport); } private registerTools(): void { // Version this.tool('get_version', 'Get Coolify API version', {}, async () => wrapHandler(() => this.client.getVersion()), ); // ========================================================================= // Servers (5 tools) // ========================================================================= this.tool('list_servers', 'List all servers', {}, async () => wrapHandler(() => this.client.listServers()), ); this.tool( 'get_server', 'Get server details', { uuid: z.string().describe('Server UUID') }, async ({ uuid }) => wrapHandler(() => this.client.getServer(uuid)), ); this.tool( 'get_server_resources', 'Get resources running on a server', { uuid: z.string().describe('Server UUID') }, async ({ uuid }) => wrapHandler(() => this.client.getServerResources(uuid)), ); this.tool( 'get_server_domains', 'Get domains configured on a server', { uuid: z.string().describe('Server UUID') }, async ({ uuid }) => wrapHandler(() => this.client.getServerDomains(uuid)), ); this.tool( 'validate_server', 'Validate server connection', { uuid: z.string().describe('Server UUID') }, async ({ uuid }) => wrapHandler(() => this.client.validateServer(uuid)), ); // ========================================================================= // Projects (5 tools) // ========================================================================= this.tool('list_projects', 'List all projects', {}, async () => wrapHandler(() => this.client.listProjects()), ); this.tool( 'get_project', 'Get project details', { uuid: z.string().describe('Project UUID') }, async ({ uuid }) => wrapHandler(() => this.client.getProject(uuid)), ); this.tool( 'create_project', 'Create a new project', { name: z.string().describe('Project name'), description: z.string().optional().describe('Description'), }, async (args) => wrapHandler(() => this.client.createProject(args)), ); this.tool( 'update_project', 'Update a project', { uuid: z.string().describe('Project UUID'), name: z.string().optional().describe('Project name'), description: z.string().optional().describe('Description'), }, async ({ uuid, ...data }) => wrapHandler(() => this.client.updateProject(uuid, data)), ); this.tool( 'delete_project', 'Delete a project', { uuid: z.string().describe('Project UUID') }, async ({ uuid }) => wrapHandler(() => this.client.deleteProject(uuid)), ); // ========================================================================= // Environments (4 tools) // ========================================================================= this.tool( 'list_environments', 'List environments in a project', { project_uuid: z.string().describe('Project UUID') }, async ({ project_uuid }) => wrapHandler(() => this.client.listProjectEnvironments(project_uuid)), ); this.tool( 'get_environment', 'Get environment details', { project_uuid: z.string().describe('Project UUID'), environment: z.string().describe('Environment name or UUID'), }, async ({ project_uuid, environment }) => wrapHandler(() => this.client.getProjectEnvironment(project_uuid, environment)), ); this.tool( 'create_environment', 'Create environment in a project', { project_uuid: z.string().describe('Project UUID'), name: z.string().describe('Environment name'), description: z.string().optional().describe('Description'), }, async ({ project_uuid, ...data }) => wrapHandler(() => this.client.createProjectEnvironment(project_uuid, data)), ); this.tool( 'delete_environment', 'Delete an environment', { environment_uuid: z.string().describe('Environment UUID') }, async ({ environment_uuid }) => wrapHandler(() => this.client.deleteProjectEnvironment(environment_uuid)), ); // ========================================================================= // Applications (15 tools) // ========================================================================= this.tool('list_applications', 'List all applications', {}, async () => wrapHandler(() => this.client.listApplications()), ); this.tool( 'get_application', 'Get application details', { uuid: z.string().describe('Application UUID') }, async ({ uuid }) => wrapHandler(() => this.client.getApplication(uuid)), ); this.tool( 'create_application_private_gh', 'Create app from private GitHub repo (GitHub App)', { project_uuid: z.string().describe('Project UUID'), server_uuid: z.string().describe('Server UUID'), github_app_uuid: z.string().describe('GitHub App UUID'), git_repository: z.string().describe('Repository (org/repo)'), git_branch: z.string().describe('Branch'), environment_name: z.string().optional().describe('Environment name'), destination_uuid: z.string().optional().describe('Destination UUID'), build_pack: z.string().optional().describe('Build pack'), ports_exposes: z.string().optional().describe('Ports to expose'), }, async (args) => wrapHandler(() => this.client.createApplicationPrivateGH(args)), ); this.tool( 'create_application_private_key', 'Create app from private repo using deploy key', { project_uuid: z.string().describe('Project UUID'), server_uuid: z.string().describe('Server UUID'), private_key_uuid: z.string().describe('Private key UUID'), git_repository: z.string().describe('Repository URL'), git_branch: z.string().describe('Branch'), environment_name: z.string().optional().describe('Environment name'), destination_uuid: z.string().optional().describe('Destination UUID'), build_pack: z.string().optional().describe('Build pack'), ports_exposes: z.string().optional().describe('Ports to expose'), }, async (args) => wrapHandler(() => this.client.createApplicationPrivateKey(args)), ); this.tool( 'update_application', 'Update an application', { uuid: z.string().describe('Application UUID'), name: z.string().optional().describe('Name'), description: z.string().optional().describe('Description'), fqdn: z.string().optional().describe('Domain'), git_branch: z.string().optional().describe('Git branch'), is_http_basic_auth_enabled: z .boolean() .optional() .describe('Enable HTTP basic authentication'), http_basic_auth_username: z.string().optional().describe('HTTP basic auth username'), http_basic_auth_password: z.string().optional().describe('HTTP basic auth password'), }, async ({ uuid, ...data }) => wrapHandler(() => this.client.updateApplication(uuid, data)), ); this.tool( 'delete_application', 'Delete an application', { uuid: z.string().describe('Application UUID'), delete_volumes: z.boolean().optional().describe('Delete volumes'), }, async ({ uuid, delete_volumes }) => wrapHandler(() => this.client.deleteApplication(uuid, { deleteVolumes: delete_volumes })), ); this.tool( 'start_application', 'Start an application', { uuid: z.string().describe('Application UUID') }, async ({ uuid }) => wrapHandler(() => this.client.startApplication(uuid)), ); this.tool( 'stop_application', 'Stop an application', { uuid: z.string().describe('Application UUID') }, async ({ uuid }) => wrapHandler(() => this.client.stopApplication(uuid)), ); this.tool( 'restart_application', 'Restart an application', { uuid: z.string().describe('Application UUID') }, async ({ uuid }) => wrapHandler(() => this.client.restartApplication(uuid)), ); this.tool( 'get_application_logs', 'Get application logs', { uuid: z.string().describe('Application UUID'), lines: z.number().optional().describe('Number of lines'), }, async ({ uuid, lines }) => wrapHandler(() => this.client.getApplicationLogs(uuid, lines)), ); // Application env vars this.tool( 'list_application_envs', 'List application environment variables', { uuid: z.string().describe('Application UUID') }, async ({ uuid }) => wrapHandler(() => this.client.listApplicationEnvVars(uuid)), ); this.tool( 'create_application_env', 'Create application environment variable', { uuid: z.string().describe('Application UUID'), key: z.string().describe('Variable key'), value: z.string().describe('Variable value'), is_build_time: z.boolean().optional().describe('Build time variable'), }, async ({ uuid, ...data }) => wrapHandler(() => this.client.createApplicationEnvVar(uuid, data)), ); this.tool( 'update_application_env', 'Update application environment variable', { uuid: z.string().describe('Application UUID'), key: z.string().describe('Variable key'), value: z.string().describe('Variable value'), }, async ({ uuid, ...data }) => wrapHandler(() => this.client.updateApplicationEnvVar(uuid, data)), ); this.tool( 'delete_application_env', 'Delete application environment variable', { uuid: z.string().describe('Application UUID'), env_uuid: z.string().describe('Env variable UUID'), }, async ({ uuid, env_uuid }) => wrapHandler(() => this.client.deleteApplicationEnvVar(uuid, env_uuid)), ); // ========================================================================= // Databases (5 tools) // ========================================================================= this.tool('list_databases', 'List all databases', {}, async () => wrapHandler(() => this.client.listDatabases()), ); this.tool( 'get_database', 'Get database details', { uuid: z.string().describe('Database UUID') }, async ({ uuid }) => wrapHandler(() => this.client.getDatabase(uuid)), ); this.tool( 'start_database', 'Start a database', { uuid: z.string().describe('Database UUID') }, async ({ uuid }) => wrapHandler(() => this.client.startDatabase(uuid)), ); this.tool( 'stop_database', 'Stop a database', { uuid: z.string().describe('Database UUID') }, async ({ uuid }) => wrapHandler(() => this.client.stopDatabase(uuid)), ); this.tool( 'restart_database', 'Restart a database', { uuid: z.string().describe('Database UUID') }, async ({ uuid }) => wrapHandler(() => this.client.restartDatabase(uuid)), ); // ========================================================================= // Services (9 tools) // ========================================================================= this.tool('list_services', 'List all services', {}, async () => wrapHandler(() => this.client.listServices()), ); this.tool( 'get_service', 'Get service details', { uuid: z.string().describe('Service UUID') }, async ({ uuid }) => wrapHandler(() => this.client.getService(uuid)), ); this.tool( 'update_service', 'Update a service (IMPORTANT: See UpdateServiceRequest type docs for Traefik basic auth requirements)', { uuid: z.string().describe('Service UUID'), name: z.string().optional().describe('Service name'), description: z.string().optional().describe('Description'), docker_compose_raw: z .string() .optional() .describe( 'Base64 encoded docker-compose YAML. CRITICAL FOR BASIC AUTH: (1) Manually disable label escaping in Coolify UI first (no API). (2) Use $$ in htpasswd hashes even with escaping disabled (Traefik requirement). (3) Generate: htpasswd -nb user pass, then replace $ with $$.', ), }, async ({ uuid, ...data }) => wrapHandler(() => this.client.updateService(uuid, data)), ); this.tool( 'start_service', 'Start a service', { uuid: z.string().describe('Service UUID') }, async ({ uuid }) => wrapHandler(() => this.client.startService(uuid)), ); this.tool( 'stop_service', 'Stop a service', { uuid: z.string().describe('Service UUID') }, async ({ uuid }) => wrapHandler(() => this.client.stopService(uuid)), ); this.tool( 'restart_service', 'Restart a service', { uuid: z.string().describe('Service UUID') }, async ({ uuid }) => wrapHandler(() => this.client.restartService(uuid)), ); // Service env vars this.tool( 'list_service_envs', 'List service environment variables', { uuid: z.string().describe('Service UUID') }, async ({ uuid }) => wrapHandler(() => this.client.listServiceEnvVars(uuid)), ); this.tool( 'create_service_env', 'Create service environment variable', { uuid: z.string().describe('Service UUID'), key: z.string().describe('Variable key'), value: z.string().describe('Variable value'), }, async ({ uuid, ...data }) => wrapHandler(() => this.client.createServiceEnvVar(uuid, data)), ); this.tool( 'delete_service_env', 'Delete service environment variable', { uuid: z.string().describe('Service UUID'), env_uuid: z.string().describe('Env variable UUID'), }, async ({ uuid, env_uuid }) => wrapHandler(() => this.client.deleteServiceEnvVar(uuid, env_uuid)), ); // ========================================================================= // Deployments (4 tools) // ========================================================================= this.tool('list_deployments', 'List running deployments', {}, async () => wrapHandler(() => this.client.listDeployments()), ); this.tool( 'get_deployment', 'Get deployment details', { uuid: z.string().describe('Deployment UUID') }, async ({ uuid }) => wrapHandler(() => this.client.getDeployment(uuid)), ); this.tool( 'deploy', 'Deploy by tag or UUID', { tag_or_uuid: z.string().describe('Tag or UUID'), force: z.boolean().optional().describe('Force rebuild'), }, async ({ tag_or_uuid, force }) => wrapHandler(() => this.client.deployByTagOrUuid(tag_or_uuid, force)), ); this.tool( 'list_application_deployments', 'List deployments for an application', { uuid: z.string().describe('Application UUID') }, async ({ uuid }) => wrapHandler(() => this.client.listApplicationDeployments(uuid)), ); } }

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/StuMason/coolify-mcp'

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