@masonator/coolify-mcp 2.9.0 → 2.11.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 +25 -22
- package/dist/__tests__/coolify-client.test.js +656 -0
- package/dist/__tests__/mcp-server.test.js +215 -0
- package/dist/lib/coolify-client.d.ts +42 -1
- package/dist/lib/coolify-client.js +225 -0
- package/dist/lib/mcp-server.js +449 -20
- package/dist/types/coolify.d.ts +172 -0
- package/package.json +2 -2
package/dist/lib/mcp-server.js
CHANGED
|
@@ -294,7 +294,7 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
294
294
|
// =========================================================================
|
|
295
295
|
this.tool('list_applications', 'List apps (summary)', { page: z.number().optional(), per_page: z.number().optional() }, async ({ page, per_page }) => wrapWithActions(() => this.client.listApplications({ page, per_page, summary: true }), undefined, (result) => getPagination('list_applications', page, per_page, result.length)));
|
|
296
296
|
this.tool('get_application', 'App details', { uuid: z.string() }, async ({ uuid }) => wrapWithActions(() => this.client.getApplication(uuid), (app) => getApplicationActions(app.uuid, app.status)));
|
|
297
|
-
this.tool('application', 'Manage app: create/update/delete', {
|
|
297
|
+
this.tool('application', 'Manage app: create/update/delete/delete_preview', {
|
|
298
298
|
action: z.enum([
|
|
299
299
|
'create_public',
|
|
300
300
|
'create_github',
|
|
@@ -302,6 +302,7 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
302
302
|
'create_dockerimage',
|
|
303
303
|
'update',
|
|
304
304
|
'delete',
|
|
305
|
+
'delete_preview',
|
|
305
306
|
]),
|
|
306
307
|
uuid: z.string().optional(),
|
|
307
308
|
// Create fields
|
|
@@ -340,8 +341,22 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
340
341
|
health_check_timeout: z.number().optional(),
|
|
341
342
|
health_check_retries: z.number().optional(),
|
|
342
343
|
health_check_start_period: z.number().optional(),
|
|
344
|
+
// Build configuration fields (accepted on create_public/github/key + update;
|
|
345
|
+
// create_dockerimage ignores these — pre-built image, no build step)
|
|
346
|
+
base_directory: z.string().optional(),
|
|
347
|
+
publish_directory: z.string().optional(),
|
|
348
|
+
install_command: z.string().optional(),
|
|
349
|
+
build_command: z.string().optional(),
|
|
350
|
+
start_command: z.string().optional(),
|
|
351
|
+
dockerfile_location: z.string().optional(),
|
|
352
|
+
watch_paths: z.string().optional(),
|
|
353
|
+
// Update-only: Coolify strips dockerfile_target_build on every create endpoint
|
|
354
|
+
// (controller $allowedFields line 1014) but accepts on PATCH (line 2497).
|
|
355
|
+
dockerfile_target_build: z.string().optional(),
|
|
343
356
|
// Delete fields
|
|
344
357
|
delete_volumes: z.boolean().optional(),
|
|
358
|
+
// Preview fields
|
|
359
|
+
pull_request_id: z.number().optional(),
|
|
345
360
|
}, async (args) => {
|
|
346
361
|
const { action, uuid, delete_volumes } = args;
|
|
347
362
|
switch (action) {
|
|
@@ -375,6 +390,25 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
375
390
|
description: args.description,
|
|
376
391
|
fqdn: args.fqdn,
|
|
377
392
|
domains: args.domains,
|
|
393
|
+
base_directory: args.base_directory,
|
|
394
|
+
publish_directory: args.publish_directory,
|
|
395
|
+
install_command: args.install_command,
|
|
396
|
+
build_command: args.build_command,
|
|
397
|
+
start_command: args.start_command,
|
|
398
|
+
dockerfile_location: args.dockerfile_location,
|
|
399
|
+
watch_paths: args.watch_paths,
|
|
400
|
+
health_check_enabled: args.health_check_enabled,
|
|
401
|
+
health_check_path: args.health_check_path,
|
|
402
|
+
health_check_port: args.health_check_port,
|
|
403
|
+
health_check_host: args.health_check_host,
|
|
404
|
+
health_check_method: args.health_check_method,
|
|
405
|
+
health_check_return_code: args.health_check_return_code,
|
|
406
|
+
health_check_scheme: args.health_check_scheme,
|
|
407
|
+
health_check_response_text: args.health_check_response_text,
|
|
408
|
+
health_check_interval: args.health_check_interval,
|
|
409
|
+
health_check_timeout: args.health_check_timeout,
|
|
410
|
+
health_check_retries: args.health_check_retries,
|
|
411
|
+
health_check_start_period: args.health_check_start_period,
|
|
378
412
|
custom_docker_run_options: args.custom_docker_run_options,
|
|
379
413
|
custom_labels: args.custom_labels,
|
|
380
414
|
instant_deploy: args.instant_deploy,
|
|
@@ -409,6 +443,25 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
409
443
|
description: args.description,
|
|
410
444
|
fqdn: args.fqdn,
|
|
411
445
|
domains: args.domains,
|
|
446
|
+
base_directory: args.base_directory,
|
|
447
|
+
publish_directory: args.publish_directory,
|
|
448
|
+
install_command: args.install_command,
|
|
449
|
+
build_command: args.build_command,
|
|
450
|
+
start_command: args.start_command,
|
|
451
|
+
dockerfile_location: args.dockerfile_location,
|
|
452
|
+
watch_paths: args.watch_paths,
|
|
453
|
+
health_check_enabled: args.health_check_enabled,
|
|
454
|
+
health_check_path: args.health_check_path,
|
|
455
|
+
health_check_port: args.health_check_port,
|
|
456
|
+
health_check_host: args.health_check_host,
|
|
457
|
+
health_check_method: args.health_check_method,
|
|
458
|
+
health_check_return_code: args.health_check_return_code,
|
|
459
|
+
health_check_scheme: args.health_check_scheme,
|
|
460
|
+
health_check_response_text: args.health_check_response_text,
|
|
461
|
+
health_check_interval: args.health_check_interval,
|
|
462
|
+
health_check_timeout: args.health_check_timeout,
|
|
463
|
+
health_check_retries: args.health_check_retries,
|
|
464
|
+
health_check_start_period: args.health_check_start_period,
|
|
412
465
|
custom_docker_run_options: args.custom_docker_run_options,
|
|
413
466
|
custom_labels: args.custom_labels,
|
|
414
467
|
instant_deploy: args.instant_deploy,
|
|
@@ -443,6 +496,25 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
443
496
|
description: args.description,
|
|
444
497
|
fqdn: args.fqdn,
|
|
445
498
|
domains: args.domains,
|
|
499
|
+
base_directory: args.base_directory,
|
|
500
|
+
publish_directory: args.publish_directory,
|
|
501
|
+
install_command: args.install_command,
|
|
502
|
+
build_command: args.build_command,
|
|
503
|
+
start_command: args.start_command,
|
|
504
|
+
dockerfile_location: args.dockerfile_location,
|
|
505
|
+
watch_paths: args.watch_paths,
|
|
506
|
+
health_check_enabled: args.health_check_enabled,
|
|
507
|
+
health_check_path: args.health_check_path,
|
|
508
|
+
health_check_port: args.health_check_port,
|
|
509
|
+
health_check_host: args.health_check_host,
|
|
510
|
+
health_check_method: args.health_check_method,
|
|
511
|
+
health_check_return_code: args.health_check_return_code,
|
|
512
|
+
health_check_scheme: args.health_check_scheme,
|
|
513
|
+
health_check_response_text: args.health_check_response_text,
|
|
514
|
+
health_check_interval: args.health_check_interval,
|
|
515
|
+
health_check_timeout: args.health_check_timeout,
|
|
516
|
+
health_check_retries: args.health_check_retries,
|
|
517
|
+
health_check_start_period: args.health_check_start_period,
|
|
446
518
|
custom_docker_run_options: args.custom_docker_run_options,
|
|
447
519
|
custom_labels: args.custom_labels,
|
|
448
520
|
instant_deploy: args.instant_deploy,
|
|
@@ -474,6 +546,21 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
474
546
|
description: args.description,
|
|
475
547
|
fqdn: args.fqdn,
|
|
476
548
|
domains: args.domains,
|
|
549
|
+
// Build-config fields (base_directory, install_command, etc.)
|
|
550
|
+
// are intentionally NOT forwarded: /applications/dockerimage is
|
|
551
|
+
// for pre-built registry images and has no build step.
|
|
552
|
+
health_check_enabled: args.health_check_enabled,
|
|
553
|
+
health_check_path: args.health_check_path,
|
|
554
|
+
health_check_port: args.health_check_port,
|
|
555
|
+
health_check_host: args.health_check_host,
|
|
556
|
+
health_check_method: args.health_check_method,
|
|
557
|
+
health_check_return_code: args.health_check_return_code,
|
|
558
|
+
health_check_scheme: args.health_check_scheme,
|
|
559
|
+
health_check_response_text: args.health_check_response_text,
|
|
560
|
+
health_check_interval: args.health_check_interval,
|
|
561
|
+
health_check_timeout: args.health_check_timeout,
|
|
562
|
+
health_check_retries: args.health_check_retries,
|
|
563
|
+
health_check_start_period: args.health_check_start_period,
|
|
477
564
|
custom_docker_run_options: args.custom_docker_run_options,
|
|
478
565
|
custom_labels: args.custom_labels,
|
|
479
566
|
instant_deploy: args.instant_deploy,
|
|
@@ -489,6 +576,12 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
489
576
|
if (!uuid)
|
|
490
577
|
return { content: [{ type: 'text', text: 'Error: uuid required' }] };
|
|
491
578
|
return wrap(() => this.client.deleteApplication(uuid, { deleteVolumes: delete_volumes }));
|
|
579
|
+
case 'delete_preview':
|
|
580
|
+
if (!uuid || !args.pull_request_id)
|
|
581
|
+
return {
|
|
582
|
+
content: [{ type: 'text', text: 'Error: uuid, pull_request_id required' }],
|
|
583
|
+
};
|
|
584
|
+
return wrap(() => this.client.deleteApplicationPreview(uuid, args.pull_request_id));
|
|
492
585
|
}
|
|
493
586
|
});
|
|
494
587
|
this.tool('application_logs', 'Get app logs', { uuid: z.string(), lines: z.number().optional() }, async ({ uuid, lines }) => wrap(() => this.client.getApplicationLogs(uuid, lines)));
|
|
@@ -682,9 +775,9 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
682
775
|
// =========================================================================
|
|
683
776
|
// Environment Variables (1 tool - consolidated)
|
|
684
777
|
// =========================================================================
|
|
685
|
-
this.tool('env_vars', "Manage env vars for app or
|
|
686
|
-
resource: z.enum(['application', 'service']),
|
|
687
|
-
action: z.enum(['list', 'create', 'update', 'delete']),
|
|
778
|
+
this.tool('env_vars', "Manage env vars for app, service, or database. Values are masked by default (returned as '***') to avoid leaking secrets to MCP clients; pass reveal=true on the list action when the caller explicitly needs the plaintext (e.g. 'what is FOO set to?'). Set is_buildtime=false (and/or is_runtime=true) for runtime-only vars to avoid Dockerfile ARG issues with multiline values like PEM keys.", {
|
|
779
|
+
resource: z.enum(['application', 'service', 'database']),
|
|
780
|
+
action: z.enum(['list', 'create', 'update', 'delete', 'bulk_update']),
|
|
688
781
|
uuid: z.string(),
|
|
689
782
|
key: z.string().optional(),
|
|
690
783
|
value: z.string().optional(),
|
|
@@ -692,7 +785,19 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
692
785
|
is_buildtime: z.boolean().optional(),
|
|
693
786
|
is_runtime: z.boolean().optional(),
|
|
694
787
|
reveal: z.boolean().optional(),
|
|
695
|
-
|
|
788
|
+
data: z
|
|
789
|
+
.array(z.object({
|
|
790
|
+
key: z.string(),
|
|
791
|
+
value: z.string(),
|
|
792
|
+
is_preview: z.boolean().optional(),
|
|
793
|
+
is_buildtime: z.boolean().optional(),
|
|
794
|
+
is_runtime: z.boolean().optional(),
|
|
795
|
+
is_literal: z.boolean().optional(),
|
|
796
|
+
is_multiline: z.boolean().optional(),
|
|
797
|
+
is_shown_once: z.boolean().optional(),
|
|
798
|
+
}))
|
|
799
|
+
.optional(),
|
|
800
|
+
}, async ({ resource, action, uuid, key, value, env_uuid, is_buildtime, is_runtime, reveal, data, }) => {
|
|
696
801
|
if (resource === 'application') {
|
|
697
802
|
switch (action) {
|
|
698
803
|
case 'list':
|
|
@@ -719,31 +824,54 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
719
824
|
if (!env_uuid)
|
|
720
825
|
return { content: [{ type: 'text', text: 'Error: env_uuid required' }] };
|
|
721
826
|
return wrap(() => this.client.deleteApplicationEnvVar(uuid, env_uuid));
|
|
827
|
+
case 'bulk_update':
|
|
828
|
+
if (!data)
|
|
829
|
+
return { content: [{ type: 'text', text: 'Error: data array required' }] };
|
|
830
|
+
return wrap(() => this.client.bulkUpdateApplicationEnvVars(uuid, { data }));
|
|
722
831
|
}
|
|
723
832
|
}
|
|
724
|
-
else {
|
|
833
|
+
else if (resource === 'service') {
|
|
725
834
|
switch (action) {
|
|
726
835
|
case 'list':
|
|
727
836
|
return wrap(() => this.client.listServiceEnvVars(uuid, { reveal }));
|
|
728
837
|
case 'create':
|
|
729
838
|
if (!key || !value)
|
|
730
839
|
return { content: [{ type: 'text', text: 'Error: key, value required' }] };
|
|
731
|
-
return wrap(() => this.client.createServiceEnvVar(uuid, {
|
|
732
|
-
key,
|
|
733
|
-
value,
|
|
734
|
-
is_buildtime,
|
|
735
|
-
is_runtime,
|
|
736
|
-
}));
|
|
840
|
+
return wrap(() => this.client.createServiceEnvVar(uuid, { key, value, is_buildtime, is_runtime }));
|
|
737
841
|
case 'update':
|
|
738
|
-
|
|
739
|
-
content: [
|
|
740
|
-
|
|
741
|
-
],
|
|
742
|
-
};
|
|
842
|
+
if (!key || !value)
|
|
843
|
+
return { content: [{ type: 'text', text: 'Error: key, value required' }] };
|
|
844
|
+
return wrap(() => this.client.updateServiceEnvVar(uuid, { key, value, is_buildtime, is_runtime }));
|
|
743
845
|
case 'delete':
|
|
744
846
|
if (!env_uuid)
|
|
745
847
|
return { content: [{ type: 'text', text: 'Error: env_uuid required' }] };
|
|
746
848
|
return wrap(() => this.client.deleteServiceEnvVar(uuid, env_uuid));
|
|
849
|
+
case 'bulk_update':
|
|
850
|
+
if (!data)
|
|
851
|
+
return { content: [{ type: 'text', text: 'Error: data array required' }] };
|
|
852
|
+
return wrap(() => this.client.bulkUpdateServiceEnvVars(uuid, { data }));
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
else {
|
|
856
|
+
switch (action) {
|
|
857
|
+
case 'list':
|
|
858
|
+
return wrap(() => this.client.listDatabaseEnvVars(uuid));
|
|
859
|
+
case 'create':
|
|
860
|
+
if (!key || !value)
|
|
861
|
+
return { content: [{ type: 'text', text: 'Error: key, value required' }] };
|
|
862
|
+
return wrap(() => this.client.createDatabaseEnvVar(uuid, { key, value, is_buildtime, is_runtime }));
|
|
863
|
+
case 'update':
|
|
864
|
+
if (!key || !value)
|
|
865
|
+
return { content: [{ type: 'text', text: 'Error: key, value required' }] };
|
|
866
|
+
return wrap(() => this.client.updateDatabaseEnvVar(uuid, { key, value, is_buildtime, is_runtime }));
|
|
867
|
+
case 'delete':
|
|
868
|
+
if (!env_uuid)
|
|
869
|
+
return { content: [{ type: 'text', text: 'Error: env_uuid required' }] };
|
|
870
|
+
return wrap(() => this.client.deleteDatabaseEnvVar(uuid, env_uuid));
|
|
871
|
+
case 'bulk_update':
|
|
872
|
+
if (!data)
|
|
873
|
+
return { content: [{ type: 'text', text: 'Error: data array required' }] };
|
|
874
|
+
return wrap(() => this.client.bulkUpdateDatabaseEnvVars(uuid, { data }));
|
|
747
875
|
}
|
|
748
876
|
}
|
|
749
877
|
});
|
|
@@ -845,10 +973,21 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
845
973
|
// =========================================================================
|
|
846
974
|
// GitHub Apps (1 tool - consolidated)
|
|
847
975
|
// =========================================================================
|
|
848
|
-
this.tool('github_apps', 'Manage GitHub Apps: list/get/create/update/delete', {
|
|
849
|
-
action: z.enum([
|
|
976
|
+
this.tool('github_apps', 'Manage GitHub Apps: list/get/create/update/delete/list_repos/list_branches', {
|
|
977
|
+
action: z.enum([
|
|
978
|
+
'list',
|
|
979
|
+
'get',
|
|
980
|
+
'create',
|
|
981
|
+
'update',
|
|
982
|
+
'delete',
|
|
983
|
+
'list_repos',
|
|
984
|
+
'list_branches',
|
|
985
|
+
]),
|
|
850
986
|
// GitHub apps use integer id, not uuid
|
|
851
987
|
id: z.number().optional(),
|
|
988
|
+
// Repo/branch browsing
|
|
989
|
+
owner: z.string().optional(),
|
|
990
|
+
repo: z.string().optional(),
|
|
852
991
|
// Create/Update fields
|
|
853
992
|
name: z.string().optional(),
|
|
854
993
|
organization: z.string().optional(),
|
|
@@ -924,12 +1063,22 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
924
1063
|
if (!id)
|
|
925
1064
|
return { content: [{ type: 'text', text: 'Error: id required' }] };
|
|
926
1065
|
return wrap(() => this.client.deleteGitHubApp(id));
|
|
1066
|
+
case 'list_repos':
|
|
1067
|
+
if (!id)
|
|
1068
|
+
return { content: [{ type: 'text', text: 'Error: id required' }] };
|
|
1069
|
+
return wrap(() => this.client.listGitHubAppRepositories(id));
|
|
1070
|
+
case 'list_branches':
|
|
1071
|
+
if (!id || !args.owner || !args.repo)
|
|
1072
|
+
return {
|
|
1073
|
+
content: [{ type: 'text', text: 'Error: id, owner, repo required' }],
|
|
1074
|
+
};
|
|
1075
|
+
return wrap(() => this.client.listGitHubAppBranches(id, args.owner, args.repo));
|
|
927
1076
|
}
|
|
928
1077
|
});
|
|
929
1078
|
// =========================================================================
|
|
930
1079
|
// Database Backups (1 tool - consolidated)
|
|
931
1080
|
// =========================================================================
|
|
932
|
-
this.tool('database_backups', 'Manage backups: list_schedules/get_schedule/list_executions/get_execution/create/update/delete', {
|
|
1081
|
+
this.tool('database_backups', 'Manage backups: list_schedules/get_schedule/list_executions/get_execution/create/update/delete/delete_execution', {
|
|
933
1082
|
action: z.enum([
|
|
934
1083
|
'list_schedules',
|
|
935
1084
|
'get_schedule',
|
|
@@ -938,6 +1087,7 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
938
1087
|
'create',
|
|
939
1088
|
'update',
|
|
940
1089
|
'delete',
|
|
1090
|
+
'delete_execution',
|
|
941
1091
|
]),
|
|
942
1092
|
database_uuid: z.string(),
|
|
943
1093
|
backup_uuid: z.string().optional(),
|
|
@@ -989,6 +1139,14 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
989
1139
|
if (!backup_uuid)
|
|
990
1140
|
return { content: [{ type: 'text', text: 'Error: backup_uuid required' }] };
|
|
991
1141
|
return wrap(() => this.client.deleteDatabaseBackup(database_uuid, backup_uuid));
|
|
1142
|
+
case 'delete_execution':
|
|
1143
|
+
if (!backup_uuid || !execution_uuid)
|
|
1144
|
+
return {
|
|
1145
|
+
content: [
|
|
1146
|
+
{ type: 'text', text: 'Error: backup_uuid, execution_uuid required' },
|
|
1147
|
+
],
|
|
1148
|
+
};
|
|
1149
|
+
return wrap(() => this.client.deleteBackupExecution(database_uuid, backup_uuid, execution_uuid));
|
|
992
1150
|
}
|
|
993
1151
|
});
|
|
994
1152
|
// =========================================================================
|
|
@@ -1053,6 +1211,277 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
1053
1211
|
}
|
|
1054
1212
|
});
|
|
1055
1213
|
// =========================================================================
|
|
1214
|
+
// Storages (1 tool - consolidated for app/db/service)
|
|
1215
|
+
// =========================================================================
|
|
1216
|
+
this.tool('storages', 'Manage persistent/file storages for app, database, or service: list/create/update/delete', {
|
|
1217
|
+
resource: z.enum(['application', 'database', 'service']),
|
|
1218
|
+
action: z.enum(['list', 'create', 'update', 'delete']),
|
|
1219
|
+
uuid: z.string(),
|
|
1220
|
+
storage_uuid: z.string().optional(),
|
|
1221
|
+
type: z.enum(['persistent', 'file']).optional(),
|
|
1222
|
+
mount_path: z.string().optional(),
|
|
1223
|
+
name: z.string().optional(),
|
|
1224
|
+
host_path: z.string().optional(),
|
|
1225
|
+
content: z.string().optional(),
|
|
1226
|
+
is_directory: z.boolean().optional(),
|
|
1227
|
+
fs_path: z.string().optional(),
|
|
1228
|
+
is_preview_suffix_enabled: z.boolean().optional(),
|
|
1229
|
+
}, async (args) => {
|
|
1230
|
+
const { resource, action, uuid, storage_uuid } = args;
|
|
1231
|
+
if (action === 'create' && (!args.type || !args.mount_path))
|
|
1232
|
+
return { content: [{ type: 'text', text: 'Error: type, mount_path required' }] };
|
|
1233
|
+
if (action === 'update' && (!args.type || !storage_uuid))
|
|
1234
|
+
return {
|
|
1235
|
+
content: [{ type: 'text', text: 'Error: type, storage_uuid required' }],
|
|
1236
|
+
};
|
|
1237
|
+
if (action === 'delete' && !storage_uuid)
|
|
1238
|
+
return { content: [{ type: 'text', text: 'Error: storage_uuid required' }] };
|
|
1239
|
+
const methods = {
|
|
1240
|
+
application: {
|
|
1241
|
+
list: () => this.client.listApplicationStorages(uuid),
|
|
1242
|
+
create: () => this.client.createApplicationStorage(uuid, {
|
|
1243
|
+
type: args.type,
|
|
1244
|
+
mount_path: args.mount_path,
|
|
1245
|
+
name: args.name,
|
|
1246
|
+
host_path: args.host_path,
|
|
1247
|
+
content: args.content,
|
|
1248
|
+
is_directory: args.is_directory,
|
|
1249
|
+
fs_path: args.fs_path,
|
|
1250
|
+
is_preview_suffix_enabled: args.is_preview_suffix_enabled,
|
|
1251
|
+
}),
|
|
1252
|
+
update: () => this.client.updateApplicationStorage(uuid, {
|
|
1253
|
+
uuid: storage_uuid,
|
|
1254
|
+
type: args.type,
|
|
1255
|
+
mount_path: args.mount_path,
|
|
1256
|
+
name: args.name,
|
|
1257
|
+
host_path: args.host_path,
|
|
1258
|
+
content: args.content,
|
|
1259
|
+
is_directory: args.is_directory,
|
|
1260
|
+
is_preview_suffix_enabled: args.is_preview_suffix_enabled,
|
|
1261
|
+
}),
|
|
1262
|
+
delete: () => this.client.deleteApplicationStorage(uuid, storage_uuid),
|
|
1263
|
+
},
|
|
1264
|
+
database: {
|
|
1265
|
+
list: () => this.client.listDatabaseStorages(uuid),
|
|
1266
|
+
create: () => this.client.createDatabaseStorage(uuid, {
|
|
1267
|
+
type: args.type,
|
|
1268
|
+
mount_path: args.mount_path,
|
|
1269
|
+
name: args.name,
|
|
1270
|
+
host_path: args.host_path,
|
|
1271
|
+
content: args.content,
|
|
1272
|
+
is_directory: args.is_directory,
|
|
1273
|
+
fs_path: args.fs_path,
|
|
1274
|
+
is_preview_suffix_enabled: args.is_preview_suffix_enabled,
|
|
1275
|
+
}),
|
|
1276
|
+
update: () => this.client.updateDatabaseStorage(uuid, {
|
|
1277
|
+
uuid: storage_uuid,
|
|
1278
|
+
type: args.type,
|
|
1279
|
+
mount_path: args.mount_path,
|
|
1280
|
+
name: args.name,
|
|
1281
|
+
host_path: args.host_path,
|
|
1282
|
+
content: args.content,
|
|
1283
|
+
is_directory: args.is_directory,
|
|
1284
|
+
is_preview_suffix_enabled: args.is_preview_suffix_enabled,
|
|
1285
|
+
}),
|
|
1286
|
+
delete: () => this.client.deleteDatabaseStorage(uuid, storage_uuid),
|
|
1287
|
+
},
|
|
1288
|
+
service: {
|
|
1289
|
+
list: () => this.client.listServiceStorages(uuid),
|
|
1290
|
+
create: () => this.client.createServiceStorage(uuid, {
|
|
1291
|
+
type: args.type,
|
|
1292
|
+
mount_path: args.mount_path,
|
|
1293
|
+
name: args.name,
|
|
1294
|
+
host_path: args.host_path,
|
|
1295
|
+
content: args.content,
|
|
1296
|
+
is_directory: args.is_directory,
|
|
1297
|
+
fs_path: args.fs_path,
|
|
1298
|
+
is_preview_suffix_enabled: args.is_preview_suffix_enabled,
|
|
1299
|
+
}),
|
|
1300
|
+
update: () => this.client.updateServiceStorage(uuid, {
|
|
1301
|
+
uuid: storage_uuid,
|
|
1302
|
+
type: args.type,
|
|
1303
|
+
mount_path: args.mount_path,
|
|
1304
|
+
name: args.name,
|
|
1305
|
+
host_path: args.host_path,
|
|
1306
|
+
content: args.content,
|
|
1307
|
+
is_directory: args.is_directory,
|
|
1308
|
+
is_preview_suffix_enabled: args.is_preview_suffix_enabled,
|
|
1309
|
+
}),
|
|
1310
|
+
delete: () => this.client.deleteServiceStorage(uuid, storage_uuid),
|
|
1311
|
+
},
|
|
1312
|
+
};
|
|
1313
|
+
return wrap(() => methods[resource][action]());
|
|
1314
|
+
});
|
|
1315
|
+
// =========================================================================
|
|
1316
|
+
// Scheduled Tasks (1 tool - consolidated for app/service)
|
|
1317
|
+
// =========================================================================
|
|
1318
|
+
this.tool('scheduled_tasks', 'Manage scheduled tasks for app or service: list/create/update/delete/list_executions', {
|
|
1319
|
+
resource: z.enum(['application', 'service']),
|
|
1320
|
+
action: z.enum(['list', 'create', 'update', 'delete', 'list_executions']),
|
|
1321
|
+
uuid: z.string(),
|
|
1322
|
+
task_uuid: z.string().optional(),
|
|
1323
|
+
name: z.string().optional(),
|
|
1324
|
+
command: z.string().optional(),
|
|
1325
|
+
frequency: z.string().optional(),
|
|
1326
|
+
container: z.string().optional(),
|
|
1327
|
+
timeout: z.number().optional(),
|
|
1328
|
+
enabled: z.boolean().optional(),
|
|
1329
|
+
}, async (args) => {
|
|
1330
|
+
const { resource, action, uuid, task_uuid } = args;
|
|
1331
|
+
const isApp = resource === 'application';
|
|
1332
|
+
switch (action) {
|
|
1333
|
+
case 'list':
|
|
1334
|
+
return wrap(() => isApp
|
|
1335
|
+
? this.client.listApplicationScheduledTasks(uuid)
|
|
1336
|
+
: this.client.listServiceScheduledTasks(uuid));
|
|
1337
|
+
case 'create':
|
|
1338
|
+
if (!args.name || !args.command || !args.frequency)
|
|
1339
|
+
return {
|
|
1340
|
+
content: [
|
|
1341
|
+
{ type: 'text', text: 'Error: name, command, frequency required' },
|
|
1342
|
+
],
|
|
1343
|
+
};
|
|
1344
|
+
return wrap(() => {
|
|
1345
|
+
const data = {
|
|
1346
|
+
name: args.name,
|
|
1347
|
+
command: args.command,
|
|
1348
|
+
frequency: args.frequency,
|
|
1349
|
+
container: args.container,
|
|
1350
|
+
timeout: args.timeout,
|
|
1351
|
+
enabled: args.enabled,
|
|
1352
|
+
};
|
|
1353
|
+
return isApp
|
|
1354
|
+
? this.client.createApplicationScheduledTask(uuid, data)
|
|
1355
|
+
: this.client.createServiceScheduledTask(uuid, data);
|
|
1356
|
+
});
|
|
1357
|
+
case 'update':
|
|
1358
|
+
if (!task_uuid)
|
|
1359
|
+
return { content: [{ type: 'text', text: 'Error: task_uuid required' }] };
|
|
1360
|
+
return wrap(() => {
|
|
1361
|
+
const data = {
|
|
1362
|
+
name: args.name,
|
|
1363
|
+
command: args.command,
|
|
1364
|
+
frequency: args.frequency,
|
|
1365
|
+
container: args.container,
|
|
1366
|
+
timeout: args.timeout,
|
|
1367
|
+
enabled: args.enabled,
|
|
1368
|
+
};
|
|
1369
|
+
return isApp
|
|
1370
|
+
? this.client.updateApplicationScheduledTask(uuid, task_uuid, data)
|
|
1371
|
+
: this.client.updateServiceScheduledTask(uuid, task_uuid, data);
|
|
1372
|
+
});
|
|
1373
|
+
case 'delete':
|
|
1374
|
+
if (!task_uuid)
|
|
1375
|
+
return { content: [{ type: 'text', text: 'Error: task_uuid required' }] };
|
|
1376
|
+
return wrap(() => isApp
|
|
1377
|
+
? this.client.deleteApplicationScheduledTask(uuid, task_uuid)
|
|
1378
|
+
: this.client.deleteServiceScheduledTask(uuid, task_uuid));
|
|
1379
|
+
case 'list_executions':
|
|
1380
|
+
if (!task_uuid)
|
|
1381
|
+
return { content: [{ type: 'text', text: 'Error: task_uuid required' }] };
|
|
1382
|
+
return wrap(() => isApp
|
|
1383
|
+
? this.client.listApplicationScheduledTaskExecutions(uuid, task_uuid)
|
|
1384
|
+
: this.client.listServiceScheduledTaskExecutions(uuid, task_uuid));
|
|
1385
|
+
}
|
|
1386
|
+
});
|
|
1387
|
+
// =========================================================================
|
|
1388
|
+
// Hetzner Cloud (1 tool - consolidated)
|
|
1389
|
+
// =========================================================================
|
|
1390
|
+
this.tool('hetzner', 'Hetzner cloud: list_locations/list_server_types/list_images/list_ssh_keys/create_server', {
|
|
1391
|
+
action: z.enum([
|
|
1392
|
+
'list_locations',
|
|
1393
|
+
'list_server_types',
|
|
1394
|
+
'list_images',
|
|
1395
|
+
'list_ssh_keys',
|
|
1396
|
+
'create_server',
|
|
1397
|
+
]),
|
|
1398
|
+
cloud_provider_token_uuid: z.string().optional(),
|
|
1399
|
+
location: z.string().optional(),
|
|
1400
|
+
server_type: z.string().optional(),
|
|
1401
|
+
image: z.number().optional(),
|
|
1402
|
+
name: z.string().optional(),
|
|
1403
|
+
private_key_uuid: z.string().optional(),
|
|
1404
|
+
enable_ipv4: z.boolean().optional(),
|
|
1405
|
+
enable_ipv6: z.boolean().optional(),
|
|
1406
|
+
hetzner_ssh_key_ids: z.array(z.number()).optional(),
|
|
1407
|
+
cloud_init_script: z.string().optional(),
|
|
1408
|
+
instant_validate: z.boolean().optional(),
|
|
1409
|
+
}, async (args) => {
|
|
1410
|
+
const { action, cloud_provider_token_uuid: tokenUuid } = args;
|
|
1411
|
+
switch (action) {
|
|
1412
|
+
case 'list_locations':
|
|
1413
|
+
if (!tokenUuid)
|
|
1414
|
+
return {
|
|
1415
|
+
content: [
|
|
1416
|
+
{ type: 'text', text: 'Error: cloud_provider_token_uuid required' },
|
|
1417
|
+
],
|
|
1418
|
+
};
|
|
1419
|
+
return wrap(() => this.client.listHetznerLocations(tokenUuid));
|
|
1420
|
+
case 'list_server_types':
|
|
1421
|
+
if (!tokenUuid)
|
|
1422
|
+
return {
|
|
1423
|
+
content: [
|
|
1424
|
+
{ type: 'text', text: 'Error: cloud_provider_token_uuid required' },
|
|
1425
|
+
],
|
|
1426
|
+
};
|
|
1427
|
+
return wrap(() => this.client.listHetznerServerTypes(tokenUuid));
|
|
1428
|
+
case 'list_images':
|
|
1429
|
+
if (!tokenUuid)
|
|
1430
|
+
return {
|
|
1431
|
+
content: [
|
|
1432
|
+
{ type: 'text', text: 'Error: cloud_provider_token_uuid required' },
|
|
1433
|
+
],
|
|
1434
|
+
};
|
|
1435
|
+
return wrap(() => this.client.listHetznerImages(tokenUuid));
|
|
1436
|
+
case 'list_ssh_keys':
|
|
1437
|
+
if (!tokenUuid)
|
|
1438
|
+
return {
|
|
1439
|
+
content: [
|
|
1440
|
+
{ type: 'text', text: 'Error: cloud_provider_token_uuid required' },
|
|
1441
|
+
],
|
|
1442
|
+
};
|
|
1443
|
+
return wrap(() => this.client.listHetznerSSHKeys(tokenUuid));
|
|
1444
|
+
case 'create_server':
|
|
1445
|
+
if (!args.location || !args.server_type || !args.image || !args.private_key_uuid)
|
|
1446
|
+
return {
|
|
1447
|
+
content: [
|
|
1448
|
+
{
|
|
1449
|
+
type: 'text',
|
|
1450
|
+
text: 'Error: location, server_type, image, private_key_uuid required',
|
|
1451
|
+
},
|
|
1452
|
+
],
|
|
1453
|
+
};
|
|
1454
|
+
return wrap(() => this.client.createHetznerServer({
|
|
1455
|
+
cloud_provider_token_uuid: tokenUuid,
|
|
1456
|
+
location: args.location,
|
|
1457
|
+
server_type: args.server_type,
|
|
1458
|
+
image: args.image,
|
|
1459
|
+
name: args.name,
|
|
1460
|
+
private_key_uuid: args.private_key_uuid,
|
|
1461
|
+
enable_ipv4: args.enable_ipv4,
|
|
1462
|
+
enable_ipv6: args.enable_ipv6,
|
|
1463
|
+
hetzner_ssh_key_ids: args.hetzner_ssh_key_ids,
|
|
1464
|
+
cloud_init_script: args.cloud_init_script,
|
|
1465
|
+
instant_validate: args.instant_validate,
|
|
1466
|
+
}));
|
|
1467
|
+
}
|
|
1468
|
+
});
|
|
1469
|
+
// =========================================================================
|
|
1470
|
+
// System (1 tool - health/list_resources/api_control consolidated)
|
|
1471
|
+
// =========================================================================
|
|
1472
|
+
this.tool('system', 'System operations: health/list_resources/enable_api/disable_api', { action: z.enum(['health', 'list_resources', 'enable_api', 'disable_api']) }, async ({ action }) => {
|
|
1473
|
+
switch (action) {
|
|
1474
|
+
case 'health':
|
|
1475
|
+
return wrap(() => this.client.getHealth());
|
|
1476
|
+
case 'list_resources':
|
|
1477
|
+
return wrap(() => this.client.listResources());
|
|
1478
|
+
case 'enable_api':
|
|
1479
|
+
return wrap(() => this.client.enableApi());
|
|
1480
|
+
case 'disable_api':
|
|
1481
|
+
return wrap(() => this.client.disableApi());
|
|
1482
|
+
}
|
|
1483
|
+
});
|
|
1484
|
+
// =========================================================================
|
|
1056
1485
|
// Documentation Search (1 tool)
|
|
1057
1486
|
// =========================================================================
|
|
1058
1487
|
this.tool('search_docs', 'Search Coolify documentation for how-to guides, configuration, troubleshooting', {
|