@mks2508/coolify-mks-cli-mcp 0.5.0 → 0.6.1
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/coolify-state.d.ts +51 -0
- package/dist/cli/coolify-state.d.ts.map +1 -0
- package/dist/cli/index.js +2862 -631
- package/dist/coolify/config.d.ts +1 -1
- package/dist/coolify/config.d.ts.map +1 -1
- package/dist/coolify/index.d.ts +626 -12
- package/dist/coolify/index.d.ts.map +1 -1
- package/dist/coolify/types.d.ts +87 -3
- package/dist/coolify/types.d.ts.map +1 -1
- package/dist/dist-C4hIkHif.js +66 -0
- package/dist/dist-C4hIkHif.js.map +1 -0
- package/dist/dist-DEPvJhbP.js +3 -0
- package/dist/index.cjs +8511 -28542
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +32 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8470 -28506
- package/dist/index.js.map +1 -1
- package/dist/network.d.ts +75 -0
- package/dist/network.d.ts.map +1 -0
- package/dist/sdk.d.ts +356 -0
- package/dist/sdk.d.ts.map +1 -0
- package/dist/server/index.d.ts +9 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/sse.js +3 -1
- package/dist/server/stdio.d.ts +0 -2
- package/dist/server/stdio.d.ts.map +1 -1
- package/dist/server/stdio.js +3307 -1618
- package/dist/tools/definitions.d.ts +1 -1
- package/dist/tools/definitions.d.ts.map +1 -1
- package/dist/tools/handlers.d.ts +6 -7
- package/dist/tools/handlers.d.ts.map +1 -1
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/trace.d.ts +71 -0
- package/dist/trace.d.ts.map +1 -0
- package/dist/utils/format.d.ts +1 -1
- package/dist/utils/format.d.ts.map +1 -1
- package/package.json +15 -9
- package/src/cli/actions.ts +162 -0
- package/src/cli/commands/active-deployments.ts +24 -0
- package/src/cli/commands/build-logs.ts +25 -22
- package/src/cli/commands/cancel-deploy.ts +35 -0
- package/src/cli/commands/config.ts +53 -47
- package/src/cli/commands/create.ts +74 -53
- package/src/cli/commands/databases.ts +63 -0
- package/src/cli/commands/db.ts +68 -0
- package/src/cli/commands/delete.ts +41 -29
- package/src/cli/commands/deploy.ts +42 -21
- package/src/cli/commands/deployments.ts +41 -31
- package/src/cli/commands/destinations.ts +19 -27
- package/src/cli/commands/diagnose.ts +139 -0
- package/src/cli/commands/env.ts +66 -41
- package/src/cli/commands/environments.ts +36 -32
- package/src/cli/commands/exec.ts +39 -0
- package/src/cli/commands/keys.ts +46 -0
- package/src/cli/commands/list.ts +29 -27
- package/src/cli/commands/logs.ts +33 -18
- package/src/cli/commands/network.ts +145 -0
- package/src/cli/commands/projects.ts +51 -39
- package/src/cli/commands/restart.ts +34 -18
- package/src/cli/commands/server-resources.ts +71 -0
- package/src/cli/commands/servers.ts +23 -23
- package/src/cli/commands/service-logs.ts +24 -16
- package/src/cli/commands/services.ts +63 -0
- package/src/cli/commands/show.ts +72 -41
- package/src/cli/commands/start.ts +34 -18
- package/src/cli/commands/stop.ts +34 -18
- package/src/cli/commands/svc.ts +68 -0
- package/src/cli/commands/teams.ts +60 -0
- package/src/cli/commands/update.ts +73 -49
- package/src/cli/commands/version.ts +37 -0
- package/src/cli/coolify-state.ts +88 -0
- package/src/cli/index.ts +383 -151
- package/src/coolify/config.ts +29 -27
- package/src/coolify/index.ts +1829 -123
- package/src/coolify/types.ts +217 -124
- package/src/index.ts +82 -868
- package/src/network.ts +298 -0
- package/src/sdk.ts +597 -0
- package/src/server/index.ts +13 -0
- package/src/server/sse.ts +33 -25
- package/src/server/stdio.ts +24 -27
- package/src/tools/definitions.ts +893 -264
- package/src/tools/handlers.ts +556 -748
- package/src/tools/index.ts +8 -0
- package/src/trace.ts +116 -0
- package/src/utils/format.ts +36 -33
package/src/tools/handlers.ts
CHANGED
|
@@ -1,771 +1,579 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MCP Tool handlers for Coolify.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* All handlers route through the Coolify SDK facade.
|
|
5
|
+
* Uses a generic mcpCall wrapper to eliminate boilerplate.
|
|
5
6
|
*
|
|
6
7
|
* @module
|
|
7
8
|
*/
|
|
8
9
|
|
|
9
|
-
import type { CallToolResult } from
|
|
10
|
-
import {
|
|
11
|
-
|
|
10
|
+
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
11
|
+
import { Coolify } from "../sdk.js";
|
|
12
|
+
|
|
13
|
+
/** Singleton SDK for MCP usage (reads env vars / config file). */
|
|
14
|
+
let _sdk: Coolify | null = null;
|
|
15
|
+
function getSdk(): Coolify {
|
|
16
|
+
if (!_sdk) _sdk = Coolify.fromEnv();
|
|
17
|
+
return _sdk;
|
|
18
|
+
}
|
|
12
19
|
|
|
13
20
|
/**
|
|
14
|
-
*
|
|
21
|
+
* Wraps an SDK call into an MCP tool result.
|
|
22
|
+
* On success → JSON response. On error → isError response.
|
|
23
|
+
*
|
|
24
|
+
* @param fn - Async function that calls the SDK (throws on error)
|
|
25
|
+
* @param label - Error context label
|
|
26
|
+
* @returns MCP CallToolResult
|
|
27
|
+
*/
|
|
28
|
+
async function mcpCall(
|
|
29
|
+
fn: (sdk: Coolify) => Promise<unknown>,
|
|
30
|
+
label: string,
|
|
31
|
+
): Promise<CallToolResult> {
|
|
32
|
+
try {
|
|
33
|
+
const data = await fn(getSdk());
|
|
34
|
+
return {
|
|
35
|
+
content: [
|
|
36
|
+
{
|
|
37
|
+
type: "text",
|
|
38
|
+
text: JSON.stringify(
|
|
39
|
+
typeof data === "object" && data !== null
|
|
40
|
+
? { success: true, ...data }
|
|
41
|
+
: { success: true, result: data },
|
|
42
|
+
null,
|
|
43
|
+
2,
|
|
44
|
+
),
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
};
|
|
48
|
+
} catch (error) {
|
|
49
|
+
return {
|
|
50
|
+
content: [
|
|
51
|
+
{
|
|
52
|
+
type: "text",
|
|
53
|
+
text: `${label}: ${error instanceof Error ? error.message : String(error)}`,
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
isError: true,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Wraps SDK call returning an array into { count, items } format. */
|
|
62
|
+
async function mcpList(
|
|
63
|
+
fn: (sdk: Coolify) => Promise<unknown[]>,
|
|
64
|
+
itemKey: string,
|
|
65
|
+
label: string,
|
|
66
|
+
): Promise<CallToolResult> {
|
|
67
|
+
return mcpCall(async (sdk) => {
|
|
68
|
+
const items = await fn(sdk);
|
|
69
|
+
return { count: items.length, [itemKey]: items };
|
|
70
|
+
}, label);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Main handler — routes tool calls to SDK methods.
|
|
15
75
|
*
|
|
16
76
|
* @param name - Tool name
|
|
17
77
|
* @param args - Tool arguments
|
|
18
|
-
* @
|
|
19
|
-
* @returns Tool call result
|
|
78
|
+
* @returns MCP tool result
|
|
20
79
|
*/
|
|
21
80
|
export async function handleToolCall(
|
|
22
81
|
name: string,
|
|
23
82
|
args: Record<string, unknown>,
|
|
24
|
-
coolify: CoolifyService
|
|
25
83
|
): Promise<CallToolResult> {
|
|
26
|
-
const
|
|
27
|
-
if (isErr(initResult)) {
|
|
28
|
-
return {
|
|
29
|
-
content: [{ type: 'text', text: `Coolify not configured: ${initResult.error.message}` }],
|
|
30
|
-
isError: true
|
|
31
|
-
}
|
|
32
|
-
}
|
|
84
|
+
const a = args as any;
|
|
33
85
|
|
|
34
86
|
switch (name) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
87
|
+
// ─── Applications ──────────────────────────────────────────────────
|
|
88
|
+
case "deploy":
|
|
89
|
+
return mcpCall(
|
|
90
|
+
(s) =>
|
|
91
|
+
s.applications
|
|
92
|
+
.deploy(a.uuid, { force: a.force, tag: a.tag })
|
|
93
|
+
.then((r) => ({
|
|
94
|
+
deploymentUuid: r.deploymentUuid,
|
|
95
|
+
resourceUuid: r.resourceUuid,
|
|
96
|
+
message: "Deployment started",
|
|
97
|
+
})),
|
|
98
|
+
"Deployment failed",
|
|
99
|
+
);
|
|
100
|
+
case "list_applications":
|
|
101
|
+
return mcpList(
|
|
102
|
+
(s) => s.applications.list(),
|
|
103
|
+
"applications",
|
|
104
|
+
"Failed to list applications",
|
|
105
|
+
);
|
|
106
|
+
case "get_application_details":
|
|
107
|
+
return mcpCall(
|
|
108
|
+
(s) =>
|
|
109
|
+
s.applications.resolve(a.uuid).then((app) => ({ application: app })),
|
|
110
|
+
"Failed to get application",
|
|
111
|
+
);
|
|
112
|
+
case "start_application":
|
|
113
|
+
return mcpCall(
|
|
114
|
+
(s) =>
|
|
115
|
+
s.applications
|
|
116
|
+
.start(a.uuid, { force: a.force, instantDeploy: a.instantDeploy })
|
|
117
|
+
.then(() => ({
|
|
118
|
+
message: `Application ${a.uuid} started`,
|
|
119
|
+
})),
|
|
120
|
+
"Failed to start application",
|
|
121
|
+
);
|
|
122
|
+
case "stop_application":
|
|
123
|
+
return mcpCall(
|
|
124
|
+
(s) =>
|
|
125
|
+
s.applications.stop(a.uuid).then(() => ({
|
|
126
|
+
message: `Application ${a.uuid} stopped`,
|
|
127
|
+
})),
|
|
128
|
+
"Failed to stop application",
|
|
129
|
+
);
|
|
130
|
+
case "restart_application":
|
|
131
|
+
return mcpCall(
|
|
132
|
+
(s) =>
|
|
133
|
+
s.applications.restart(a.uuid).then(() => ({
|
|
134
|
+
message: `Application ${a.uuid} restarted`,
|
|
135
|
+
})),
|
|
136
|
+
"Failed to restart application",
|
|
137
|
+
);
|
|
138
|
+
case "delete_application":
|
|
139
|
+
return mcpCall(
|
|
140
|
+
(s) =>
|
|
141
|
+
s.applications.delete(a.uuid).then(() => ({
|
|
142
|
+
message: `Application ${a.uuid} deleted`,
|
|
143
|
+
})),
|
|
144
|
+
"Failed to delete application",
|
|
145
|
+
);
|
|
146
|
+
case "update_application":
|
|
147
|
+
return mcpCall(
|
|
148
|
+
(s) =>
|
|
149
|
+
s.applications
|
|
150
|
+
.update(a.uuid, {
|
|
151
|
+
name: a.name,
|
|
152
|
+
description: a.description,
|
|
153
|
+
buildPack: a.buildPack,
|
|
154
|
+
gitBranch: a.gitBranch,
|
|
155
|
+
portsExposes: a.portsExposes,
|
|
156
|
+
installCommand: a.installCommand,
|
|
157
|
+
buildCommand: a.buildCommand,
|
|
158
|
+
startCommand: a.startCommand,
|
|
159
|
+
domains: a.domains,
|
|
160
|
+
isForceHttpsEnabled: a.isForceHttpsEnabled,
|
|
161
|
+
isAutoDeployEnabled: a.isAutoDeployEnabled,
|
|
162
|
+
})
|
|
163
|
+
.then((app) => ({
|
|
164
|
+
message: `Application ${a.uuid} updated`,
|
|
165
|
+
application: app,
|
|
166
|
+
})),
|
|
167
|
+
"Failed to update application",
|
|
168
|
+
);
|
|
169
|
+
case "get_application_logs":
|
|
170
|
+
return mcpCall(
|
|
171
|
+
(s) =>
|
|
172
|
+
s.applications
|
|
173
|
+
.logs(a.uuid, { tail: a.tail, serviceName: a.serviceName })
|
|
174
|
+
.then((logs) => ({
|
|
175
|
+
timestamp: logs.timestamp,
|
|
176
|
+
logCount: logs.logs.length,
|
|
177
|
+
logs: logs.logs,
|
|
178
|
+
})),
|
|
179
|
+
"Failed to get logs",
|
|
180
|
+
);
|
|
181
|
+
case "get_deployment_history":
|
|
182
|
+
return mcpList(
|
|
183
|
+
(s) => s.applications.deployments(a.uuid),
|
|
184
|
+
"deployments",
|
|
185
|
+
"Failed to get deployment history",
|
|
186
|
+
);
|
|
187
|
+
case "get_application_deployments":
|
|
188
|
+
return mcpList(
|
|
189
|
+
(s) => s.applications.deployments(a.uuid),
|
|
190
|
+
"deployments",
|
|
191
|
+
"Failed to get deployments",
|
|
192
|
+
);
|
|
193
|
+
case "execute_command":
|
|
194
|
+
return mcpCall(
|
|
195
|
+
(s) => s.applications.exec(a.uuid, a.command),
|
|
196
|
+
"Failed to execute command",
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
// ─── Environment Variables ─────────────────────────────────────────
|
|
200
|
+
case "get_env_vars":
|
|
201
|
+
return mcpCall(
|
|
202
|
+
(s) =>
|
|
203
|
+
s.applications.envVars(a.uuid).then((vars) => ({
|
|
204
|
+
total: vars.length,
|
|
205
|
+
runtime: vars.filter((v) => v.is_runtime),
|
|
206
|
+
buildtime: vars.filter((v) => v.is_buildtime),
|
|
207
|
+
})),
|
|
208
|
+
"Failed to get env vars",
|
|
209
|
+
);
|
|
210
|
+
case "set_env_vars":
|
|
211
|
+
return mcpCall((s) => {
|
|
212
|
+
const entries = Object.entries(a.envVars as Record<string, string>);
|
|
213
|
+
return s.applications
|
|
214
|
+
.bulkSetEnv(
|
|
215
|
+
a.uuid,
|
|
216
|
+
entries.map(([key, value]) => ({ key, value })),
|
|
217
|
+
)
|
|
218
|
+
.then(() => ({
|
|
219
|
+
message: `Set ${entries.length} environment variable(s)`,
|
|
220
|
+
}));
|
|
221
|
+
}, "Failed to set env vars");
|
|
222
|
+
case "bulk_update_env_vars":
|
|
223
|
+
return mcpCall(
|
|
224
|
+
(s) =>
|
|
225
|
+
s.applications.bulkSetEnv(a.uuid, a.envVars).then(() => ({
|
|
226
|
+
message: `Bulk updated ${a.envVars.length} variable(s)`,
|
|
227
|
+
})),
|
|
228
|
+
"Failed to bulk update env vars",
|
|
229
|
+
);
|
|
230
|
+
|
|
231
|
+
// ─── Domains ───────────────────────────────────────────────────────
|
|
232
|
+
case "set_domains":
|
|
233
|
+
return mcpCall(
|
|
234
|
+
(s) =>
|
|
235
|
+
s.applications
|
|
236
|
+
.update(a.uuid, {
|
|
237
|
+
domains: a.domains,
|
|
238
|
+
isForceHttpsEnabled: a.forceHttps ?? true,
|
|
239
|
+
})
|
|
240
|
+
.then(() => ({
|
|
241
|
+
message: `Domains set for ${a.uuid}`,
|
|
242
|
+
domains: a.domains.split(",").map((d: string) => d.trim()),
|
|
243
|
+
})),
|
|
244
|
+
"Failed to set domains",
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
// ─── Deployment Status ─────────────────────────────────────────────
|
|
248
|
+
case "get_deployment_status":
|
|
249
|
+
return mcpCall(
|
|
250
|
+
(s) =>
|
|
251
|
+
s.applications
|
|
252
|
+
.resolve(a.uuid)
|
|
253
|
+
.then((app) => ({ status: app.status })),
|
|
254
|
+
"Failed to get status",
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
// ─── Deployments ───────────────────────────────────────────────────
|
|
258
|
+
case "list_deployments":
|
|
259
|
+
return mcpList(
|
|
260
|
+
(s) => s.deployments.active(),
|
|
261
|
+
"deployments",
|
|
262
|
+
"Failed to list deployments",
|
|
263
|
+
);
|
|
264
|
+
case "get_deployment":
|
|
265
|
+
return mcpCall(
|
|
266
|
+
(s) =>
|
|
267
|
+
s.deployments.get(a.deploymentUuid).then((d) => ({ deployment: d })),
|
|
268
|
+
"Failed to get deployment",
|
|
269
|
+
);
|
|
270
|
+
case "cancel_deployment":
|
|
271
|
+
return mcpCall(
|
|
272
|
+
(s) =>
|
|
273
|
+
s.deployments
|
|
274
|
+
.cancel(a.deploymentUuid)
|
|
275
|
+
.then(() => ({ message: "Deployment cancelled" })),
|
|
276
|
+
"Failed to cancel deployment",
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
// ─── Servers ───────────────────────────────────────────────────────
|
|
280
|
+
case "list_servers":
|
|
281
|
+
return mcpList(
|
|
282
|
+
(s) => s.servers.list(),
|
|
283
|
+
"servers",
|
|
284
|
+
"Failed to list servers",
|
|
285
|
+
);
|
|
286
|
+
case "get_server":
|
|
287
|
+
return mcpCall(
|
|
288
|
+
(s) => s.servers.get(a.serverUuid).then((srv) => ({ server: srv })),
|
|
289
|
+
"Failed to get server",
|
|
290
|
+
);
|
|
291
|
+
case "get_server_destinations":
|
|
292
|
+
return mcpList(
|
|
293
|
+
(s) => s.servers.destinations(a.serverUuid),
|
|
294
|
+
"destinations",
|
|
295
|
+
"Failed to get destinations",
|
|
296
|
+
);
|
|
297
|
+
case "get_server_resources":
|
|
298
|
+
return mcpList(
|
|
299
|
+
(s) => s.servers.resources(a.serverUuid),
|
|
300
|
+
"resources",
|
|
301
|
+
"Failed to get server resources",
|
|
302
|
+
);
|
|
303
|
+
case "get_server_domains":
|
|
304
|
+
return mcpList(
|
|
305
|
+
(s) => s.servers.domains(a.serverUuid),
|
|
306
|
+
"domains",
|
|
307
|
+
"Failed to get server domains",
|
|
308
|
+
);
|
|
309
|
+
case "validate_server":
|
|
310
|
+
return mcpCall(
|
|
311
|
+
(s) =>
|
|
312
|
+
s.servers
|
|
313
|
+
.validate(a.serverUuid)
|
|
314
|
+
.then(() => ({ message: "Server validated" })),
|
|
315
|
+
"Failed to validate server",
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
// ─── Projects ──────────────────────────────────────────────────────
|
|
319
|
+
case "list_projects":
|
|
320
|
+
return mcpList(
|
|
321
|
+
(s) => s.projects.list(),
|
|
322
|
+
"projects",
|
|
323
|
+
"Failed to list projects",
|
|
324
|
+
);
|
|
325
|
+
case "create_project":
|
|
326
|
+
return mcpCall(
|
|
327
|
+
(s) =>
|
|
328
|
+
s.projects.create(a.name, a.description).then((p) => ({
|
|
329
|
+
message: `Project "${a.name}" created`,
|
|
330
|
+
uuid: p.uuid,
|
|
331
|
+
})),
|
|
332
|
+
"Failed to create project",
|
|
333
|
+
);
|
|
334
|
+
case "create_application":
|
|
335
|
+
return mcpCall(
|
|
336
|
+
(s) =>
|
|
337
|
+
s.applications
|
|
338
|
+
.create({
|
|
339
|
+
name: a.name,
|
|
340
|
+
description: a.description,
|
|
341
|
+
projectUuid: a.projectUuid,
|
|
342
|
+
environmentUuid: a.environmentUuid,
|
|
343
|
+
serverUuid: a.serverUuid,
|
|
344
|
+
type: a.type || "public",
|
|
345
|
+
githubAppUuid: a.githubAppUuid,
|
|
346
|
+
githubRepoUrl: a.githubRepoUrl,
|
|
347
|
+
branch: a.branch,
|
|
348
|
+
buildPack: a.buildPack,
|
|
349
|
+
portsExposes: a.portsExposes,
|
|
350
|
+
dockerComposeLocation: a.dockerComposeLocation,
|
|
351
|
+
dockerfileLocation: a.dockerfileLocation,
|
|
352
|
+
baseDirectory: a.baseDirectory,
|
|
353
|
+
})
|
|
354
|
+
.then((r) => ({
|
|
355
|
+
message: `Application "${a.name}" created`,
|
|
356
|
+
uuid: r.uuid,
|
|
357
|
+
})),
|
|
358
|
+
"Failed to create application",
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
// ─── Teams ─────────────────────────────────────────────────────────
|
|
362
|
+
case "list_teams":
|
|
363
|
+
return mcpList((s) => s.teams.list(), "teams", "Failed to list teams");
|
|
364
|
+
case "get_current_team":
|
|
365
|
+
return mcpCall(
|
|
366
|
+
(s) => s.teams.current().then((t) => ({ team: t })),
|
|
367
|
+
"Failed to get current team",
|
|
368
|
+
);
|
|
369
|
+
case "get_team_members":
|
|
370
|
+
return mcpList(
|
|
371
|
+
(s) => s.teams.members(a.teamId),
|
|
372
|
+
"members",
|
|
373
|
+
"Failed to get team members",
|
|
374
|
+
);
|
|
375
|
+
|
|
376
|
+
// ─── Databases ─────────────────────────────────────────────────────
|
|
377
|
+
case "list_databases":
|
|
378
|
+
return mcpList(
|
|
379
|
+
(s) => s.databases.list(),
|
|
380
|
+
"databases",
|
|
381
|
+
"Failed to list databases",
|
|
382
|
+
);
|
|
383
|
+
case "get_database":
|
|
384
|
+
return mcpCall(
|
|
385
|
+
(s) => s.databases.get(a.uuid).then((db) => ({ database: db })),
|
|
386
|
+
"Failed to get database",
|
|
387
|
+
);
|
|
388
|
+
case "create_database":
|
|
389
|
+
return mcpCall(
|
|
390
|
+
(s) =>
|
|
391
|
+
s.databases.create(a.dbType, a.data).then((r) => ({
|
|
392
|
+
message: `${a.dbType} database created`,
|
|
393
|
+
uuid: r.uuid,
|
|
394
|
+
})),
|
|
395
|
+
"Failed to create database",
|
|
396
|
+
);
|
|
397
|
+
case "delete_database":
|
|
398
|
+
return mcpCall(
|
|
399
|
+
(s) =>
|
|
400
|
+
s.databases
|
|
401
|
+
.delete(a.uuid)
|
|
402
|
+
.then(() => ({ message: "Database deleted" })),
|
|
403
|
+
"Failed to delete database",
|
|
404
|
+
);
|
|
405
|
+
case "start_database":
|
|
406
|
+
return mcpCall(
|
|
407
|
+
(s) =>
|
|
408
|
+
s.databases
|
|
409
|
+
.start(a.uuid)
|
|
410
|
+
.then(() => ({ message: "Database started" })),
|
|
411
|
+
"Failed to start database",
|
|
412
|
+
);
|
|
413
|
+
case "stop_database":
|
|
414
|
+
return mcpCall(
|
|
415
|
+
(s) =>
|
|
416
|
+
s.databases
|
|
417
|
+
.stop(a.uuid)
|
|
418
|
+
.then(() => ({ message: "Database stopped" })),
|
|
419
|
+
"Failed to stop database",
|
|
420
|
+
);
|
|
421
|
+
case "restart_database":
|
|
422
|
+
return mcpCall(
|
|
423
|
+
(s) =>
|
|
424
|
+
s.databases
|
|
425
|
+
.restart(a.uuid)
|
|
426
|
+
.then(() => ({ message: "Database restarted" })),
|
|
427
|
+
"Failed to restart database",
|
|
428
|
+
);
|
|
429
|
+
|
|
430
|
+
// ─── Services ──────────────────────────────────────────────────────
|
|
431
|
+
case "list_services":
|
|
432
|
+
return mcpList(
|
|
433
|
+
(s) => s.services.list(),
|
|
434
|
+
"services",
|
|
435
|
+
"Failed to list services",
|
|
436
|
+
);
|
|
437
|
+
case "get_service":
|
|
438
|
+
return mcpCall(
|
|
439
|
+
(s) => s.services.get(a.uuid).then((svc) => ({ service: svc })),
|
|
440
|
+
"Failed to get service",
|
|
441
|
+
);
|
|
442
|
+
case "start_service":
|
|
443
|
+
return mcpCall(
|
|
444
|
+
(s) =>
|
|
445
|
+
s.services.start(a.uuid).then(() => ({ message: "Service started" })),
|
|
446
|
+
"Failed to start service",
|
|
447
|
+
);
|
|
448
|
+
case "stop_service":
|
|
449
|
+
return mcpCall(
|
|
450
|
+
(s) =>
|
|
451
|
+
s.services.stop(a.uuid).then(() => ({ message: "Service stopped" })),
|
|
452
|
+
"Failed to stop service",
|
|
453
|
+
);
|
|
454
|
+
case "restart_service":
|
|
455
|
+
return mcpCall(
|
|
456
|
+
(s) =>
|
|
457
|
+
s.services
|
|
458
|
+
.restart(a.uuid)
|
|
459
|
+
.then(() => ({ message: "Service restarted" })),
|
|
460
|
+
"Failed to restart service",
|
|
461
|
+
);
|
|
462
|
+
case "delete_service":
|
|
463
|
+
return mcpCall(
|
|
464
|
+
(s) =>
|
|
465
|
+
s.services
|
|
466
|
+
.delete(a.uuid)
|
|
467
|
+
.then(() => ({ message: "Service deleted" })),
|
|
468
|
+
"Failed to delete service",
|
|
469
|
+
);
|
|
470
|
+
|
|
471
|
+
// ─── Private Keys ──────────────────────────────────────────────────
|
|
472
|
+
case "list_private_keys":
|
|
473
|
+
return mcpList(
|
|
474
|
+
(s) => s.keys.list(),
|
|
475
|
+
"keys",
|
|
476
|
+
"Failed to list private keys",
|
|
477
|
+
);
|
|
478
|
+
case "get_private_key":
|
|
479
|
+
return mcpCall(
|
|
480
|
+
(s) => s.keys.get(a.uuid).then((k) => ({ privateKey: k })),
|
|
481
|
+
"Failed to get private key",
|
|
482
|
+
);
|
|
483
|
+
|
|
484
|
+
// ─── Smart Resolution ──────────────────────────────────────────────
|
|
485
|
+
case "resolve_application":
|
|
486
|
+
return mcpCall(
|
|
487
|
+
(s) =>
|
|
488
|
+
s.applications.resolve(a.query).then((app) => ({
|
|
489
|
+
application: {
|
|
490
|
+
uuid: app.uuid,
|
|
491
|
+
name: app.name,
|
|
492
|
+
status: app.status,
|
|
493
|
+
fqdn: app.fqdn,
|
|
494
|
+
},
|
|
495
|
+
})),
|
|
496
|
+
"Failed to resolve application",
|
|
497
|
+
);
|
|
498
|
+
case "resolve_server":
|
|
499
|
+
return mcpCall(
|
|
500
|
+
(s) =>
|
|
501
|
+
s.servers.resolve(a.query).then((srv) => ({
|
|
502
|
+
server: {
|
|
503
|
+
uuid: srv.uuid,
|
|
504
|
+
name: srv.name,
|
|
505
|
+
ip: srv.ip,
|
|
506
|
+
is_reachable: srv.is_reachable,
|
|
507
|
+
},
|
|
508
|
+
})),
|
|
509
|
+
"Failed to resolve server",
|
|
510
|
+
);
|
|
511
|
+
|
|
512
|
+
// ─── Diagnostics ───────────────────────────────────────────────────
|
|
513
|
+
case "diagnose_application":
|
|
514
|
+
return mcpCall((s) => s.diagnose.app(a.query), "Diagnosis failed");
|
|
515
|
+
case "diagnose_server":
|
|
516
|
+
return mcpCall((s) => s.diagnose.server(a.query), "Diagnosis failed");
|
|
517
|
+
case "find_infrastructure_issues":
|
|
518
|
+
return mcpCall(
|
|
519
|
+
(s) => s.diagnose.infrastructure(),
|
|
520
|
+
"Infrastructure scan failed",
|
|
521
|
+
);
|
|
522
|
+
|
|
523
|
+
// ─── Batch Operations ──────────────────────────────────────────────
|
|
524
|
+
case "restart_project_apps":
|
|
525
|
+
return mcpCall(
|
|
526
|
+
(s) => s.batch.restartProject(a.projectUuid),
|
|
527
|
+
"Batch restart failed",
|
|
528
|
+
);
|
|
529
|
+
case "redeploy_project_apps":
|
|
530
|
+
return mcpCall(
|
|
531
|
+
(s) => s.batch.redeployProject(a.projectUuid, a.force),
|
|
532
|
+
"Batch redeploy failed",
|
|
533
|
+
);
|
|
534
|
+
case "stop_all_apps":
|
|
535
|
+
return mcpCall((s) => s.batch.stopAll(), "Stop all failed");
|
|
536
|
+
|
|
537
|
+
// ─── Network Diagnostics ─────────────────────────────────────────
|
|
538
|
+
case "inspect_network":
|
|
539
|
+
return mcpCall(
|
|
540
|
+
(s) => s.network.inspect(a.uuid, a.servicesToTest),
|
|
541
|
+
"Network inspection failed",
|
|
542
|
+
);
|
|
543
|
+
case "analyze_deploy_failure":
|
|
544
|
+
return mcpCall(
|
|
545
|
+
(s) => s.diagnose.deployFailure(a.deploymentUuid),
|
|
546
|
+
"Deploy analysis failed",
|
|
547
|
+
);
|
|
548
|
+
|
|
549
|
+
// ─── Version / Health ──────────────────────────────────────────────
|
|
550
|
+
case "get_version":
|
|
551
|
+
return mcpCall(
|
|
552
|
+
(s) => s.version().then((v) => ({ version: v.version })),
|
|
553
|
+
"Failed to get version",
|
|
554
|
+
);
|
|
555
|
+
case "health_check":
|
|
556
|
+
return mcpCall(
|
|
557
|
+
(s) =>
|
|
558
|
+
s.servers.list().then(() => ({
|
|
559
|
+
status: "healthy",
|
|
560
|
+
message: "Coolify API is accessible",
|
|
561
|
+
})),
|
|
562
|
+
"Health check failed",
|
|
563
|
+
);
|
|
564
|
+
case "get_resource_usage":
|
|
565
|
+
return mcpCall(
|
|
566
|
+
(s) =>
|
|
567
|
+
s.applications
|
|
568
|
+
.resolve(a.uuid)
|
|
569
|
+
.then((app) => ({ status: app.status })),
|
|
570
|
+
"Failed to get resource usage",
|
|
571
|
+
);
|
|
219
572
|
|
|
220
|
-
|
|
221
|
-
return {
|
|
222
|
-
content: [{
|
|
223
|
-
type: 'text',
|
|
224
|
-
text: JSON.stringify({
|
|
225
|
-
success: true,
|
|
226
|
-
deploymentUuid: result.value.deploymentUuid,
|
|
227
|
-
resourceUuid: result.value.resourceUuid,
|
|
228
|
-
message: 'Deployment started'
|
|
229
|
-
}, null, 2)
|
|
230
|
-
}]
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
return {
|
|
235
|
-
content: [{ type: 'text', text: `Deployment failed: ${result.error.message}` }],
|
|
236
|
-
isError: true
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
async function handleGetEnvVars(coolify: CoolifyService, args: GetEnvVarsArgs): Promise<CallToolResult> {
|
|
241
|
-
const result = await coolify.getEnvironmentVariables(args.uuid)
|
|
242
|
-
|
|
243
|
-
if (isOk(result)) {
|
|
244
|
-
const runtimeVars = result.value.filter(ev => ev.is_runtime)
|
|
245
|
-
const buildtimeVars = result.value.filter(ev => ev.is_buildtime)
|
|
246
|
-
return {
|
|
247
|
-
content: [{
|
|
248
|
-
type: 'text',
|
|
249
|
-
text: JSON.stringify({
|
|
250
|
-
success: true,
|
|
251
|
-
total: result.value.length,
|
|
252
|
-
runtimeCount: runtimeVars.length,
|
|
253
|
-
buildtimeCount: buildtimeVars.length,
|
|
254
|
-
runtime: runtimeVars,
|
|
255
|
-
buildtime: buildtimeVars
|
|
256
|
-
}, null, 2)
|
|
257
|
-
}]
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
return {
|
|
262
|
-
content: [{ type: 'text', text: `Failed to get env vars: ${result.error.message}` }],
|
|
263
|
-
isError: true
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
async function handleSetEnvVars(coolify: CoolifyService, args: SetEnvVarsArgs): Promise<CallToolResult> {
|
|
268
|
-
const result = await coolify.setEnvironmentVariables(args.uuid, args.envVars)
|
|
269
|
-
|
|
270
|
-
if (isOk(result)) {
|
|
271
|
-
return {
|
|
272
|
-
content: [{
|
|
273
|
-
type: 'text',
|
|
274
|
-
text: `Set ${Object.keys(args.envVars).length} environment variable(s). Use deploy tool to apply changes.`
|
|
275
|
-
}]
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
return {
|
|
280
|
-
content: [{ type: 'text', text: `Failed to set env vars: ${result.error.message}` }],
|
|
281
|
-
isError: true
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
async function handleGetDeploymentStatus(coolify: CoolifyService, args: GetDeploymentStatusArgs): Promise<CallToolResult> {
|
|
286
|
-
const result = await coolify.getApplicationStatus(args.uuid)
|
|
287
|
-
|
|
288
|
-
if (isOk(result)) {
|
|
289
|
-
return {
|
|
290
|
-
content: [{ type: 'text', text: JSON.stringify({ status: result.value }, null, 2) }]
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
return {
|
|
295
|
-
content: [{ type: 'text', text: `Failed to get status: ${result.error.message}` }],
|
|
296
|
-
isError: true
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
async function handleListApplications(coolify: CoolifyService, args: ListApplicationsArgs): Promise<CallToolResult> {
|
|
301
|
-
const result = await coolify.listApplications(args.teamId, args.projectId)
|
|
302
|
-
|
|
303
|
-
if (isOk(result)) {
|
|
304
|
-
return {
|
|
305
|
-
content: [{
|
|
306
|
-
type: 'text',
|
|
307
|
-
text: JSON.stringify({ success: true, count: result.value.length, applications: result.value }, null, 2)
|
|
308
|
-
}]
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
return {
|
|
313
|
-
content: [{ type: 'text', text: `Failed to list applications: ${result.error.message}` }],
|
|
314
|
-
isError: true
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
async function handleDeleteApplication(coolify: CoolifyService, args: DeleteApplicationArgs): Promise<CallToolResult> {
|
|
319
|
-
const result = await coolify.deleteApplication(args.uuid)
|
|
320
|
-
|
|
321
|
-
if (isOk(result)) {
|
|
322
|
-
return {
|
|
323
|
-
content: [{
|
|
324
|
-
type: 'text',
|
|
325
|
-
text: JSON.stringify({ success: true, message: `Application ${args.uuid} deleted successfully` }, null, 2)
|
|
326
|
-
}]
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
return {
|
|
331
|
-
content: [{ type: 'text', text: `Failed to delete application: ${result.error.message}` }],
|
|
332
|
-
isError: true
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
async function handleGetApplicationLogs(coolify: CoolifyService, args: GetApplicationLogsArgs): Promise<CallToolResult> {
|
|
337
|
-
const result = await coolify.getApplicationLogs(args.uuid, { tail: args.tail })
|
|
338
|
-
|
|
339
|
-
if (isOk(result)) {
|
|
340
|
-
return {
|
|
341
|
-
content: [{
|
|
342
|
-
type: 'text',
|
|
343
|
-
text: JSON.stringify({
|
|
344
|
-
success: true,
|
|
345
|
-
timestamp: result.value.timestamp,
|
|
346
|
-
logCount: result.value.logs.length,
|
|
347
|
-
logs: result.value.logs
|
|
348
|
-
}, null, 2)
|
|
349
|
-
}]
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
return {
|
|
354
|
-
content: [{ type: 'text', text: `Failed to get logs: ${result.error.message}` }],
|
|
355
|
-
isError: true
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
async function handleStartApplication(coolify: CoolifyService, args: StartApplicationArgs): Promise<CallToolResult> {
|
|
360
|
-
const result = await coolify.startApplication(args.uuid)
|
|
361
|
-
|
|
362
|
-
if (isOk(result)) {
|
|
363
|
-
return {
|
|
364
|
-
content: [{
|
|
365
|
-
type: 'text',
|
|
366
|
-
text: JSON.stringify({ success: true, message: `Application ${args.uuid} started`, application: result.value }, null, 2)
|
|
367
|
-
}]
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
return {
|
|
372
|
-
content: [{ type: 'text', text: `Failed to start application: ${result.error.message}` }],
|
|
373
|
-
isError: true
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
async function handleStopApplication(coolify: CoolifyService, args: StopApplicationArgs): Promise<CallToolResult> {
|
|
378
|
-
const result = await coolify.stopApplication(args.uuid)
|
|
379
|
-
|
|
380
|
-
if (isOk(result)) {
|
|
381
|
-
return {
|
|
382
|
-
content: [{
|
|
383
|
-
type: 'text',
|
|
384
|
-
text: JSON.stringify({ success: true, message: `Application ${args.uuid} stopped`, application: result.value }, null, 2)
|
|
385
|
-
}]
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
return {
|
|
390
|
-
content: [{ type: 'text', text: `Failed to stop application: ${result.error.message}` }],
|
|
391
|
-
isError: true
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
async function handleRestartApplication(coolify: CoolifyService, args: RestartApplicationArgs): Promise<CallToolResult> {
|
|
396
|
-
const result = await coolify.restartApplication(args.uuid)
|
|
397
|
-
|
|
398
|
-
if (isOk(result)) {
|
|
399
|
-
return {
|
|
400
|
-
content: [{
|
|
401
|
-
type: 'text',
|
|
402
|
-
text: JSON.stringify({ success: true, message: `Application ${args.uuid} restarted`, application: result.value }, null, 2)
|
|
403
|
-
}]
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
return {
|
|
408
|
-
content: [{ type: 'text', text: `Failed to restart application: ${result.error.message}` }],
|
|
409
|
-
isError: true
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
async function handleGetDeploymentHistory(coolify: CoolifyService, args: GetDeploymentHistoryArgs): Promise<CallToolResult> {
|
|
414
|
-
const result = await coolify.getApplicationDeploymentHistory(args.uuid)
|
|
415
|
-
|
|
416
|
-
if (isOk(result)) {
|
|
417
|
-
return {
|
|
418
|
-
content: [{
|
|
419
|
-
type: 'text',
|
|
420
|
-
text: JSON.stringify({ success: true, count: result.value.length, deployments: result.value }, null, 2)
|
|
421
|
-
}]
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
return {
|
|
426
|
-
content: [{ type: 'text', text: `Failed to get deployment history: ${result.error.message}` }],
|
|
427
|
-
isError: true
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
async function handleUpdateApplication(coolify: CoolifyService, args: UpdateApplicationArgs): Promise<CallToolResult> {
|
|
432
|
-
const result = await coolify.updateApplication(args.uuid, {
|
|
433
|
-
name: args.name,
|
|
434
|
-
description: args.description,
|
|
435
|
-
buildPack: args.buildPack,
|
|
436
|
-
gitBranch: args.gitBranch,
|
|
437
|
-
portsExposes: args.portsExposes,
|
|
438
|
-
installCommand: args.installCommand,
|
|
439
|
-
buildCommand: args.buildCommand,
|
|
440
|
-
startCommand: args.startCommand,
|
|
441
|
-
domains: args.domains,
|
|
442
|
-
isForceHttpsEnabled: args.isForceHttpsEnabled,
|
|
443
|
-
isAutoDeployEnabled: args.isAutoDeployEnabled
|
|
444
|
-
})
|
|
445
|
-
|
|
446
|
-
if (isOk(result)) {
|
|
447
|
-
return {
|
|
448
|
-
content: [{
|
|
449
|
-
type: 'text',
|
|
450
|
-
text: JSON.stringify({
|
|
451
|
-
success: true,
|
|
452
|
-
message: `Application ${args.uuid} updated. Use deploy tool to apply changes.`,
|
|
453
|
-
application: result.value
|
|
454
|
-
}, null, 2)
|
|
455
|
-
}]
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
return {
|
|
460
|
-
content: [{ type: 'text', text: `Failed to update application: ${result.error.message}` }],
|
|
461
|
-
isError: true
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
async function handleSetDomains(coolify: CoolifyService, args: SetDomainsArgs): Promise<CallToolResult> {
|
|
466
|
-
const result = await coolify.updateApplication(args.uuid, {
|
|
467
|
-
domains: args.domains,
|
|
468
|
-
isForceHttpsEnabled: args.forceHttps ?? true
|
|
469
|
-
})
|
|
470
|
-
|
|
471
|
-
if (isOk(result)) {
|
|
472
|
-
const domainList = args.domains.split(',').map(d => d.trim())
|
|
473
|
-
return {
|
|
474
|
-
content: [{
|
|
475
|
-
type: 'text',
|
|
476
|
-
text: JSON.stringify({
|
|
477
|
-
success: true,
|
|
478
|
-
message: `Domains configured for application ${args.uuid}`,
|
|
479
|
-
domains: domainList,
|
|
480
|
-
forceHttps: args.forceHttps ?? true,
|
|
481
|
-
nextSteps: [
|
|
482
|
-
'Ensure DNS records point to your server IP',
|
|
483
|
-
'Use deploy tool to apply domain changes',
|
|
484
|
-
'SSL certificates will be auto-generated via Let\'s Encrypt'
|
|
485
|
-
]
|
|
486
|
-
}, null, 2)
|
|
487
|
-
}]
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
return {
|
|
492
|
-
content: [{ type: 'text', text: `Failed to set domains: ${result.error.message}` }],
|
|
493
|
-
isError: true
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
async function handleListServers(coolify: CoolifyService): Promise<CallToolResult> {
|
|
498
|
-
const result = await coolify.listServers()
|
|
499
|
-
|
|
500
|
-
if (isOk(result)) {
|
|
501
|
-
return {
|
|
502
|
-
content: [{
|
|
503
|
-
type: 'text',
|
|
504
|
-
text: JSON.stringify({ success: true, count: result.value.length, servers: result.value }, null, 2)
|
|
505
|
-
}]
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
return {
|
|
510
|
-
content: [{ type: 'text', text: `Failed to list servers: ${result.error.message}` }],
|
|
511
|
-
isError: true
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
async function handleGetServer(coolify: CoolifyService, args: GetServerArgs): Promise<CallToolResult> {
|
|
516
|
-
const result = await coolify.getServer(args.serverUuid)
|
|
517
|
-
|
|
518
|
-
if (isOk(result)) {
|
|
519
|
-
return {
|
|
520
|
-
content: [{ type: 'text', text: JSON.stringify({ success: true, server: result.value }, null, 2) }]
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
return {
|
|
525
|
-
content: [{ type: 'text', text: `Failed to get server: ${result.error.message}` }],
|
|
526
|
-
isError: true
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
async function handleListProjects(coolify: CoolifyService): Promise<CallToolResult> {
|
|
531
|
-
const result = await coolify.listProjects()
|
|
532
|
-
|
|
533
|
-
if (isOk(result)) {
|
|
534
|
-
return {
|
|
535
|
-
content: [{
|
|
536
|
-
type: 'text',
|
|
537
|
-
text: JSON.stringify({ success: true, count: result.value.length, projects: result.value }, null, 2)
|
|
538
|
-
}]
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
return {
|
|
543
|
-
content: [{ type: 'text', text: `Failed to list projects: ${result.error.message}` }],
|
|
544
|
-
isError: true
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
async function handleListTeams(coolify: CoolifyService): Promise<CallToolResult> {
|
|
549
|
-
const result = await coolify.listTeams()
|
|
550
|
-
|
|
551
|
-
if (isOk(result)) {
|
|
552
|
-
return {
|
|
553
|
-
content: [{
|
|
554
|
-
type: 'text',
|
|
555
|
-
text: JSON.stringify({ success: true, count: result.value.length, teams: result.value }, null, 2)
|
|
556
|
-
}]
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
return {
|
|
561
|
-
content: [{ type: 'text', text: `Failed to list teams: ${result.error.message}` }],
|
|
562
|
-
isError: true
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
async function handleGetServerDestinations(coolify: CoolifyService, args: GetServerDestinationsArgs): Promise<CallToolResult> {
|
|
567
|
-
const result = await coolify.getServerDestinations(args.serverUuid)
|
|
568
|
-
|
|
569
|
-
if (isOk(result)) {
|
|
570
|
-
return {
|
|
571
|
-
content: [{
|
|
572
|
-
type: 'text',
|
|
573
|
-
text: JSON.stringify({
|
|
574
|
-
success: true,
|
|
575
|
-
serverUuid: args.serverUuid,
|
|
576
|
-
count: result.value.length,
|
|
577
|
-
destinations: result.value
|
|
578
|
-
}, null, 2)
|
|
579
|
-
}]
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
return {
|
|
584
|
-
content: [{ type: 'text', text: `Failed to get destinations: ${result.error.message}` }],
|
|
585
|
-
isError: true
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
async function handleCreateApplication(coolify: CoolifyService, args: CreateApplicationArgs): Promise<CallToolResult> {
|
|
590
|
-
const result = await coolify.createApplication({
|
|
591
|
-
name: args.name,
|
|
592
|
-
description: args.description,
|
|
593
|
-
projectUuid: args.projectUuid,
|
|
594
|
-
environmentUuid: args.environmentUuid,
|
|
595
|
-
serverUuid: args.serverUuid,
|
|
596
|
-
type: (args.type as any) || 'public',
|
|
597
|
-
githubRepoUrl: args.githubRepoUrl,
|
|
598
|
-
branch: args.branch,
|
|
599
|
-
buildPack: args.buildPack,
|
|
600
|
-
dockerComposeLocation: args.dockerComposeLocation,
|
|
601
|
-
dockerfileLocation: args.dockerfileLocation,
|
|
602
|
-
baseDirectory: args.baseDirectory,
|
|
603
|
-
})
|
|
604
|
-
|
|
605
|
-
if (isOk(result)) {
|
|
606
|
-
return {
|
|
607
|
-
content: [{
|
|
608
|
-
type: 'text',
|
|
609
|
-
text: JSON.stringify({
|
|
610
|
-
success: true,
|
|
611
|
-
message: `Application "${args.name}" created successfully`,
|
|
612
|
-
uuid: result.value.uuid,
|
|
613
|
-
nextSteps: [
|
|
614
|
-
'Use set_env_vars to configure environment variables',
|
|
615
|
-
'Use deploy to start the first deployment'
|
|
616
|
-
]
|
|
617
|
-
}, null, 2)
|
|
618
|
-
}]
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
return {
|
|
623
|
-
content: [{ type: 'text', text: `Failed to create application: ${result.error.message}` }],
|
|
624
|
-
isError: true
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
async function handleCreateProject(coolify: CoolifyService, args: CreateProjectArgs): Promise<CallToolResult> {
|
|
629
|
-
const result = await coolify.createProject(args.name, args.description)
|
|
630
|
-
|
|
631
|
-
if (isOk(result)) {
|
|
632
|
-
return {
|
|
633
|
-
content: [{
|
|
634
|
-
type: 'text',
|
|
635
|
-
text: JSON.stringify({
|
|
636
|
-
success: true,
|
|
637
|
-
message: `Project "${args.name}" created successfully`,
|
|
638
|
-
uuid: result.value.uuid,
|
|
639
|
-
}, null, 2)
|
|
640
|
-
}]
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
return {
|
|
645
|
-
content: [{ type: 'text', text: `Failed to create project: ${result.error.message}` }],
|
|
646
|
-
isError: true
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
async function handleGetResourceUsage(coolify: CoolifyService, args: GetResourceUsageArgs): Promise<CallToolResult> {
|
|
651
|
-
// For now, use getApplicationStatus - Coolify API doesn't have a separate resource usage endpoint
|
|
652
|
-
const result = await coolify.getApplicationStatus(args.uuid)
|
|
653
|
-
|
|
654
|
-
if (isOk(result)) {
|
|
655
|
-
return {
|
|
656
|
-
content: [{ type: 'text', text: JSON.stringify({ success: true, status: result.value }, null, 2) }]
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
return {
|
|
661
|
-
content: [{ type: 'text', text: `Failed to get resource usage: ${result.error.message}` }],
|
|
662
|
-
isError: true
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
async function handleHealthCheck(coolify: CoolifyService): Promise<CallToolResult> {
|
|
667
|
-
// Try to list servers as a health check
|
|
668
|
-
const result = await coolify.listServers()
|
|
669
|
-
|
|
670
|
-
if (isOk(result)) {
|
|
671
|
-
return {
|
|
672
|
-
content: [{
|
|
673
|
-
type: 'text',
|
|
674
|
-
text: JSON.stringify({ success: true, status: 'healthy', message: 'Coolify API is accessible' }, null, 2)
|
|
675
|
-
}]
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
return {
|
|
680
|
-
content: [{ type: 'text', text: `Health check failed: ${result.error.message}` }],
|
|
681
|
-
isError: true
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
async function handleGetApplicationDetails(coolify: CoolifyService, args: GetApplicationDetailsArgs): Promise<CallToolResult> {
|
|
686
|
-
// List all applications and filter by UUID to get full details
|
|
687
|
-
const result = await coolify.listApplications()
|
|
688
|
-
|
|
689
|
-
if (isOk(result)) {
|
|
690
|
-
const app = result.value.find((a) => a.uuid === args.uuid)
|
|
691
|
-
if (app) {
|
|
573
|
+
default:
|
|
692
574
|
return {
|
|
693
|
-
content: [{ type:
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
return {
|
|
697
|
-
content: [{ type: 'text', text: `Application ${args.uuid} not found` }],
|
|
698
|
-
isError: true
|
|
699
|
-
}
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
return {
|
|
703
|
-
content: [{ type: 'text', text: `Failed to get application details: ${result.error.message}` }],
|
|
704
|
-
isError: true
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
async function handleListDeployments(coolify: CoolifyService): Promise<CallToolResult> {
|
|
709
|
-
const result = await coolify.listDeployments()
|
|
710
|
-
|
|
711
|
-
if (isOk(result)) {
|
|
712
|
-
return {
|
|
713
|
-
content: [{
|
|
714
|
-
type: 'text',
|
|
715
|
-
text: JSON.stringify({
|
|
716
|
-
success: true,
|
|
717
|
-
count: result.value.length,
|
|
718
|
-
deployments: result.value
|
|
719
|
-
}, null, 2)
|
|
720
|
-
}]
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
return {
|
|
725
|
-
content: [{ type: 'text', text: `Failed to list deployments: ${result.error.message}` }],
|
|
726
|
-
isError: true
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
async function handleGetDeployment(coolify: CoolifyService, args: GetDeploymentArgs): Promise<CallToolResult> {
|
|
731
|
-
const result = await coolify.getDeployment(args.deploymentUuid)
|
|
732
|
-
|
|
733
|
-
if (isOk(result)) {
|
|
734
|
-
return {
|
|
735
|
-
content: [{
|
|
736
|
-
type: 'text',
|
|
737
|
-
text: JSON.stringify({
|
|
738
|
-
success: true,
|
|
739
|
-
deployment: result.value
|
|
740
|
-
}, null, 2)
|
|
741
|
-
}]
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
return {
|
|
746
|
-
content: [{ type: 'text', text: `Failed to get deployment: ${result.error.message}` }],
|
|
747
|
-
isError: true
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
async function handleGetApplicationDeployments(coolify: CoolifyService, args: GetApplicationDeploymentsArgs): Promise<CallToolResult> {
|
|
752
|
-
const result = await coolify.getApplicationDeployments(args.uuid, args.skip, args.take)
|
|
753
|
-
|
|
754
|
-
if (isOk(result)) {
|
|
755
|
-
return {
|
|
756
|
-
content: [{
|
|
757
|
-
type: 'text',
|
|
758
|
-
text: JSON.stringify({
|
|
759
|
-
success: true,
|
|
760
|
-
count: result.value.length,
|
|
761
|
-
deployments: result.value
|
|
762
|
-
}, null, 2)
|
|
763
|
-
}]
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
return {
|
|
768
|
-
content: [{ type: 'text', text: `Failed to get application deployments: ${result.error.message}` }],
|
|
769
|
-
isError: true
|
|
575
|
+
content: [{ type: "text", text: `Unknown tool: ${name}` }],
|
|
576
|
+
isError: true,
|
|
577
|
+
};
|
|
770
578
|
}
|
|
771
579
|
}
|