Skip to main content
Glama

services

Manage Coolify services by listing, creating, updating, deleting, controlling lifecycle operations, and handling environment variables through programmatic commands.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
operationYesOperation to perform
idNoService UUID
env_idNoEnvironment variable UUID
bodyNoJSON request body

Implementation Reference

  • Registration of the 'services' MCP tool using server.tool(), including inline input schema validation with Zod and a wrapper handler that delegates to servicesHandler.
    // Register services tool with proper Zod schema format server.tool( 'services', { operation: z.enum([ 'list', 'get', 'create', 'update', 'delete', 'start', 'stop', 'restart', 'list_envs', 'create_env', 'update_env', 'update_envs_bulk', 'delete_env', 'get_service_types' ]).describe("Operation to perform"), id: z.string().optional().describe("Service UUID"), env_id: z.string().optional().describe("Environment variable UUID"), body: z.string().optional().describe("JSON request body") }, async ({ operation, id, env_id, body }) => { try { console.error('Services tool received args:', JSON.stringify({ operation, id, env_id, body }, null, 2)); const result = await servicesHandler({ operation, id, env_id, body }); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; } catch (error) { return { content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } );
  • Core handler function servicesHandler that implements the logic for all 'services' tool operations by routing to generated SDK API calls via safeApiCall.
    export async function servicesHandler(args: ServicesToolArgs) { const { operation, id, env_id, body } = args; // Helper to parse body if provided const parseBody = (body?: string) => { if (!body) return undefined; try { return JSON.parse(body); } catch (error) { throw new Error(`Invalid JSON in body parameter: ${error instanceof Error ? error.message : String(error)}`); } }; // Special operation to get available service types if (operation === 'get_service_types') { return { success: true, data: { service_types: SERVICE_TYPES, count: SERVICE_TYPES.length, description: "All available one-click service types supported by Coolify" } }; } // Route to appropriate generated service method switch (operation) { case 'list': return await safeApiCall(() => listServices()); case 'get': if (!id) throw new Error('ID required for get operation'); return await safeApiCall(() => getServiceByUuid({ path: { uuid: id } })); case 'create': if (!body) throw new Error('Body required for create operation'); const createData = parseBody(body); return await safeApiCall(() => createService({ body: createData })); case 'update': if (!id || !body) throw new Error('ID and body required for update operation'); const updateData = parseBody(body); return await safeApiCall(() => updateServiceByUuid({ body: updateData, path: { uuid: id } } as any)); case 'delete': if (!id) throw new Error('ID required for delete operation'); // Parse body for delete options if provided const deleteOptions = body ? parseBody(body) : undefined; return await safeApiCall(() => deleteServiceByUuid({ path: { uuid: id }, ...(deleteOptions && { query: deleteOptions }) })); case 'start': if (!id) throw new Error('ID required for start operation'); return await safeApiCall(() => startServiceByUuid({ path: { uuid: id } })); case 'stop': if (!id) throw new Error('ID required for stop operation'); return await safeApiCall(() => stopServiceByUuid({ path: { uuid: id } })); case 'restart': if (!id) throw new Error('ID required for restart operation'); return await safeApiCall(() => restartServiceByUuid({ path: { uuid: id } })); case 'list_envs': if (!id) throw new Error('ID required for list_envs operation'); return await safeApiCall(() => listEnvsByServiceUuid({ path: { uuid: id } })); case 'create_env': if (!id || !body) throw new Error('ID and body required for create_env operation'); const createEnvData = parseBody(body); return await safeApiCall(() => createEnvByServiceUuid({ path: { uuid: id }, body: createEnvData })); case 'update_env': if (!id || !body) throw new Error('ID and body required for update_env operation'); const updateEnvData = parseBody(body); return await safeApiCall(() => updateEnvByServiceUuid({ path: { uuid: id }, body: updateEnvData })); case 'update_envs_bulk': if (!id || !body) throw new Error('ID and body required for update_envs_bulk operation'); const bulkEnvData = parseBody(body); return await safeApiCall(() => updateEnvsByServiceUuid({ path: { uuid: id }, body: bulkEnvData })); case 'delete_env': if (!id || !env_id) throw new Error('ID and env_id required for delete_env operation'); return await safeApiCall(() => deleteEnvByServiceUuid({ path: { uuid: id, env_uuid: env_id } })); default: throw new Error(`Unknown operation: ${operation}`); } }
  • Zod schema definition for services tool input validation (servicesToolSchema), matching the inline schema used in registration.
    export const servicesToolSchema = z.object({ operation: z.enum([ 'list', 'get', 'create', 'update', 'delete', 'start', 'stop', 'restart', 'list_envs', 'create_env', 'update_env', 'update_envs_bulk', 'delete_env', 'get_service_types' ]).describe("Operation to perform"), id: z.string().optional().describe("Service UUID"), env_id: z.string().optional().describe("Environment variable UUID"), body: z.string().optional().describe("JSON request body") });
  • Exported SERVICE_TYPES constant listing all supported one-click service types, kept in sync with OpenAPI spec via build script, used in get_service_types operation.
    export const SERVICE_TYPES = [ 'activepieces', 'appsmith', 'appwrite', 'authentik', 'babybuddy', 'budge', 'changedetection', 'chatwoot', 'classicpress-with-mariadb', 'classicpress-with-mysql', 'classicpress-without-database', 'cloudflared', 'code-server', 'dashboard', 'directus', 'directus-with-postgresql', 'docker-registry', 'docuseal', 'docuseal-with-postgres', 'dokuwiki', 'duplicati', 'emby', 'embystat', 'fider', 'filebrowser', 'firefly', 'formbricks', 'ghost', 'gitea', 'gitea-with-mariadb', 'gitea-with-mysql', 'gitea-with-postgresql', 'glance', 'glances', 'glitchtip', 'grafana', 'grafana-with-postgresql', 'grocy', 'heimdall', 'homepage', 'jellyfin', 'kuzzle', 'listmonk', 'logto', 'mediawiki', 'meilisearch', 'metabase', 'metube', 'minio', 'moodle', 'n8n', 'n8n-with-postgresql', 'next-image-transformation', 'nextcloud', 'nocodb', 'odoo', 'openblocks', 'pairdrop', 'penpot', 'phpmyadmin', 'pocketbase', 'posthog', 'reactive-resume', 'rocketchat', 'shlink', 'slash', 'snapdrop', 'statusnook', 'stirling-pdf', 'supabase', 'syncthing', 'tolgee', 'trigger', 'trigger-with-external-database', 'twenty', 'umami', 'unleash-with-postgresql', 'unleash-without-database', 'uptime-kuma', 'vaultwarden', 'vikunja', 'weblate', 'whoogle', 'wordpress-with-mariadb', 'wordpress-with-mysql', 'wordpress-without-database' ] as const satisfies readonly ServiceType[];

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

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