@mks2508/coolify-mks-cli-mcp 0.2.0 → 0.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.
@@ -301,10 +301,13 @@ export class CoolifyService {
301
301
  if (options.portsExposes) {
302
302
  body.ports_exposes = options.portsExposes
303
303
  }
304
- // Dockerfile configuration
304
+ // Dockerfile / Docker Compose configuration
305
305
  if (options.dockerfileLocation) {
306
306
  body.dockerfile_location = options.dockerfileLocation
307
307
  }
308
+ if (options.dockerComposeLocation) {
309
+ body.docker_compose_location = options.dockerComposeLocation
310
+ }
308
311
  if (options.baseDirectory) {
309
312
  body.base_directory = options.baseDirectory
310
313
  }
@@ -390,6 +393,100 @@ export class CoolifyService {
390
393
  return ok(result.data || [])
391
394
  }
392
395
 
396
+ /**
397
+ * Sets a single environment variable for an application.
398
+ * Uses PATCH if variable exists, POST if it doesn't.
399
+ *
400
+ * @param appUuid - Application UUID
401
+ * @param key - Variable name
402
+ * @param value - Variable value
403
+ * @param isBuildTime - Whether the variable is available at build time (only for new vars)
404
+ * @returns Result indicating success or error
405
+ */
406
+ async setEnvironmentVariable(
407
+ appUuid: string,
408
+ key: string,
409
+ value: string,
410
+ isBuildTime: boolean = false
411
+ ): Promise<Result<void, Error>> {
412
+ log.info(`Setting environment variable ${key} for ${appUuid}`)
413
+
414
+ // Check if variable already exists
415
+ const existingVars = await this.getEnvironmentVariables(appUuid)
416
+ if (isErr(existingVars)) {
417
+ return err(existingVars.error)
418
+ }
419
+
420
+ const exists = existingVars.value.some(ev => ev.key === key)
421
+
422
+ if (exists) {
423
+ // Use PATCH to update existing variable
424
+ log.debug(`Variable ${key} exists, using PATCH to update`)
425
+ const result = await this.request<{ uuid: string }>(`/applications/${appUuid}/envs`, {
426
+ method: 'PATCH',
427
+ body: JSON.stringify({ key, value }),
428
+ })
429
+
430
+ if (result.error) {
431
+ log.error(`Failed to update env var: ${result.error}`)
432
+ return err(new Error(result.error))
433
+ }
434
+ } else {
435
+ // Use POST to create new variable
436
+ log.debug(`Variable ${key} does not exist, using POST to create`)
437
+ const result = await this.request<{ uuid: string }>(`/applications/${appUuid}/envs`, {
438
+ method: 'POST',
439
+ body: JSON.stringify({ key, value }),
440
+ })
441
+
442
+ if (result.error) {
443
+ log.error(`Failed to create env var: ${result.error}`)
444
+ return err(new Error(result.error))
445
+ }
446
+ }
447
+
448
+ log.success(`Environment variable ${key} set for ${appUuid}`)
449
+ return ok(undefined)
450
+ }
451
+
452
+ /**
453
+ * Deletes an environment variable from an application.
454
+ *
455
+ * @param appUuid - Application UUID
456
+ * @param key - Variable name to delete
457
+ * @returns Result indicating success or error
458
+ */
459
+ async deleteEnvironmentVariable(
460
+ appUuid: string,
461
+ key: string
462
+ ): Promise<Result<void, Error>> {
463
+ log.info(`Deleting environment variable ${key} from ${appUuid}`)
464
+
465
+ // First get all env vars to find the UUID of the one to delete
466
+ const envVarsResult = await this.getEnvironmentVariables(appUuid)
467
+ if (isErr(envVarsResult)) {
468
+ return err(envVarsResult.error)
469
+ }
470
+
471
+ const envVar = envVarsResult.value.find(ev => ev.key === key)
472
+ if (!envVar) {
473
+ log.error(`Environment variable ${key} not found`)
474
+ return err(new Error(`Environment variable ${key} not found`))
475
+ }
476
+
477
+ const result = await this.request(`/applications/${appUuid}/envs/${envVar.uuid}`, {
478
+ method: 'DELETE',
479
+ })
480
+
481
+ if (result.error) {
482
+ log.error(`Failed to delete env var: ${result.error}`)
483
+ return err(new Error(result.error))
484
+ }
485
+
486
+ log.success(`Environment variable ${key} deleted from ${appUuid}`)
487
+ return ok(undefined)
488
+ }
489
+
393
490
  /**
394
491
  * Gets the status of an application.
395
492
  *
@@ -462,6 +559,33 @@ export class CoolifyService {
462
559
  return ok(result.data || [])
463
560
  }
464
561
 
562
+ /**
563
+ * Creates a new project.
564
+ *
565
+ * @param name - Project name
566
+ * @param description - Optional project description
567
+ * @returns Result with created project or error
568
+ */
569
+ async createProject(
570
+ name: string,
571
+ description?: string
572
+ ): Promise<Result<ICoolifyProject, Error>> {
573
+ log.info(`Creating project: ${name}`)
574
+
575
+ const result = await this.request<ICoolifyProject>('/projects', {
576
+ method: 'POST',
577
+ body: JSON.stringify({ name, description: description || '' }),
578
+ })
579
+
580
+ if (result.error) {
581
+ log.error(`Failed to create project: ${result.error}`)
582
+ return err(new Error(result.error))
583
+ }
584
+
585
+ log.success(`Project created: ${result.data?.uuid}`)
586
+ return ok(result.data!)
587
+ }
588
+
465
589
  /**
466
590
  * Gets environments for a project.
467
591
  *
@@ -601,6 +725,9 @@ export class CoolifyService {
601
725
  if (options.startCommand) body.start_command = options.startCommand
602
726
  if (options.dockerfileLocation) body.dockerfile_location = options.dockerfileLocation
603
727
  if (options.baseDirectory) body.base_directory = options.baseDirectory
728
+ if (options.domains) body.domains = options.domains
729
+ if (options.isForceHttpsEnabled !== undefined) body.is_force_https_enabled = options.isForceHttpsEnabled
730
+ if (options.isAutoDeployEnabled !== undefined) body.is_auto_deploy_enabled = options.isAutoDeployEnabled
604
731
 
605
732
  const result = await this.request<ICoolifyApplication>(`/applications/${appUuid}`, {
606
733
  method: 'PATCH',
@@ -635,16 +762,25 @@ export class CoolifyService {
635
762
 
636
763
  const endpoint = `/applications/${appUuid}/logs${params.toString() ? `?${params.toString()}` : ''}`
637
764
 
638
- const result = await this.request<{ logs: string[] }>(endpoint)
765
+ const result = await this.request<{ logs: string | string[] }>(endpoint)
639
766
 
640
767
  if (result.error) {
641
768
  log.error(`Failed to get logs: ${result.error}`)
642
769
  return err(new Error(result.error))
643
770
  }
644
771
 
772
+ // Coolify API returns logs as a single newline-delimited string for
773
+ // docker-compose apps, but as string[] for single-container apps.
774
+ const rawLogs = result.data?.logs
775
+ const logsArray: string[] = Array.isArray(rawLogs)
776
+ ? rawLogs
777
+ : typeof rawLogs === 'string'
778
+ ? rawLogs.split('\n').filter((l: string) => l.length > 0)
779
+ : []
780
+
645
781
  log.success(`Logs retrieved for application: ${appUuid}`)
646
782
  return ok({
647
- logs: result.data?.logs || [],
783
+ logs: logsArray,
648
784
  timestamp: new Date().toISOString(),
649
785
  })
650
786
  }
@@ -743,6 +879,79 @@ export class CoolifyService {
743
879
  log.success(`Application restarted: ${appUuid}`)
744
880
  return ok(result.data as ICoolifyApplication)
745
881
  }
882
+
883
+ /**
884
+ * Lists all active and queued deployments.
885
+ *
886
+ * @returns Result with deployments list or error
887
+ */
888
+ async listDeployments(): Promise<Result<ICoolifyDeployment[], Error>> {
889
+ log.info('Listing active deployments')
890
+
891
+ const result = await this.request<ICoolifyDeployment[]>('/deployments')
892
+
893
+ if (result.error) {
894
+ log.error(`Failed to list deployments: ${result.error}`)
895
+ return err(new Error(result.error))
896
+ }
897
+
898
+ log.success(`Listed ${result.data?.length || 0} active deployments`)
899
+ return ok(result.data || [])
900
+ }
901
+
902
+ /**
903
+ * Gets detailed information about a specific deployment.
904
+ *
905
+ * @param deploymentUuid - Deployment UUID
906
+ * @returns Result with deployment details or error
907
+ */
908
+ async getDeployment(
909
+ deploymentUuid: string
910
+ ): Promise<Result<ICoolifyDeployment, Error>> {
911
+ log.info(`Getting deployment details for ${deploymentUuid}`)
912
+
913
+ const result = await this.request<ICoolifyDeployment>(`/deployments/${deploymentUuid}`)
914
+
915
+ if (result.error) {
916
+ log.error(`Failed to get deployment: ${result.error}`)
917
+ return err(new Error(result.error))
918
+ }
919
+
920
+ log.success(`Deployment details retrieved: ${deploymentUuid}`)
921
+ return ok(result.data as ICoolifyDeployment)
922
+ }
923
+
924
+ /**
925
+ * Gets deployment history for a specific application.
926
+ *
927
+ * @param appUuid - Application UUID
928
+ * @param skip - Number of deployments to skip
929
+ * @param take - Number of deployments to return
930
+ * @returns Result with deployments list or error
931
+ */
932
+ async getApplicationDeployments(
933
+ appUuid: string,
934
+ skip: number = 0,
935
+ take: number = 10
936
+ ): Promise<Result<ICoolifyDeployment[], Error>> {
937
+ log.info(`Getting deployments for application ${appUuid}`)
938
+
939
+ const params = new URLSearchParams()
940
+ if (skip > 0) params.set('skip', skip.toString())
941
+ if (take !== 10) params.set('take', take.toString())
942
+
943
+ const endpoint = `/applications/${appUuid}/deployments${params.toString() ? `?${params.toString()}` : ''}`
944
+ const result = await this.request<{ count: number; deployments: ICoolifyDeployment[] }>(endpoint)
945
+
946
+ if (result.error) {
947
+ log.error(`Failed to get application deployments: ${result.error}`)
948
+ return err(new Error(result.error))
949
+ }
950
+
951
+ const deployments = result.data?.deployments || []
952
+ log.success(`Retrieved ${deployments.length} deployments for ${appUuid}`)
953
+ return ok(deployments)
954
+ }
746
955
  }
747
956
 
748
957
  let instance: CoolifyService | null = null
@@ -768,7 +977,12 @@ export type {
768
977
  ICoolifyApplication,
769
978
  ICoolifyDeployment,
770
979
  ICoolifyAppOptions,
980
+ ICoolifyAppResult,
771
981
  ICoolifyDeployOptions,
982
+ ICoolifyDeployResult,
983
+ ICoolifyDeleteResult,
772
984
  ICoolifyUpdateOptions,
773
985
  ICoolifyLogsOptions,
774
- }
986
+ ICoolifyLogs,
987
+ IProgressCallback,
988
+ } from './types.js'
@@ -46,6 +46,8 @@ export interface ICoolifyAppOptions {
46
46
  environmentUuid: string
47
47
  /** Server UUID */
48
48
  serverUuid: string
49
+ /** Destination UUID (optional, for specific destination targeting) */
50
+ destinationUuid?: string
49
51
  /** Application type */
50
52
  type?: TCoolifyApplicationType
51
53
  /** GitHub repository URL (for git-based apps) */
@@ -53,13 +55,15 @@ export interface ICoolifyAppOptions {
53
55
  /** Git branch */
54
56
  branch?: string
55
57
  /** Build pack type */
56
- buildPack?: 'dockerfile' | 'nixpacks' | 'static'
58
+ buildPack?: 'dockerfile' | 'nixpacks' | 'static' | 'dockercompose'
57
59
  /** Ports to expose */
58
60
  portsExposes?: string
59
61
  /** Docker image (for docker-image type) */
60
62
  dockerImage?: string
61
63
  /** Docker Compose content (for docker-compose type) */
62
64
  dockerCompose?: string
65
+ /** Docker Compose file location relative to repo root (for dockercompose buildPack) */
66
+ dockerComposeLocation?: string
63
67
  /** Environment variables */
64
68
  envVars?: Record<string, string>
65
69
  /** Dockerfile location (path relative to repo root, e.g., "apps/haidodocs/Dockerfile") */
@@ -77,7 +81,7 @@ export interface ICoolifyUpdateOptions {
77
81
  /** Application description */
78
82
  description?: string
79
83
  /** Build pack type */
80
- buildPack?: 'dockerfile' | 'nixpacks' | 'static'
84
+ buildPack?: 'dockerfile' | 'nixpacks' | 'static' | 'dockercompose'
81
85
  /** Git branch */
82
86
  gitBranch?: string
83
87
  /** Ports to expose */
@@ -92,6 +96,12 @@ export interface ICoolifyUpdateOptions {
92
96
  dockerfileLocation?: string
93
97
  /** Base directory for build context (default: "/") */
94
98
  baseDirectory?: string
99
+ /** Domains/FQDN - comma separated list of domains with protocol (e.g., "https://app.example.com,https://www.example.com") */
100
+ domains?: string
101
+ /** Force HTTPS redirect */
102
+ isForceHttpsEnabled?: boolean
103
+ /** Enable auto deploy on git push */
104
+ isAutoDeployEnabled?: boolean
95
105
  }
96
106
 
97
107
  /**
package/src/index.ts CHANGED
@@ -455,7 +455,7 @@ Redeploy after updating to apply changes.`,
455
455
  uuid: z.string().uuid().describe('Application UUID'),
456
456
  name: z.string().optional().describe('New application name'),
457
457
  description: z.string().optional().describe('New description'),
458
- buildPack: z.enum(['dockerfile', 'nixpacks', 'static']).optional().describe('Build pack type'),
458
+ buildPack: z.enum(['dockerfile', 'nixpacks', 'static', 'dockercompose']).optional().describe('Build pack type'),
459
459
  gitBranch: z.string().optional().describe('Git branch to deploy'),
460
460
  portsExposes: z.string().optional().describe('Ports to expose (comma-separated)'),
461
461
  installCommand: z.string().optional().describe('Install command (nixpacks)'),
@@ -694,7 +694,11 @@ The GitHub repository must be accessible via the configured GitHub App.`,
694
694
  githubRepoUrl: z.string().describe('GitHub repository URL (e.g., https://github.com/user/repo)'),
695
695
  description: z.string().optional().describe('Application description'),
696
696
  branch: z.string().default('main').describe('Git branch to deploy'),
697
- buildPack: z.enum(['dockerfile', 'nixpacks', 'static']).default('nixpacks').describe('Build pack type'),
697
+ buildPack: z.enum(['dockerfile', 'nixpacks', 'static', 'dockercompose']).default('nixpacks').describe('Build pack type'),
698
+ type: z.enum(['public', 'private-github-app', 'private-deploy-key', 'dockerfile', 'docker-image', 'docker-compose']).default('public').describe('Application type'),
699
+ dockerComposeLocation: z.string().optional().describe('Docker Compose file location relative to repo root'),
700
+ dockerfileLocation: z.string().optional().describe('Dockerfile location relative to repo root'),
701
+ baseDirectory: z.string().optional().describe('Base directory for build context'),
698
702
  },
699
703
  async (args) => {
700
704
  const initResult = await coolify.init()
@@ -711,10 +715,13 @@ The GitHub repository must be accessible via the configured GitHub App.`,
711
715
  projectUuid: args.projectUuid,
712
716
  environmentUuid: args.environmentUuid,
713
717
  serverUuid: args.serverUuid,
714
- type: 'public',
718
+ type: args.type as any,
715
719
  githubRepoUrl: args.githubRepoUrl,
716
720
  branch: args.branch,
717
721
  buildPack: args.buildPack,
722
+ dockerComposeLocation: args.dockerComposeLocation,
723
+ dockerfileLocation: args.dockerfileLocation,
724
+ baseDirectory: args.baseDirectory,
718
725
  })
719
726
 
720
727
  if (isOk(result)) {
@@ -229,7 +229,7 @@ Returns list of all deployments with status, timestamps, and commit info.`,
229
229
  name: 'update_application',
230
230
  description: `Update configuration for a Coolify application.
231
231
 
232
- Can modify name, description, build settings, and commands.
232
+ Can modify name, description, build settings, commands, and domains.
233
233
  Redeploy after updating to apply changes.`,
234
234
  inputSchema: {
235
235
  type: 'object' as const,
@@ -250,7 +250,7 @@ Redeploy after updating to apply changes.`,
250
250
  buildPack: {
251
251
  type: 'string' as const,
252
252
  description: 'Build pack type',
253
- enum: ['dockerfile', 'nixpacks', 'static']
253
+ enum: ['dockerfile', 'nixpacks', 'static', 'dockercompose']
254
254
  },
255
255
  gitBranch: {
256
256
  type: 'string' as const,
@@ -271,11 +271,54 @@ Redeploy after updating to apply changes.`,
271
271
  startCommand: {
272
272
  type: 'string' as const,
273
273
  description: 'Start command'
274
+ },
275
+ domains: {
276
+ type: 'string' as const,
277
+ description: 'Domains/FQDN - comma separated list with protocol (e.g., "https://app.example.com,https://www.example.com")'
278
+ },
279
+ isForceHttpsEnabled: {
280
+ type: 'boolean' as const,
281
+ description: 'Force HTTPS redirect'
282
+ },
283
+ isAutoDeployEnabled: {
284
+ type: 'boolean' as const,
285
+ description: 'Enable auto deploy on git push'
274
286
  }
275
287
  },
276
288
  required: ['uuid']
277
289
  }
278
290
  },
291
+ {
292
+ name: 'set_domains',
293
+ description: `Set domains/FQDN for a Coolify application.
294
+
295
+ Configure custom domains for your application. Coolify automatically handles SSL certificates via Let's Encrypt.
296
+
297
+ Domain format:
298
+ - Use FQDN with protocol: https://app.example.com
299
+ - Multiple domains separated by comma: https://app.example.com,https://www.example.com
300
+ - Can include port mapping: https://api.example.com:3000`,
301
+ inputSchema: {
302
+ type: 'object' as const,
303
+ properties: {
304
+ uuid: {
305
+ type: 'string' as const,
306
+ description: 'Application UUID',
307
+ format: 'uuid'
308
+ },
309
+ domains: {
310
+ type: 'string' as const,
311
+ description: 'Domains/FQDN - comma separated list with protocol (e.g., "https://app.example.com,https://www.example.com")'
312
+ },
313
+ forceHttps: {
314
+ type: 'boolean' as const,
315
+ description: 'Force HTTPS redirect (default: true)',
316
+ default: true
317
+ }
318
+ },
319
+ required: ['uuid', 'domains']
320
+ }
321
+ },
279
322
  {
280
323
  name: 'list_servers',
281
324
  description: `List all available servers in Coolify.
@@ -380,11 +423,49 @@ The GitHub repository must be accessible via the configured GitHub App.`,
380
423
  buildPack: {
381
424
  type: 'string' as const,
382
425
  description: 'Build pack type',
383
- enum: ['dockerfile', 'nixpacks', 'static'],
426
+ enum: ['dockerfile', 'nixpacks', 'static', 'dockercompose'],
384
427
  default: 'nixpacks'
428
+ },
429
+ type: {
430
+ type: 'string' as const,
431
+ description: 'Application type',
432
+ enum: ['public', 'private-github-app', 'private-deploy-key', 'dockerfile', 'docker-image', 'docker-compose'],
433
+ default: 'public'
434
+ },
435
+ dockerComposeLocation: {
436
+ type: 'string' as const,
437
+ description: 'Docker Compose file location relative to repo root (for dockercompose buildPack)'
438
+ },
439
+ dockerfileLocation: {
440
+ type: 'string' as const,
441
+ description: 'Dockerfile location relative to repo root'
442
+ },
443
+ baseDirectory: {
444
+ type: 'string' as const,
445
+ description: 'Base directory for build context (default: "/")'
385
446
  }
386
447
  },
387
- required: ['name', 'serverUuid', 'destinationUuid', 'githubRepoUrl']
448
+ required: ['name', 'serverUuid', 'githubRepoUrl']
449
+ }
450
+ },
451
+ {
452
+ name: 'create_project',
453
+ description: `Create a new project in Coolify.
454
+
455
+ Projects organize applications into logical groups. Each project has one or more environments (e.g., production, staging).`,
456
+ inputSchema: {
457
+ type: 'object' as const,
458
+ properties: {
459
+ name: {
460
+ type: 'string' as const,
461
+ description: 'Project name'
462
+ },
463
+ description: {
464
+ type: 'string' as const,
465
+ description: 'Project description'
466
+ }
467
+ },
468
+ required: ['name']
388
469
  }
389
470
  },
390
471
  {
@@ -414,6 +495,62 @@ Returns connection status and API version info if available.`,
414
495
  properties: {}
415
496
  }
416
497
  },
498
+ {
499
+ name: 'list_deployments',
500
+ description: `List all active and queued deployments across all applications.
501
+
502
+ Returns deployments that are currently in progress or waiting in queue.
503
+ Useful for monitoring ongoing builds and deployments.`,
504
+ inputSchema: {
505
+ type: 'object' as const,
506
+ properties: {}
507
+ }
508
+ },
509
+ {
510
+ name: 'get_deployment',
511
+ description: `Get detailed information about a specific deployment.
512
+
513
+ Returns deployment status, logs, timestamps, and error messages if any.
514
+ Use deployment UUID from list_deployments or get_application_deployments.`,
515
+ inputSchema: {
516
+ type: 'object' as const,
517
+ properties: {
518
+ deploymentUuid: {
519
+ type: 'string' as const,
520
+ description: 'Deployment UUID'
521
+ }
522
+ },
523
+ required: ['deploymentUuid']
524
+ }
525
+ },
526
+ {
527
+ name: 'get_application_deployments',
528
+ description: `Get deployment history for a specific application.
529
+
530
+ Returns list of all deployments with status, timestamps, commit info, and logs.
531
+ Useful for debugging failed deployments and tracking deployment history.`,
532
+ inputSchema: {
533
+ type: 'object' as const,
534
+ properties: {
535
+ uuid: {
536
+ type: 'string' as const,
537
+ description: 'Application UUID',
538
+ format: 'uuid'
539
+ },
540
+ skip: {
541
+ type: 'number' as const,
542
+ description: 'Number of deployments to skip (pagination)',
543
+ default: 0
544
+ },
545
+ take: {
546
+ type: 'number' as const,
547
+ description: 'Number of deployments to return (default: 10)',
548
+ default: 10
549
+ }
550
+ },
551
+ required: ['uuid']
552
+ }
553
+ },
417
554
  {
418
555
  name: 'get_application_details',
419
556
  description: `Get detailed information about a Coolify application.