This is page 1 of 4. Use http://codebase.md/stumason/coolify-mcp?page={x} to view the full context. # Directory Structure ``` ├── .cursor │ └── rules │ ├── 000-cursor-rules.mdc │ ├── 801-feature-workflow.mdc │ ├── 802-coolify-mcp-workflow.mdc │ └── 803-npm-publish-workflow.mdc ├── .eslintrc.json ├── .github │ └── workflows │ └── ci.yml ├── .gitignore ├── .lintstagedrc.json ├── .markdownlint-cli2.jsonc ├── .prettierrc ├── .repomixignore ├── debug.js ├── docs │ ├── coolify-openapi.yaml │ ├── features │ │ ├── 001-core-server-setup.md │ │ ├── 002-server-info-resource.md │ │ ├── 003-project-management.md │ │ ├── 004-environment-management.md │ │ ├── 005-application-deployment.md │ │ ├── 006-database-management.md │ │ ├── 007-service-management.md │ │ ├── 008-mcp-resources-implementation.md │ │ ├── 009-mcp-prompts-implementation.md │ │ ├── 010-private-key-management.md │ │ ├── 011-team-management.md │ │ ├── 012-backup-management.md │ │ ├── 013-npx-config-fix.md │ │ └── future-adrs.md │ ├── mcp-example-clients.md │ ├── mcp-js-readme.md │ └── openapi-chunks │ ├── applications-api.yaml │ ├── databases-api.yaml │ ├── deployments-api.yaml │ ├── private-keys-api.yaml │ ├── projects-api.yaml │ ├── resources-api.yaml │ ├── schemas.yaml │ ├── servers-api.yaml │ ├── services-api.yaml │ ├── teams-api.yaml │ └── untagged-api.yaml ├── jest.config.js ├── package-lock.json ├── package.json ├── README.md ├── repomix-output.xml ├── src │ ├── __tests__ │ │ ├── coolify-client.test.ts │ │ └── resources │ │ ├── application-resources.test.ts │ │ ├── database-resources.test.ts │ │ ├── deployment-resources.test.ts │ │ └── service-resources.test.ts │ ├── index.ts │ ├── lib │ │ ├── coolify-client.ts │ │ ├── mcp-server.ts │ │ └── resource.ts │ ├── resources │ │ ├── application-resources.ts │ │ ├── database-resources.ts │ │ ├── deployment-resources.ts │ │ ├── index.ts │ │ └── service-resources.ts │ └── types │ └── coolify.ts └── tsconfig.json ``` # Files -------------------------------------------------------------------------------- /.repomixignore: -------------------------------------------------------------------------------- ``` .cursor/ .github/ .husky/ docs/ package-lock.json ``` -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- ``` { "semi": true, "trailingComma": "all", "singleQuote": true, "printWidth": 100, "tabWidth": 2 } ``` -------------------------------------------------------------------------------- /.lintstagedrc.json: -------------------------------------------------------------------------------- ```json { "src/**/*.ts": ["eslint --fix", "prettier --write"], "*.json": ["prettier --write"], "*.md": ["prettier --write", "markdownlint-cli2"] } ``` -------------------------------------------------------------------------------- /.markdownlint-cli2.jsonc: -------------------------------------------------------------------------------- ``` { "config": { "line-length": false, "no-duplicate-heading": false, "no-inline-html": false, }, "ignores": ["node_modules", "dist"], } ``` -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- ``` # Dependencies node_modules/ # Build output dist/ build/ /lib/ coverage/ # IDE and editor files .idea/ .vscode/ *.swp *.swo .DS_Store Thumbs.db # Environment variables .env .env.local .env.*.local # Logs logs/ *.log npm-debug.log* yarn-debug.log* yarn-error.log* # Test coverage coverage/ .nyc_output/ # Optional npm cache directory .npm # Optional eslint cache .eslintcache # Optional REPL history .node_repl_history # Output of 'npm pack' *.tgz # Yarn Integrity file .yarn-integrity ``` -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- ```json { "env": { "node": true, "es2021": true }, "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"], "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": "latest", "sourceType": "module" }, "plugins": ["@typescript-eslint"], "rules": { "@typescript-eslint/explicit-function-return-type": "warn", "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }], "@typescript-eslint/no-explicit-any": "warn" } } ``` -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- ```markdown # Coolify MCP Server A Model Context Protocol (MCP) server implementation for [Coolify](https://coolify.io/), enabling AI assistants to interact with your Coolify instances through natural language. ## Example Prompts Here are example prompts you can use with MCP-compatible AI assistants to interact with your Coolify instance: ### Server Management ``` # List and Inspect Servers - Show me all Coolify servers in my instance - What's the status of server {uuid}? - Show me the resources running on server {uuid} - What domains are configured for server {uuid}? - Can you validate the connection to server {uuid}? # Resource Monitoring - How much CPU and memory is server {uuid} using? - List all resources running on server {uuid} - Show me the current status of all servers ``` ### Project Management ``` # Project Operations - List all my Coolify projects - Create a new project called "my-webapp" with description "My web application" - Show me the details of project {uuid} - Update project {uuid} to change its name to "new-name" - Delete project {uuid} # Environment Management - Show me the environments in project {uuid} - Get details of the production environment in project {uuid} - What variables are set in the staging environment of project {uuid}? ``` ### Application and Service Management ``` # Application Management - List all applications - Show me details of application {uuid} - Create a new application called "my-nodejs-app" - Delete application {uuid} # Service Operations - Show me all running services - Create a new WordPress service: - Name: my-blog - Project UUID: {project_uuid} - Server UUID: {server_uuid} - Type: wordpress-with-mysql - What's the status of service {uuid}? - Delete service {uuid} and clean up its resources ``` ### Database Management ``` # Database Operations - List all databases - Show me the configuration of database {uuid} - Update database {uuid}: - Increase memory limit to 1GB - Change public port to 5432 - Update password - Delete database {uuid} and clean up volumes # Database Types - Create a PostgreSQL database - Set up a Redis instance - Configure a MongoDB database - Initialize a MySQL database ``` ### Deployment Management ``` # Deployment Operations - Show me all active deployments - What's the status of deployment {uuid}? - Deploy application {uuid} - Force rebuild and deploy application {uuid} - List recent deployments for application {uuid} ``` ## Installation ### Prerequisites - Node.js >= 18 - A running Coolify instance - Coolify API access token ### Setup in AI Tools #### Claude Desktop ```json "coolify": { "command": "npx", "args": [ "-y", "@masonator/coolify-mcp" ], "env": { "COOLIFY_ACCESS_TOKEN": "0|your-secret-token", "COOLIFY_BASE_URL": "https://your-coolify-instance.com" } } ``` #### Cursor ```bash env COOLIFY_ACCESS_TOKEN:0|your-secret-token COOLIFY_BASE_URL:https://your-coolify-instance.com npx -y @stumason/coolify-mcp ``` ## Development ### Local Setup ```bash # Clone the repository git clone https://github.com/stumason/coolify-mcp.git cd coolify-mcp # Install dependencies npm install # Build the project npm run build # Run tests npm test ``` ### Environment Variables ```bash # Required COOLIFY_ACCESS_TOKEN=your_access_token_here # Optional (defaults to http://localhost:3000) COOLIFY_BASE_URL=https://your.coolify.instance ``` ## API Reference ### Resource Types #### Application ```typescript interface Application { uuid: string; name: string; // Additional properties based on your Coolify instance } ``` #### Service ```typescript interface Service { id: number; uuid: string; name: string; type: ServiceType; // Various types like 'wordpress', 'mysql', etc. status: 'running' | 'stopped' | 'error'; project_uuid: string; environment_uuid: string; server_uuid: string; domains?: string[]; } ``` #### Database ```typescript interface Database { id: number; uuid: string; name: string; type: 'postgresql' | 'mysql' | 'mongodb' | 'redis' | /* other types */; status: 'running' | 'stopped' | 'error'; is_public: boolean; public_port?: number; // Additional configuration based on database type } ``` #### Deployment ```typescript interface Deployment { id: number; uuid: string; application_uuid: string; status: string; created_at: string; updated_at: string; } ``` ## Contributing Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change. ## License MIT ## Support For support, please: 1. Check the [issues](https://github.com/stumason/coolify-mcp/issues) page 2. Create a new issue if needed 3. Join the Coolify community ``` -------------------------------------------------------------------------------- /docs/features/012-backup-management.md: -------------------------------------------------------------------------------- ```markdown ``` -------------------------------------------------------------------------------- /src/resources/index.ts: -------------------------------------------------------------------------------- ```typescript export * from './database-resources.js'; export * from './deployment-resources.js'; export * from './application-resources.js'; export * from './service-resources.js'; ``` -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- ```javascript /** @type {import('ts-jest').JestConfigWithTsJest} */ export default { preset: 'ts-jest', testEnvironment: 'node', moduleNameMapper: { '^(\\.{1,2}/.*)\\.js$': '$1', }, transform: { '^.+\\.tsx?$': [ 'ts-jest', { useESM: true, }, ], }, extensionsToTreatAsEsm: ['.ts'], testPathIgnorePatterns: ['/node_modules/', '/dist/', '\\.d\\.ts$'], }; ``` -------------------------------------------------------------------------------- /debug.js: -------------------------------------------------------------------------------- ```javascript import { CoolifyMcpServer } from './dist/lib/mcp-server.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; // Enable debug logging process.env.DEBUG = '*'; const server = new CoolifyMcpServer({ baseUrl: 'https://coolify.dev', // Replace with your actual Coolify URL accessToken: 'your-actual-token' // Replace with your actual Coolify token }); const transport = new StdioServerTransport(); await server.connect(transport); ``` -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- ```json { "compilerOptions": { "target": "ES2020", "module": "NodeNext", "moduleResolution": "NodeNext", "declaration": true, "outDir": "./dist", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, "allowJs": true, "resolveJsonModule": true }, "include": ["src"], "exclude": ["node_modules", "dist", "tests"] } ``` -------------------------------------------------------------------------------- /docs/openapi-chunks/resources-api.yaml: -------------------------------------------------------------------------------- ```yaml openapi: 3.1.0 info: title: Coolify version: '0.1' paths: /resources: get: tags: - Resources summary: List description: Get all resources. operationId: list-resources responses: '200': description: Get all resources content: application/json: schema: type: string example: Content is very complex. Will be implemented later. '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] ``` -------------------------------------------------------------------------------- /docs/features/001-core-server-setup.md: -------------------------------------------------------------------------------- ```markdown # ADR 001: Core Server Setup ## Context Need basic MCP server implementation that can authenticate with Coolify and handle basic operations. ## Implementation Checklist - [x] Project structure setup - [x] TypeScript configuration - [x] ESLint + Prettier - [x] Jest/Vitest setup - [x] Basic GitHub Actions CI - [x] Core MCP Server - [x] Basic server class implementation - [x] Environment configuration (COOLIFY_ACCESS_TOKEN, COOLIFY_BASE_URL) - [x] Coolify API client wrapper - [x] Error handling structure - [x] Testing Infrastructure - [x] Mock Coolify API responses - [x] Basic integration test framework ## Dependencies - None (This is our first implementation) ``` -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- ```yaml name: CI on: push: branches: [main] pull_request: branches: [main] jobs: build: runs-on: ubuntu-latest strategy: matrix: node-version: [18.x, 20.x] steps: - uses: actions/checkout@v4 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} cache: 'npm' - name: Install dependencies run: npm ci - name: Security audit run: npm audit --audit-level=high - name: Format check run: npx prettier --check . - name: Lint run: npm run lint - name: Build run: npm run build - name: Test run: npm test ``` -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- ```typescript #!/usr/bin/env node import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CoolifyMcpServer } from './lib/mcp-server.js'; import { CoolifyConfig } from './types/coolify.js'; declare const process: NodeJS.Process; async function main(): Promise<void> { const config: CoolifyConfig = { baseUrl: process.env.COOLIFY_BASE_URL || 'http://localhost:3000', accessToken: process.env.COOLIFY_ACCESS_TOKEN || '', }; if (!config.accessToken) { throw new Error('COOLIFY_ACCESS_TOKEN environment variable is required'); } const server = new CoolifyMcpServer(config); const transport = new StdioServerTransport(); await server.connect(transport); } main().catch((error) => { console.error('Fatal error:', error); process.exit(1); }); ``` -------------------------------------------------------------------------------- /src/resources/deployment-resources.ts: -------------------------------------------------------------------------------- ```typescript import { Resource } from '../lib/resource.js'; import { CoolifyClient } from '../lib/coolify-client.js'; import { Deployment } from '../types/coolify.js'; export class DeploymentResources { private client: CoolifyClient; constructor(client: CoolifyClient) { this.client = client; } @Resource('coolify/deployments/list') async listDeployments(): Promise<Deployment[]> { // TODO: Implement listDeployments in CoolifyClient throw new Error('Not implemented'); } @Resource('coolify/deployments/{id}') async getDeployment(_id: string): Promise<Deployment> { // TODO: Implement getDeployment in CoolifyClient throw new Error('Not implemented'); } @Resource('coolify/deploy') async deploy(params: { uuid: string; forceRebuild?: boolean }): Promise<Deployment> { return this.client.deployApplication(params.uuid); } } ``` -------------------------------------------------------------------------------- /src/lib/resource.ts: -------------------------------------------------------------------------------- ```typescript import 'reflect-metadata'; /** * Metadata key for storing the resource URI */ const RESOURCE_URI_KEY = Symbol('resourceUri'); /** * Decorator for marking methods as MCP resources. * @param uri The URI pattern for the resource */ export function Resource(uri: string): MethodDecorator { return function ( target: object, propertyKey: string | symbol, descriptor: PropertyDescriptor, ): PropertyDescriptor { // Store the URI pattern in the method's metadata Reflect.defineMetadata(RESOURCE_URI_KEY, uri, target, propertyKey); return descriptor; }; } /** * Get the resource URI for a decorated method * @param target The class instance or constructor * @param propertyKey The method name * @returns The resource URI or undefined if not a resource */ export function getResourceUri(target: object, propertyKey: string | symbol): string | undefined { return Reflect.getMetadata(RESOURCE_URI_KEY, target, propertyKey); } ``` -------------------------------------------------------------------------------- /src/resources/service-resources.ts: -------------------------------------------------------------------------------- ```typescript import { Resource } from '../lib/resource.js'; import { CoolifyClient } from '../lib/coolify-client.js'; import { Service, CreateServiceRequest, DeleteServiceOptions } from '../types/coolify.js'; export class ServiceResources { private client: CoolifyClient; constructor(client: CoolifyClient) { this.client = client; } @Resource('coolify/services/list') async listServices(): Promise<Service[]> { return this.client.listServices(); } @Resource('coolify/services/{id}') async getService(id: string): Promise<Service> { return this.client.getService(id); } @Resource('coolify/services/create') async createService(data: CreateServiceRequest): Promise<{ uuid: string; domains: string[] }> { return this.client.createService(data); } @Resource('coolify/services/{id}/delete') async deleteService(id: string, options?: DeleteServiceOptions): Promise<{ message: string }> { return this.client.deleteService(id, options); } } ``` -------------------------------------------------------------------------------- /docs/features/002-server-info-resource.md: -------------------------------------------------------------------------------- ```markdown # ADR 002: Server Information Resources ## Context First useful feature - ability to get server information and status through MCP resources. ## API Endpoints Used - GET `/servers` (Line ~500) - Lists all servers - Response: Array of Server objects - Auth: Bearer token required - GET `/servers/{uuid}` (Line ~550) - Get server details - Response: Server object with status - Auth: Bearer token required - GET `/servers/{uuid}/status` (Line ~600) - Get server health and resource usage - Response: ServerStatus object - Auth: Bearer token required ## Implementation Checklist - [x] Basic Resource Implementation - [x] Server info resource (resources://coolify/server/info) - [x] Basic server details - [x] Version information - [x] Server status resource (resources://coolify/server/status) - [x] Health check - [x] Resource usage - [x] Resource Testing - [x] Unit tests for resource formatters - [x] Integration tests with mock data - [x] Live test with real Coolify instance ## Dependencies - ADR 001 (Core Server Setup) ``` -------------------------------------------------------------------------------- /src/resources/database-resources.ts: -------------------------------------------------------------------------------- ```typescript import { Resource } from '../lib/resource.js'; import { CoolifyClient } from '../lib/coolify-client.js'; import { Database, DatabaseUpdateRequest } from '../types/coolify.js'; export class DatabaseResources { private client: CoolifyClient; constructor(client: CoolifyClient) { this.client = client; } @Resource('coolify/databases/list') async listDatabases(): Promise<Database[]> { return this.client.listDatabases(); } @Resource('coolify/databases/{id}') async getDatabase(id: string): Promise<Database> { return this.client.getDatabase(id); } @Resource('coolify/databases/{id}/update') async updateDatabase(id: string, data: DatabaseUpdateRequest): Promise<Database> { return this.client.updateDatabase(id, data); } @Resource('coolify/databases/{id}/delete') async deleteDatabase( id: string, options?: { deleteConfigurations?: boolean; deleteVolumes?: boolean; dockerCleanup?: boolean; deleteConnectedNetworks?: boolean; }, ): Promise<{ message: string }> { return this.client.deleteDatabase(id, options); } } ``` -------------------------------------------------------------------------------- /src/resources/application-resources.ts: -------------------------------------------------------------------------------- ```typescript import { Resource } from '../lib/resource.js'; import { CoolifyClient } from '../lib/coolify-client.js'; import { Application, CreateApplicationRequest } from '../types/coolify.js'; export class ApplicationResources { private client: CoolifyClient; constructor(client: CoolifyClient) { this.client = client; } @Resource('coolify/applications/list') async listApplications(): Promise<Application[]> { // TODO: Implement listApplications in CoolifyClient throw new Error('Not implemented'); } @Resource('coolify/applications/{id}') async getApplication(_id: string): Promise<Application> { // TODO: Implement getApplication in CoolifyClient throw new Error('Not implemented'); } @Resource('coolify/applications/create') async createApplication(_data: CreateApplicationRequest): Promise<{ uuid: string }> { // TODO: Implement createApplication in CoolifyClient throw new Error('Not implemented'); } @Resource('coolify/applications/{id}/delete') async deleteApplication(_id: string): Promise<{ message: string }> { // TODO: Implement deleteApplication in CoolifyClient throw new Error('Not implemented'); } } ``` -------------------------------------------------------------------------------- /src/__tests__/resources/application-resources.test.ts: -------------------------------------------------------------------------------- ```typescript import { ApplicationResources } from '../../resources/application-resources.js'; import { CoolifyClient } from '../../lib/coolify-client.js'; import { jest } from '@jest/globals'; jest.mock('../../lib/coolify-client.js'); describe('ApplicationResources', () => { let resources: ApplicationResources; let mockClient: jest.Mocked<CoolifyClient>; beforeEach(() => { mockClient = { deployApplication: jest.fn(), } as unknown as jest.Mocked<CoolifyClient>; resources = new ApplicationResources(mockClient); }); describe('listApplications', () => { it('should throw not implemented error', async () => { await expect(resources.listApplications()).rejects.toThrow('Not implemented'); }); }); describe('getApplication', () => { it('should throw not implemented error', async () => { await expect(resources.getApplication('test-id')).rejects.toThrow('Not implemented'); }); }); describe('createApplication', () => { it('should throw not implemented error', async () => { await expect(resources.createApplication({ name: 'test-app' })).rejects.toThrow( 'Not implemented', ); }); }); describe('deleteApplication', () => { it('should throw not implemented error', async () => { await expect(resources.deleteApplication('test-id')).rejects.toThrow('Not implemented'); }); }); }); ``` -------------------------------------------------------------------------------- /docs/features/011-team-management.md: -------------------------------------------------------------------------------- ```markdown # ADR 011: Team Management ## Context Implementation of team management features through MCP resources, allowing users to manage teams and team members in Coolify. ## API Endpoints Used - GET `/teams` (List) - Lists all teams - Response: Array of Team objects - Auth: Bearer token required - GET `/teams/{id}` (Get) - Get team details by ID - Response: Team object - Auth: Bearer token required - GET `/teams/{id}/members` (List Members) - Get team members by team ID - Response: Array of User objects - Auth: Bearer token required - GET `/teams/current` (Get Current) - Get currently authenticated team - Response: Team object - Auth: Bearer token required - GET `/teams/current/members` (Get Current Members) - Get currently authenticated team members - Response: Array of User objects - Auth: Bearer token required ## Implementation Checklist - [ ] Basic Team Management - [ ] List teams resource - [ ] Get team details - [ ] List team members - [ ] Get current team - [ ] Get current team members - [ ] Team Features - [ ] Team information display - [ ] Member list management - [ ] Team permissions handling - [ ] Current team context - [ ] Resource Testing - [ ] Unit tests for team operations - [ ] Integration tests with mock data - [ ] Live test with real Coolify instance - [ ] Permission testing ## Dependencies - ADR 001 (Core Server Setup) - ADR 002 (Server Information Resources) ``` -------------------------------------------------------------------------------- /docs/features/003-project-management.md: -------------------------------------------------------------------------------- ```markdown # ADR 003: Project Management ## Context Basic project management functionality - first interactive feature allowing users to create and manage projects. ## API Endpoints Used - GET `/projects` (Line ~800) - Lists all projects - Response: Array of Project objects - Auth: Bearer token required - POST `/projects` (Line ~850) - Create new project - Request body: { name: string, description?: string } - Response: Project object - Auth: Bearer token required - GET `/projects/{uuid}` (Line ~900) - Get project details - Response: Project object with relationships - Auth: Bearer token required - DELETE `/projects/{uuid}` (Line ~950) - Delete project - Response: 204 No Content - Auth: Bearer token required - PUT `/projects/{uuid}` (Line ~1000) - Update project - Request body: { name?: string, description?: string } - Response: Updated Project object - Auth: Bearer token required ## Implementation Checklist - [x] Project List Resource - [x] resources://coolify/projects/list implementation - [x] Pagination support - [x] Basic filtering - [x] Project Management Tools - [x] createProject tool - [x] deleteProject tool - [x] updateProject tool - [x] Project Detail Resource - [x] resources://coolify/projects/{id} implementation - [x] Project status and configuration - [x] Testing - [x] CRUD operation tests - [x] Error handling tests - [x] Resource format tests ## Dependencies - ADR 001 (Core Server Setup) - ADR 002 (Server Information Resources) ``` -------------------------------------------------------------------------------- /docs/features/010-private-key-management.md: -------------------------------------------------------------------------------- ```markdown # ADR 010: Private Key Management ## Context Implementation of private key management features through MCP resources, allowing users to manage SSH keys for server access and deployment. ## API Endpoints Used - GET `/security/keys` (List) - Lists all private keys - Response: Array of PrivateKey objects - Auth: Bearer token required - POST `/security/keys` (Create) - Create a new private key - Required fields: - private_key - Optional fields: - name - description - Response: { uuid: string } - Auth: Bearer token required - GET `/security/keys/{uuid}` (Get) - Get private key details - Response: PrivateKey object - Auth: Bearer token required - PATCH `/security/keys` (Update) - Update a private key - Required fields: - private_key - Optional fields: - name - description - Response: { uuid: string } - Auth: Bearer token required - DELETE `/security/keys/{uuid}` (Delete) - Delete a private key - Response: { message: string } - Auth: Bearer token required ## Implementation Checklist - [ ] Basic Key Management - [ ] List private keys resource - [ ] Get private key details - [ ] Create private key - [ ] Update private key - [ ] Delete private key - [ ] Security Features - [ ] Secure key storage - [ ] Key validation - [ ] Usage tracking - [ ] Access control - [ ] Resource Testing - [ ] Unit tests for key operations - [ ] Integration tests with mock data - [ ] Live test with real Coolify instance - [ ] Security testing ## Dependencies - ADR 001 (Core Server Setup) - ADR 002 (Server Information Resources) ``` -------------------------------------------------------------------------------- /docs/features/004-environment-management.md: -------------------------------------------------------------------------------- ```markdown # ADR 004: Environment Management ## Context Environment management within projects - allows retrieving environment information and deploying applications within environments. ## API Endpoints Used - GET `/projects/{uuid}/{environment_name_or_uuid}` - Get environment details by project UUID and environment name/UUID - Response: Environment object - Auth: Bearer token required - POST `/applications/{uuid}/deploy` - Deploy an application using its UUID - Response: Deployment object - Auth: Bearer token required Note: Environment creation and management is handled through the Projects API. Environments are created and configured as part of project setup. ## Implementation Status ### Completed - [x] Environment Detail Resource - [x] GET project environment endpoint implemented - [x] Client method: `getProjectEnvironment` - [x] MCP tool: `get_project_environment` - [x] Application Deployment - [x] Deploy application endpoint implemented - [x] Client method: `deployApplication` - [x] MCP tool: `deploy_application` ### Environment Schema ```typescript interface Environment { id: number; name: string; project_id: number; created_at: string; updated_at: string; description: string; } ``` ## Dependencies - ADR 001 (Core Server Setup) - ADR 003 (Project Management) ## Notes - Environment management is tightly coupled with projects in the Coolify API - Environment variables are managed at the application level during application creation/updates - Direct environment CRUD operations are not available through dedicated endpoints - Environment information can be retrieved through the project endpoints ``` -------------------------------------------------------------------------------- /docs/features/006-database-management.md: -------------------------------------------------------------------------------- ```markdown # ADR 006: Database Management ## Context Implementation of database management features through MCP resources, allowing users to manage various types of databases (PostgreSQL, MySQL, MariaDB, MongoDB, Redis, etc.). ## API Endpoints Used - GET `/databases` (List) - Lists all databases - Response: Array of Database objects - Auth: Bearer token required - GET `/databases/{uuid}` (Get) - Get database details - Response: Database object - Auth: Bearer token required - DELETE `/databases/{uuid}` (Delete) - Delete database - Optional query params: - delete_configurations (boolean, default: true) - delete_volumes (boolean, default: true) - docker_cleanup (boolean, default: true) - delete_connected_networks (boolean, default: true) - Auth: Bearer token required - PATCH `/databases/{uuid}` (Update) - Update database configuration - Supports various database types: - PostgreSQL - MariaDB - MySQL - MongoDB - Redis - KeyDB - Clickhouse - Dragonfly ## Implementation Checklist - [x] Basic Database Management - [x] List databases resource - [x] Get database details - [x] Delete database - [x] Update database configuration - [x] Database Type Support - [x] PostgreSQL configuration - [x] MariaDB configuration - [x] MySQL configuration - [x] MongoDB configuration - [x] Redis configuration - [x] KeyDB configuration - [x] Clickhouse configuration - [x] Dragonfly configuration - [x] Resource Testing - [x] Unit tests for database operations - [x] Integration tests with mock data - [x] Live test with real Coolify instance ## Dependencies - ADR 001 (Core Server Setup) - ADR 002 (Server Information Resources) ``` -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- ```json { "name": "@masonator/coolify-mcp", "scope": "@masonator", "version": "0.2.8", "description": "MCP server implementation for Coolify", "type": "module", "main": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { ".": { "import": "./dist/index.js", "require": "./dist/index.cjs", "types": "./dist/index.d.ts" } }, "bin": { "coolify-mcp": "dist/index.js" }, "files": [ "dist" ], "scripts": { "build": "tsc && shx chmod +x dist/*.js", "dev": "tsc --watch", "test": "NODE_OPTIONS=--experimental-vm-modules jest", "test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch", "test:coverage": "NODE_OPTIONS=--experimental-vm-modules jest --coverage", "lint": "eslint . --ext .ts", "lint:fix": "eslint . --ext .ts --fix", "format": "prettier --write .", "format:check": "prettier --check .", "prepare": "husky", "prepublishOnly": "npm test && npm run lint", "start": "node dist/index.js" }, "keywords": [ "coolify", "mcp", "model-context-protocol" ], "author": "Stuart Mason", "license": "MIT", "dependencies": { "@modelcontextprotocol/sdk": "^1.6.1", "reflect-metadata": "^0.2.2", "zod": "^3.24.2" }, "devDependencies": { "@types/debug": "^4.1.12", "@types/jest": "^29.5.14", "@types/node": "^20.17.23", "@typescript-eslint/eslint-plugin": "^7.18.0", "@typescript-eslint/parser": "^7.18.0", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", "husky": "^9.0.11", "jest": "^29.7.0", "lint-staged": "^15.2.2", "markdownlint-cli2": "^0.12.1", "prettier": "^3.5.3", "shx": "^0.3.4", "ts-jest": "^29.2.6", "typescript": "^5.8.2" }, "engines": { "node": ">=18" } } ``` -------------------------------------------------------------------------------- /docs/features/009-mcp-prompts-implementation.md: -------------------------------------------------------------------------------- ```markdown # ADR 009: MCP Prompts Implementation ## Context Create reusable prompt templates for common Coolify workflows to make interactions more efficient. ## Implementation Checklist - [ ] Deployment Prompts - [ ] "deploy-application" prompt ```typescript { applicationId: string, version?: string, environment?: string } ``` - [ ] "rollback-deployment" prompt ```typescript { applicationId: string, deploymentId: string } ``` - [ ] Configuration Prompts - [ ] "configure-database" prompt ```typescript { databaseId: string, settings: DatabaseSettings } ``` - [ ] "configure-environment" prompt ```typescript { environmentId: string, variables: Record<string, string> } ``` - [ ] Service Management Prompts - [ ] "setup-service" prompt ```typescript { environmentId: string, serviceType: string, configuration: ServiceConfig } ``` - [ ] "troubleshoot-service" prompt ```typescript { serviceId: string, issueType?: "connectivity" | "performance" | "logs" } ``` - [ ] Resource Management Prompts - [ ] "optimize-resources" prompt ```typescript { resourceId: string, resourceType: "application" | "service" | "database" } ``` - [ ] "backup-management" prompt ```typescript { resourceId: string, operation: "create" | "restore" | "list" } ``` - [ ] Testing - [ ] Prompt validation tests - [ ] Response formatting tests - [ ] Error handling tests - [ ] Integration tests with actual commands ## Dependencies - ADR 001 (Core Server Setup) - ADR 005 (Application Deployment) - ADR 006 (Database Management) - ADR 007 (Service Management) - ADR 008 (MCP Resources Implementation) ``` -------------------------------------------------------------------------------- /src/__tests__/resources/deployment-resources.test.ts: -------------------------------------------------------------------------------- ```typescript import { DeploymentResources } from '../../resources/deployment-resources.js'; import { CoolifyClient } from '../../lib/coolify-client.js'; import { jest } from '@jest/globals'; jest.mock('../../lib/coolify-client.js'); describe('DeploymentResources', () => { let mockClient: jest.Mocked<CoolifyClient>; let resources: DeploymentResources; const mockDeployment = { id: 1, uuid: 'test-uuid', status: 'running', created_at: '2024-01-01', updated_at: '2024-01-01', application_uuid: 'app-uuid', environment_uuid: 'env-uuid', }; beforeEach(() => { mockClient = { deployApplication: jest.fn(), } as unknown as jest.Mocked<CoolifyClient>; resources = new DeploymentResources(mockClient); }); describe('listDeployments', () => { it('should throw not implemented error', async () => { await expect(resources.listDeployments()).rejects.toThrow('Not implemented'); }); }); describe('getDeployment', () => { it('should throw not implemented error', async () => { await expect(resources.getDeployment('test-id')).rejects.toThrow('Not implemented'); }); }); describe('deploy', () => { it('should deploy an application', async () => { mockClient.deployApplication.mockResolvedValue(mockDeployment); const result = await resources.deploy({ uuid: 'test-uuid' }); expect(result).toEqual(mockDeployment); expect(mockClient.deployApplication).toHaveBeenCalledWith('test-uuid'); }); it('should handle deployment errors', async () => { const error = new Error('Deployment failed'); mockClient.deployApplication.mockRejectedValue(error); await expect(resources.deploy({ uuid: 'test-uuid' })).rejects.toThrow('Deployment failed'); expect(mockClient.deployApplication).toHaveBeenCalledWith('test-uuid'); }); }); }); ``` -------------------------------------------------------------------------------- /docs/features/005-application-deployment.md: -------------------------------------------------------------------------------- ```markdown # ADR 005: Application Deployment ## Context Core application deployment functionality - allows deploying and managing applications within environments. ## API Endpoints Used - GET `/applications` (Line 10) - Lists all applications - Query params: environment_uuid (optional) - Response: Array of Application objects - Auth: Bearer token required - ✅ Implemented - POST `/applications/public` (Line 31) - Create new application from public repository - Request body: { project_uuid: string, environment_uuid: string, git_repository: string, git_branch: string, build_pack: "nixpacks" | "static" | "dockerfile" | "dockercompose", ports_exposes: string, name?: string, ...additional configuration } - Response: Application object - Auth: Bearer token required - ✅ Implemented - GET `/applications/{uuid}` (Line ~1600) - Get application details - Response: Application object with status - Auth: Bearer token required - ✅ Implemented - DELETE `/applications/{uuid}` (Line ~1650) - Delete application - Response: 204 No Content - Auth: Bearer token required - ✅ Implemented - POST `/applications/{uuid}/deploy` (Line ~1700) - Trigger application deployment - Response: Deployment object - Auth: Bearer token required - ✅ Implemented ## Implementation Checklist - [x] Application List Resource - [x] resources://coolify/applications/list - [x] Filter by environment/project - [x] Status information - [x] Application Management Tools - [x] createApplication tool - [x] deployApplication tool - [x] configureApplication tool - [x] deleteApplication tool - [x] Application Monitoring - [x] resources://coolify/applications/{id}/status - [x] Basic metrics - [x] Testing - [x] Deployment workflow tests - [x] Configuration management tests ## Dependencies - ADR 001 (Core Server Setup) - ADR 004 (Environment Management) ``` -------------------------------------------------------------------------------- /docs/features/future-adrs.md: -------------------------------------------------------------------------------- ```markdown # Future ADR Considerations Based on available Coolify API endpoints, here are potential future features to implement: ## Deployment Management - Webhook integration for GitHub, GitLab, Bitbucket, Gitea - POST `/webhooks/github/{uuid}` (Line ~4000) - POST `/webhooks/gitlab/{uuid}` (Line ~4050) - POST `/webhooks/bitbucket/{uuid}` (Line ~4100) - POST `/webhooks/gitea/{uuid}` (Line ~4150) - Build pack support - POST `/applications/{uuid}/buildpack` (Line ~4200) - GET `/buildpacks/templates` (Line ~4250) - Custom deployment commands - POST `/applications/{uuid}/commands/pre-deploy` (Line ~4300) - POST `/applications/{uuid}/commands/post-deploy` (Line ~4350) ## Resource Management - Resource limits management - PUT `/applications/{uuid}/limits` (Line ~4400) - PUT `/services/{uuid}/limits` (Line ~4450) - GET `/resources/usage` (Line ~4500) - Health check configuration - PUT `/applications/{uuid}/health` (Line ~4550) - GET `/applications/{uuid}/health/status` (Line ~4600) ## Network Management - Domain management - POST `/domains` (Line ~4650) - GET `/domains/{uuid}/verify` (Line ~4700) - PUT `/domains/{uuid}/ssl` (Line ~4750) - SSL/TLS configuration - POST `/certificates` (Line ~4800) - GET `/certificates/{uuid}/status` (Line ~4850) ## Build Management - Build server configuration - POST `/build-servers` (Line ~4900) - GET `/build-servers/{uuid}/status` (Line ~4950) - PUT `/build-servers/{uuid}/cache` (Line ~5000) ## Team Management - Team member management - POST `/teams` (Line ~5050) - POST `/teams/{uuid}/members` (Line ~5100) - PUT `/teams/{uuid}/permissions` (Line ~5150) - API key management - POST `/api-keys` (Line ~5200) - GET `/api-keys/{uuid}/usage` (Line ~5250) ## Monitoring and Logging - Resource usage monitoring - GET `/monitoring/resources` (Line ~5300) - GET `/monitoring/alerts` (Line ~5350) - Centralized logging - GET `/logs/aggregate` (Line ~5400) - POST `/logs/search` (Line ~5450) Each of these could be developed into full ADRs once the core functionality is stable. The line numbers reference the OpenAPI specification for implementation details. ``` -------------------------------------------------------------------------------- /docs/features/007-service-management.md: -------------------------------------------------------------------------------- ```markdown # ADR 007: Service Management ## Context Implementation of one-click service management features through MCP resources, allowing users to deploy and manage various pre-configured services. ## API Endpoints Used - GET `/services` (List) - Lists all services - Response: Array of Service objects - Auth: Bearer token required - POST `/services` (Create) - Create a one-click service - Required fields: - server_uuid - project_uuid - environment_name/uuid - type (one of many supported service types) - Optional fields: - name - description - destination_uuid - instant_deploy - Auth: Bearer token required - GET `/services/{uuid}` (Get) - Get service details - Response: Service object - Auth: Bearer token required - DELETE `/services/{uuid}` (Delete) - Delete service - Optional query params: - delete_configurations (boolean, default: true) - delete_volumes (boolean, default: true) - docker_cleanup (boolean, default: true) - delete_connected_networks (boolean, default: true) - Auth: Bearer token required ## Supported Service Types - Development Tools: - code-server - gitea (with various DB options) - docker-registry - CMS & Documentation: - wordpress (with various DB options) - ghost - mediawiki - dokuwiki - Monitoring & Analytics: - grafana - umami - glances - uptime-kuma - Collaboration & Communication: - rocketchat - chatwoot - nextcloud - Database Management: - phpmyadmin - nocodb - directus - And many more specialized services ## Implementation Checklist - [x] Basic Service Management - [x] List services resource - [x] Get service details - [x] Create service - [x] Delete service - [x] Service Type Support - [x] Development tools deployment - [x] CMS system deployment - [x] Monitoring tools deployment - [x] Collaboration tools deployment - [x] Database tools deployment - [x] Resource Testing - [x] Unit tests for service operations - [x] Integration tests with mock data - [x] Live test with real Coolify instance ## Dependencies - ADR 001 (Core Server Setup) - ADR 002 (Server Information Resources) - ADR 003 (Project Management) ``` -------------------------------------------------------------------------------- /docs/features/008-mcp-resources-implementation.md: -------------------------------------------------------------------------------- ```markdown # ADR 008: MCP Resources Implementation ## Context Implement MCP resources for managing Coolify entities through the available API endpoints. ## API Endpoints Used - Database Management: - GET `/databases` - List databases - GET `/databases/{uuid}` - Get database details - POST `/databases/{type}` - Create database - PATCH `/databases/{uuid}` - Update database - DELETE `/databases/{uuid}` - Delete database - Deployment Management: - GET `/deployments` - List deployments - GET `/deployments/{uuid}` - Get deployment details - GET `/deploy` - Deploy by tag or uuid - Application Management: - GET `/applications` - List applications - GET `/applications/{uuid}` - Get application details - POST `/applications/public` - Create public application - DELETE `/applications/{uuid}` - Delete application - Service Management: - GET `/services` - List services - GET `/services/{uuid}` - Get service details - POST `/services` - Create service - DELETE `/services/{uuid}` - Delete service ## Implementation Checklist - [ ] Database Resources - [ ] resources://coolify/databases/list - [ ] resources://coolify/databases/{id} - [ ] resources://coolify/databases/create/{type} - [ ] resources://coolify/databases/{id}/update - [ ] resources://coolify/databases/{id}/delete - [ ] Deployment Resources - [ ] resources://coolify/deployments/list - [ ] resources://coolify/deployments/{id} - [ ] resources://coolify/deploy - Support for tag-based deployment - Support for UUID-based deployment - Force rebuild option - [ ] Application Resources - [ ] resources://coolify/applications/list - [ ] resources://coolify/applications/{id} - [ ] resources://coolify/applications/create - [ ] resources://coolify/applications/{id}/delete - [ ] Service Resources - [ ] resources://coolify/services/list - [ ] resources://coolify/services/{id} - [ ] resources://coolify/services/create - [ ] resources://coolify/services/{id}/delete - [ ] Testing - [ ] Database operation tests - [ ] Deployment operation tests - [ ] Application operation tests - [ ] Service operation tests - [ ] Error handling tests - [ ] Permission validation tests ## Dependencies - ADR 001 (Core Server Setup) - ADR 005 (Application Deployment) - ADR 006 (Database Management) - ADR 007 (Service Management) ``` -------------------------------------------------------------------------------- /src/__tests__/resources/database-resources.test.ts: -------------------------------------------------------------------------------- ```typescript import { DatabaseResources } from '../../resources/database-resources.js'; import { CoolifyClient } from '../../lib/coolify-client.js'; import { PostgresDatabase } from '../../types/coolify.js'; import { jest } from '@jest/globals'; jest.mock('../../lib/coolify-client.js'); describe('DatabaseResources', () => { let mockClient: jest.Mocked<CoolifyClient>; let resources: DatabaseResources; const mockDatabase: PostgresDatabase = { id: 1, uuid: 'test-uuid', name: 'test-db', description: 'test description', type: 'postgresql', status: 'running', created_at: '2024-01-01', updated_at: '2024-01-01', is_public: false, image: 'postgres:latest', postgres_user: 'test', postgres_password: 'test', postgres_db: 'test', }; beforeEach(() => { mockClient = { listDatabases: jest.fn(), getDatabase: jest.fn(), updateDatabase: jest.fn(), deleteDatabase: jest.fn(), } as unknown as jest.Mocked<CoolifyClient>; resources = new DatabaseResources(mockClient); }); describe('listDatabases', () => { it('should return a list of databases', async () => { mockClient.listDatabases.mockResolvedValue([mockDatabase]); const result = await resources.listDatabases(); expect(result).toEqual([mockDatabase]); expect(mockClient.listDatabases).toHaveBeenCalled(); }); }); describe('getDatabase', () => { it('should return a database by uuid', async () => { mockClient.getDatabase.mockResolvedValue(mockDatabase); const result = await resources.getDatabase('test-uuid'); expect(result).toEqual(mockDatabase); expect(mockClient.getDatabase).toHaveBeenCalledWith('test-uuid'); }); }); describe('updateDatabase', () => { it('should update a database', async () => { const updateData = { name: 'updated-db', description: 'updated description', }; mockClient.updateDatabase.mockResolvedValue({ ...mockDatabase, ...updateData }); const result = await resources.updateDatabase('test-uuid', updateData); expect(result).toEqual({ ...mockDatabase, ...updateData }); expect(mockClient.updateDatabase).toHaveBeenCalledWith('test-uuid', updateData); }); }); describe('deleteDatabase', () => { it('should delete a database', async () => { const mockResponse = { message: 'Database deleted successfully' }; mockClient.deleteDatabase.mockResolvedValue(mockResponse); const result = await resources.deleteDatabase('test-uuid', {}); expect(result).toEqual(mockResponse); expect(mockClient.deleteDatabase).toHaveBeenCalledWith('test-uuid', {}); }); }); }); ``` -------------------------------------------------------------------------------- /docs/openapi-chunks/untagged-api.yaml: -------------------------------------------------------------------------------- ```yaml openapi: 3.1.0 info: title: Coolify version: '0.1' paths: /version: get: summary: Version description: Get Coolify version. operationId: version responses: '200': description: Returns the version of the application content: application/json: schema: type: string example: v4.0.0 '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] /enable: get: summary: Enable API description: Enable API (only with root permissions). operationId: enable-api responses: '200': description: Enable API. content: application/json: schema: properties: message: type: string example: API enabled. type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '403': description: You are not allowed to enable the API. content: application/json: schema: properties: message: type: string example: You are not allowed to enable the API. type: object security: - bearerAuth: [] /disable: get: summary: Disable API description: Disable API (only with root permissions). operationId: disable-api responses: '200': description: Disable API. content: application/json: schema: properties: message: type: string example: API disabled. type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '403': description: You are not allowed to disable the API. content: application/json: schema: properties: message: type: string example: You are not allowed to disable the API. type: object security: - bearerAuth: [] /health: get: summary: Healthcheck description: Healthcheck endpoint. operationId: healthcheck responses: '200': description: Healthcheck endpoint. content: application/json: schema: type: string example: OK '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' ``` -------------------------------------------------------------------------------- /src/__tests__/resources/service-resources.test.ts: -------------------------------------------------------------------------------- ```typescript import { ServiceResources } from '../../resources/service-resources.js'; import { CoolifyClient } from '../../lib/coolify-client.js'; import { Service, ServiceType } from '../../types/coolify.js'; import { jest } from '@jest/globals'; jest.mock('../../lib/coolify-client.js'); describe('ServiceResources', () => { let mockClient: jest.Mocked<CoolifyClient>; let resources: ServiceResources; const mockService: Service = { id: 1, uuid: 'test-uuid', name: 'test-service', description: 'test description', type: 'code-server', status: 'running', created_at: '2024-01-01', updated_at: '2024-01-01', project_uuid: 'project-uuid', environment_name: 'test-env', environment_uuid: 'env-uuid', server_uuid: 'server-uuid', domains: ['test.com'], }; beforeEach(() => { mockClient = { listServices: jest.fn(), getService: jest.fn(), createService: jest.fn(), deleteService: jest.fn(), } as unknown as jest.Mocked<CoolifyClient>; resources = new ServiceResources(mockClient); }); describe('listServices', () => { it('should return a list of services', async () => { mockClient.listServices.mockResolvedValue([mockService]); const result = await resources.listServices(); expect(result).toEqual([mockService]); expect(mockClient.listServices).toHaveBeenCalled(); }); }); describe('getService', () => { it('should return a service by uuid', async () => { mockClient.getService.mockResolvedValue(mockService); const result = await resources.getService('test-uuid'); expect(result).toEqual(mockService); expect(mockClient.getService).toHaveBeenCalledWith('test-uuid'); }); }); describe('createService', () => { it('should create a new service', async () => { const createData = { name: 'new-service', type: 'code-server' as ServiceType, project_uuid: 'project-uuid', environment_name: 'test-env', environment_uuid: 'env-uuid', server_uuid: 'server-uuid', }; const mockResponse = { uuid: 'new-uuid', domains: ['new-service.test.com'], }; mockClient.createService.mockResolvedValue(mockResponse); const result = await resources.createService(createData); expect(result).toEqual(mockResponse); expect(mockClient.createService).toHaveBeenCalledWith(createData); }); }); describe('deleteService', () => { it('should delete a service', async () => { const mockResponse = { message: 'Service deleted' }; mockClient.deleteService.mockResolvedValue(mockResponse); const result = await resources.deleteService('test-uuid'); expect(result).toEqual(mockResponse); expect(mockClient.deleteService).toHaveBeenCalledWith('test-uuid', undefined); }); }); }); ``` -------------------------------------------------------------------------------- /docs/openapi-chunks/deployments-api.yaml: -------------------------------------------------------------------------------- ```yaml openapi: 3.1.0 info: title: Coolify version: '0.1' paths: /deployments: get: tags: - Deployments summary: List description: List currently running deployments operationId: list-deployments responses: '200': description: Get all currently running deployments. content: application/json: schema: type: array items: $ref: '#/components/schemas/ApplicationDeploymentQueue' '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] /deployments/{uuid}: get: tags: - Deployments summary: Get description: Get deployment by UUID. operationId: get-deployment-by-uuid parameters: - name: uuid in: path description: Deployment UUID required: true schema: type: string responses: '200': description: Get deployment by UUID. content: application/json: schema: $ref: '#/components/schemas/ApplicationDeploymentQueue' '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /deploy: get: tags: - Deployments summary: Deploy description: Deploy by tag or uuid. `Post` request also accepted. operationId: deploy-by-tag-or-uuid parameters: - name: tag in: query description: Tag name(s). Comma separated list is also accepted. schema: type: string - name: uuid in: query description: Resource UUID(s). Comma separated list is also accepted. schema: type: string - name: force in: query description: Force rebuild (without cache) schema: type: boolean responses: '200': description: Get deployment(s) UUID's content: application/json: schema: properties: deployments: type: array items: properties: message: type: string resource_uuid: type: string deployment_uuid: type: string type: object type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] ``` -------------------------------------------------------------------------------- /docs/openapi-chunks/teams-api.yaml: -------------------------------------------------------------------------------- ```yaml openapi: 3.1.0 info: title: Coolify version: '0.1' paths: /teams: get: tags: - Teams summary: List description: Get all teams. operationId: list-teams responses: '200': description: List of teams. content: application/json: schema: type: array items: $ref: '#/components/schemas/Team' '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] /teams/{id}: get: tags: - Teams summary: Get description: Get team by TeamId. operationId: get-team-by-id parameters: - name: id in: path description: Team ID required: true schema: type: integer responses: '200': description: List of teams. content: application/json: schema: $ref: '#/components/schemas/Team' '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /teams/{id}/members: get: tags: - Teams summary: Members description: Get members by TeamId. operationId: get-members-by-team-id parameters: - name: id in: path description: Team ID required: true schema: type: integer responses: '200': description: List of members. content: application/json: schema: type: array items: $ref: '#/components/schemas/User' '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /teams/current: get: tags: - Teams summary: Authenticated Team description: Get currently authenticated team. operationId: get-current-team responses: '200': description: Current Team. content: application/json: schema: $ref: '#/components/schemas/Team' '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] /teams/current/members: get: tags: - Teams summary: Authenticated Team Members description: Get currently authenticated team members. operationId: get-current-team-members responses: '200': description: Currently authenticated team members. content: application/json: schema: type: array items: $ref: '#/components/schemas/User' '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] ``` -------------------------------------------------------------------------------- /docs/openapi-chunks/private-keys-api.yaml: -------------------------------------------------------------------------------- ```yaml openapi: 3.1.0 info: title: Coolify version: '0.1' paths: /security/keys: get: tags: - Private Keys summary: List description: List all private keys. operationId: list-private-keys responses: '200': description: Get all private keys. content: application/json: schema: type: array items: $ref: '#/components/schemas/PrivateKey' '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] post: tags: - Private Keys summary: Create description: Create a new private key. operationId: create-private-key requestBody: required: true content: application/json: schema: required: - private_key properties: name: type: string description: type: string private_key: type: string type: object additionalProperties: false responses: '201': description: The created private key's UUID. content: application/json: schema: properties: uuid: type: string type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] patch: tags: - Private Keys summary: Update description: Update a private key. operationId: update-private-key requestBody: required: true content: application/json: schema: required: - private_key properties: name: type: string description: type: string private_key: type: string type: object additionalProperties: false responses: '201': description: The updated private key's UUID. content: application/json: schema: properties: uuid: type: string type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] /security/keys/{uuid}: get: tags: - Private Keys summary: Get description: Get key by UUID. operationId: get-private-key-by-uuid parameters: - name: uuid in: path description: Private Key UUID required: true schema: type: string responses: '200': description: Get all private keys. content: application/json: schema: $ref: '#/components/schemas/PrivateKey' '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': description: Private Key not found. security: - bearerAuth: [] delete: tags: - Private Keys summary: Delete description: Delete a private key. operationId: delete-private-key-by-uuid parameters: - name: uuid in: path description: Private Key UUID required: true schema: type: string responses: '200': description: Private Key deleted. content: application/json: schema: properties: message: type: string example: Private Key deleted. type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': description: Private Key not found. security: - bearerAuth: [] ``` -------------------------------------------------------------------------------- /docs/openapi-chunks/projects-api.yaml: -------------------------------------------------------------------------------- ```yaml openapi: 3.1.0 info: title: Coolify version: '0.1' paths: /projects: get: tags: - Projects summary: List description: List projects. operationId: list-projects responses: '200': description: Get all projects. content: application/json: schema: type: array items: $ref: '#/components/schemas/Project' '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] post: tags: - Projects summary: Create description: Create Project. operationId: create-project requestBody: description: Project created. required: true content: application/json: schema: properties: name: type: string description: The name of the project. description: type: string description: The description of the project. type: object responses: '201': description: Project created. content: application/json: schema: properties: uuid: type: string example: og888os description: The UUID of the project. type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /projects/{uuid}: get: tags: - Projects summary: Get description: Get project by UUID. operationId: get-project-by-uuid parameters: - name: uuid in: path description: Project UUID required: true schema: type: string responses: '200': description: Project details content: application/json: schema: $ref: '#/components/schemas/Project' '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': description: Project not found. security: - bearerAuth: [] delete: tags: - Projects summary: Delete description: Delete project by UUID. operationId: delete-project-by-uuid parameters: - name: uuid in: path description: UUID of the application. required: true schema: type: string format: uuid responses: '200': description: Project deleted. content: application/json: schema: properties: message: type: string example: Project deleted. type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] patch: tags: - Projects summary: Update description: Update Project. operationId: update-project-by-uuid requestBody: description: Project updated. required: true content: application/json: schema: properties: name: type: string description: The name of the project. description: type: string description: The description of the project. type: object responses: '201': description: Project updated. content: application/json: schema: properties: uuid: type: string example: og888os name: type: string example: Project Name description: type: string example: Project Description type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /projects/{uuid}/{environment_name_or_uuid}: get: tags: - Projects summary: Environment description: Get environment by name or UUID. operationId: get-environment-by-name-or-uuid parameters: - name: uuid in: path description: Project UUID required: true schema: type: string - name: environment_name_or_uuid in: path description: Environment name or UUID required: true schema: type: string responses: '200': description: Environment details content: application/json: schema: $ref: '#/components/schemas/Environment' '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] ``` -------------------------------------------------------------------------------- /src/lib/coolify-client.ts: -------------------------------------------------------------------------------- ```typescript 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 } ``` -------------------------------------------------------------------------------- /src/__tests__/coolify-client.test.ts: -------------------------------------------------------------------------------- ```typescript import { jest } from '@jest/globals'; import { CoolifyClient } from '../lib/coolify-client.js'; import { ServiceType, CreateServiceRequest } from '../types/coolify.js'; const mockFetch = jest.fn() as any; describe('CoolifyClient', () => { let client: CoolifyClient; const mockServers = [ { id: 1, uuid: 'test-uuid', name: 'test-server', status: 'running', }, ]; const mockServerInfo = { id: 1, uuid: 'test-uuid', name: 'test-server', status: 'running', }; const mockServerResources = { resources: [ { name: 'memory', value: '2GB', }, { name: 'disk', value: '20GB', }, ], }; const mockService = { id: 1, uuid: 'test-uuid', name: 'test-service', type: 'code-server' as ServiceType, status: 'running', created_at: '2024-01-01', updated_at: '2024-01-01', }; const errorResponse = { message: 'Resource not found', }; beforeEach(() => { mockFetch.mockClear(); (global as any).fetch = mockFetch; client = new CoolifyClient({ baseUrl: 'http://localhost:3000', accessToken: 'test-api-key', }); }); describe('listServers', () => { it('should return a list of servers', async () => { mockFetch.mockImplementationOnce( async () => ({ ok: true, json: async () => mockServers, }) as Response, ); const servers = await client.listServers(); expect(servers).toEqual(mockServers); expect(mockFetch).toHaveBeenCalledWith('http://localhost:3000/api/v1/servers', { headers: { 'Content-Type': 'application/json', Authorization: 'Bearer test-api-key', }, }); }); it('should handle errors', async () => { mockFetch.mockImplementationOnce(() => Promise.resolve({ ok: false, json: async () => errorResponse, } as Response), ); await expect(client.listServers()).rejects.toThrow('Resource not found'); }); }); describe('getServer', () => { it('should get server info', async () => { mockFetch.mockImplementationOnce(() => Promise.resolve({ ok: true, json: async () => mockServerInfo, } as Response), ); const result = await client.getServer('test-uuid'); expect(result).toEqual(mockServerInfo); expect(mockFetch).toHaveBeenCalledWith('http://localhost:3000/api/v1/servers/test-uuid', { headers: { 'Content-Type': 'application/json', Authorization: 'Bearer test-api-key', }, }); }); it('should handle errors', async () => { mockFetch.mockImplementationOnce(() => Promise.resolve({ ok: false, json: async () => errorResponse, } as Response), ); await expect(client.getServer('test-uuid')).rejects.toThrow('Resource not found'); }); }); describe('getServerResources', () => { it('should get server resources', async () => { mockFetch.mockImplementationOnce(() => Promise.resolve({ ok: true, json: async () => mockServerResources, } as Response), ); const result = await client.getServerResources('test-uuid'); expect(result).toEqual(mockServerResources); expect(mockFetch).toHaveBeenCalledWith( 'http://localhost:3000/api/v1/servers/test-uuid/resources', { headers: { 'Content-Type': 'application/json', Authorization: 'Bearer test-api-key', }, }, ); }); it('should handle errors', async () => { mockFetch.mockImplementationOnce(() => Promise.resolve({ ok: false, json: async () => errorResponse, } as Response), ); await expect(client.getServerResources('test-uuid')).rejects.toThrow('Resource not found'); }); }); describe('listServices', () => { it('should list services', async () => { mockFetch.mockImplementationOnce(() => Promise.resolve({ ok: true, json: () => Promise.resolve([mockService]), } as Response), ); const result = await client.listServices(); expect(result).toEqual([mockService]); expect(mockFetch).toHaveBeenCalledWith('http://localhost:3000/api/v1/services', { headers: { 'Content-Type': 'application/json', Authorization: 'Bearer test-api-key', }, }); }); }); describe('getService', () => { it('should get service info', async () => { mockFetch.mockImplementationOnce(() => Promise.resolve({ ok: true, json: () => Promise.resolve(mockService), } as Response), ); const result = await client.getService('test-uuid'); expect(result).toEqual(mockService); expect(mockFetch).toHaveBeenCalledWith('http://localhost:3000/api/v1/services/test-uuid', { headers: { 'Content-Type': 'application/json', Authorization: 'Bearer test-api-key', }, }); }); }); describe('createService', () => { it('should create a service', async () => { mockFetch.mockImplementationOnce(() => Promise.resolve({ ok: true, json: () => Promise.resolve({ uuid: 'test-uuid', domains: ['test.com'], }), } as Response), ); const createData: CreateServiceRequest = { name: 'test-service', type: 'code-server', project_uuid: 'project-uuid', environment_uuid: 'env-uuid', server_uuid: 'server-uuid', }; const result = await client.createService(createData); expect(result).toEqual({ uuid: 'test-uuid', domains: ['test.com'], }); expect(mockFetch).toHaveBeenCalledWith('http://localhost:3000/api/v1/services', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: 'Bearer test-api-key', }, body: JSON.stringify(createData), }); }); }); describe('deleteService', () => { it('should delete a service', async () => { mockFetch.mockImplementationOnce(() => Promise.resolve({ ok: true, json: () => Promise.resolve({ message: 'Service deleted' }), } as Response), ); const result = await client.deleteService('test-uuid'); expect(result).toEqual({ message: 'Service deleted' }); expect(mockFetch).toHaveBeenCalledWith('http://localhost:3000/api/v1/services/test-uuid', { method: 'DELETE', headers: { 'Content-Type': 'application/json', Authorization: 'Bearer test-api-key', }, }); }); }); describe('error handling', () => { it('should handle network errors', async () => { const errorMessage = 'Network error'; mockFetch.mockImplementationOnce(() => Promise.reject(new Error(errorMessage))); await expect(client.listServers()).rejects.toThrow(errorMessage); }); }); }); ``` -------------------------------------------------------------------------------- /src/types/coolify.ts: -------------------------------------------------------------------------------- ```typescript export interface CoolifyConfig { baseUrl: string; accessToken: string; } export interface ServerInfo { uuid: string; name: string; status: 'running' | 'stopped' | 'error'; version: string; resources: { cpu: number; memory: number; disk: number; }; } export interface ResourceStatus { id: number; uuid: string; name: string; type: string; created_at: string; updated_at: string; status: string; } export type ServerResources = ResourceStatus[]; export interface ErrorResponse { error: string; status: number; message: string; } export interface ServerDomain { ip: string; domains: string[]; } export interface ValidationResponse { message: string; } export interface Environment { id: number; uuid: string; name: string; project_uuid: string; variables?: Record<string, string>; created_at: string; updated_at: string; } export interface Project { id: number; uuid: string; name: string; description?: string; environments?: Environment[]; } export interface CreateProjectRequest { name: string; description?: string; } export interface UpdateProjectRequest { name?: string; description?: string; } export interface LogEntry { timestamp: string; level: string; message: string; } export interface Deployment { id: number; uuid: string; application_uuid: string; status: string; created_at: string; updated_at: string; } export interface DatabaseBase { id: number; uuid: string; name: string; description?: string; type: | 'postgresql' | 'mysql' | 'mariadb' | 'mongodb' | 'redis' | 'keydb' | 'clickhouse' | 'dragonfly'; status: 'running' | 'stopped' | 'error'; created_at: string; updated_at: string; is_public: boolean; public_port?: number; image: string; limits?: { memory?: string; memory_swap?: string; memory_swappiness?: number; memory_reservation?: string; cpus?: string; cpuset?: string; cpu_shares?: number; }; } export interface PostgresDatabase extends DatabaseBase { type: 'postgresql'; postgres_user: string; postgres_password: string; postgres_db: string; postgres_initdb_args?: string; postgres_host_auth_method?: string; postgres_conf?: string; } export interface MySQLDatabase extends DatabaseBase { type: 'mysql'; mysql_root_password: string; mysql_user?: string; mysql_password?: string; mysql_database?: string; } export interface MariaDBDatabase extends DatabaseBase { type: 'mariadb'; mariadb_root_password: string; mariadb_user?: string; mariadb_password?: string; mariadb_database?: string; mariadb_conf?: string; } export interface MongoDBDatabase extends DatabaseBase { type: 'mongodb'; mongo_initdb_root_username: string; mongo_initdb_root_password: string; mongo_initdb_database?: string; mongo_conf?: string; } export interface RedisDatabase extends DatabaseBase { type: 'redis'; redis_password?: string; redis_conf?: string; } export interface KeyDBDatabase extends DatabaseBase { type: 'keydb'; keydb_password?: string; keydb_conf?: string; } export interface ClickhouseDatabase extends DatabaseBase { type: 'clickhouse'; clickhouse_admin_user: string; clickhouse_admin_password: string; } export interface DragonflyDatabase extends DatabaseBase { type: 'dragonfly'; dragonfly_password: string; } export type Database = | PostgresDatabase | MySQLDatabase | MariaDBDatabase | MongoDBDatabase | RedisDatabase | KeyDBDatabase | ClickhouseDatabase | DragonflyDatabase; export interface DatabaseUpdateRequest { name?: string; description?: string; image?: string; is_public?: boolean; public_port?: number; limits_memory?: string; limits_memory_swap?: string; limits_memory_swappiness?: number; limits_memory_reservation?: string; limits_cpus?: string; limits_cpuset?: string; limits_cpu_shares?: number; postgres_user?: string; postgres_password?: string; postgres_db?: string; postgres_initdb_args?: string; postgres_host_auth_method?: string; postgres_conf?: string; clickhouse_admin_user?: string; clickhouse_admin_password?: string; dragonfly_password?: string; redis_password?: string; redis_conf?: string; keydb_password?: string; keydb_conf?: string; mariadb_conf?: string; mariadb_root_password?: string; mariadb_user?: string; mariadb_password?: string; mariadb_database?: string; mongo_conf?: string; mongo_initdb_root_username?: string; mongo_initdb_root_password?: string; mongo_initdb_database?: string; mysql_root_password?: string; mysql_password?: string; mysql_user?: string; mysql_database?: string; } export type ServiceType = | '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'; export interface Service { id: number; uuid: string; name: string; description?: string; type: ServiceType; status: 'running' | 'stopped' | 'error'; created_at: string; updated_at: string; project_uuid: string; environment_name: string; environment_uuid: string; server_uuid: string; destination_uuid?: string; domains?: string[]; } export interface CreateServiceRequest { type: ServiceType; name?: string; description?: string; project_uuid: string; environment_name?: string; environment_uuid?: string; server_uuid: string; destination_uuid?: string; instant_deploy?: boolean; } export interface DeleteServiceOptions { deleteConfigurations?: boolean; deleteVolumes?: boolean; dockerCleanup?: boolean; deleteConnectedNetworks?: boolean; } export interface Application { uuid: string; name: string; // Add other application properties as needed } export interface CreateApplicationRequest { name: string; // Add other required fields for application creation } ``` -------------------------------------------------------------------------------- /docs/openapi-chunks/servers-api.yaml: -------------------------------------------------------------------------------- ```yaml openapi: 3.1.0 info: title: Coolify version: '0.1' paths: /servers: get: tags: - Servers summary: List description: List all servers. operationId: list-servers responses: '200': description: Get all servers. content: application/json: schema: type: array items: $ref: '#/components/schemas/Server' '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] post: tags: - Servers summary: Create description: Create Server. operationId: create-server requestBody: description: Server created. required: true content: application/json: schema: properties: name: type: string example: My Server description: The name of the server. description: type: string example: My Server Description description: The description of the server. ip: type: string example: 127.0.0.1 description: The IP of the server. port: type: integer example: 22 description: The port of the server. user: type: string example: root description: The user of the server. private_key_uuid: type: string example: og888os description: The UUID of the private key. is_build_server: type: boolean example: false description: Is build server. instant_validate: type: boolean example: false description: Instant validate. proxy_type: type: string enum: - traefik - caddy - none example: traefik description: The proxy type. type: object responses: '201': description: Server created. content: application/json: schema: properties: uuid: type: string example: og888os description: The UUID of the server. type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /servers/{uuid}: get: tags: - Servers summary: Get description: Get server by UUID. operationId: get-server-by-uuid parameters: - name: uuid in: path description: Server's UUID required: true schema: type: string responses: '200': description: Get server by UUID content: application/json: schema: $ref: '#/components/schemas/Server' '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] delete: tags: - Servers summary: Delete description: Delete server by UUID. operationId: delete-server-by-uuid parameters: - name: uuid in: path description: UUID of the server. required: true schema: type: string format: uuid responses: '200': description: Server deleted. content: application/json: schema: properties: message: type: string example: Server deleted. type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] patch: tags: - Servers summary: Update description: Update Server. operationId: update-server-by-uuid parameters: - name: uuid in: path description: Server UUID required: true schema: type: string requestBody: description: Server updated. required: true content: application/json: schema: properties: name: type: string description: The name of the server. description: type: string description: The description of the server. ip: type: string description: The IP of the server. port: type: integer description: The port of the server. user: type: string description: The user of the server. private_key_uuid: type: string description: The UUID of the private key. is_build_server: type: boolean description: Is build server. instant_validate: type: boolean description: Instant validate. proxy_type: type: string enum: - traefik - caddy - none description: The proxy type. type: object responses: '201': description: Server updated. content: application/json: schema: $ref: '#/components/schemas/Server' '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /servers/{uuid}/resources: get: tags: - Servers summary: Resources description: Get resources by server. operationId: get-resources-by-server-uuid parameters: - name: uuid in: path description: Server's UUID required: true schema: type: string responses: '200': description: Get resources by server content: application/json: schema: type: array items: properties: id: type: integer uuid: type: string name: type: string type: type: string created_at: type: string updated_at: type: string status: type: string type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] /servers/{uuid}/domains: get: tags: - Servers summary: Domains description: Get domains by server. operationId: get-domains-by-server-uuid parameters: - name: uuid in: path description: Server's UUID required: true schema: type: string responses: '200': description: Get domains by server content: application/json: schema: type: array items: properties: ip: type: string domains: type: array items: type: string type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] /servers/{uuid}/validate: get: tags: - Servers summary: Validate description: Validate server by UUID. operationId: validate-server-by-uuid parameters: - name: uuid in: path description: Server UUID required: true schema: type: string responses: '201': description: Server validation started. content: application/json: schema: properties: message: type: string example: Validation started. type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] ``` -------------------------------------------------------------------------------- /docs/features/013-npx-config-fix.md: -------------------------------------------------------------------------------- ```markdown # npx config fix I want to be able to have the following config: ```json { "mcpServers": { "coolify": { "command": "npx", "args": ["-y", "@masonator/coolify-mcp"], "env": { "COOLIFY_ACCESS_TOKEN": "token", "COOLIFY_BASE_URL": "https://url" } }, "github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "pat" } } } } ``` The github config is correct, but the coolify config currently does not work. I get the following error: ``` 2025-03-07T09:43:34.691Z [coolify] [info] Initializing server... 2025-03-07T09:43:34.783Z [coolify] [info] Server started and connected successfully 2025-03-07T09:43:35.882Z [coolify] [info] Message from client: {"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"claude-ai","version":"0.1.0"}},"jsonrpc":"2.0","id":0} node:internal/modules/cjs/loader:603 throw e; ^ Error: Cannot find module '/Users/stumason/.npm/_npx/4e3adc8df0812880/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/mcp' at createEsmNotFoundErr (node:internal/modules/cjs/loader:1186:15) at finalizeEsmResolution (node:internal/modules/cjs/loader:1174:15) at resolveExports (node:internal/modules/cjs/loader:596:14) at Module._findPath (node:internal/modules/cjs/loader:673:31) at Module._resolveFilename (node:internal/modules/cjs/loader:1135:27) at Module._load (node:internal/modules/cjs/loader:990:27) at Module.require (node:internal/modules/cjs/loader:1237:19) at require (node:internal/modules/helpers:176:18) at Object.<anonymous> (/Users/stumason/.npm/_npx/4e3adc8df0812880/node_modules/@masonator/coolify-mcp/dist/lib/mcp-server.js:4:15) at Module._compile (node:internal/modules/cjs/loader:1378:14) { code: 'MODULE_NOT_FOUND', path: '/Users/stumason/.npm/_npx/4e3adc8df0812880/node_modules/@modelcontextprotocol/sdk/package.json' } node:internal/modules/cjs/loader:603 throw e; ^ Error: Cannot find module '/Users/stumason/.npm/_npx/4e3adc8df0812880/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/mcp' at createEsmNotFoundErr (node:internal/modules/cjs/loader:1186:15) at finalizeEsmResolution (node:internal/modules/cjs/loader:1174:15) at resolveExports (node:internal/modules/cjs/loader:596:14) at Module._findPath (node:internal/modules/cjs/loader:673:31) at Module._resolveFilename (node:internal/modules/cjs/loader:1135:27) at Module._load (node:internal/modules/cjs/loader:990:27) at Module.require (node:internal/modules/cjs/loader:1237:19) at require (node:internal/modules/helpers:176:18) at Object.<anonymous> (/Users/stumason/.npm/_npx/4e3adc8df0812880/node_modules/@masonator/coolify-mcp/dist/lib/mcp-server.js:4:15) at Module._compile (node:internal/modules/cjs/loader:1378:14) { code: 'MODULE_NOT_FOUND', path: '/Users/stumason/.npm/_npx/4e3adc8df0812880/node_modules/@modelcontextprotocol/sdk/package.json' } Node.js v21.6.0 Node.js v21.6.0 2025-03-07T09:43:36.909Z [coolify] [info] Server transport closed 2025-03-07T09:43:36.910Z [coolify] [info] Client transport closed 2025-03-07T09:43:36.910Z [coolify] [info] Server transport closed unexpectedly, this is likely due to the process exiting early. If you are developing this MCP server you can add output to stderr (i.e. `console.error('...')` in JavaScript, `print('...', file=sys.stderr)` in python) and it will appear in this log. 2025-03-07T09:43:36.910Z [coolify] [error] Server disconnected. For troubleshooting guidance, please visit our [debugging documentation](https://modelcontextprotocol.io/docs/tools/debugging) {"context":"connection"} 2025-03-07T09:43:36.911Z [coolify] [info] Client transport closed 2025-03-07T09:43:36.912Z [coolify] [info] Server transport closed 2025-03-07T09:43:36.912Z [coolify] [info] Client transport closed 2025-03-07T09:43:36.912Z [coolify] [info] Server transport closed unexpectedly, this is likely due to the process exiting early. If you are developing this MCP server you can add output to stderr (i.e. `console.error('...')` in JavaScript, `print('...', file=sys.stderr)` in python) and it will appear in this log. 2025-03-07T09:43:36.912Z [coolify] [error] Server disconnected. For troubleshooting guidance, please visit our [debugging documentation](https://modelcontextprotocol.io/docs/tools/debugging) {"context":"connection"} 2025-03-07T09:43:36.913Z [coolify] [info] Client transport closed 2025-03-07T09:51:22.595Z [coolify] [info] Initializing server... 2025-03-07T09:51:22.618Z [coolify] [info] Server started and connected successfully 2025-03-07T09:51:22.621Z [coolify] [info] Message from client: {"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"claude-ai","version":"0.1.0"}},"jsonrpc":"2.0","id":0} 2025-03-07T09:51:23.837Z [coolify] [info] Initializing server... 2025-03-07T09:51:23.853Z [coolify] [info] Server started and connected successfully 2025-03-07T09:51:23.948Z [coolify] [info] Message from client: {"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"claude-ai","version":"0.1.0"}},"jsonrpc":"2.0","id":0} node:internal/modules/cjs/loader:603 throw e; ^ Error: Cannot find module '/Users/stumason/.npm/_npx/4e3adc8df0812880/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/mcp' at createEsmNotFoundErr (node:internal/modules/cjs/loader:1186:15) at finalizeEsmResolution (node:internal/modules/cjs/loader:1174:15) at resolveExports (node:internal/modules/cjs/loader:596:14) at Module._findPath (node:internal/modules/cjs/loader:673:31) at Module._resolveFilename (node:internal/modules/cjs/loader:1135:27) at Module._load (node:internal/modules/cjs/loader:990:27) at Module.require (node:internal/modules/cjs/loader:1237:19) at require (node:internal/modules/helpers:176:18) at Object.<anonymous> (/Users/stumason/.npm/_npx/4e3adc8df0812880/node_modules/@masonator/coolify-mcp/dist/lib/mcp-server.js:4:15) at Module._compile (node:internal/modules/cjs/loader:1378:14) { code: 'MODULE_NOT_FOUND', path: '/Users/stumason/.npm/_npx/4e3adc8df0812880/node_modules/@modelcontextprotocol/sdk/package.json' } Node.js v21.6.0 2025-03-07T09:51:25.767Z [coolify] [info] Server transport closed 2025-03-07T09:51:25.768Z [coolify] [info] Client transport closed 2025-03-07T09:51:25.768Z [coolify] [info] Server transport closed unexpectedly, this is likely due to the process exiting early. If you are developing this MCP server you can add output to stderr (i.e. `console.error('...')` in JavaScript, `print('...', file=sys.stderr)` in python) and it will appear in this log. 2025-03-07T09:51:25.768Z [coolify] [error] Server disconnected. For troubleshooting guidance, please visit our [debugging documentation](https://modelcontextprotocol.io/docs/tools/debugging) {"context":"connection"} 2025-03-07T09:51:25.769Z [coolify] [info] Client transport closed node:internal/modules/cjs/loader:603 throw e; ^ Error: Cannot find module '/Users/stumason/.npm/_npx/4e3adc8df0812880/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/mcp' at createEsmNotFoundErr (node:internal/modules/cjs/loader:1186:15) at finalizeEsmResolution (node:internal/modules/cjs/loader:1174:15) at resolveExports (node:internal/modules/cjs/loader:596:14) at Module._findPath (node:internal/modules/cjs/loader:673:31) at Module._resolveFilename (node:internal/modules/cjs/loader:1135:27) at Module._load (node:internal/modules/cjs/loader:990:27) at Module.require (node:internal/modules/cjs/loader:1237:19) at require (node:internal/modules/helpers:176:18) at Object.<anonymous> (/Users/stumason/.npm/_npx/4e3adc8df0812880/node_modules/@masonator/coolify-mcp/dist/lib/mcp-server.js:4:15) at Module._compile (node:internal/modules/cjs/loader:1378:14) { code: 'MODULE_NOT_FOUND', path: '/Users/stumason/.npm/_npx/4e3adc8df0812880/node_modules/@modelcontextprotocol/sdk/package.json' } Node.js v21.6.0 2025-03-07T09:51:25.851Z [coolify] [info] Server transport closed 2025-03-07T09:51:25.851Z [coolify] [info] Client transport closed 2025-03-07T09:51:25.852Z [coolify] [info] Server transport closed unexpectedly, this is likely due to the process exiting early. If you are developing this MCP server you can add output to stderr (i.e. `console.error('...')` in JavaScript, `print('...', file=sys.stderr)` in python) and it will appear in this log. 2025-03-07T09:51:25.852Z [coolify] [error] Server disconnected. For troubleshooting guidance, please visit our [debugging documentation](https://modelcontextprotocol.io/docs/tools/debugging) {"context":"connection"} 2025-03-07T09:51:25.852Z [coolify] [info] Client transport closed ``` For reference, the github package.json looks like this: ```json { "name": "@modelcontextprotocol/server-github", "version": "0.6.2", "description": "MCP server for using the GitHub API", "license": "MIT", "author": "Anthropic, PBC (https://anthropic.com)", "homepage": "https://modelcontextprotocol.io", "bugs": "https://github.com/modelcontextprotocol/servers/issues", "type": "module", "bin": { "mcp-server-github": "dist/index.js" }, "files": ["dist"], "scripts": { "build": "tsc && shx chmod +x dist/*.js", "prepare": "npm run build", "watch": "tsc --watch" }, "dependencies": { "@modelcontextprotocol/sdk": "1.0.1", "@types/node": "^22", "@types/node-fetch": "^2.6.12", "node-fetch": "^3.3.2", "universal-user-agent": "^7.0.2", "zod": "^3.22.4", "zod-to-json-schema": "^3.23.5" }, "devDependencies": { "shx": "^0.3.4", "typescript": "^5.6.2" } } ``` ``` -------------------------------------------------------------------------------- /docs/mcp-js-readme.md: -------------------------------------------------------------------------------- ```markdown # MCP TypeScript SDK   ## Table of Contents - [Overview](#overview) - [Installation](#installation) - [Quickstart](#quickstart) - [What is MCP?](#what-is-mcp) - [Core Concepts](#core-concepts) - [Server](#server) - [Resources](#resources) - [Tools](#tools) - [Prompts](#prompts) - [Running Your Server](#running-your-server) - [stdio](#stdio) - [HTTP with SSE](#http-with-sse) - [Testing and Debugging](#testing-and-debugging) - [Examples](#examples) - [Echo Server](#echo-server) - [SQLite Explorer](#sqlite-explorer) - [Advanced Usage](#advanced-usage) - [Low-Level Server](#low-level-server) - [Writing MCP Clients](#writing-mcp-clients) - [Server Capabilities](#server-capabilities) ## Overview The Model Context Protocol allows applications to provide context for LLMs in a standardized way, separating the concerns of providing context from the actual LLM interaction. This TypeScript SDK implements the full MCP specification, making it easy to: - Build MCP clients that can connect to any MCP server - Create MCP servers that expose resources, prompts and tools - Use standard transports like stdio and SSE - Handle all MCP protocol messages and lifecycle events ## Installation ```bash npm install @modelcontextprotocol/sdk ``` ## Quick Start Let's create a simple MCP server that exposes a calculator tool and some data: ```typescript import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { z } from 'zod'; // Create an MCP server const server = new McpServer({ name: 'Demo', version: '1.0.0', }); // Add an addition tool server.tool('add', { a: z.number(), b: z.number() }, async ({ a, b }) => ({ content: [{ type: 'text', text: String(a + b) }], })); // Add a dynamic greeting resource server.resource( 'greeting', new ResourceTemplate('greeting://{name}', { list: undefined }), async (uri, { name }) => ({ contents: [ { uri: uri.href, text: `Hello, ${name}!`, }, ], }), ); // Start receiving messages on stdin and sending messages on stdout const transport = new StdioServerTransport(); await server.connect(transport); ``` ## What is MCP? The [Model Context Protocol (MCP)](https://modelcontextprotocol.io) lets you build servers that expose data and functionality to LLM applications in a secure, standardized way. Think of it like a web API, but specifically designed for LLM interactions. MCP servers can: - Expose data through **Resources** (think of these sort of like GET endpoints; they are used to load information into the LLM's context) - Provide functionality through **Tools** (sort of like POST endpoints; they are used to execute code or otherwise produce a side effect) - Define interaction patterns through **Prompts** (reusable templates for LLM interactions) - And more! ## Core Concepts ### Server The McpServer is your core interface to the MCP protocol. It handles connection management, protocol compliance, and message routing: ```typescript const server = new McpServer({ name: 'My App', version: '1.0.0', }); ``` ### Resources Resources are how you expose data to LLMs. They're similar to GET endpoints in a REST API - they provide data but shouldn't perform significant computation or have side effects: ```typescript // Static resource server.resource('config', 'config://app', async (uri) => ({ contents: [ { uri: uri.href, text: 'App configuration here', }, ], })); // Dynamic resource with parameters server.resource( 'user-profile', new ResourceTemplate('users://{userId}/profile', { list: undefined }), async (uri, { userId }) => ({ contents: [ { uri: uri.href, text: `Profile data for user ${userId}`, }, ], }), ); ``` ### Tools Tools let LLMs take actions through your server. Unlike resources, tools are expected to perform computation and have side effects: ```typescript // Simple tool with parameters server.tool( 'calculate-bmi', { weightKg: z.number(), heightM: z.number(), }, async ({ weightKg, heightM }) => ({ content: [ { type: 'text', text: String(weightKg / (heightM * heightM)), }, ], }), ); // Async tool with external API call server.tool('fetch-weather', { city: z.string() }, async ({ city }) => { const response = await fetch(`https://api.weather.com/${city}`); const data = await response.text(); return { content: [{ type: 'text', text: data }], }; }); ``` ### Prompts Prompts are reusable templates that help LLMs interact with your server effectively: ```typescript server.prompt('review-code', { code: z.string() }, ({ code }) => ({ messages: [ { role: 'user', content: { type: 'text', text: `Please review this code:\n\n${code}`, }, }, ], })); ``` ## Running Your Server MCP servers in TypeScript need to be connected to a transport to communicate with clients. How you start the server depends on the choice of transport: ### stdio For command-line tools and direct integrations: ```typescript import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; const server = new McpServer({ name: 'example-server', version: '1.0.0', }); // ... set up server resources, tools, and prompts ... const transport = new StdioServerTransport(); await server.connect(transport); ``` ### HTTP with SSE For remote servers, start a web server with a Server-Sent Events (SSE) endpoint, and a separate endpoint for the client to send its messages to: ```typescript import express from 'express'; import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js'; const server = new McpServer({ name: 'example-server', version: '1.0.0', }); // ... set up server resources, tools, and prompts ... const app = express(); app.get('/sse', async (req, res) => { const transport = new SSEServerTransport('/messages', res); await server.connect(transport); }); app.post('/messages', async (req, res) => { // Note: to support multiple simultaneous connections, these messages will // need to be routed to a specific matching transport. (This logic isn't // implemented here, for simplicity.) await transport.handlePostMessage(req, res); }); app.listen(3001); ``` ### Testing and Debugging To test your server, you can use the [MCP Inspector](https://github.com/modelcontextprotocol/inspector). See its README for more information. ## Examples ### Echo Server A simple server demonstrating resources, tools, and prompts: ```typescript import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; const server = new McpServer({ name: 'Echo', version: '1.0.0', }); server.resource( 'echo', new ResourceTemplate('echo://{message}', { list: undefined }), async (uri, { message }) => ({ contents: [ { uri: uri.href, text: `Resource echo: ${message}`, }, ], }), ); server.tool('echo', { message: z.string() }, async ({ message }) => ({ content: [{ type: 'text', text: `Tool echo: ${message}` }], })); server.prompt('echo', { message: z.string() }, ({ message }) => ({ messages: [ { role: 'user', content: { type: 'text', text: `Please process this message: ${message}`, }, }, ], })); ``` ### SQLite Explorer A more complex example showing database integration: ```typescript import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import sqlite3 from 'sqlite3'; import { promisify } from 'util'; import { z } from 'zod'; const server = new McpServer({ name: 'SQLite Explorer', version: '1.0.0', }); // Helper to create DB connection const getDb = () => { const db = new sqlite3.Database('database.db'); return { all: promisify<string, any[]>(db.all.bind(db)), close: promisify(db.close.bind(db)), }; }; server.resource('schema', 'schema://main', async (uri) => { const db = getDb(); try { const tables = await db.all("SELECT sql FROM sqlite_master WHERE type='table'"); return { contents: [ { uri: uri.href, text: tables.map((t: { sql: string }) => t.sql).join('\n'), }, ], }; } finally { await db.close(); } }); server.tool('query', { sql: z.string() }, async ({ sql }) => { const db = getDb(); try { const results = await db.all(sql); return { content: [ { type: 'text', text: JSON.stringify(results, null, 2), }, ], }; } catch (err: unknown) { const error = err as Error; return { content: [ { type: 'text', text: `Error: ${error.message}`, }, ], isError: true, }; } finally { await db.close(); } }); ``` ## Advanced Usage ### Low-Level Server For more control, you can use the low-level Server class directly: ```typescript import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { ListPromptsRequestSchema, GetPromptRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; const server = new Server( { name: 'example-server', version: '1.0.0', }, { capabilities: { prompts: {}, }, }, ); server.setRequestHandler(ListPromptsRequestSchema, async () => { return { prompts: [ { name: 'example-prompt', description: 'An example prompt template', arguments: [ { name: 'arg1', description: 'Example argument', required: true, }, ], }, ], }; }); server.setRequestHandler(GetPromptRequestSchema, async (request) => { if (request.params.name !== 'example-prompt') { throw new Error('Unknown prompt'); } return { description: 'Example prompt', messages: [ { role: 'user', content: { type: 'text', text: 'Example prompt text', }, }, ], }; }); const transport = new StdioServerTransport(); await server.connect(transport); ``` ### Writing MCP Clients The SDK provides a high-level client interface: ```typescript import { Client } from '@modelcontextprotocol/sdk/client/index.js'; import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'; const transport = new StdioClientTransport({ command: 'node', args: ['server.js'], }); const client = new Client( { name: 'example-client', version: '1.0.0', }, { capabilities: { prompts: {}, resources: {}, tools: {}, }, }, ); await client.connect(transport); // List prompts const prompts = await client.listPrompts(); // Get a prompt const prompt = await client.getPrompt('example-prompt', { arg1: 'value', }); // List resources const resources = await client.listResources(); // Read a resource const resource = await client.readResource('file:///example.txt'); // Call a tool const result = await client.callTool({ name: 'example-tool', arguments: { arg1: 'value', }, }); ``` ## Documentation - [Model Context Protocol documentation](https://modelcontextprotocol.io) - [MCP Specification](https://spec.modelcontextprotocol.io) - [Example Servers](https://github.com/modelcontextprotocol/servers) ## Contributing Issues and pull requests are welcome on GitHub at https://github.com/modelcontextprotocol/typescript-sdk. ## License This project is licensed under the MIT License—see the [LICENSE](LICENSE) file for details. ``` -------------------------------------------------------------------------------- /src/lib/mcp-server.ts: -------------------------------------------------------------------------------- ```typescript import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js'; import { CoolifyClient } from './coolify-client.js'; import debug from 'debug'; import { z } from 'zod'; import type { ServerInfo, ServerResources, ServerDomain, ValidationResponse, Project, CreateProjectRequest, UpdateProjectRequest, Environment, Deployment, Database, DatabaseUpdateRequest, Service, CreateServiceRequest, DeleteServiceOptions, } from '../types/coolify.js'; const log = debug('coolify:mcp'); // Define valid service types const serviceTypes = [ '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; export class CoolifyMcpServer extends McpServer { private client: CoolifyClient; constructor(config: { baseUrl: string; accessToken: string }) { super({ name: 'coolify', version: '0.1.18' }); log('Initializing server with config: %o', config); this.client = new CoolifyClient(config); } async initialize(): Promise<void> { // Register capabilities first await this.server.registerCapabilities({ tools: {} }); // Then register all tools this.tool('list_servers', 'List all Coolify servers', {}, async () => { const servers = await this.client.listServers(); return { content: [{ type: 'text', text: JSON.stringify(servers, null, 2) }] }; }); this.tool('get_server', 'Get details about a specific Coolify server', { uuid: z.string().describe('UUID of the server to get details for') }, async (args) => { const server = await this.client.getServer(args.uuid); return { content: [{ type: 'text', text: JSON.stringify(server, null, 2) }] }; }); this.tool('get_server_resources', 'Get the current resources running on a specific Coolify server', { uuid: z.string() }, async (args, _extra) => { const resources = await this.client.getServerResources(args.uuid); return { content: [{ type: 'text', text: JSON.stringify(resources, null, 2) }] }; }); this.tool('get_server_domains', 'Get domains for a specific Coolify server', { uuid: z.string() }, async (args, _extra) => { const domains = await this.client.getServerDomains(args.uuid); return { content: [{ type: 'text', text: JSON.stringify(domains, null, 2) }] }; }); this.tool('validate_server', 'Validate a specific Coolify server', { uuid: z.string() }, async (args, _extra) => { const validation = await this.client.validateServer(args.uuid); return { content: [{ type: 'text', text: JSON.stringify(validation, null, 2) }] }; }); this.tool('list_projects', 'List all Coolify projects', {}, async (_args, _extra) => { const projects = await this.client.listProjects(); return { content: [{ type: 'text', text: JSON.stringify(projects, null, 2) }] }; }); this.tool('get_project', 'Get details about a specific Coolify project', { uuid: z.string() }, async (args, _extra) => { const project = await this.client.getProject(args.uuid); return { content: [{ type: 'text', text: JSON.stringify(project, null, 2) }] }; }); this.tool('create_project', 'Create a new Coolify project', { name: z.string(), description: z.string().optional() }, async (args, _extra) => { const result = await this.client.createProject({ name: args.name, description: args.description }); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; }); this.tool('update_project', 'Update an existing Coolify project', { uuid: z.string(), name: z.string(), description: z.string().optional() }, async (args, _extra) => { const { uuid, ...updateData } = args; const result = await this.client.updateProject(uuid, updateData); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; }); this.tool('delete_project', 'Delete a Coolify project', { uuid: z.string() }, async (args, _extra) => { const result = await this.client.deleteProject(args.uuid); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; }); this.tool('get_project_environment', 'Get environment details for a Coolify project', { project_uuid: z.string(), environment_name_or_uuid: z.string() }, async (args, _extra) => { const environment = await this.client.getProjectEnvironment(args.project_uuid, args.environment_name_or_uuid); return { content: [{ type: 'text', text: JSON.stringify(environment, null, 2) }] }; }); this.tool('list_databases', 'List all Coolify databases', {}, async (_args, _extra) => { const databases = await this.client.listDatabases(); return { content: [{ type: 'text', text: JSON.stringify(databases, null, 2) }] }; }); this.tool('get_database', 'Get details about a specific Coolify database', { uuid: z.string() }, async (args, _extra) => { const database = await this.client.getDatabase(args.uuid); return { content: [{ type: 'text', text: JSON.stringify(database, null, 2) }] }; }); this.tool('update_database', 'Update a Coolify database', { uuid: z.string(), data: z.record(z.unknown()) }, async (args, _extra) => { const result = await this.client.updateDatabase(args.uuid, args.data); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; }); const deleteOptionsSchema = { deleteConfigurations: z.boolean().optional(), deleteVolumes: z.boolean().optional(), dockerCleanup: z.boolean().optional(), deleteConnectedNetworks: z.boolean().optional() }; this.tool('delete_database', 'Delete a Coolify database', { uuid: z.string(), options: z.object(deleteOptionsSchema).optional() }, async (args, _extra) => { const result = await this.client.deleteDatabase(args.uuid, args.options); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; }); this.tool('deploy_application', 'Deploy a Coolify application', { uuid: z.string() }, async (args, _extra) => { const result = await this.client.deployApplication(args.uuid); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; }); this.tool('list_services', 'List all Coolify services', {}, async (_args, _extra) => { const services = await this.client.listServices(); return { content: [{ type: 'text', text: JSON.stringify(services, null, 2) }] }; }); this.tool('get_service', 'Get details about a specific Coolify service', { uuid: z.string() }, async (args, _extra) => { const service = await this.client.getService(args.uuid); return { content: [{ type: 'text', text: JSON.stringify(service, null, 2) }] }; }); this.tool('create_service', 'Create a new Coolify service', { type: z.enum(serviceTypes), project_uuid: z.string(), server_uuid: z.string(), name: z.string().optional(), description: z.string().optional(), environment_name: z.string().optional(), environment_uuid: z.string().optional(), destination_uuid: z.string().optional(), instant_deploy: z.boolean().optional() }, async (args, _extra) => { const result = await this.client.createService(args); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; }); this.tool('delete_service', 'Delete a Coolify service', { uuid: z.string(), options: z.object(deleteOptionsSchema).optional() }, async (args, _extra) => { const result = await this.client.deleteService(args.uuid, args.options); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; }); } async connect(transport: Transport): Promise<void> { log('Starting server...'); log('Validating connection...'); await this.client.validateConnection(); await this.initialize(); await super.connect(transport); log('Server started successfully'); } async list_servers(): Promise<ServerInfo[]> { return this.client.listServers(); } async get_server(uuid: string): Promise<ServerInfo> { return this.client.getServer(uuid); } async get_server_resources(uuid: string): Promise<ServerResources> { return this.client.getServerResources(uuid); } async get_server_domains(uuid: string): Promise<ServerDomain[]> { return this.client.getServerDomains(uuid); } async validate_server(uuid: string): Promise<ValidationResponse> { return this.client.validateServer(uuid); } async list_projects(): Promise<Project[]> { return this.client.listProjects(); } async get_project(uuid: string): Promise<Project> { return this.client.getProject(uuid); } async create_project(project: CreateProjectRequest): Promise<{ uuid: string }> { return this.client.createProject(project); } async update_project(uuid: string, project: UpdateProjectRequest): Promise<Project> { return this.client.updateProject(uuid, project); } async delete_project(uuid: string): Promise<{ message: string }> { return this.client.deleteProject(uuid); } async get_project_environment( projectUuid: string, environmentNameOrUuid: string, ): Promise<Environment> { return this.client.getProjectEnvironment(projectUuid, environmentNameOrUuid); } async deploy_application(params: { uuid: string }): Promise<Deployment> { return this.client.deployApplication(params.uuid); } async list_databases(): Promise<Database[]> { return this.client.listDatabases(); } async get_database(uuid: string): Promise<Database> { return this.client.getDatabase(uuid); } async update_database(uuid: string, data: DatabaseUpdateRequest): Promise<Database> { return this.client.updateDatabase(uuid, data); } async delete_database( uuid: string, options?: { deleteConfigurations?: boolean; deleteVolumes?: boolean; dockerCleanup?: boolean; deleteConnectedNetworks?: boolean; }, ): Promise<{ message: string }> { return this.client.deleteDatabase(uuid, options); } async list_services(): Promise<Service[]> { return this.client.listServices(); } async get_service(uuid: string): Promise<Service> { return this.client.getService(uuid); } async create_service(data: CreateServiceRequest): Promise<{ uuid: string; domains: string[] }> { return this.client.createService(data); } async delete_service(uuid: string, options?: DeleteServiceOptions): Promise<{ message: string }> { return this.client.deleteService(uuid, options); } } ``` -------------------------------------------------------------------------------- /docs/openapi-chunks/services-api.yaml: -------------------------------------------------------------------------------- ```yaml openapi: 3.1.0 info: title: Coolify version: '0.1' paths: /services: get: tags: - Services summary: List description: List all services. operationId: list-services responses: '200': description: Get all services content: application/json: schema: type: array items: $ref: '#/components/schemas/Service' '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] post: tags: - Services summary: Create description: Create a one-click service operationId: create-service requestBody: required: true content: application/json: schema: required: - server_uuid - project_uuid - environment_name - environment_uuid - type properties: type: description: The one-click service type type: string enum: - 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 name: type: string maxLength: 255 description: Name of the service. description: type: string nullable: true description: Description of the service. project_uuid: type: string description: Project UUID. environment_name: type: string description: Environment name. You need to provide at least one of environment_name or environment_uuid. environment_uuid: type: string description: Environment UUID. You need to provide at least one of environment_name or environment_uuid. server_uuid: type: string description: Server UUID. destination_uuid: type: string description: Destination UUID. Required if server has multiple destinations. instant_deploy: type: boolean default: false description: Start the service immediately after creation. type: object responses: '201': description: Create a service. content: application/json: schema: properties: uuid: type: string description: Service UUID. domains: type: array items: type: string description: Service domains. type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] /services/{uuid}: get: tags: - Services summary: Get description: Get service by UUID. operationId: get-service-by-uuid parameters: - name: uuid in: path description: Service UUID required: true schema: type: string responses: '200': description: Get a service by UUID. content: application/json: schema: $ref: '#/components/schemas/Service' '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] delete: tags: - Services summary: Delete description: Delete service by UUID. operationId: delete-service-by-uuid parameters: - name: uuid in: path description: Service UUID required: true schema: type: string - name: delete_configurations in: query description: Delete configurations. required: false schema: type: boolean default: true - name: delete_volumes in: query description: Delete volumes. required: false schema: type: boolean default: true - name: docker_cleanup in: query description: Run docker cleanup. required: false schema: type: boolean default: true - name: delete_connected_networks in: query description: Delete connected networks. required: false schema: type: boolean default: true responses: '200': description: Delete a service by UUID content: application/json: schema: properties: message: type: string example: Service deletion request queued. type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /services/{uuid}/envs: get: tags: - Services summary: List Envs description: List all envs by service UUID. operationId: list-envs-by-service-uuid parameters: - name: uuid in: path description: UUID of the service. required: true schema: type: string format: uuid responses: '200': description: All environment variables by service UUID. content: application/json: schema: type: array items: $ref: '#/components/schemas/EnvironmentVariable' '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] post: tags: - Services summary: Create Env description: Create env by service UUID. operationId: create-env-by-service-uuid parameters: - name: uuid in: path description: UUID of the service. required: true schema: type: string format: uuid requestBody: description: Env created. required: true content: application/json: schema: properties: key: type: string description: The key of the environment variable. value: type: string description: The value of the environment variable. is_preview: type: boolean description: The flag to indicate if the environment variable is used in preview deployments. is_build_time: type: boolean description: The flag to indicate if the environment variable is used in build time. is_literal: type: boolean description: The flag to indicate if the environment variable is a literal, nothing espaced. is_multiline: type: boolean description: The flag to indicate if the environment variable is multiline. is_shown_once: type: boolean description: The flag to indicate if the environment variable's value is shown on the UI. type: object responses: '201': description: Environment variable created. content: application/json: schema: properties: uuid: type: string example: nc0k04gk8g0cgsk440g0koko type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] patch: tags: - Services summary: Update Env description: Update env by service UUID. operationId: update-env-by-service-uuid parameters: - name: uuid in: path description: UUID of the service. required: true schema: type: string format: uuid requestBody: description: Env updated. required: true content: application/json: schema: required: - key - value properties: key: type: string description: The key of the environment variable. value: type: string description: The value of the environment variable. is_preview: type: boolean description: The flag to indicate if the environment variable is used in preview deployments. is_build_time: type: boolean description: The flag to indicate if the environment variable is used in build time. is_literal: type: boolean description: The flag to indicate if the environment variable is a literal, nothing espaced. is_multiline: type: boolean description: The flag to indicate if the environment variable is multiline. is_shown_once: type: boolean description: The flag to indicate if the environment variable's value is shown on the UI. type: object responses: '201': description: Environment variable updated. content: application/json: schema: properties: message: type: string example: Environment variable updated. type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /services/{uuid}/envs/bulk: patch: tags: - Services summary: Update Envs (Bulk) description: Update multiple envs by service UUID. operationId: update-envs-by-service-uuid parameters: - name: uuid in: path description: UUID of the service. required: true schema: type: string format: uuid requestBody: description: Bulk envs updated. required: true content: application/json: schema: required: - data properties: data: type: array items: properties: key: type: string description: The key of the environment variable. value: type: string description: The value of the environment variable. is_preview: type: boolean description: The flag to indicate if the environment variable is used in preview deployments. is_build_time: type: boolean description: The flag to indicate if the environment variable is used in build time. is_literal: type: boolean description: The flag to indicate if the environment variable is a literal, nothing espaced. is_multiline: type: boolean description: The flag to indicate if the environment variable is multiline. is_shown_once: type: boolean description: The flag to indicate if the environment variable's value is shown on the UI. type: object type: object responses: '201': description: Environment variables updated. content: application/json: schema: properties: message: type: string example: Environment variables updated. type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /services/{uuid}/envs/{env_uuid}: delete: tags: - Services summary: Delete Env description: Delete env by UUID. operationId: delete-env-by-service-uuid parameters: - name: uuid in: path description: UUID of the service. required: true schema: type: string format: uuid - name: env_uuid in: path description: UUID of the environment variable. required: true schema: type: string format: uuid responses: '200': description: Environment variable deleted. content: application/json: schema: properties: message: type: string example: Environment variable deleted. type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /services/{uuid}/start: get: tags: - Services summary: Start description: Start service. `Post` request is also accepted. operationId: start-service-by-uuid parameters: - name: uuid in: path description: UUID of the service. required: true schema: type: string format: uuid responses: '200': description: Start service. content: application/json: schema: properties: message: type: string example: Service starting request queued. type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /services/{uuid}/stop: get: tags: - Services summary: Stop description: Stop service. `Post` request is also accepted. operationId: stop-service-by-uuid parameters: - name: uuid in: path description: UUID of the service. required: true schema: type: string format: uuid responses: '200': description: Stop service. content: application/json: schema: properties: message: type: string example: Service stopping request queued. type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /services/{uuid}/restart: get: tags: - Services summary: Restart description: Restart service. `Post` request is also accepted. operationId: restart-service-by-uuid parameters: - name: uuid in: path description: UUID of the service. required: true schema: type: string format: uuid responses: '200': description: Restart service. content: application/json: schema: properties: message: type: string example: Service restaring request queued. type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] ``` -------------------------------------------------------------------------------- /docs/openapi-chunks/schemas.yaml: -------------------------------------------------------------------------------- ```yaml openapi: 3.1.0 info: title: Coolify version: '0.1' paths: {} components: schemas: Application: description: Application model properties: id: type: integer description: The application identifier in the database. description: type: string nullable: true description: The application description. repository_project_id: type: integer nullable: true description: The repository project identifier. uuid: type: string description: The application UUID. name: type: string description: The application name. fqdn: type: string nullable: true description: The application domains. config_hash: type: string description: Configuration hash. git_repository: type: string description: Git repository URL. git_branch: type: string description: Git branch. git_commit_sha: type: string description: Git commit SHA. git_full_url: type: string nullable: true description: Git full URL. docker_registry_image_name: type: string nullable: true description: Docker registry image name. docker_registry_image_tag: type: string nullable: true description: Docker registry image tag. build_pack: type: string description: Build pack. enum: - nixpacks - static - dockerfile - dockercompose static_image: type: string description: Static image used when static site is deployed. install_command: type: string description: Install command. build_command: type: string description: Build command. start_command: type: string description: Start command. ports_exposes: type: string description: Ports exposes. ports_mappings: type: string nullable: true description: Ports mappings. base_directory: type: string description: Base directory for all commands. publish_directory: type: string description: Publish directory. health_check_enabled: type: boolean description: Health check enabled. health_check_path: type: string description: Health check path. health_check_port: type: string nullable: true description: Health check port. health_check_host: type: string nullable: true description: Health check host. health_check_method: type: string description: Health check method. health_check_return_code: type: integer description: Health check return code. health_check_scheme: type: string description: Health check scheme. health_check_response_text: type: string nullable: true description: Health check response text. health_check_interval: type: integer description: Health check interval in seconds. health_check_timeout: type: integer description: Health check timeout in seconds. health_check_retries: type: integer description: Health check retries count. health_check_start_period: type: integer description: Health check start period in seconds. limits_memory: type: string description: Memory limit. limits_memory_swap: type: string description: Memory swap limit. limits_memory_swappiness: type: integer description: Memory swappiness. limits_memory_reservation: type: string description: Memory reservation. limits_cpus: type: string description: CPU limit. limits_cpuset: type: string nullable: true description: CPU set. limits_cpu_shares: type: integer description: CPU shares. status: type: string description: Application status. preview_url_template: type: string description: Preview URL template. destination_type: type: string description: Destination type. destination_id: type: integer description: Destination identifier. source_id: type: integer nullable: true description: Source identifier. private_key_id: type: integer nullable: true description: Private key identifier. environment_id: type: integer description: Environment identifier. dockerfile: type: string nullable: true description: Dockerfile content. Used for dockerfile build pack. dockerfile_location: type: string description: Dockerfile location. custom_labels: type: string nullable: true description: Custom labels. dockerfile_target_build: type: string nullable: true description: Dockerfile target build. manual_webhook_secret_github: type: string nullable: true description: Manual webhook secret for GitHub. manual_webhook_secret_gitlab: type: string nullable: true description: Manual webhook secret for GitLab. manual_webhook_secret_bitbucket: type: string nullable: true description: Manual webhook secret for Bitbucket. manual_webhook_secret_gitea: type: string nullable: true description: Manual webhook secret for Gitea. docker_compose_location: type: string description: Docker compose location. docker_compose: type: string nullable: true description: Docker compose content. Used for docker compose build pack. docker_compose_raw: type: string nullable: true description: Docker compose raw content. docker_compose_domains: type: string nullable: true description: Docker compose domains. docker_compose_custom_start_command: type: string nullable: true description: Docker compose custom start command. docker_compose_custom_build_command: type: string nullable: true description: Docker compose custom build command. swarm_replicas: type: integer nullable: true description: Swarm replicas. Only used for swarm deployments. swarm_placement_constraints: type: string nullable: true description: Swarm placement constraints. Only used for swarm deployments. custom_docker_run_options: type: string nullable: true description: Custom docker run options. post_deployment_command: type: string nullable: true description: Post deployment command. post_deployment_command_container: type: string nullable: true description: Post deployment command container. pre_deployment_command: type: string nullable: true description: Pre deployment command. pre_deployment_command_container: type: string nullable: true description: Pre deployment command container. watch_paths: type: string nullable: true description: Watch paths. custom_healthcheck_found: type: boolean description: Custom healthcheck found. redirect: type: string nullable: true description: How to set redirect with Traefik / Caddy. www<->non-www. enum: - www - non-www - both created_at: type: string format: date-time description: The date and time when the application was created. updated_at: type: string format: date-time description: The date and time when the application was last updated. deleted_at: type: string format: date-time nullable: true description: The date and time when the application was deleted. compose_parsing_version: type: string description: How Coolify parse the compose file. custom_nginx_configuration: type: string nullable: true description: Custom Nginx configuration base64 encoded. type: object ApplicationDeploymentQueue: description: Project model properties: id: type: integer application_id: type: string deployment_uuid: type: string pull_request_id: type: integer force_rebuild: type: boolean commit: type: string status: type: string is_webhook: type: boolean is_api: type: boolean created_at: type: string updated_at: type: string logs: type: string current_process_id: type: string restart_only: type: boolean git_type: type: string server_id: type: integer application_name: type: string server_name: type: string deployment_url: type: string destination_id: type: string only_this_server: type: boolean rollback: type: boolean commit_message: type: string type: object Environment: description: Environment model properties: id: type: integer name: type: string project_id: type: integer created_at: type: string updated_at: type: string description: type: string type: object EnvironmentVariable: description: Environment Variable model properties: id: type: integer uuid: type: string resourceable_type: type: string resourceable_id: type: integer is_build_time: type: boolean is_literal: type: boolean is_multiline: type: boolean is_preview: type: boolean is_shared: type: boolean is_shown_once: type: boolean key: type: string value: type: string real_value: type: string version: type: string created_at: type: string updated_at: type: string type: object PrivateKey: description: Private Key model properties: id: type: integer uuid: type: string name: type: string description: type: string private_key: type: string format: private-key is_git_related: type: boolean team_id: type: integer created_at: type: string updated_at: type: string type: object Project: description: Project model properties: id: type: integer uuid: type: string name: type: string description: type: string environments: description: The environments of the project. type: array items: $ref: '#/components/schemas/Environment' type: object Server: description: Server model properties: id: type: integer description: The server ID. uuid: type: string description: The server UUID. name: type: string description: The server name. description: type: string description: The server description. ip: type: string description: The IP address. user: type: string description: The user. port: type: integer description: The port number. proxy: type: object description: The proxy configuration. proxy_type: type: string enum: - traefik - caddy - none description: The proxy type. high_disk_usage_notification_sent: type: boolean description: The flag to indicate if the high disk usage notification has been sent. unreachable_notification_sent: type: boolean description: The flag to indicate if the unreachable notification has been sent. unreachable_count: type: integer description: The unreachable count for your server. validation_logs: type: string description: The validation logs. log_drain_notification_sent: type: boolean description: The flag to indicate if the log drain notification has been sent. swarm_cluster: type: string description: The swarm cluster configuration. settings: $ref: '#/components/schemas/ServerSetting' type: object ServerSetting: description: Server Settings model properties: id: type: integer concurrent_builds: type: integer dynamic_timeout: type: integer force_disabled: type: boolean force_server_cleanup: type: boolean is_build_server: type: boolean is_cloudflare_tunnel: type: boolean is_jump_server: type: boolean is_logdrain_axiom_enabled: type: boolean is_logdrain_custom_enabled: type: boolean is_logdrain_highlight_enabled: type: boolean is_logdrain_newrelic_enabled: type: boolean is_metrics_enabled: type: boolean is_reachable: type: boolean is_sentinel_enabled: type: boolean is_swarm_manager: type: boolean is_swarm_worker: type: boolean is_usable: type: boolean logdrain_axiom_api_key: type: string logdrain_axiom_dataset_name: type: string logdrain_custom_config: type: string logdrain_custom_config_parser: type: string logdrain_highlight_project_id: type: string logdrain_newrelic_base_uri: type: string logdrain_newrelic_license_key: type: string sentinel_metrics_history_days: type: integer sentinel_metrics_refresh_rate_seconds: type: integer sentinel_token: type: string docker_cleanup_frequency: type: string docker_cleanup_threshold: type: integer server_id: type: integer wildcard_domain: type: string created_at: type: string updated_at: type: string delete_unused_volumes: type: boolean description: The flag to indicate if the unused volumes should be deleted. delete_unused_networks: type: boolean description: The flag to indicate if the unused networks should be deleted. type: object Service: description: Service model properties: id: type: integer description: The unique identifier of the service. Only used for database identification. uuid: type: string description: The unique identifier of the service. name: type: string description: The name of the service. environment_id: type: integer description: The unique identifier of the environment where the service is attached to. server_id: type: integer description: The unique identifier of the server where the service is running. description: type: string description: The description of the service. docker_compose_raw: type: string description: The raw docker-compose.yml file of the service. docker_compose: type: string description: The docker-compose.yml file that is parsed and modified by Coolify. destination_type: type: string description: Destination type. destination_id: type: integer description: The unique identifier of the destination where the service is running. connect_to_docker_network: type: boolean description: The flag to connect the service to the predefined Docker network. is_container_label_escape_enabled: type: boolean description: The flag to enable the container label escape. is_container_label_readonly_enabled: type: boolean description: The flag to enable the container label readonly. config_hash: type: string description: The hash of the service configuration. service_type: type: string description: The type of the service. created_at: type: string description: The date and time when the service was created. updated_at: type: string description: The date and time when the service was last updated. deleted_at: type: string description: The date and time when the service was deleted. type: object Team: description: Team model properties: id: type: integer description: The unique identifier of the team. name: type: string description: The name of the team. description: type: string description: The description of the team. personal_team: type: boolean description: Whether the team is personal or not. created_at: type: string description: The date and time the team was created. updated_at: type: string description: The date and time the team was last updated. show_boarding: type: boolean description: Whether to show the boarding screen or not. custom_server_limit: type: string description: The custom server limit. members: description: The members of the team. type: array items: $ref: '#/components/schemas/User' type: object User: description: User model properties: id: type: integer description: The user identifier in the database. name: type: string description: The user name. email: type: string description: The user email. email_verified_at: type: string description: The date when the user email was verified. created_at: type: string description: The date when the user was created. updated_at: type: string description: The date when the user was updated. two_factor_confirmed_at: type: string description: The date when the user two factor was confirmed. force_password_reset: type: boolean description: The flag to force the user to reset the password. marketing_emails: type: boolean description: The flag to receive marketing emails. type: object ``` -------------------------------------------------------------------------------- /docs/openapi-chunks/databases-api.yaml: -------------------------------------------------------------------------------- ```yaml openapi: 3.1.0 info: title: Coolify version: '0.1' paths: /databases: get: tags: - Databases summary: List description: List all databases. operationId: list-databases responses: '200': description: Get all databases content: application/json: schema: type: string example: Content is very complex. Will be implemented later. '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] /databases/{uuid}: get: tags: - Databases summary: Get description: Get database by UUID. operationId: get-database-by-uuid parameters: - name: uuid in: path description: UUID of the database. required: true schema: type: string format: uuid responses: '200': description: Get all databases content: application/json: schema: type: string example: Content is very complex. Will be implemented later. '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] delete: tags: - Databases summary: Delete description: Delete database by UUID. operationId: delete-database-by-uuid parameters: - name: uuid in: path description: UUID of the database. required: true schema: type: string format: uuid - name: delete_configurations in: query description: Delete configurations. required: false schema: type: boolean default: true - name: delete_volumes in: query description: Delete volumes. required: false schema: type: boolean default: true - name: docker_cleanup in: query description: Run docker cleanup. required: false schema: type: boolean default: true - name: delete_connected_networks in: query description: Delete connected networks. required: false schema: type: boolean default: true responses: '200': description: Database deleted. content: application/json: schema: properties: message: type: string example: Database deleted. type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] patch: tags: - Databases summary: Update description: Update database by UUID. operationId: update-database-by-uuid parameters: - name: uuid in: path description: UUID of the database. required: true schema: type: string format: uuid requestBody: description: Database data required: true content: application/json: schema: properties: name: type: string description: Name of the database description: type: string description: Description of the database image: type: string description: Docker Image of the database is_public: type: boolean description: Is the database public? public_port: type: integer description: Public port of the database limits_memory: type: string description: Memory limit of the database limits_memory_swap: type: string description: Memory swap limit of the database limits_memory_swappiness: type: integer description: Memory swappiness of the database limits_memory_reservation: type: string description: Memory reservation of the database limits_cpus: type: string description: CPU limit of the database limits_cpuset: type: string description: CPU set of the database limits_cpu_shares: type: integer description: CPU shares of the database postgres_user: type: string description: PostgreSQL user postgres_password: type: string description: PostgreSQL password postgres_db: type: string description: PostgreSQL database postgres_initdb_args: type: string description: PostgreSQL initdb args postgres_host_auth_method: type: string description: PostgreSQL host auth method postgres_conf: type: string description: PostgreSQL conf clickhouse_admin_user: type: string description: Clickhouse admin user clickhouse_admin_password: type: string description: Clickhouse admin password dragonfly_password: type: string description: DragonFly password redis_password: type: string description: Redis password redis_conf: type: string description: Redis conf keydb_password: type: string description: KeyDB password keydb_conf: type: string description: KeyDB conf mariadb_conf: type: string description: MariaDB conf mariadb_root_password: type: string description: MariaDB root password mariadb_user: type: string description: MariaDB user mariadb_password: type: string description: MariaDB password mariadb_database: type: string description: MariaDB database mongo_conf: type: string description: Mongo conf mongo_initdb_root_username: type: string description: Mongo initdb root username mongo_initdb_root_password: type: string description: Mongo initdb root password mongo_initdb_database: type: string description: Mongo initdb init database mysql_root_password: type: string description: MySQL root password mysql_password: type: string description: MySQL password mysql_user: type: string description: MySQL user mysql_database: type: string description: MySQL database mysql_conf: type: string description: MySQL conf type: object responses: '200': description: Database updated '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /databases/postgresql: post: tags: - Databases summary: Create (PostgreSQL) description: Create a new PostgreSQL database. operationId: create-database-postgresql requestBody: description: Database data required: true content: application/json: schema: required: - server_uuid - project_uuid - environment_name - environment_uuid properties: server_uuid: type: string description: UUID of the server project_uuid: type: string description: UUID of the project environment_name: type: string description: Name of the environment. You need to provide at least one of environment_name or environment_uuid. environment_uuid: type: string description: UUID of the environment. You need to provide at least one of environment_name or environment_uuid. postgres_user: type: string description: PostgreSQL user postgres_password: type: string description: PostgreSQL password postgres_db: type: string description: PostgreSQL database postgres_initdb_args: type: string description: PostgreSQL initdb args postgres_host_auth_method: type: string description: PostgreSQL host auth method postgres_conf: type: string description: PostgreSQL conf destination_uuid: type: string description: UUID of the destination if the server has multiple destinations name: type: string description: Name of the database description: type: string description: Description of the database image: type: string description: Docker Image of the database is_public: type: boolean description: Is the database public? public_port: type: integer description: Public port of the database limits_memory: type: string description: Memory limit of the database limits_memory_swap: type: string description: Memory swap limit of the database limits_memory_swappiness: type: integer description: Memory swappiness of the database limits_memory_reservation: type: string description: Memory reservation of the database limits_cpus: type: string description: CPU limit of the database limits_cpuset: type: string description: CPU set of the database limits_cpu_shares: type: integer description: CPU shares of the database instant_deploy: type: boolean description: Instant deploy the database type: object responses: '200': description: Database updated '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] /databases/clickhouse: post: tags: - Databases summary: Create (Clickhouse) description: Create a new Clickhouse database. operationId: create-database-clickhouse requestBody: description: Database data required: true content: application/json: schema: required: - server_uuid - project_uuid - environment_name - environment_uuid properties: server_uuid: type: string description: UUID of the server project_uuid: type: string description: UUID of the project environment_name: type: string description: Name of the environment. You need to provide at least one of environment_name or environment_uuid. environment_uuid: type: string description: UUID of the environment. You need to provide at least one of environment_name or environment_uuid. destination_uuid: type: string description: UUID of the destination if the server has multiple destinations clickhouse_admin_user: type: string description: Clickhouse admin user clickhouse_admin_password: type: string description: Clickhouse admin password name: type: string description: Name of the database description: type: string description: Description of the database image: type: string description: Docker Image of the database is_public: type: boolean description: Is the database public? public_port: type: integer description: Public port of the database limits_memory: type: string description: Memory limit of the database limits_memory_swap: type: string description: Memory swap limit of the database limits_memory_swappiness: type: integer description: Memory swappiness of the database limits_memory_reservation: type: string description: Memory reservation of the database limits_cpus: type: string description: CPU limit of the database limits_cpuset: type: string description: CPU set of the database limits_cpu_shares: type: integer description: CPU shares of the database instant_deploy: type: boolean description: Instant deploy the database type: object responses: '200': description: Database updated '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] /databases/dragonfly: post: tags: - Databases summary: Create (DragonFly) description: Create a new DragonFly database. operationId: create-database-dragonfly requestBody: description: Database data required: true content: application/json: schema: required: - server_uuid - project_uuid - environment_name - environment_uuid properties: server_uuid: type: string description: UUID of the server project_uuid: type: string description: UUID of the project environment_name: type: string description: Name of the environment. You need to provide at least one of environment_name or environment_uuid. environment_uuid: type: string description: UUID of the environment. You need to provide at least one of environment_name or environment_uuid. destination_uuid: type: string description: UUID of the destination if the server has multiple destinations dragonfly_password: type: string description: DragonFly password name: type: string description: Name of the database description: type: string description: Description of the database image: type: string description: Docker Image of the database is_public: type: boolean description: Is the database public? public_port: type: integer description: Public port of the database limits_memory: type: string description: Memory limit of the database limits_memory_swap: type: string description: Memory swap limit of the database limits_memory_swappiness: type: integer description: Memory swappiness of the database limits_memory_reservation: type: string description: Memory reservation of the database limits_cpus: type: string description: CPU limit of the database limits_cpuset: type: string description: CPU set of the database limits_cpu_shares: type: integer description: CPU shares of the database instant_deploy: type: boolean description: Instant deploy the database type: object responses: '200': description: Database updated '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] /databases/redis: post: tags: - Databases summary: Create (Redis) description: Create a new Redis database. operationId: create-database-redis requestBody: description: Database data required: true content: application/json: schema: required: - server_uuid - project_uuid - environment_name - environment_uuid properties: server_uuid: type: string description: UUID of the server project_uuid: type: string description: UUID of the project environment_name: type: string description: Name of the environment. You need to provide at least one of environment_name or environment_uuid. environment_uuid: type: string description: UUID of the environment. You need to provide at least one of environment_name or environment_uuid. destination_uuid: type: string description: UUID of the destination if the server has multiple destinations redis_password: type: string description: Redis password redis_conf: type: string description: Redis conf name: type: string description: Name of the database description: type: string description: Description of the database image: type: string description: Docker Image of the database is_public: type: boolean description: Is the database public? public_port: type: integer description: Public port of the database limits_memory: type: string description: Memory limit of the database limits_memory_swap: type: string description: Memory swap limit of the database limits_memory_swappiness: type: integer description: Memory swappiness of the database limits_memory_reservation: type: string description: Memory reservation of the database limits_cpus: type: string description: CPU limit of the database limits_cpuset: type: string description: CPU set of the database limits_cpu_shares: type: integer description: CPU shares of the database instant_deploy: type: boolean description: Instant deploy the database type: object responses: '200': description: Database updated '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] /databases/keydb: post: tags: - Databases summary: Create (KeyDB) description: Create a new KeyDB database. operationId: create-database-keydb requestBody: description: Database data required: true content: application/json: schema: required: - server_uuid - project_uuid - environment_name - environment_uuid properties: server_uuid: type: string description: UUID of the server project_uuid: type: string description: UUID of the project environment_name: type: string description: Name of the environment. You need to provide at least one of environment_name or environment_uuid. environment_uuid: type: string description: UUID of the environment. You need to provide at least one of environment_name or environment_uuid. destination_uuid: type: string description: UUID of the destination if the server has multiple destinations keydb_password: type: string description: KeyDB password keydb_conf: type: string description: KeyDB conf name: type: string description: Name of the database description: type: string description: Description of the database image: type: string description: Docker Image of the database is_public: type: boolean description: Is the database public? public_port: type: integer description: Public port of the database limits_memory: type: string description: Memory limit of the database limits_memory_swap: type: string description: Memory swap limit of the database limits_memory_swappiness: type: integer description: Memory swappiness of the database limits_memory_reservation: type: string description: Memory reservation of the database limits_cpus: type: string description: CPU limit of the database limits_cpuset: type: string description: CPU set of the database limits_cpu_shares: type: integer description: CPU shares of the database instant_deploy: type: boolean description: Instant deploy the database type: object responses: '200': description: Database updated '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] /databases/mariadb: post: tags: - Databases summary: Create (MariaDB) description: Create a new MariaDB database. operationId: create-database-mariadb requestBody: description: Database data required: true content: application/json: schema: required: - server_uuid - project_uuid - environment_name - environment_uuid properties: server_uuid: type: string description: UUID of the server project_uuid: type: string description: UUID of the project environment_name: type: string description: Name of the environment. You need to provide at least one of environment_name or environment_uuid. environment_uuid: type: string description: UUID of the environment. You need to provide at least one of environment_name or environment_uuid. destination_uuid: type: string description: UUID of the destination if the server has multiple destinations mariadb_conf: type: string description: MariaDB conf mariadb_root_password: type: string description: MariaDB root password mariadb_user: type: string description: MariaDB user mariadb_password: type: string description: MariaDB password mariadb_database: type: string description: MariaDB database name: type: string description: Name of the database description: type: string description: Description of the database image: type: string description: Docker Image of the database is_public: type: boolean description: Is the database public? public_port: type: integer description: Public port of the database limits_memory: type: string description: Memory limit of the database limits_memory_swap: type: string description: Memory swap limit of the database limits_memory_swappiness: type: integer description: Memory swappiness of the database limits_memory_reservation: type: string description: Memory reservation of the database limits_cpus: type: string description: CPU limit of the database limits_cpuset: type: string description: CPU set of the database limits_cpu_shares: type: integer description: CPU shares of the database instant_deploy: type: boolean description: Instant deploy the database type: object responses: '200': description: Database updated '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] /databases/mysql: post: tags: - Databases summary: Create (MySQL) description: Create a new MySQL database. operationId: create-database-mysql requestBody: description: Database data required: true content: application/json: schema: required: - server_uuid - project_uuid - environment_name - environment_uuid properties: server_uuid: type: string description: UUID of the server project_uuid: type: string description: UUID of the project environment_name: type: string description: Name of the environment. You need to provide at least one of environment_name or environment_uuid. environment_uuid: type: string description: UUID of the environment. You need to provide at least one of environment_name or environment_uuid. destination_uuid: type: string description: UUID of the destination if the server has multiple destinations mysql_root_password: type: string description: MySQL root password mysql_password: type: string description: MySQL password mysql_user: type: string description: MySQL user mysql_database: type: string description: MySQL database mysql_conf: type: string description: MySQL conf name: type: string description: Name of the database description: type: string description: Description of the database image: type: string description: Docker Image of the database is_public: type: boolean description: Is the database public? public_port: type: integer description: Public port of the database limits_memory: type: string description: Memory limit of the database limits_memory_swap: type: string description: Memory swap limit of the database limits_memory_swappiness: type: integer description: Memory swappiness of the database limits_memory_reservation: type: string description: Memory reservation of the database limits_cpus: type: string description: CPU limit of the database limits_cpuset: type: string description: CPU set of the database limits_cpu_shares: type: integer description: CPU shares of the database instant_deploy: type: boolean description: Instant deploy the database type: object responses: '200': description: Database updated '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] /databases/mongodb: post: tags: - Databases summary: Create (MongoDB) description: Create a new MongoDB database. operationId: create-database-mongodb requestBody: description: Database data required: true content: application/json: schema: required: - server_uuid - project_uuid - environment_name - environment_uuid properties: server_uuid: type: string description: UUID of the server project_uuid: type: string description: UUID of the project environment_name: type: string description: Name of the environment. You need to provide at least one of environment_name or environment_uuid. environment_uuid: type: string description: UUID of the environment. You need to provide at least one of environment_name or environment_uuid. destination_uuid: type: string description: UUID of the destination if the server has multiple destinations mongo_conf: type: string description: MongoDB conf mongo_initdb_root_username: type: string description: MongoDB initdb root username name: type: string description: Name of the database description: type: string description: Description of the database image: type: string description: Docker Image of the database is_public: type: boolean description: Is the database public? public_port: type: integer description: Public port of the database limits_memory: type: string description: Memory limit of the database limits_memory_swap: type: string description: Memory swap limit of the database limits_memory_swappiness: type: integer description: Memory swappiness of the database limits_memory_reservation: type: string description: Memory reservation of the database limits_cpus: type: string description: CPU limit of the database limits_cpuset: type: string description: CPU set of the database limits_cpu_shares: type: integer description: CPU shares of the database instant_deploy: type: boolean description: Instant deploy the database type: object responses: '200': description: Database updated '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' security: - bearerAuth: [] /databases/{uuid}/start: get: tags: - Databases summary: Start description: Start database. `Post` request is also accepted. operationId: start-database-by-uuid parameters: - name: uuid in: path description: UUID of the database. required: true schema: type: string format: uuid responses: '200': description: Start database. content: application/json: schema: properties: message: type: string example: Database starting request queued. type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /databases/{uuid}/stop: get: tags: - Databases summary: Stop description: Stop database. `Post` request is also accepted. operationId: stop-database-by-uuid parameters: - name: uuid in: path description: UUID of the database. required: true schema: type: string format: uuid responses: '200': description: Stop database. content: application/json: schema: properties: message: type: string example: Database stopping request queued. type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /databases/{uuid}/restart: get: tags: - Databases summary: Restart description: Restart database. `Post` request is also accepted. operationId: restart-database-by-uuid parameters: - name: uuid in: path description: UUID of the database. required: true schema: type: string format: uuid responses: '200': description: Restart database. content: application/json: schema: properties: message: type: string example: Database restaring request queued. type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] ```