@masonator/coolify-mcp 2.1.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -67
- package/dist/__tests__/coolify-client.test.js +10 -0
- package/dist/__tests__/mcp-server.test.js +2 -0
- package/dist/lib/coolify-client.js +9 -1
- package/dist/lib/mcp-server.d.ts +1 -1
- package/dist/lib/mcp-server.js +72 -5
- package/dist/types/coolify.d.ts +10 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,25 +17,25 @@ A Model Context Protocol (MCP) server for [Coolify](https://coolify.io/), enabli
|
|
|
17
17
|
|
|
18
18
|
This MCP server provides **34 token-optimized tools** for **debugging, management, and deployment**:
|
|
19
19
|
|
|
20
|
-
| Category | Tools
|
|
21
|
-
| -------------------- |
|
|
22
|
-
| **Infrastructure** | `get_infrastructure_overview`, `get_mcp_version`, `get_version`
|
|
23
|
-
| **Diagnostics** | `diagnose_app`, `diagnose_server`, `find_issues`
|
|
24
|
-
| **Batch Operations** | `restart_project_apps`, `bulk_env_update`, `stop_all_apps`, `redeploy_project`
|
|
25
|
-
| **Servers** | `list_servers`, `get_server`, `validate_server`, `server_resources`, `server_domains`
|
|
26
|
-
| **Projects** | `projects` (list, get, create, update, delete via action param)
|
|
27
|
-
| **Environments** | `environments` (list, get, create, delete via action param)
|
|
28
|
-
| **Applications** | `list_applications`, `get_application`, `application` (CRUD), `application_logs`
|
|
29
|
-
| **Databases** | `list_databases`, `get_database`, `database` (create 8 types, delete), `database_backups` |
|
|
30
|
-
| **Services** | `list_services`, `get_service`, `service` (create, update, delete)
|
|
31
|
-
| **Control** | `control` (start/stop/restart for apps, databases, services)
|
|
32
|
-
| **Env Vars** | `env_vars` (CRUD for application and service env vars)
|
|
33
|
-
| **Deployments** | `list_deployments`, `deploy`, `deployment` (get, cancel, list_for_app)
|
|
34
|
-
| **Private Keys** | `private_keys` (list, get, create, update, delete via action param)
|
|
35
|
-
|
|
36
|
-
###
|
|
37
|
-
|
|
38
|
-
|
|
20
|
+
| Category | Tools |
|
|
21
|
+
| -------------------- | --------------------------------------------------------------------------------------------------------------------------- |
|
|
22
|
+
| **Infrastructure** | `get_infrastructure_overview`, `get_mcp_version`, `get_version` |
|
|
23
|
+
| **Diagnostics** | `diagnose_app`, `diagnose_server`, `find_issues` |
|
|
24
|
+
| **Batch Operations** | `restart_project_apps`, `bulk_env_update`, `stop_all_apps`, `redeploy_project` |
|
|
25
|
+
| **Servers** | `list_servers`, `get_server`, `validate_server`, `server_resources`, `server_domains` |
|
|
26
|
+
| **Projects** | `projects` (list, get, create, update, delete via action param) |
|
|
27
|
+
| **Environments** | `environments` (list, get, create, delete via action param) |
|
|
28
|
+
| **Applications** | `list_applications`, `get_application`, `application` (CRUD), `application_logs` |
|
|
29
|
+
| **Databases** | `list_databases`, `get_database`, `database` (create 8 types, delete), `database_backups` (CRUD schedules, view executions) |
|
|
30
|
+
| **Services** | `list_services`, `get_service`, `service` (create, update, delete) |
|
|
31
|
+
| **Control** | `control` (start/stop/restart for apps, databases, services) |
|
|
32
|
+
| **Env Vars** | `env_vars` (CRUD for application and service env vars) |
|
|
33
|
+
| **Deployments** | `list_deployments`, `deploy`, `deployment` (get, cancel, list_for_app) |
|
|
34
|
+
| **Private Keys** | `private_keys` (list, get, create, update, delete via action param) |
|
|
35
|
+
|
|
36
|
+
### Token-Optimized Design
|
|
37
|
+
|
|
38
|
+
The server uses **85% fewer tokens** than a naive implementation (6,600 vs 43,000) by consolidating related operations into single tools with action parameters. This prevents context window exhaustion in AI assistants.
|
|
39
39
|
|
|
40
40
|
## Installation
|
|
41
41
|
|
|
@@ -216,78 +216,49 @@ These tools accept human-friendly identifiers instead of just UUIDs:
|
|
|
216
216
|
|
|
217
217
|
### Projects
|
|
218
218
|
|
|
219
|
-
- `
|
|
220
|
-
- `get_project` - Get project details
|
|
221
|
-
- `create_project` - Create a new project
|
|
222
|
-
- `update_project` - Update a project
|
|
223
|
-
- `delete_project` - Delete a project
|
|
219
|
+
- `projects` - Manage projects with `action: list|get|create|update|delete`
|
|
224
220
|
|
|
225
221
|
### Environments
|
|
226
222
|
|
|
227
|
-
- `
|
|
228
|
-
- `get_environment` - Get environment details
|
|
229
|
-
- `create_environment` - Create environment in a project
|
|
230
|
-
- `delete_environment` - Delete an environment
|
|
223
|
+
- `environments` - Manage environments with `action: list|get|create|delete`
|
|
231
224
|
|
|
232
225
|
### Applications
|
|
233
226
|
|
|
234
227
|
- `list_applications` - List all applications (returns summary)
|
|
235
228
|
- `get_application` - Get application details
|
|
236
|
-
- `
|
|
237
|
-
- `
|
|
238
|
-
- `
|
|
239
|
-
- `
|
|
240
|
-
- `start_application` - Start an application
|
|
241
|
-
- `stop_application` - Stop an application
|
|
242
|
-
- `restart_application` - Restart an application
|
|
243
|
-
- `get_application_logs` - Get application logs
|
|
244
|
-
- `list_application_envs` - List application environment variables
|
|
245
|
-
- `create_application_env` - Create application environment variable
|
|
246
|
-
- `update_application_env` - Update application environment variable
|
|
247
|
-
- `delete_application_env` - Delete application environment variable
|
|
229
|
+
- `application_logs` - Get application logs
|
|
230
|
+
- `application` - Create, update, or delete apps with `action: create_public|create_github|create_key|create_dockerimage|update|delete`
|
|
231
|
+
- `env_vars` - Manage env vars with `resource: application, action: list|create|update|delete`
|
|
232
|
+
- `control` - Start/stop/restart with `resource: application, action: start|stop|restart`
|
|
248
233
|
|
|
249
234
|
### Databases
|
|
250
235
|
|
|
251
236
|
- `list_databases` - List all databases (returns summary)
|
|
252
237
|
- `get_database` - Get database details
|
|
253
|
-
- `
|
|
254
|
-
- `
|
|
255
|
-
-
|
|
256
|
-
-
|
|
257
|
-
-
|
|
258
|
-
- `
|
|
259
|
-
- `list_backup_executions` - List execution history for a scheduled backup
|
|
260
|
-
- `get_backup_execution` - Get details of a specific backup execution
|
|
238
|
+
- `database` - Create or delete databases with `action: create|delete, type: postgresql|mysql|mariadb|mongodb|redis|keydb|clickhouse|dragonfly`
|
|
239
|
+
- `database_backups` - Manage backup schedules with `action: list_schedules|get_schedule|create|update|delete|list_executions|get_execution`
|
|
240
|
+
- Configure frequency, retention policies, S3 storage
|
|
241
|
+
- Enable/disable schedules without deletion
|
|
242
|
+
- View backup execution history
|
|
243
|
+
- `control` - Start/stop/restart with `resource: database, action: start|stop|restart`
|
|
261
244
|
|
|
262
245
|
### Services
|
|
263
246
|
|
|
264
247
|
- `list_services` - List all services (returns summary)
|
|
265
248
|
- `get_service` - Get service details
|
|
266
|
-
- `
|
|
267
|
-
- `
|
|
268
|
-
- `
|
|
269
|
-
- `start_service` - Start a service
|
|
270
|
-
- `stop_service` - Stop a service
|
|
271
|
-
- `restart_service` - Restart a service
|
|
272
|
-
- `list_service_envs` - List service environment variables
|
|
273
|
-
- `create_service_env` - Create service environment variable
|
|
274
|
-
- `delete_service_env` - Delete service environment variable
|
|
249
|
+
- `service` - Create, update, or delete services with `action: create|update|delete`
|
|
250
|
+
- `env_vars` - Manage env vars with `resource: service, action: list|create|delete`
|
|
251
|
+
- `control` - Start/stop/restart with `resource: service, action: start|stop|restart`
|
|
275
252
|
|
|
276
253
|
### Deployments
|
|
277
254
|
|
|
278
255
|
- `list_deployments` - List running deployments (returns summary)
|
|
279
|
-
- `get_deployment` - Get deployment details
|
|
280
256
|
- `deploy` - Deploy by tag or UUID
|
|
281
|
-
- `
|
|
282
|
-
- `list_application_deployments` - List deployments for an application
|
|
257
|
+
- `deployment` - Manage deployments with `action: get|cancel|list_for_app`
|
|
283
258
|
|
|
284
259
|
### Private Keys
|
|
285
260
|
|
|
286
|
-
- `
|
|
287
|
-
- `get_private_key` - Get private key details
|
|
288
|
-
- `create_private_key` - Create a new private key for deployments
|
|
289
|
-
- `update_private_key` - Update a private key
|
|
290
|
-
- `delete_private_key` - Delete a private key
|
|
261
|
+
- `private_keys` - Manage SSH keys with `action: list|get|create|update|delete`
|
|
291
262
|
|
|
292
263
|
### Batch Operations
|
|
293
264
|
|
|
@@ -303,9 +274,8 @@ Power user tools for operating on multiple resources at once:
|
|
|
303
274
|
- **Context-Optimized**: Responses are 90-99% smaller than raw API, preventing context window exhaustion
|
|
304
275
|
- **Smart Lookup**: Find apps by domain (`stuartmason.co.uk`), servers by IP, not just UUIDs
|
|
305
276
|
- **Batch Operations**: Restart entire projects, bulk update env vars, emergency stop all apps
|
|
306
|
-
- **Workflow Prompts**: Pre-built guided workflows for common tasks
|
|
307
277
|
- **Production Ready**: 98%+ test coverage, TypeScript strict mode, comprehensive error handling
|
|
308
|
-
- **Always Current**: Weekly OpenAPI drift detection ensures
|
|
278
|
+
- **Always Current**: Weekly OpenAPI drift detection ensures the server stays in sync with Coolify
|
|
309
279
|
|
|
310
280
|
## Related Links
|
|
311
281
|
|
|
@@ -377,6 +377,16 @@ describe('CoolifyClient', () => {
|
|
|
377
377
|
mockFetch.mockResolvedValueOnce(mockResponse({}, false, 500));
|
|
378
378
|
await expect(client.listServers()).rejects.toThrow('HTTP 500: Error');
|
|
379
379
|
});
|
|
380
|
+
it('should include validation errors in error message', async () => {
|
|
381
|
+
mockFetch.mockResolvedValueOnce(mockResponse({
|
|
382
|
+
message: 'Validation failed.',
|
|
383
|
+
errors: {
|
|
384
|
+
name: ['The name field is required.'],
|
|
385
|
+
email: ['The email must be valid.', 'The email is already taken.'],
|
|
386
|
+
},
|
|
387
|
+
}, false, 422));
|
|
388
|
+
await expect(client.listServers()).rejects.toThrow('Validation failed. - name: The name field is required.; email: The email must be valid., The email is already taken.');
|
|
389
|
+
});
|
|
380
390
|
});
|
|
381
391
|
// =========================================================================
|
|
382
392
|
// Server endpoints - additional coverage
|
|
@@ -52,8 +52,10 @@ describe('CoolifyMcpServer v2', () => {
|
|
|
52
52
|
// Application operations
|
|
53
53
|
expect(typeof client.listApplications).toBe('function');
|
|
54
54
|
expect(typeof client.getApplication).toBe('function');
|
|
55
|
+
expect(typeof client.createApplicationPublic).toBe('function');
|
|
55
56
|
expect(typeof client.createApplicationPrivateGH).toBe('function');
|
|
56
57
|
expect(typeof client.createApplicationPrivateKey).toBe('function');
|
|
58
|
+
expect(typeof client.createApplicationDockerImage).toBe('function');
|
|
57
59
|
expect(typeof client.updateApplication).toBe('function');
|
|
58
60
|
expect(typeof client.deleteApplication).toBe('function');
|
|
59
61
|
expect(typeof client.getApplicationLogs).toBe('function');
|
|
@@ -112,7 +112,15 @@ export class CoolifyClient {
|
|
|
112
112
|
const data = text ? JSON.parse(text) : {};
|
|
113
113
|
if (!response.ok) {
|
|
114
114
|
const error = data;
|
|
115
|
-
|
|
115
|
+
// Include validation errors if present
|
|
116
|
+
let errorMessage = error.message || `HTTP ${response.status}: ${response.statusText}`;
|
|
117
|
+
if (error.errors && Object.keys(error.errors).length > 0) {
|
|
118
|
+
const validationDetails = Object.entries(error.errors)
|
|
119
|
+
.map(([field, messages]) => `${field}: ${messages.join(', ')}`)
|
|
120
|
+
.join('; ');
|
|
121
|
+
errorMessage = `${errorMessage} - ${validationDetails}`;
|
|
122
|
+
}
|
|
123
|
+
throw new Error(errorMessage);
|
|
116
124
|
}
|
|
117
125
|
return data;
|
|
118
126
|
}
|
package/dist/lib/mcp-server.d.ts
CHANGED
package/dist/lib/mcp-server.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Coolify MCP Server v2.
|
|
2
|
+
* Coolify MCP Server v2.3.0
|
|
3
3
|
* Consolidated tools for efficient token usage
|
|
4
4
|
*/
|
|
5
5
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
6
6
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
7
7
|
import { z } from 'zod';
|
|
8
8
|
import { CoolifyClient, } from './coolify-client.js';
|
|
9
|
-
const VERSION = '2.
|
|
9
|
+
const VERSION = '2.3.0';
|
|
10
10
|
/** Wrap handler with error handling */
|
|
11
11
|
function wrap(fn) {
|
|
12
12
|
return fn()
|
|
@@ -162,7 +162,14 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
162
162
|
this.tool('list_applications', 'List apps (summary)', { page: z.number().optional(), per_page: z.number().optional() }, async ({ page, per_page }) => wrap(() => this.client.listApplications({ page, per_page, summary: true })));
|
|
163
163
|
this.tool('get_application', 'App details', { uuid: z.string() }, async ({ uuid }) => wrap(() => this.client.getApplication(uuid)));
|
|
164
164
|
this.tool('application', 'Manage app: create/update/delete', {
|
|
165
|
-
action: z.enum([
|
|
165
|
+
action: z.enum([
|
|
166
|
+
'create_public',
|
|
167
|
+
'create_github',
|
|
168
|
+
'create_key',
|
|
169
|
+
'create_dockerimage',
|
|
170
|
+
'update',
|
|
171
|
+
'delete',
|
|
172
|
+
]),
|
|
166
173
|
uuid: z.string().optional(),
|
|
167
174
|
// Create fields
|
|
168
175
|
project_uuid: z.string().optional(),
|
|
@@ -172,17 +179,51 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
172
179
|
git_repository: z.string().optional(),
|
|
173
180
|
git_branch: z.string().optional(),
|
|
174
181
|
environment_name: z.string().optional(),
|
|
182
|
+
environment_uuid: z.string().optional(),
|
|
175
183
|
build_pack: z.string().optional(),
|
|
176
184
|
ports_exposes: z.string().optional(),
|
|
185
|
+
// Docker image fields
|
|
186
|
+
docker_registry_image_name: z.string().optional(),
|
|
187
|
+
docker_registry_image_tag: z.string().optional(),
|
|
177
188
|
// Update fields
|
|
178
189
|
name: z.string().optional(),
|
|
179
190
|
description: z.string().optional(),
|
|
180
191
|
fqdn: z.string().optional(),
|
|
192
|
+
// Health check fields
|
|
193
|
+
health_check_enabled: z.boolean().optional(),
|
|
194
|
+
health_check_path: z.string().optional(),
|
|
195
|
+
health_check_port: z.number().optional(),
|
|
196
|
+
health_check_host: z.string().optional(),
|
|
197
|
+
health_check_method: z.string().optional(),
|
|
198
|
+
health_check_return_code: z.number().optional(),
|
|
199
|
+
health_check_scheme: z.string().optional(),
|
|
200
|
+
health_check_response_text: z.string().optional(),
|
|
201
|
+
health_check_interval: z.number().optional(),
|
|
202
|
+
health_check_timeout: z.number().optional(),
|
|
203
|
+
health_check_retries: z.number().optional(),
|
|
204
|
+
health_check_start_period: z.number().optional(),
|
|
181
205
|
// Delete fields
|
|
182
206
|
delete_volumes: z.boolean().optional(),
|
|
183
207
|
}, async (args) => {
|
|
184
208
|
const { action, uuid } = args;
|
|
185
209
|
switch (action) {
|
|
210
|
+
case 'create_public':
|
|
211
|
+
if (!args.project_uuid ||
|
|
212
|
+
!args.server_uuid ||
|
|
213
|
+
!args.git_repository ||
|
|
214
|
+
!args.git_branch ||
|
|
215
|
+
!args.build_pack ||
|
|
216
|
+
!args.ports_exposes) {
|
|
217
|
+
return {
|
|
218
|
+
content: [
|
|
219
|
+
{
|
|
220
|
+
type: 'text',
|
|
221
|
+
text: 'Error: project_uuid, server_uuid, git_repository, git_branch, build_pack, ports_exposes required',
|
|
222
|
+
},
|
|
223
|
+
],
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
return wrap(() => this.client.createApplicationPublic(args));
|
|
186
227
|
case 'create_github':
|
|
187
228
|
if (!args.project_uuid ||
|
|
188
229
|
!args.server_uuid ||
|
|
@@ -215,6 +256,21 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
215
256
|
};
|
|
216
257
|
}
|
|
217
258
|
return wrap(() => this.client.createApplicationPrivateKey(args));
|
|
259
|
+
case 'create_dockerimage':
|
|
260
|
+
if (!args.project_uuid ||
|
|
261
|
+
!args.server_uuid ||
|
|
262
|
+
!args.docker_registry_image_name ||
|
|
263
|
+
!args.ports_exposes) {
|
|
264
|
+
return {
|
|
265
|
+
content: [
|
|
266
|
+
{
|
|
267
|
+
type: 'text',
|
|
268
|
+
text: 'Error: project_uuid, server_uuid, docker_registry_image_name, ports_exposes required',
|
|
269
|
+
},
|
|
270
|
+
],
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
return wrap(() => this.client.createApplicationDockerImage(args));
|
|
218
274
|
case 'update':
|
|
219
275
|
if (!uuid)
|
|
220
276
|
return { content: [{ type: 'text', text: 'Error: uuid required' }] };
|
|
@@ -428,10 +484,21 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
428
484
|
this.tool('deployment', 'Manage deployment: get/cancel/list_for_app', {
|
|
429
485
|
action: z.enum(['get', 'cancel', 'list_for_app']),
|
|
430
486
|
uuid: z.string(),
|
|
431
|
-
|
|
487
|
+
lines: z.number().optional(), // Limit log output to last N lines (for 'get' action)
|
|
488
|
+
}, async ({ action, uuid, lines }) => {
|
|
432
489
|
switch (action) {
|
|
433
490
|
case 'get':
|
|
434
|
-
return wrap(() =>
|
|
491
|
+
return wrap(async () => {
|
|
492
|
+
const deployment = await this.client.getDeployment(uuid);
|
|
493
|
+
// Truncate logs to last N lines if specified
|
|
494
|
+
if (lines && deployment.logs) {
|
|
495
|
+
const logLines = deployment.logs.split('\n');
|
|
496
|
+
if (logLines.length > lines) {
|
|
497
|
+
deployment.logs = logLines.slice(-lines).join('\n');
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
return deployment;
|
|
501
|
+
});
|
|
435
502
|
case 'cancel':
|
|
436
503
|
return wrap(() => this.client.cancelDeployment(uuid));
|
|
437
504
|
case 'list_for_app':
|
package/dist/types/coolify.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export interface ErrorResponse {
|
|
|
10
10
|
error?: string;
|
|
11
11
|
message: string;
|
|
12
12
|
status?: number;
|
|
13
|
+
errors?: Record<string, string[]>;
|
|
13
14
|
}
|
|
14
15
|
export interface DeleteOptions {
|
|
15
16
|
deleteConfigurations?: boolean;
|
|
@@ -297,6 +298,15 @@ export interface UpdateApplicationRequest {
|
|
|
297
298
|
health_check_enabled?: boolean;
|
|
298
299
|
health_check_path?: string;
|
|
299
300
|
health_check_port?: number;
|
|
301
|
+
health_check_host?: string;
|
|
302
|
+
health_check_method?: string;
|
|
303
|
+
health_check_return_code?: number;
|
|
304
|
+
health_check_scheme?: string;
|
|
305
|
+
health_check_response_text?: string;
|
|
306
|
+
health_check_interval?: number;
|
|
307
|
+
health_check_timeout?: number;
|
|
308
|
+
health_check_retries?: number;
|
|
309
|
+
health_check_start_period?: number;
|
|
300
310
|
limits_memory?: string;
|
|
301
311
|
limits_memory_swap?: string;
|
|
302
312
|
limits_cpus?: string;
|