@mks2508/coolify-mks-cli-mcp 0.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/dist/cli/index.js +11788 -0
- package/dist/coolify/config.d.ts +64 -0
- package/dist/coolify/config.d.ts.map +1 -0
- package/dist/coolify/index.d.ts +201 -0
- package/dist/coolify/index.d.ts.map +1 -0
- package/dist/coolify/types.d.ts +282 -0
- package/dist/coolify/types.d.ts.map +1 -0
- package/dist/index.cjs +29150 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29127 -0
- package/dist/index.js.map +1 -0
- package/dist/server/sse.d.ts +11 -0
- package/dist/server/sse.d.ts.map +1 -0
- package/dist/server/sse.js +32 -0
- package/dist/server/stdio.d.ts +13 -0
- package/dist/server/stdio.d.ts.map +1 -0
- package/dist/server/stdio.js +18326 -0
- package/dist/tools/definitions.d.ts +13 -0
- package/dist/tools/definitions.d.ts.map +1 -0
- package/dist/tools/handlers.d.ts +19 -0
- package/dist/tools/handlers.d.ts.map +1 -0
- package/dist/utils/format.d.ts +38 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/package.json +67 -0
- package/src/cli/commands/config.ts +83 -0
- package/src/cli/commands/deploy.ts +56 -0
- package/src/cli/commands/env.ts +60 -0
- package/src/cli/commands/list.ts +63 -0
- package/src/cli/commands/logs.ts +49 -0
- package/src/cli/commands/servers.ts +52 -0
- package/src/cli/index.ts +81 -0
- package/src/coolify/config.ts +113 -0
- package/src/coolify/index.ts +688 -0
- package/src/coolify/types.ts +297 -0
- package/src/index.ts +864 -0
- package/src/server/sse.ts +50 -0
- package/src/server/stdio.ts +52 -0
- package/src/tools/definitions.ts +435 -0
- package/src/tools/handlers.ts +605 -0
- package/src/utils/format.ts +104 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,864 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coolify MCP Server - Entry point.
|
|
3
|
+
*
|
|
4
|
+
* Exports the MCP server with 21 tools for Coolify management.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { createSdkMcpServer, tool } from '@anthropic-ai/claude-agent-sdk'
|
|
10
|
+
import { z } from 'zod'
|
|
11
|
+
import { isOk, isErr } from '@mks2508/no-throw'
|
|
12
|
+
import { getCoolifyService } from './coolify/index.js'
|
|
13
|
+
|
|
14
|
+
// Create service instance
|
|
15
|
+
const coolify = getCoolifyService()
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Coolify MCP Server with 21 tools for deployment management.
|
|
19
|
+
*/
|
|
20
|
+
export const coolifyServer = createSdkMcpServer({
|
|
21
|
+
name: 'coolify-mks-cli',
|
|
22
|
+
version: '0.1.0',
|
|
23
|
+
tools: [
|
|
24
|
+
// 1. deploy
|
|
25
|
+
tool(
|
|
26
|
+
'deploy',
|
|
27
|
+
`Deploy or redeploy an application to Coolify.
|
|
28
|
+
|
|
29
|
+
Triggers a new deployment for the specified application UUID.
|
|
30
|
+
Can force rebuild without cache if needed.`,
|
|
31
|
+
{
|
|
32
|
+
uuid: z.string().uuid().describe('Application UUID in Coolify'),
|
|
33
|
+
force: z.boolean().default(false).describe('Force rebuild without cache'),
|
|
34
|
+
tag: z.string().optional().describe('Deploy specific tag/version'),
|
|
35
|
+
},
|
|
36
|
+
async (args) => {
|
|
37
|
+
const initResult = await coolify.init()
|
|
38
|
+
if (isErr(initResult)) {
|
|
39
|
+
return {
|
|
40
|
+
content: [{ type: 'text' as const, text: `Coolify not configured: ${initResult.error.message}` }],
|
|
41
|
+
isError: true,
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const result = await coolify.deploy({ uuid: args.uuid, force: args.force, tag: args.tag })
|
|
46
|
+
|
|
47
|
+
if (isOk(result)) {
|
|
48
|
+
return {
|
|
49
|
+
content: [{
|
|
50
|
+
type: 'text' as const,
|
|
51
|
+
text: JSON.stringify({
|
|
52
|
+
success: true,
|
|
53
|
+
deploymentUuid: result.value.deploymentUuid,
|
|
54
|
+
resourceUuid: result.value.resourceUuid,
|
|
55
|
+
message: 'Deployment started',
|
|
56
|
+
}, null, 2),
|
|
57
|
+
}],
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
content: [{ type: 'text' as const, text: `Deployment failed: ${result.error.message}` }],
|
|
63
|
+
isError: true,
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
),
|
|
67
|
+
|
|
68
|
+
// 2. get_env_vars
|
|
69
|
+
tool(
|
|
70
|
+
'get_env_vars',
|
|
71
|
+
`Get environment variables for a Coolify application.
|
|
72
|
+
|
|
73
|
+
Returns all environment variables with metadata including whether
|
|
74
|
+
they are runtime or buildtime, and if they are required.`,
|
|
75
|
+
{
|
|
76
|
+
uuid: z.string().uuid().describe('Application UUID'),
|
|
77
|
+
},
|
|
78
|
+
async (args) => {
|
|
79
|
+
const initResult = await coolify.init()
|
|
80
|
+
if (isErr(initResult)) {
|
|
81
|
+
return {
|
|
82
|
+
content: [{ type: 'text' as const, text: `Coolify not configured: ${initResult.error.message}` }],
|
|
83
|
+
isError: true,
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const result = await coolify.getEnvironmentVariables(args.uuid)
|
|
88
|
+
|
|
89
|
+
if (isOk(result)) {
|
|
90
|
+
const runtimeVars = result.value.filter(ev => ev.is_runtime)
|
|
91
|
+
const buildtimeVars = result.value.filter(ev => ev.is_buildtime)
|
|
92
|
+
return {
|
|
93
|
+
content: [{
|
|
94
|
+
type: 'text' as const,
|
|
95
|
+
text: JSON.stringify({
|
|
96
|
+
success: true,
|
|
97
|
+
total: result.value.length,
|
|
98
|
+
runtimeCount: runtimeVars.length,
|
|
99
|
+
buildtimeCount: buildtimeVars.length,
|
|
100
|
+
runtime: runtimeVars,
|
|
101
|
+
buildtime: buildtimeVars,
|
|
102
|
+
}, null, 2),
|
|
103
|
+
}],
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
content: [{ type: 'text' as const, text: `Failed to get env vars: ${result.error.message}` }],
|
|
109
|
+
isError: true,
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
),
|
|
113
|
+
|
|
114
|
+
// 3. set_env_vars
|
|
115
|
+
tool(
|
|
116
|
+
'set_env_vars',
|
|
117
|
+
`Set environment variables for a Coolify application.
|
|
118
|
+
|
|
119
|
+
Updates or adds environment variables. Existing vars not in the
|
|
120
|
+
input are preserved. Redeploy after setting to apply changes.`,
|
|
121
|
+
{
|
|
122
|
+
uuid: z.string().uuid().describe('Application UUID'),
|
|
123
|
+
envVars: z.record(z.string()).describe('Key-value pairs of environment variables'),
|
|
124
|
+
},
|
|
125
|
+
async (args) => {
|
|
126
|
+
const initResult = await coolify.init()
|
|
127
|
+
if (isErr(initResult)) {
|
|
128
|
+
return {
|
|
129
|
+
content: [{ type: 'text' as const, text: `Coolify not configured: ${initResult.error.message}` }],
|
|
130
|
+
isError: true,
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const result = await coolify.setEnvironmentVariables(args.uuid, args.envVars)
|
|
135
|
+
|
|
136
|
+
if (isOk(result)) {
|
|
137
|
+
return {
|
|
138
|
+
content: [{
|
|
139
|
+
type: 'text' as const,
|
|
140
|
+
text: `Set ${Object.keys(args.envVars).length} environment variable(s). Use deploy tool to apply changes.`,
|
|
141
|
+
}],
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
content: [{ type: 'text' as const, text: `Failed to set env vars: ${result.error.message}` }],
|
|
147
|
+
isError: true,
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
),
|
|
151
|
+
|
|
152
|
+
// 4. get_deployment_status
|
|
153
|
+
tool(
|
|
154
|
+
'get_deployment_status',
|
|
155
|
+
`Get the current status of a Coolify application.
|
|
156
|
+
|
|
157
|
+
Returns deployment state, health status, and resource usage.`,
|
|
158
|
+
{
|
|
159
|
+
uuid: z.string().uuid().describe('Application UUID'),
|
|
160
|
+
},
|
|
161
|
+
async (args) => {
|
|
162
|
+
const initResult = await coolify.init()
|
|
163
|
+
if (isErr(initResult)) {
|
|
164
|
+
return {
|
|
165
|
+
content: [{ type: 'text' as const, text: `Coolify not configured: ${initResult.error.message}` }],
|
|
166
|
+
isError: true,
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const result = await coolify.getApplicationStatus(args.uuid)
|
|
171
|
+
|
|
172
|
+
if (isOk(result)) {
|
|
173
|
+
return {
|
|
174
|
+
content: [{ type: 'text' as const, text: JSON.stringify({ status: result.value }, null, 2) }],
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
content: [{ type: 'text' as const, text: `Failed to get status: ${result.error.message}` }],
|
|
180
|
+
isError: true,
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
),
|
|
184
|
+
|
|
185
|
+
// 4. list_applications
|
|
186
|
+
tool(
|
|
187
|
+
'list_applications',
|
|
188
|
+
`List all applications in Coolify.
|
|
189
|
+
|
|
190
|
+
Optionally filter by team or project ID.`,
|
|
191
|
+
{
|
|
192
|
+
teamId: z.string().optional().describe('Filter by Team ID'),
|
|
193
|
+
projectId: z.string().optional().describe('Filter by Project ID'),
|
|
194
|
+
},
|
|
195
|
+
async (args) => {
|
|
196
|
+
const initResult = await coolify.init()
|
|
197
|
+
if (isErr(initResult)) {
|
|
198
|
+
return {
|
|
199
|
+
content: [{ type: 'text' as const, text: `Coolify not configured: ${initResult.error.message}` }],
|
|
200
|
+
isError: true,
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const result = await coolify.listApplications(args.teamId, args.projectId)
|
|
205
|
+
|
|
206
|
+
if (isOk(result)) {
|
|
207
|
+
return {
|
|
208
|
+
content: [{
|
|
209
|
+
type: 'text' as const,
|
|
210
|
+
text: JSON.stringify({ success: true, count: result.value.length, applications: result.value }, null, 2),
|
|
211
|
+
}],
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return {
|
|
216
|
+
content: [{ type: 'text' as const, text: `Failed to list applications: ${result.error.message}` }],
|
|
217
|
+
isError: true,
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
),
|
|
221
|
+
|
|
222
|
+
// 5. delete_application
|
|
223
|
+
tool(
|
|
224
|
+
'delete_application',
|
|
225
|
+
`Delete an application from Coolify.
|
|
226
|
+
|
|
227
|
+
WARNING: This action is irreversible. All deployments, environment
|
|
228
|
+
variables, domains, and history will be permanently deleted.`,
|
|
229
|
+
{
|
|
230
|
+
uuid: z.string().uuid().describe('Application UUID to delete'),
|
|
231
|
+
},
|
|
232
|
+
async (args) => {
|
|
233
|
+
const initResult = await coolify.init()
|
|
234
|
+
if (isErr(initResult)) {
|
|
235
|
+
return {
|
|
236
|
+
content: [{ type: 'text' as const, text: `Coolify not configured: ${initResult.error.message}` }],
|
|
237
|
+
isError: true,
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const result = await coolify.deleteApplication(args.uuid)
|
|
242
|
+
|
|
243
|
+
if (isOk(result)) {
|
|
244
|
+
return {
|
|
245
|
+
content: [{
|
|
246
|
+
type: 'text' as const,
|
|
247
|
+
text: JSON.stringify({ success: true, message: `Application ${args.uuid} deleted successfully` }, null, 2),
|
|
248
|
+
}],
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return {
|
|
253
|
+
content: [{ type: 'text' as const, text: `Failed to delete application: ${result.error.message}` }],
|
|
254
|
+
isError: true,
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
),
|
|
258
|
+
|
|
259
|
+
// 6. get_application_logs
|
|
260
|
+
tool(
|
|
261
|
+
'get_application_logs',
|
|
262
|
+
`Get logs for a Coolify application.
|
|
263
|
+
|
|
264
|
+
Retrieve recent logs with optional tail limit.`,
|
|
265
|
+
{
|
|
266
|
+
uuid: z.string().uuid().describe('Application UUID'),
|
|
267
|
+
tail: z.number().optional().describe('Number of log lines to retrieve'),
|
|
268
|
+
},
|
|
269
|
+
async (args) => {
|
|
270
|
+
const initResult = await coolify.init()
|
|
271
|
+
if (isErr(initResult)) {
|
|
272
|
+
return {
|
|
273
|
+
content: [{ type: 'text' as const, text: `Coolify not configured: ${initResult.error.message}` }],
|
|
274
|
+
isError: true,
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const result = await coolify.getApplicationLogs(args.uuid, { tail: args.tail })
|
|
279
|
+
|
|
280
|
+
if (isOk(result)) {
|
|
281
|
+
return {
|
|
282
|
+
content: [{
|
|
283
|
+
type: 'text' as const,
|
|
284
|
+
text: JSON.stringify({
|
|
285
|
+
success: true,
|
|
286
|
+
timestamp: result.value.timestamp,
|
|
287
|
+
logCount: result.value.logs.length,
|
|
288
|
+
logs: result.value.logs,
|
|
289
|
+
}, null, 2),
|
|
290
|
+
}],
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return {
|
|
295
|
+
content: [{ type: 'text' as const, text: `Failed to get logs: ${result.error.message}` }],
|
|
296
|
+
isError: true,
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
),
|
|
300
|
+
|
|
301
|
+
// 7. start_application
|
|
302
|
+
tool(
|
|
303
|
+
'start_application',
|
|
304
|
+
`Start a stopped Coolify application.
|
|
305
|
+
|
|
306
|
+
Use this to start applications that were previously stopped.`,
|
|
307
|
+
{
|
|
308
|
+
uuid: z.string().uuid().describe('Application UUID to start'),
|
|
309
|
+
},
|
|
310
|
+
async (args) => {
|
|
311
|
+
const initResult = await coolify.init()
|
|
312
|
+
if (isErr(initResult)) {
|
|
313
|
+
return {
|
|
314
|
+
content: [{ type: 'text' as const, text: `Coolify not configured: ${initResult.error.message}` }],
|
|
315
|
+
isError: true,
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const result = await coolify.startApplication(args.uuid)
|
|
320
|
+
|
|
321
|
+
if (isOk(result)) {
|
|
322
|
+
return {
|
|
323
|
+
content: [{
|
|
324
|
+
type: 'text' as const,
|
|
325
|
+
text: JSON.stringify({ success: true, message: `Application ${args.uuid} started`, application: result.value }, null, 2),
|
|
326
|
+
}],
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return {
|
|
331
|
+
content: [{ type: 'text' as const, text: `Failed to start application: ${result.error.message}` }],
|
|
332
|
+
isError: true,
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
),
|
|
336
|
+
|
|
337
|
+
// 8. stop_application
|
|
338
|
+
tool(
|
|
339
|
+
'stop_application',
|
|
340
|
+
`Stop a running Coolify application.
|
|
341
|
+
|
|
342
|
+
WARNING: This will make the application temporarily unavailable.
|
|
343
|
+
Containers will be stopped but not deleted.`,
|
|
344
|
+
{
|
|
345
|
+
uuid: z.string().uuid().describe('Application UUID to stop'),
|
|
346
|
+
},
|
|
347
|
+
async (args) => {
|
|
348
|
+
const initResult = await coolify.init()
|
|
349
|
+
if (isErr(initResult)) {
|
|
350
|
+
return {
|
|
351
|
+
content: [{ type: 'text' as const, text: `Coolify not configured: ${initResult.error.message}` }],
|
|
352
|
+
isError: true,
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const result = await coolify.stopApplication(args.uuid)
|
|
357
|
+
|
|
358
|
+
if (isOk(result)) {
|
|
359
|
+
return {
|
|
360
|
+
content: [{
|
|
361
|
+
type: 'text' as const,
|
|
362
|
+
text: JSON.stringify({ success: true, message: `Application ${args.uuid} stopped`, application: result.value }, null, 2),
|
|
363
|
+
}],
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
return {
|
|
368
|
+
content: [{ type: 'text' as const, text: `Failed to stop application: ${result.error.message}` }],
|
|
369
|
+
isError: true,
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
),
|
|
373
|
+
|
|
374
|
+
// 9. restart_application
|
|
375
|
+
tool(
|
|
376
|
+
'restart_application',
|
|
377
|
+
`Restart a Coolify application.
|
|
378
|
+
|
|
379
|
+
Equivalent to stopping and then starting the application.
|
|
380
|
+
Useful to apply configuration changes or recover from errors.`,
|
|
381
|
+
{
|
|
382
|
+
uuid: z.string().uuid().describe('Application UUID to restart'),
|
|
383
|
+
},
|
|
384
|
+
async (args) => {
|
|
385
|
+
const initResult = await coolify.init()
|
|
386
|
+
if (isErr(initResult)) {
|
|
387
|
+
return {
|
|
388
|
+
content: [{ type: 'text' as const, text: `Coolify not configured: ${initResult.error.message}` }],
|
|
389
|
+
isError: true,
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
const result = await coolify.restartApplication(args.uuid)
|
|
394
|
+
|
|
395
|
+
if (isOk(result)) {
|
|
396
|
+
return {
|
|
397
|
+
content: [{
|
|
398
|
+
type: 'text' as const,
|
|
399
|
+
text: JSON.stringify({ success: true, message: `Application ${args.uuid} restarted`, application: result.value }, null, 2),
|
|
400
|
+
}],
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return {
|
|
405
|
+
content: [{ type: 'text' as const, text: `Failed to restart application: ${result.error.message}` }],
|
|
406
|
+
isError: true,
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
),
|
|
410
|
+
|
|
411
|
+
// 10. get_deployment_history
|
|
412
|
+
tool(
|
|
413
|
+
'get_deployment_history',
|
|
414
|
+
`Get deployment history for a Coolify application.
|
|
415
|
+
|
|
416
|
+
Returns list of all deployments with status, timestamps, and commit info.`,
|
|
417
|
+
{
|
|
418
|
+
uuid: z.string().uuid().describe('Application UUID'),
|
|
419
|
+
},
|
|
420
|
+
async (args) => {
|
|
421
|
+
const initResult = await coolify.init()
|
|
422
|
+
if (isErr(initResult)) {
|
|
423
|
+
return {
|
|
424
|
+
content: [{ type: 'text' as const, text: `Coolify not configured: ${initResult.error.message}` }],
|
|
425
|
+
isError: true,
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
const result = await coolify.getApplicationDeploymentHistory(args.uuid)
|
|
430
|
+
|
|
431
|
+
if (isOk(result)) {
|
|
432
|
+
return {
|
|
433
|
+
content: [{
|
|
434
|
+
type: 'text' as const,
|
|
435
|
+
text: JSON.stringify({ success: true, count: result.value.length, deployments: result.value }, null, 2),
|
|
436
|
+
}],
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
return {
|
|
441
|
+
content: [{ type: 'text' as const, text: `Failed to get deployment history: ${result.error.message}` }],
|
|
442
|
+
isError: true,
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
),
|
|
446
|
+
|
|
447
|
+
// 11. update_application
|
|
448
|
+
tool(
|
|
449
|
+
'update_application',
|
|
450
|
+
`Update configuration for a Coolify application.
|
|
451
|
+
|
|
452
|
+
Can modify name, description, build settings, and commands.
|
|
453
|
+
Redeploy after updating to apply changes.`,
|
|
454
|
+
{
|
|
455
|
+
uuid: z.string().uuid().describe('Application UUID'),
|
|
456
|
+
name: z.string().optional().describe('New application name'),
|
|
457
|
+
description: z.string().optional().describe('New description'),
|
|
458
|
+
buildPack: z.enum(['dockerfile', 'nixpacks', 'static']).optional().describe('Build pack type'),
|
|
459
|
+
gitBranch: z.string().optional().describe('Git branch to deploy'),
|
|
460
|
+
portsExposes: z.string().optional().describe('Ports to expose (comma-separated)'),
|
|
461
|
+
installCommand: z.string().optional().describe('Install command (nixpacks)'),
|
|
462
|
+
buildCommand: z.string().optional().describe('Build command'),
|
|
463
|
+
startCommand: z.string().optional().describe('Start command'),
|
|
464
|
+
},
|
|
465
|
+
async (args) => {
|
|
466
|
+
const initResult = await coolify.init()
|
|
467
|
+
if (isErr(initResult)) {
|
|
468
|
+
return {
|
|
469
|
+
content: [{ type: 'text' as const, text: `Coolify not configured: ${initResult.error.message}` }],
|
|
470
|
+
isError: true,
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
const result = await coolify.updateApplication(args.uuid, {
|
|
475
|
+
name: args.name,
|
|
476
|
+
description: args.description,
|
|
477
|
+
buildPack: args.buildPack,
|
|
478
|
+
gitBranch: args.gitBranch,
|
|
479
|
+
portsExposes: args.portsExposes,
|
|
480
|
+
installCommand: args.installCommand,
|
|
481
|
+
buildCommand: args.buildCommand,
|
|
482
|
+
startCommand: args.startCommand,
|
|
483
|
+
})
|
|
484
|
+
|
|
485
|
+
if (isOk(result)) {
|
|
486
|
+
return {
|
|
487
|
+
content: [{
|
|
488
|
+
type: 'text' as const,
|
|
489
|
+
text: JSON.stringify({
|
|
490
|
+
success: true,
|
|
491
|
+
message: `Application ${args.uuid} updated. Use deploy tool to apply changes.`,
|
|
492
|
+
application: result.value,
|
|
493
|
+
}, null, 2),
|
|
494
|
+
}],
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
return {
|
|
499
|
+
content: [{ type: 'text' as const, text: `Failed to update application: ${result.error.message}` }],
|
|
500
|
+
isError: true,
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
),
|
|
504
|
+
|
|
505
|
+
// 12. list_servers
|
|
506
|
+
tool(
|
|
507
|
+
'list_servers',
|
|
508
|
+
`List all available servers in Coolify.
|
|
509
|
+
|
|
510
|
+
Returns server UUIDs, names, and IPs. Use server UUID when creating applications.`,
|
|
511
|
+
{},
|
|
512
|
+
async () => {
|
|
513
|
+
const initResult = await coolify.init()
|
|
514
|
+
if (isErr(initResult)) {
|
|
515
|
+
return {
|
|
516
|
+
content: [{ type: 'text' as const, text: `Coolify not configured: ${initResult.error.message}` }],
|
|
517
|
+
isError: true,
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
const result = await coolify.listServers()
|
|
522
|
+
|
|
523
|
+
if (isOk(result)) {
|
|
524
|
+
return {
|
|
525
|
+
content: [{
|
|
526
|
+
type: 'text' as const,
|
|
527
|
+
text: JSON.stringify({ success: true, count: result.value.length, servers: result.value }, null, 2),
|
|
528
|
+
}],
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
return {
|
|
533
|
+
content: [{ type: 'text' as const, text: `Failed to list servers: ${result.error.message}` }],
|
|
534
|
+
isError: true,
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
),
|
|
538
|
+
|
|
539
|
+
// 13. get_server
|
|
540
|
+
tool(
|
|
541
|
+
'get_server',
|
|
542
|
+
`Get details of a specific Coolify server.
|
|
543
|
+
|
|
544
|
+
Returns server information including name, IP, status, and configuration.`,
|
|
545
|
+
{
|
|
546
|
+
serverUuid: z.string().uuid().describe('Server UUID to get details for'),
|
|
547
|
+
},
|
|
548
|
+
async (args) => {
|
|
549
|
+
const initResult = await coolify.init()
|
|
550
|
+
if (isErr(initResult)) {
|
|
551
|
+
return {
|
|
552
|
+
content: [{ type: 'text' as const, text: `Coolify not configured: ${initResult.error.message}` }],
|
|
553
|
+
isError: true,
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
const result = await coolify.getServer(args.serverUuid)
|
|
558
|
+
|
|
559
|
+
if (isOk(result)) {
|
|
560
|
+
return {
|
|
561
|
+
content: [{ type: 'text' as const, text: JSON.stringify({ success: true, server: result.value }, null, 2) }],
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
return {
|
|
566
|
+
content: [{ type: 'text' as const, text: `Failed to get server: ${result.error.message}` }],
|
|
567
|
+
isError: true,
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
),
|
|
571
|
+
|
|
572
|
+
// 14. list_projects
|
|
573
|
+
tool(
|
|
574
|
+
'list_projects',
|
|
575
|
+
`List all projects in Coolify.
|
|
576
|
+
|
|
577
|
+
Returns project UUIDs, names, and associated environments.`,
|
|
578
|
+
{},
|
|
579
|
+
async () => {
|
|
580
|
+
const initResult = await coolify.init()
|
|
581
|
+
if (isErr(initResult)) {
|
|
582
|
+
return {
|
|
583
|
+
content: [{ type: 'text' as const, text: `Coolify not configured: ${initResult.error.message}` }],
|
|
584
|
+
isError: true,
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
const result = await coolify.listProjects()
|
|
589
|
+
|
|
590
|
+
if (isOk(result)) {
|
|
591
|
+
return {
|
|
592
|
+
content: [{
|
|
593
|
+
type: 'text' as const,
|
|
594
|
+
text: JSON.stringify({ success: true, count: result.value.length, projects: result.value }, null, 2),
|
|
595
|
+
}],
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
return {
|
|
600
|
+
content: [{ type: 'text' as const, text: `Failed to list projects: ${result.error.message}` }],
|
|
601
|
+
isError: true,
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
),
|
|
605
|
+
|
|
606
|
+
// 15. list_teams
|
|
607
|
+
tool(
|
|
608
|
+
'list_teams',
|
|
609
|
+
`List all teams in Coolify.
|
|
610
|
+
|
|
611
|
+
Returns team IDs, names, and configuration.`,
|
|
612
|
+
{},
|
|
613
|
+
async () => {
|
|
614
|
+
const initResult = await coolify.init()
|
|
615
|
+
if (isErr(initResult)) {
|
|
616
|
+
return {
|
|
617
|
+
content: [{ type: 'text' as const, text: `Coolify not configured: ${initResult.error.message}` }],
|
|
618
|
+
isError: true,
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
const result = await coolify.listTeams()
|
|
623
|
+
|
|
624
|
+
if (isOk(result)) {
|
|
625
|
+
return {
|
|
626
|
+
content: [{
|
|
627
|
+
type: 'text' as const,
|
|
628
|
+
text: JSON.stringify({ success: true, count: result.value.length, teams: result.value }, null, 2),
|
|
629
|
+
}],
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
return {
|
|
634
|
+
content: [{ type: 'text' as const, text: `Failed to list teams: ${result.error.message}` }],
|
|
635
|
+
isError: true,
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
),
|
|
639
|
+
|
|
640
|
+
// 16. get_server_destinations
|
|
641
|
+
tool(
|
|
642
|
+
'get_server_destinations',
|
|
643
|
+
`Get available destinations for a Coolify server.
|
|
644
|
+
|
|
645
|
+
Returns destination UUIDs needed when creating applications.
|
|
646
|
+
Each destination represents a Docker network/environment on the server.`,
|
|
647
|
+
{
|
|
648
|
+
serverUuid: z.string().uuid().describe('Server UUID to get destinations for'),
|
|
649
|
+
},
|
|
650
|
+
async (args) => {
|
|
651
|
+
const initResult = await coolify.init()
|
|
652
|
+
if (isErr(initResult)) {
|
|
653
|
+
return {
|
|
654
|
+
content: [{ type: 'text' as const, text: `Coolify not configured: ${initResult.error.message}` }],
|
|
655
|
+
isError: true,
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
const result = await coolify.getServerDestinations(args.serverUuid)
|
|
660
|
+
|
|
661
|
+
if (isOk(result)) {
|
|
662
|
+
return {
|
|
663
|
+
content: [{
|
|
664
|
+
type: 'text' as const,
|
|
665
|
+
text: JSON.stringify({
|
|
666
|
+
success: true,
|
|
667
|
+
serverUuid: args.serverUuid,
|
|
668
|
+
count: result.value.length,
|
|
669
|
+
destinations: result.value,
|
|
670
|
+
}, null, 2),
|
|
671
|
+
}],
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
return {
|
|
676
|
+
content: [{ type: 'text' as const, text: `Failed to get destinations: ${result.error.message}` }],
|
|
677
|
+
isError: true,
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
),
|
|
681
|
+
|
|
682
|
+
// 17. create_application
|
|
683
|
+
tool(
|
|
684
|
+
'create_application',
|
|
685
|
+
`Create a new application in Coolify from a GitHub repository.
|
|
686
|
+
|
|
687
|
+
Requires server UUID and destination UUID (get them from list_servers and get_server_destinations).
|
|
688
|
+
The GitHub repository must be accessible via the configured GitHub App.`,
|
|
689
|
+
{
|
|
690
|
+
name: z.string().describe('Application name'),
|
|
691
|
+
serverUuid: z.string().uuid().describe('Server UUID to deploy to'),
|
|
692
|
+
destinationUuid: z.string().uuid().describe('Destination UUID (Docker network)'),
|
|
693
|
+
githubRepoUrl: z.string().describe('GitHub repository URL (e.g., https://github.com/user/repo)'),
|
|
694
|
+
description: z.string().optional().describe('Application description'),
|
|
695
|
+
branch: z.string().default('main').describe('Git branch to deploy'),
|
|
696
|
+
buildPack: z.enum(['dockerfile', 'nixpacks', 'static']).default('nixpacks').describe('Build pack type'),
|
|
697
|
+
},
|
|
698
|
+
async (args) => {
|
|
699
|
+
const initResult = await coolify.init()
|
|
700
|
+
if (isErr(initResult)) {
|
|
701
|
+
return {
|
|
702
|
+
content: [{ type: 'text' as const, text: `Coolify not configured: ${initResult.error.message}` }],
|
|
703
|
+
isError: true,
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
const result = await coolify.createApplication({
|
|
708
|
+
name: args.name,
|
|
709
|
+
description: args.description,
|
|
710
|
+
serverUuid: args.serverUuid,
|
|
711
|
+
destinationUuid: args.destinationUuid,
|
|
712
|
+
githubRepoUrl: args.githubRepoUrl,
|
|
713
|
+
branch: args.branch,
|
|
714
|
+
buildPack: args.buildPack,
|
|
715
|
+
})
|
|
716
|
+
|
|
717
|
+
if (isOk(result)) {
|
|
718
|
+
return {
|
|
719
|
+
content: [{
|
|
720
|
+
type: 'text' as const,
|
|
721
|
+
text: JSON.stringify({
|
|
722
|
+
success: true,
|
|
723
|
+
message: `Application "${args.name}" created successfully`,
|
|
724
|
+
uuid: result.value.uuid,
|
|
725
|
+
nextSteps: [
|
|
726
|
+
'Use set_env_vars to configure environment variables',
|
|
727
|
+
'Use deploy to start the first deployment',
|
|
728
|
+
],
|
|
729
|
+
}, null, 2),
|
|
730
|
+
}],
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
return {
|
|
735
|
+
content: [{ type: 'text' as const, text: `Failed to create application: ${result.error.message}` }],
|
|
736
|
+
isError: true,
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
),
|
|
740
|
+
|
|
741
|
+
// 18. get_resource_usage (placeholder - using status)
|
|
742
|
+
tool(
|
|
743
|
+
'get_resource_usage',
|
|
744
|
+
`Get resource usage for a Coolify application.
|
|
745
|
+
|
|
746
|
+
Returns current resource consumption metrics.`,
|
|
747
|
+
{
|
|
748
|
+
uuid: z.string().uuid().describe('Application UUID'),
|
|
749
|
+
},
|
|
750
|
+
async (args) => {
|
|
751
|
+
const initResult = await coolify.init()
|
|
752
|
+
if (isErr(initResult)) {
|
|
753
|
+
return {
|
|
754
|
+
content: [{ type: 'text' as const, text: `Coolify not configured: ${initResult.error.message}` }],
|
|
755
|
+
isError: true,
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
// For now, use getApplicationStatus - Coolify API doesn't have a separate resource usage endpoint
|
|
760
|
+
const result = await coolify.getApplicationStatus(args.uuid)
|
|
761
|
+
|
|
762
|
+
if (isOk(result)) {
|
|
763
|
+
return {
|
|
764
|
+
content: [{
|
|
765
|
+
type: 'text' as const,
|
|
766
|
+
text: JSON.stringify({ success: true, status: result.value }, null, 2),
|
|
767
|
+
}],
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
return {
|
|
772
|
+
content: [{ type: 'text' as const, text: `Failed to get resource usage: ${result.error.message}` }],
|
|
773
|
+
isError: true,
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
),
|
|
777
|
+
|
|
778
|
+
// 19. health_check
|
|
779
|
+
tool(
|
|
780
|
+
'health_check',
|
|
781
|
+
`Check if Coolify API is accessible and credentials are valid.
|
|
782
|
+
|
|
783
|
+
Returns connection status and API version info if available.`,
|
|
784
|
+
{},
|
|
785
|
+
async () => {
|
|
786
|
+
const initResult = await coolify.init()
|
|
787
|
+
if (isErr(initResult)) {
|
|
788
|
+
return {
|
|
789
|
+
content: [{ type: 'text' as const, text: `Coolify health check failed: ${initResult.error.message}` }],
|
|
790
|
+
isError: true,
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
// Try to list servers as a health check
|
|
795
|
+
const result = await coolify.listServers()
|
|
796
|
+
|
|
797
|
+
if (isOk(result)) {
|
|
798
|
+
return {
|
|
799
|
+
content: [{
|
|
800
|
+
type: 'text' as const,
|
|
801
|
+
text: JSON.stringify({ success: true, status: 'healthy', message: 'Coolify API is accessible' }, null, 2),
|
|
802
|
+
}],
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
return {
|
|
807
|
+
content: [{ type: 'text' as const, text: `Health check failed: ${result.error.message}` }],
|
|
808
|
+
isError: true,
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
),
|
|
812
|
+
|
|
813
|
+
// 20. get_application_details (enhanced get_deployment_status)
|
|
814
|
+
tool(
|
|
815
|
+
'get_application_details',
|
|
816
|
+
`Get detailed information about a Coolify application.
|
|
817
|
+
|
|
818
|
+
Returns full application configuration including name, description,
|
|
819
|
+
build settings, environment, and deployment status.`,
|
|
820
|
+
{
|
|
821
|
+
uuid: z.string().uuid().describe('Application UUID'),
|
|
822
|
+
},
|
|
823
|
+
async (args) => {
|
|
824
|
+
const initResult = await coolify.init()
|
|
825
|
+
if (isErr(initResult)) {
|
|
826
|
+
return {
|
|
827
|
+
content: [{ type: 'text' as const, text: `Coolify not configured: ${initResult.error.message}` }],
|
|
828
|
+
isError: true,
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
// List all applications and filter by UUID to get full details
|
|
833
|
+
const result = await coolify.listApplications()
|
|
834
|
+
|
|
835
|
+
if (isOk(result)) {
|
|
836
|
+
const app = result.value.find((a) => a.uuid === args.uuid)
|
|
837
|
+
if (app) {
|
|
838
|
+
return {
|
|
839
|
+
content: [{ type: 'text' as const, text: JSON.stringify({ success: true, application: app }, null, 2) }],
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
return {
|
|
843
|
+
content: [{ type: 'text' as const, text: `Application ${args.uuid} not found` }],
|
|
844
|
+
isError: true,
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
return {
|
|
849
|
+
content: [{ type: 'text' as const, text: `Failed to get application details: ${result.error.message}` }],
|
|
850
|
+
isError: true,
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
),
|
|
854
|
+
],
|
|
855
|
+
})
|
|
856
|
+
|
|
857
|
+
// Auto-start server when running as main process (not when imported)
|
|
858
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
859
|
+
coolifyServer
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
// Re-export CoolifyService for library usage
|
|
863
|
+
export { getCoolifyService } from './coolify/index.js'
|
|
864
|
+
export type * from './coolify/index.js'
|