Coolify MCP Server

by StuMason
Verified
import { CoolifyConfig, ErrorResponse, ServerInfo, ServerResources, ServerDomain, ValidationResponse, Project, CreateProjectRequest, UpdateProjectRequest, Environment, Deployment, Database, DatabaseUpdateRequest, Service, CreateServiceRequest, DeleteServiceOptions, } from '../types/coolify.js'; export class CoolifyClient { private baseUrl: string; private accessToken: string; constructor(config: CoolifyConfig) { if (!config.baseUrl) { throw new Error('Coolify base URL is required'); } if (!config.accessToken) { throw new Error('Coolify access token is required'); } this.baseUrl = config.baseUrl.replace(/\/$/, ''); this.accessToken = config.accessToken; } private async request<T>(path: string, options: RequestInit = {}): Promise<T> { try { const url = `${this.baseUrl}/api/v1${path}`; const response = await fetch(url, { headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${this.accessToken}`, }, ...options, }); const data = await response.json(); if (!response.ok) { const error = data as ErrorResponse; throw new Error(error.message || `HTTP ${response.status}: ${response.statusText}`); } return data as T; } catch (error) { if (error instanceof TypeError && error.message.includes('fetch')) { throw new Error( `Failed to connect to Coolify server at ${this.baseUrl}. Please check if the server is running and the URL is correct.`, ); } throw error; } } async listServers(): Promise<ServerInfo[]> { return this.request<ServerInfo[]>('/servers'); } async getServer(uuid: string): Promise<ServerInfo> { return this.request<ServerInfo>(`/servers/${uuid}`); } async getServerResources(uuid: string): Promise<ServerResources> { return this.request<ServerResources>(`/servers/${uuid}/resources`); } async getServerDomains(uuid: string): Promise<ServerDomain[]> { return this.request<ServerDomain[]>(`/servers/${uuid}/domains`); } async validateServer(uuid: string): Promise<ValidationResponse> { return this.request<ValidationResponse>(`/servers/${uuid}/validate`); } async validateConnection(): Promise<void> { try { await this.listServers(); } catch (error) { throw new Error( `Failed to connect to Coolify server: ${error instanceof Error ? error.message : 'Unknown error'}`, ); } } async listProjects(): Promise<Project[]> { return this.request<Project[]>('/projects'); } async getProject(uuid: string): Promise<Project> { return this.request<Project>(`/projects/${uuid}`); } async createProject(project: CreateProjectRequest): Promise<{ uuid: string }> { return this.request<{ uuid: string }>('/projects', { method: 'POST', body: JSON.stringify(project), }); } async updateProject(uuid: string, project: UpdateProjectRequest): Promise<Project> { return this.request<Project>(`/projects/${uuid}`, { method: 'PATCH', body: JSON.stringify(project), }); } async deleteProject(uuid: string): Promise<{ message: string }> { return this.request<{ message: string }>(`/projects/${uuid}`, { method: 'DELETE', }); } async getProjectEnvironment( projectUuid: string, environmentNameOrUuid: string, ): Promise<Environment> { return this.request<Environment>(`/projects/${projectUuid}/${environmentNameOrUuid}`); } async deployApplication(uuid: string): Promise<Deployment> { const response = await this.request<Deployment>(`/applications/${uuid}/deploy`, { method: 'POST', }); return response; } async listDatabases(): Promise<Database[]> { return this.request<Database[]>('/databases'); } async getDatabase(uuid: string): Promise<Database> { return this.request<Database>(`/databases/${uuid}`); } async updateDatabase(uuid: string, data: DatabaseUpdateRequest): Promise<Database> { return this.request<Database>(`/databases/${uuid}`, { method: 'PATCH', body: JSON.stringify(data), }); } async deleteDatabase( uuid: string, options?: { deleteConfigurations?: boolean; deleteVolumes?: boolean; dockerCleanup?: boolean; deleteConnectedNetworks?: boolean; }, ): Promise<{ message: string }> { const queryParams = new URLSearchParams(); if (options) { if (options.deleteConfigurations !== undefined) { queryParams.set('delete_configurations', options.deleteConfigurations.toString()); } if (options.deleteVolumes !== undefined) { queryParams.set('delete_volumes', options.deleteVolumes.toString()); } if (options.dockerCleanup !== undefined) { queryParams.set('docker_cleanup', options.dockerCleanup.toString()); } if (options.deleteConnectedNetworks !== undefined) { queryParams.set('delete_connected_networks', options.deleteConnectedNetworks.toString()); } } const queryString = queryParams.toString(); const url = queryString ? `/databases/${uuid}?${queryString}` : `/databases/${uuid}`; return this.request<{ message: string }>(url, { method: 'DELETE', }); } async listServices(): Promise<Service[]> { return this.request<Service[]>('/services'); } async getService(uuid: string): Promise<Service> { return this.request<Service>(`/services/${uuid}`); } async createService(data: CreateServiceRequest): Promise<{ uuid: string; domains: string[] }> { return this.request<{ uuid: string; domains: string[] }>('/services', { method: 'POST', body: JSON.stringify(data), }); } async deleteService(uuid: string, options?: DeleteServiceOptions): Promise<{ message: string }> { const queryParams = new URLSearchParams(); if (options) { if (options.deleteConfigurations !== undefined) { queryParams.set('delete_configurations', options.deleteConfigurations.toString()); } if (options.deleteVolumes !== undefined) { queryParams.set('delete_volumes', options.deleteVolumes.toString()); } if (options.dockerCleanup !== undefined) { queryParams.set('docker_cleanup', options.dockerCleanup.toString()); } if (options.deleteConnectedNetworks !== undefined) { queryParams.set('delete_connected_networks', options.deleteConnectedNetworks.toString()); } } const queryString = queryParams.toString(); const url = queryString ? `/services/${uuid}?${queryString}` : `/services/${uuid}`; return this.request<{ message: string }>(url, { method: 'DELETE', }); } // Add more methods as needed for other endpoints }