services
Manage and control Coolify MCP Server deployments by performing operations like listing, creating, updating, and deleting services, along with handling environment variables and service types.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| body | No | JSON request body | |
| env_id | No | Environment variable UUID | |
| id | No | Service UUID | |
| operation | Yes | Operation to perform |
Implementation Reference
- src/mcp/tools/services.ts:130-235 (handler)Main handler function for the 'services' tool. Routes different operations (list, get, create, update, delete, start, stop, restart, env management) to generated API calls using 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}`); } }
- src/mcp/tools/services.ts:117-126 (schema)Zod schema defining input parameters for the services tool: operation (enum), id (optional), env_id (optional), body (optional JSON string).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") });
- src/mcp-server.ts:141-180 (registration)Registration of the 'services' MCP tool using server.tool(). Imports and uses servicesHandler from services.ts, with inline Zod schema matching servicesToolSchema.// 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 }; } } );
- src/mcp/tools/services.ts:24-111 (helper)Exported constant array of all supported one-click service types, automatically synced with OpenAPI spec via 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[];