@masonator/coolify-mcp 0.9.0 → 1.1.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 CHANGED
@@ -6,22 +6,36 @@ A Model Context Protocol (MCP) server for [Coolify](https://coolify.io/), enabli
6
6
 
7
7
  ## Features
8
8
 
9
- This MCP server provides **65 tools** focused on **debugging, management, and deployment**:
9
+ This MCP server provides **67 tools** and **7 workflow prompts** for **debugging, management, and deployment**:
10
10
 
11
11
  | Category | Tools |
12
12
  | -------------------- | -------------------------------------------------------------------------------------------------------- |
13
- | **Infrastructure** | overview (all resources at once) |
13
+ | **Infrastructure** | overview, mcp_version (all resources at once) |
14
14
  | **Diagnostics** | diagnose_app, diagnose_server, find_issues (smart lookup by name/domain/IP) |
15
15
  | **Batch Operations** | restart_project_apps, bulk_env_update, stop_all_apps, redeploy_project |
16
16
  | **Servers** | list, get, validate, resources, domains |
17
17
  | **Projects** | list, get, create, update, delete |
18
18
  | **Environments** | list, get, create, delete |
19
19
  | **Applications** | list, get, update, delete, start, stop, restart, logs, env vars (CRUD), create (private-gh, private-key) |
20
- | **Databases** | list, get, start, stop, restart, backups (list, get), backup executions (list, get) |
20
+ | **Databases** | list, get, delete, start, stop, restart, backups (list, get), backup executions (list, get) |
21
21
  | **Services** | list, get, create, update, delete, start, stop, restart, env vars (list, create, delete) |
22
22
  | **Deployments** | list, get, deploy, cancel, list by application |
23
23
  | **Private Keys** | list, get, create, update, delete |
24
24
 
25
+ ### Workflow Prompts
26
+
27
+ Pre-built guided workflows that walk you through common tasks:
28
+
29
+ | Prompt | Description |
30
+ | ------------------ | ----------------------------------------------------------- |
31
+ | `debug-app` | Debug an application - gathers logs, status, env vars |
32
+ | `health-check` | Full infrastructure health analysis |
33
+ | `deploy-app` | Step-by-step deployment wizard from Git repository |
34
+ | `troubleshoot-ssl` | SSL/TLS certificate diagnosis workflow |
35
+ | `restart-project` | Safely restart all apps in a project with status monitoring |
36
+ | `env-audit` | Audit and compare environment variables across applications |
37
+ | `backup-status` | Check database backup status and history |
38
+
25
39
  ## Installation
26
40
 
27
41
  ### Prerequisites
@@ -180,6 +194,7 @@ node dist/index.js
180
194
  ### Infrastructure
181
195
 
182
196
  - `get_version` - Get Coolify API version
197
+ - `get_mcp_version` - Get coolify-mcp server version (useful to verify which version is installed)
183
198
  - `get_infrastructure_overview` - Get a high-level overview of all infrastructure (servers, projects, applications, databases, services)
184
199
 
185
200
  ### Diagnostics (Smart Lookup)
@@ -237,6 +252,7 @@ These tools accept human-friendly identifiers instead of just UUIDs:
237
252
  - `start_database` - Start a database
238
253
  - `stop_database` - Stop a database
239
254
  - `restart_database` - Restart a database
255
+ - `delete_database` - Delete a database (with optional volume cleanup)
240
256
  - `list_database_backups` - List scheduled backups for a database
241
257
  - `get_database_backup` - Get details of a scheduled backup
242
258
  - `list_backup_executions` - List execution history for a scheduled backup
@@ -15,6 +15,7 @@ const mockListServices = jest.fn();
15
15
  const mockDiagnoseApplication = jest.fn();
16
16
  const mockDiagnoseServer = jest.fn();
17
17
  const mockFindInfrastructureIssues = jest.fn();
18
+ const mockDeleteDatabase = jest.fn();
18
19
  // Mock the CoolifyClient module
19
20
  jest.mock('../lib/coolify-client.js', () => ({
20
21
  CoolifyClient: jest.fn().mockImplementation(() => ({
@@ -26,6 +27,7 @@ jest.mock('../lib/coolify-client.js', () => ({
26
27
  diagnoseApplication: mockDiagnoseApplication,
27
28
  diagnoseServer: mockDiagnoseServer,
28
29
  findInfrastructureIssues: mockFindInfrastructureIssues,
30
+ deleteDatabase: mockDeleteDatabase,
29
31
  getVersion: jest.fn(),
30
32
  })),
31
33
  }));
@@ -303,5 +305,29 @@ describe('CoolifyMcpServer', () => {
303
305
  expect(result.issues).toHaveLength(0);
304
306
  });
305
307
  });
308
+ describe('delete_database', () => {
309
+ it('should call deleteDatabase with uuid', async () => {
310
+ mockDeleteDatabase.mockResolvedValue({ message: 'Database deletion request queued.' });
311
+ await mockDeleteDatabase('db-uuid-123');
312
+ expect(mockDeleteDatabase).toHaveBeenCalledWith('db-uuid-123');
313
+ });
314
+ it('should call deleteDatabase with delete_volumes option', async () => {
315
+ mockDeleteDatabase.mockResolvedValue({ message: 'Database deletion request queued.' });
316
+ await mockDeleteDatabase('db-uuid-123', { deleteVolumes: true });
317
+ expect(mockDeleteDatabase).toHaveBeenCalledWith('db-uuid-123', { deleteVolumes: true });
318
+ });
319
+ });
320
+ });
321
+ describe('version tools', () => {
322
+ it('get_mcp_version should return correct version format', () => {
323
+ // The VERSION constant is '1.1.0' in mcp-server.ts
324
+ // This test verifies the expected output structure
325
+ const expectedResponse = {
326
+ version: '1.1.0',
327
+ name: '@masonator/coolify-mcp',
328
+ };
329
+ expect(expectedResponse.version).toBe('1.1.0');
330
+ expect(expectedResponse.name).toBe('@masonator/coolify-mcp');
331
+ });
306
332
  });
307
333
  });
@@ -26,4 +26,5 @@ export declare class CoolifyMcpServer extends McpServer {
26
26
  constructor(config: CoolifyConfig);
27
27
  connect(transport: Transport): Promise<void>;
28
28
  private registerTools;
29
+ private registerPrompts;
29
30
  }
@@ -20,7 +20,7 @@
20
20
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
21
21
  import { z } from 'zod';
22
22
  import { CoolifyClient, } from './coolify-client.js';
23
- const VERSION = '0.9.0';
23
+ const VERSION = '1.1.0';
24
24
  /** Wrap tool handler with consistent error handling */
25
25
  function wrapHandler(fn) {
26
26
  return fn()
@@ -44,17 +44,26 @@ export class CoolifyMcpServer extends McpServer {
44
44
  super({
45
45
  name: 'coolify',
46
46
  version: VERSION,
47
- capabilities: { tools: {} },
47
+ capabilities: { tools: {}, prompts: {} },
48
48
  });
49
49
  this.client = new CoolifyClient(config);
50
50
  this.registerTools();
51
+ this.registerPrompts();
51
52
  }
52
53
  async connect(transport) {
53
54
  await super.connect(transport);
54
55
  }
55
56
  registerTools() {
56
- // Version
57
+ // Version tools
57
58
  this.tool('get_version', 'Get Coolify API version', {}, async () => wrapHandler(() => this.client.getVersion()));
59
+ this.tool('get_mcp_version', 'Get the version of this MCP server (coolify-mcp). Useful to verify which version is installed.', {}, async () => ({
60
+ content: [
61
+ {
62
+ type: 'text',
63
+ text: JSON.stringify({ version: VERSION, name: '@masonator/coolify-mcp' }, null, 2),
64
+ },
65
+ ],
66
+ }));
58
67
  // Infrastructure Overview - high-level view of all resources
59
68
  this.tool('get_infrastructure_overview', 'Get a high-level overview of all infrastructure (servers, projects, applications, databases, services). Returns counts and summaries. Start here to understand the infrastructure.', {}, async () => wrapHandler(async () => {
60
69
  const results = await Promise.allSettled([
@@ -210,7 +219,7 @@ export class CoolifyMcpServer extends McpServer {
210
219
  env_uuid: z.string().describe('Env variable UUID'),
211
220
  }, async ({ uuid, env_uuid }) => wrapHandler(() => this.client.deleteApplicationEnvVar(uuid, env_uuid)));
212
221
  // =========================================================================
213
- // Databases (5 tools)
222
+ // Databases (6 tools)
214
223
  // =========================================================================
215
224
  this.tool('list_databases', 'List all databases (returns summary: uuid, name, type, status). Use get_database for full details.', {
216
225
  page: z.number().optional().describe('Page number for pagination'),
@@ -220,6 +229,10 @@ export class CoolifyMcpServer extends McpServer {
220
229
  this.tool('start_database', 'Start a database', { uuid: z.string().describe('Database UUID') }, async ({ uuid }) => wrapHandler(() => this.client.startDatabase(uuid)));
221
230
  this.tool('stop_database', 'Stop a database', { uuid: z.string().describe('Database UUID') }, async ({ uuid }) => wrapHandler(() => this.client.stopDatabase(uuid)));
222
231
  this.tool('restart_database', 'Restart a database', { uuid: z.string().describe('Database UUID') }, async ({ uuid }) => wrapHandler(() => this.client.restartDatabase(uuid)));
232
+ this.tool('delete_database', 'Delete a database. WARNING: This permanently deletes the database and optionally its volumes. Data cannot be recovered unless you have backups.', {
233
+ uuid: z.string().describe('Database UUID'),
234
+ delete_volumes: z.boolean().optional().describe('Delete volumes (default: false)'),
235
+ }, async ({ uuid, delete_volumes }) => wrapHandler(() => this.client.deleteDatabase(uuid, { deleteVolumes: delete_volumes })));
223
236
  // =========================================================================
224
237
  // Services (11 tools)
225
238
  // =========================================================================
@@ -374,4 +387,239 @@ export class CoolifyMcpServer extends McpServer {
374
387
  force: z.boolean().optional().describe('Force rebuild (default: true)'),
375
388
  }, async ({ project_uuid, force }) => wrapHandler(() => this.client.redeployProjectApps(project_uuid, force ?? true)));
376
389
  }
390
+ // ===========================================================================
391
+ // Prompt Templates - Guided Workflows
392
+ // ===========================================================================
393
+ registerPrompts() {
394
+ // -------------------------------------------------------------------------
395
+ // debug-app: Comprehensive application debugging workflow
396
+ // -------------------------------------------------------------------------
397
+ this.prompt('debug-app', 'Debug an application - gathers status, logs, env vars, and recent deployments to diagnose issues', {
398
+ query: z
399
+ .string()
400
+ .describe('Application identifier: UUID, name, or domain (e.g., "my-app" or "example.com")'),
401
+ }, async ({ query }) => {
402
+ return {
403
+ messages: [
404
+ {
405
+ role: 'user',
406
+ content: {
407
+ type: 'text',
408
+ text: `I need help debugging my Coolify application "${query}". Please:
409
+
410
+ 1. First, use the diagnose_app tool with query="${query}" to get comprehensive diagnostics
411
+ 2. Analyze the results and identify:
412
+ - Current health status and any issues
413
+ - Recent deployment failures or errors in logs
414
+ - Missing or misconfigured environment variables
415
+ - Any patterns suggesting the root cause
416
+ 3. Provide a clear diagnosis with:
417
+ - What's wrong (if anything)
418
+ - Likely root cause
419
+ - Recommended fix steps
420
+ 4. If the app seems healthy, confirm this and suggest any optimizations
421
+
422
+ Start by running diagnose_app now.`,
423
+ },
424
+ },
425
+ ],
426
+ };
427
+ });
428
+ // -------------------------------------------------------------------------
429
+ // health-check: Full infrastructure health analysis
430
+ // -------------------------------------------------------------------------
431
+ this.prompt('health-check', 'Perform a comprehensive health check of your entire Coolify infrastructure', {}, async () => {
432
+ return {
433
+ messages: [
434
+ {
435
+ role: 'user',
436
+ content: {
437
+ type: 'text',
438
+ text: `Please perform a comprehensive health check of my Coolify infrastructure:
439
+
440
+ 1. Run find_issues to scan for problems across all servers, apps, databases, and services
441
+ 2. Run get_infrastructure_overview to get the full picture
442
+ 3. For any issues found, provide:
443
+ - Severity (critical/warning/info)
444
+ - Affected resource and current status
445
+ - Recommended remediation steps
446
+ 4. Summarize the overall health:
447
+ - Total resources and their states
448
+ - Any immediate actions needed
449
+ - Preventive recommendations
450
+
451
+ Start by running find_issues now.`,
452
+ },
453
+ },
454
+ ],
455
+ };
456
+ });
457
+ // -------------------------------------------------------------------------
458
+ // deploy-app: Step-by-step deployment wizard
459
+ // -------------------------------------------------------------------------
460
+ this.prompt('deploy-app', 'Step-by-step wizard to deploy a new application from a Git repository', {
461
+ repo: z.string().describe('Git repository URL or org/repo format'),
462
+ branch: z.string().optional().describe('Branch to deploy (default: main)'),
463
+ }, async ({ repo, branch }) => {
464
+ const branchName = branch || 'main';
465
+ return {
466
+ messages: [
467
+ {
468
+ role: 'user',
469
+ content: {
470
+ type: 'text',
471
+ text: `I want to deploy a new application from ${repo} (branch: ${branchName}). Please guide me through the process:
472
+
473
+ 1. First, run list_projects to show available projects
474
+ 2. Ask me which project to deploy to (or help create a new one)
475
+ 3. Run list_servers to show available servers
476
+ 4. Ask me which server to deploy on
477
+ 5. Run list_private_keys to check available deploy keys
478
+ 6. Based on the repository type:
479
+ - If GitHub and we have a GitHub App configured, use create_application_private_gh
480
+ - Otherwise, help set up a deploy key and use create_application_private_key
481
+ 7. After creation, ask about:
482
+ - Environment variables needed
483
+ - Domain/FQDN configuration
484
+ - Whether to deploy immediately
485
+
486
+ Start by showing me the available projects.`,
487
+ },
488
+ },
489
+ ],
490
+ };
491
+ });
492
+ // -------------------------------------------------------------------------
493
+ // troubleshoot-ssl: SSL certificate diagnosis workflow
494
+ // -------------------------------------------------------------------------
495
+ this.prompt('troubleshoot-ssl', 'Diagnose SSL/TLS certificate issues for a domain', {
496
+ domain: z.string().describe('Domain having SSL issues (e.g., "example.com")'),
497
+ }, async ({ domain }) => {
498
+ return {
499
+ messages: [
500
+ {
501
+ role: 'user',
502
+ content: {
503
+ type: 'text',
504
+ text: `I'm having SSL/TLS certificate issues with the domain "${domain}". Please help me diagnose:
505
+
506
+ 1. First, use diagnose_app with query="${domain}" to find the application
507
+ 2. Check the application's FQDN configuration
508
+ 3. Look for common SSL issues:
509
+ - Is the domain correctly configured in the FQDN field?
510
+ - Are there any proxy/redirect issues in the logs?
511
+ - Is Let's Encrypt renewal working (check for ACME errors)?
512
+ 4. Check the server's domain configuration using get_server_domains
513
+ 5. Provide remediation steps:
514
+ - If domain misconfiguration: show how to fix with update_application
515
+ - If SSL renewal issue: suggest checking DNS and Traefik config
516
+ - If proxy issue: suggest checking Traefik labels
517
+
518
+ Start by finding the application for this domain.`,
519
+ },
520
+ },
521
+ ],
522
+ };
523
+ });
524
+ // -------------------------------------------------------------------------
525
+ // restart-project: Safely restart all apps in a project
526
+ // -------------------------------------------------------------------------
527
+ this.prompt('restart-project', 'Safely restart all applications in a project with status monitoring', {
528
+ project: z.string().describe('Project UUID or name'),
529
+ }, async ({ project }) => {
530
+ return {
531
+ messages: [
532
+ {
533
+ role: 'user',
534
+ content: {
535
+ type: 'text',
536
+ text: `I need to restart all applications in the project "${project}". Please handle this safely:
537
+
538
+ 1. First, run list_projects to find the project UUID (if a name was given)
539
+ 2. Run get_project to confirm the project details and list its environments
540
+ 3. Run list_applications to find all apps in this project
541
+ 4. Show me a summary of what will be restarted:
542
+ - List each application with current status
543
+ - Warn about any that are already unhealthy
544
+ 5. Ask for my confirmation before proceeding
545
+ 6. If confirmed, run restart_project_apps with the project UUID
546
+ 7. After restart, check the results and report:
547
+ - Which apps restarted successfully
548
+ - Any failures and why
549
+ - Current status of each app
550
+
551
+ Start by finding the project.`,
552
+ },
553
+ },
554
+ ],
555
+ };
556
+ });
557
+ // -------------------------------------------------------------------------
558
+ // env-audit: Audit environment variables across apps
559
+ // -------------------------------------------------------------------------
560
+ this.prompt('env-audit', 'Audit and compare environment variables across applications', {
561
+ apps: z
562
+ .string()
563
+ .optional()
564
+ .describe('Comma-separated app names/UUIDs to audit (optional, defaults to all)'),
565
+ key: z.string().optional().describe('Specific env var key to check across apps'),
566
+ }, async ({ apps, key }) => {
567
+ return {
568
+ messages: [
569
+ {
570
+ role: 'user',
571
+ content: {
572
+ type: 'text',
573
+ text: `Please audit environment variables across my applications${apps ? ` (${apps})` : ''}${key ? ` focusing on the "${key}" variable` : ''}:
574
+
575
+ 1. Run list_applications to get the list of apps
576
+ 2. For ${apps ? 'the specified apps' : 'each application'}, run list_application_envs
577
+ 3. Analyze the environment variables:
578
+ ${key ? `- Check if "${key}" is set consistently across all apps` : '- Identify common variables that differ between apps'}
579
+ - Flag any sensitive-looking values that might be exposed
580
+ - Identify missing variables that exist in some apps but not others
581
+ - Check for any empty or placeholder values
582
+ 4. Provide a summary:
583
+ - Table showing variable presence across apps
584
+ - Recommendations for standardization
585
+ - Any security concerns
586
+
587
+ Start by listing the applications.`,
588
+ },
589
+ },
590
+ ],
591
+ };
592
+ });
593
+ // -------------------------------------------------------------------------
594
+ // backup-status: Check database backup status
595
+ // -------------------------------------------------------------------------
596
+ this.prompt('backup-status', 'Check backup status and history for all databases', {}, async () => {
597
+ return {
598
+ messages: [
599
+ {
600
+ role: 'user',
601
+ content: {
602
+ type: 'text',
603
+ text: `Please check the backup status of all my databases:
604
+
605
+ 1. Run list_databases to get all databases
606
+ 2. For each database, run list_database_backups to check scheduled backups
607
+ 3. For databases with backups configured, run list_backup_executions to check recent history
608
+ 4. Report:
609
+ - Databases WITHOUT any backup schedules (critical!)
610
+ - Last successful backup for each database
611
+ - Any failed backups in the last 7 days
612
+ - Backup frequency and retention settings
613
+ 5. Provide recommendations:
614
+ - Which databases need backup configuration
615
+ - Any backup schedules that seem too infrequent
616
+ - Storage concerns if backups are piling up
617
+
618
+ Start by listing all databases.`,
619
+ },
620
+ },
621
+ ],
622
+ };
623
+ });
624
+ }
377
625
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@masonator/coolify-mcp",
3
3
  "scope": "@masonator",
4
- "version": "0.9.0",
4
+ "version": "1.1.0",
5
5
  "description": "MCP server implementation for Coolify",
6
6
  "type": "module",
7
7
  "main": "./dist/index.js",