quicklify 1.1.0 → 1.2.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/LICENSE +1 -1
- package/README.md +46 -22
- package/README.tr.md +46 -22
- package/SECURITY.md +63 -34
- package/dist/commands/add.d.ts +1 -0
- package/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +41 -65
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/backup.d.ts +2 -11
- package/dist/commands/backup.d.ts.map +1 -1
- package/dist/commands/backup.js +111 -53
- package/dist/commands/backup.js.map +1 -1
- package/dist/commands/destroy.d.ts.map +1 -1
- package/dist/commands/destroy.js +58 -37
- package/dist/commands/destroy.js.map +1 -1
- package/dist/commands/domain.d.ts +2 -9
- package/dist/commands/domain.d.ts.map +1 -1
- package/dist/commands/domain.js +47 -56
- package/dist/commands/domain.js.map +1 -1
- package/dist/commands/firewall.d.ts +3 -10
- package/dist/commands/firewall.d.ts.map +1 -1
- package/dist/commands/firewall.js +28 -51
- package/dist/commands/firewall.js.map +1 -1
- package/dist/commands/health.d.ts +2 -2
- package/dist/commands/health.d.ts.map +1 -1
- package/dist/commands/health.js +77 -19
- package/dist/commands/health.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +115 -29
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/interactive.d.ts +2 -0
- package/dist/commands/interactive.d.ts.map +1 -0
- package/dist/commands/interactive.js +357 -0
- package/dist/commands/interactive.js.map +1 -0
- package/dist/commands/list.d.ts.map +1 -1
- package/dist/commands/list.js +4 -2
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/logs.d.ts.map +1 -1
- package/dist/commands/logs.js +9 -1
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/maintain.d.ts.map +1 -1
- package/dist/commands/maintain.js +28 -47
- package/dist/commands/maintain.js.map +1 -1
- package/dist/commands/monitor.js +1 -1
- package/dist/commands/monitor.js.map +1 -1
- package/dist/commands/remove.d.ts.map +1 -1
- package/dist/commands/remove.js +25 -0
- package/dist/commands/remove.js.map +1 -1
- package/dist/commands/restart.d.ts.map +1 -1
- package/dist/commands/restart.js +39 -39
- package/dist/commands/restart.js.map +1 -1
- package/dist/commands/restore.d.ts +2 -13
- package/dist/commands/restore.d.ts.map +1 -1
- package/dist/commands/restore.js +42 -54
- package/dist/commands/restore.js.map +1 -1
- package/dist/commands/secure.d.ts +2 -9
- package/dist/commands/secure.d.ts.map +1 -1
- package/dist/commands/secure.js +2 -97
- package/dist/commands/secure.js.map +1 -1
- package/dist/commands/snapshot.d.ts.map +1 -1
- package/dist/commands/snapshot.js +55 -67
- package/dist/commands/snapshot.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +33 -16
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +23 -16
- package/dist/commands/update.js.map +1 -1
- package/dist/constants.d.ts +14 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +23 -0
- package/dist/constants.js.map +1 -0
- package/dist/core/backup.d.ts +16 -0
- package/dist/core/backup.d.ts.map +1 -1
- package/dist/core/backup.js +159 -1
- package/dist/core/backup.js.map +1 -1
- package/dist/core/domain.d.ts.map +1 -1
- package/dist/core/domain.js +1 -5
- package/dist/core/domain.js.map +1 -1
- package/dist/core/firewall.d.ts +2 -0
- package/dist/core/firewall.d.ts.map +1 -1
- package/dist/core/firewall.js +12 -0
- package/dist/core/firewall.js.map +1 -1
- package/dist/core/logs.js +1 -1
- package/dist/core/logs.js.map +1 -1
- package/dist/core/maintain.d.ts.map +1 -1
- package/dist/core/maintain.js +1 -2
- package/dist/core/maintain.js.map +1 -1
- package/dist/core/manage.d.ts +10 -1
- package/dist/core/manage.d.ts.map +1 -1
- package/dist/core/manage.js +42 -4
- package/dist/core/manage.js.map +1 -1
- package/dist/core/provision.d.ts +2 -1
- package/dist/core/provision.d.ts.map +1 -1
- package/dist/core/provision.js +7 -12
- package/dist/core/provision.js.map +1 -1
- package/dist/core/secure.d.ts.map +1 -1
- package/dist/core/secure.js +8 -2
- package/dist/core/secure.js.map +1 -1
- package/dist/core/status.d.ts.map +1 -1
- package/dist/core/status.js +2 -1
- package/dist/core/status.js.map +1 -1
- package/dist/index.js +17 -4
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +13 -7
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/serverBackup.d.ts +2 -7
- package/dist/mcp/tools/serverBackup.d.ts.map +1 -1
- package/dist/mcp/tools/serverBackup.js +120 -234
- package/dist/mcp/tools/serverBackup.js.map +1 -1
- package/dist/mcp/tools/serverInfo.d.ts +18 -2
- package/dist/mcp/tools/serverInfo.d.ts.map +1 -1
- package/dist/mcp/tools/serverInfo.js +121 -57
- package/dist/mcp/tools/serverInfo.js.map +1 -1
- package/dist/mcp/tools/serverLogs.d.ts +2 -7
- package/dist/mcp/tools/serverLogs.d.ts.map +1 -1
- package/dist/mcp/tools/serverLogs.js +36 -57
- package/dist/mcp/tools/serverLogs.js.map +1 -1
- package/dist/mcp/tools/serverMaintain.d.ts +3 -8
- package/dist/mcp/tools/serverMaintain.d.ts.map +1 -1
- package/dist/mcp/tools/serverMaintain.js +48 -109
- package/dist/mcp/tools/serverMaintain.js.map +1 -1
- package/dist/mcp/tools/serverManage.d.ts +5 -0
- package/dist/mcp/tools/serverManage.d.ts.map +1 -1
- package/dist/mcp/tools/serverManage.js +92 -109
- package/dist/mcp/tools/serverManage.js.map +1 -1
- package/dist/mcp/tools/serverProvision.d.ts +5 -0
- package/dist/mcp/tools/serverProvision.d.ts.map +1 -1
- package/dist/mcp/tools/serverProvision.js +67 -76
- package/dist/mcp/tools/serverProvision.js.map +1 -1
- package/dist/mcp/tools/serverSecure.d.ts +2 -7
- package/dist/mcp/tools/serverSecure.d.ts.map +1 -1
- package/dist/mcp/tools/serverSecure.js +109 -170
- package/dist/mcp/tools/serverSecure.js.map +1 -1
- package/dist/mcp/utils.d.ts +42 -0
- package/dist/mcp/utils.d.ts.map +1 -0
- package/dist/mcp/utils.js +61 -0
- package/dist/mcp/utils.js.map +1 -0
- package/dist/providers/base.d.ts +2 -2
- package/dist/providers/base.d.ts.map +1 -1
- package/dist/providers/digitalocean.d.ts +2 -2
- package/dist/providers/digitalocean.d.ts.map +1 -1
- package/dist/providers/digitalocean.js +3 -3
- package/dist/providers/digitalocean.js.map +1 -1
- package/dist/providers/hetzner.d.ts +2 -2
- package/dist/providers/hetzner.d.ts.map +1 -1
- package/dist/providers/hetzner.js +7 -4
- package/dist/providers/hetzner.js.map +1 -1
- package/dist/providers/linode.d.ts +2 -2
- package/dist/providers/linode.d.ts.map +1 -1
- package/dist/providers/linode.js +2 -2
- package/dist/providers/linode.js.map +1 -1
- package/dist/providers/vultr.d.ts +2 -2
- package/dist/providers/vultr.d.ts.map +1 -1
- package/dist/providers/vultr.js +2 -2
- package/dist/providers/vultr.js.map +1 -1
- package/dist/types/index.d.ts +11 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/cloudInit.d.ts +1 -0
- package/dist/utils/cloudInit.d.ts.map +1 -1
- package/dist/utils/cloudInit.js +62 -0
- package/dist/utils/cloudInit.js.map +1 -1
- package/dist/utils/config.js +1 -1
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/errorMapper.d.ts.map +1 -1
- package/dist/utils/errorMapper.js +5 -1
- package/dist/utils/errorMapper.js.map +1 -1
- package/dist/utils/modeGuard.d.ts +5 -0
- package/dist/utils/modeGuard.d.ts.map +1 -0
- package/dist/utils/modeGuard.js +13 -0
- package/dist/utils/modeGuard.js.map +1 -0
- package/dist/utils/openBrowser.d.ts.map +1 -1
- package/dist/utils/openBrowser.js +3 -1
- package/dist/utils/openBrowser.js.map +1 -1
- package/dist/utils/prompts.d.ts +2 -2
- package/dist/utils/prompts.d.ts.map +1 -1
- package/dist/utils/prompts.js +3 -3
- package/dist/utils/prompts.js.map +1 -1
- package/dist/utils/ssh.d.ts +9 -0
- package/dist/utils/ssh.d.ts.map +1 -1
- package/dist/utils/ssh.js +175 -15
- package/dist/utils/ssh.js.map +1 -1
- package/dist/utils/sshKey.d.ts.map +1 -1
- package/dist/utils/sshKey.js +3 -0
- package/dist/utils/sshKey.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { isSafeMode } from "../../core/manage.js";
|
|
3
3
|
import { provisionServer } from "../../core/provision.js";
|
|
4
|
-
import {
|
|
4
|
+
import { mcpSuccess, mcpError } from "../utils.js";
|
|
5
5
|
// ─── Schema ──────────────────────────────────────────────────────────────────
|
|
6
6
|
export const serverProvisionSchema = {
|
|
7
7
|
provider: z
|
|
@@ -22,23 +22,17 @@ export const serverProvisionSchema = {
|
|
|
22
22
|
.enum(["starter", "production", "dev"])
|
|
23
23
|
.default("starter")
|
|
24
24
|
.describe("Template for default region/size. 'starter' = cheapest, 'production' = more resources, 'dev' = development. Explicit region/size override template defaults. Default: starter"),
|
|
25
|
+
mode: z
|
|
26
|
+
.enum(["coolify", "bare"])
|
|
27
|
+
.default("coolify")
|
|
28
|
+
.describe("Server mode: 'coolify' installs Coolify, 'bare' provisions generic VPS without Coolify. Default: coolify"),
|
|
25
29
|
};
|
|
26
30
|
// ─── Handler ─────────────────────────────────────────────────────────────────
|
|
27
31
|
export async function handleServerProvision(params) {
|
|
32
|
+
const mode = params.mode ?? "coolify";
|
|
28
33
|
// SAFE_MODE guard
|
|
29
34
|
if (isSafeMode()) {
|
|
30
|
-
return
|
|
31
|
-
content: [
|
|
32
|
-
{
|
|
33
|
-
type: "text",
|
|
34
|
-
text: JSON.stringify({
|
|
35
|
-
error: "Provision is disabled in SAFE_MODE",
|
|
36
|
-
hint: "Set QUICKLIFY_SAFE_MODE=false to enable server provisioning. WARNING: This creates billable cloud resources.",
|
|
37
|
-
}),
|
|
38
|
-
},
|
|
39
|
-
],
|
|
40
|
-
isError: true,
|
|
41
|
-
};
|
|
35
|
+
return mcpError("Provision is disabled in SAFE_MODE", "Set QUICKLIFY_SAFE_MODE=false to enable server provisioning. WARNING: This creates billable cloud resources.");
|
|
42
36
|
}
|
|
43
37
|
try {
|
|
44
38
|
const result = await provisionServer({
|
|
@@ -47,79 +41,76 @@ export async function handleServerProvision(params) {
|
|
|
47
41
|
size: params.size,
|
|
48
42
|
name: params.name,
|
|
49
43
|
template: params.template,
|
|
44
|
+
mode,
|
|
50
45
|
});
|
|
51
46
|
if (!result.success) {
|
|
52
|
-
return
|
|
53
|
-
|
|
54
|
-
{
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
...(result.hint ? { hint: result.hint } : {}),
|
|
59
|
-
suggested_actions: [
|
|
60
|
-
{
|
|
61
|
-
command: "server_info { action: 'list' }",
|
|
62
|
-
reason: "Check existing servers",
|
|
63
|
-
},
|
|
64
|
-
],
|
|
65
|
-
}),
|
|
66
|
-
},
|
|
67
|
-
],
|
|
68
|
-
isError: true,
|
|
69
|
-
};
|
|
47
|
+
return mcpError(result.error ?? "Provision failed", result.hint, [
|
|
48
|
+
{
|
|
49
|
+
command: "server_info { action: 'list' }",
|
|
50
|
+
reason: "Check existing servers",
|
|
51
|
+
},
|
|
52
|
+
]);
|
|
70
53
|
}
|
|
71
54
|
if (!result.server) {
|
|
72
|
-
return
|
|
73
|
-
content: [{ type: "text", text: JSON.stringify({ error: "Unexpected: server record missing" }) }],
|
|
74
|
-
isError: true,
|
|
75
|
-
};
|
|
55
|
+
return mcpError("Unexpected: server record missing");
|
|
76
56
|
}
|
|
77
57
|
const server = result.server;
|
|
78
|
-
|
|
79
|
-
|
|
58
|
+
const suggestedActions = mode === "bare"
|
|
59
|
+
? [
|
|
60
|
+
{
|
|
61
|
+
command: `ssh root@${server.ip}`,
|
|
62
|
+
reason: "Connect to your bare server via SSH",
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
command: `server_secure { action: 'secure-setup', server: '${server.name}' }`,
|
|
66
|
+
reason: "Harden SSH security + install fail2ban",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
command: `server_secure { action: 'firewall-setup', server: '${server.name}' }`,
|
|
70
|
+
reason: "Setup UFW firewall",
|
|
71
|
+
},
|
|
80
72
|
{
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
success: true,
|
|
84
|
-
message: `Server "${server.name}" provisioned on ${server.provider}`,
|
|
85
|
-
server: {
|
|
86
|
-
id: server.id,
|
|
87
|
-
name: server.name,
|
|
88
|
-
provider: server.provider,
|
|
89
|
-
ip: server.ip,
|
|
90
|
-
region: server.region,
|
|
91
|
-
size: server.size,
|
|
92
|
-
createdAt: server.createdAt,
|
|
93
|
-
},
|
|
94
|
-
...(result.hint ? { hint: result.hint } : {}),
|
|
95
|
-
suggested_actions: [
|
|
96
|
-
{
|
|
97
|
-
command: `server_info { action: 'health', server: '${server.name}' }`,
|
|
98
|
-
reason: "Check Coolify health (wait 3-5 minutes after creation for Coolify to initialize)",
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
command: `server_secure { action: 'secure-setup', server: '${server.name}' }`,
|
|
102
|
-
reason: "Harden SSH security + install fail2ban",
|
|
103
|
-
},
|
|
104
|
-
{
|
|
105
|
-
command: `server_secure { action: 'firewall-setup', server: '${server.name}' }`,
|
|
106
|
-
reason: "Setup UFW firewall with Coolify ports",
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
command: `server_info { action: 'status', server: '${server.name}' }`,
|
|
110
|
-
reason: "Check cloud provider status",
|
|
111
|
-
},
|
|
112
|
-
],
|
|
113
|
-
}),
|
|
73
|
+
command: `server_info { action: 'status', server: '${server.name}' }`,
|
|
74
|
+
reason: "Check cloud provider status",
|
|
114
75
|
},
|
|
115
|
-
]
|
|
116
|
-
|
|
76
|
+
]
|
|
77
|
+
: [
|
|
78
|
+
{
|
|
79
|
+
command: `server_info { action: 'health', server: '${server.name}' }`,
|
|
80
|
+
reason: "Check Coolify health (wait 3-5 minutes after creation for Coolify to initialize)",
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
command: `server_secure { action: 'secure-setup', server: '${server.name}' }`,
|
|
84
|
+
reason: "Harden SSH security + install fail2ban",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
command: `server_secure { action: 'firewall-setup', server: '${server.name}' }`,
|
|
88
|
+
reason: "Setup UFW firewall with Coolify ports",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
command: `server_info { action: 'status', server: '${server.name}' }`,
|
|
92
|
+
reason: "Check cloud provider status",
|
|
93
|
+
},
|
|
94
|
+
];
|
|
95
|
+
return mcpSuccess({
|
|
96
|
+
success: true,
|
|
97
|
+
message: `Server "${server.name}" provisioned on ${server.provider}`,
|
|
98
|
+
server: {
|
|
99
|
+
id: server.id,
|
|
100
|
+
name: server.name,
|
|
101
|
+
provider: server.provider,
|
|
102
|
+
ip: server.ip,
|
|
103
|
+
region: server.region,
|
|
104
|
+
size: server.size,
|
|
105
|
+
mode,
|
|
106
|
+
createdAt: server.createdAt,
|
|
107
|
+
},
|
|
108
|
+
...(result.hint ? { hint: result.hint } : {}),
|
|
109
|
+
suggested_actions: suggestedActions,
|
|
110
|
+
});
|
|
117
111
|
}
|
|
118
112
|
catch (error) {
|
|
119
|
-
return
|
|
120
|
-
content: [{ type: "text", text: JSON.stringify({ error: getErrorMessage(error) }) }],
|
|
121
|
-
isError: true,
|
|
122
|
-
};
|
|
113
|
+
return mcpError(error instanceof Error ? error.message : String(error));
|
|
123
114
|
}
|
|
124
115
|
}
|
|
125
116
|
//# sourceMappingURL=serverProvision.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serverProvision.js","sourceRoot":"","sources":["../../../src/mcp/tools/serverProvision.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"serverProvision.js","sourceRoot":"","sources":["../../../src/mcp/tools/serverProvision.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { type McpResponse } from "../utils.js";
|
|
2
3
|
export declare const serverSecureSchema: {
|
|
3
4
|
action: z.ZodEnum<{
|
|
4
5
|
"secure-setup": "secure-setup";
|
|
@@ -29,12 +30,6 @@ export declare function handleServerSecure(params: {
|
|
|
29
30
|
protocol?: "tcp" | "udp";
|
|
30
31
|
domain?: string;
|
|
31
32
|
ssl?: boolean;
|
|
32
|
-
}): Promise<
|
|
33
|
-
content: Array<{
|
|
34
|
-
type: "text";
|
|
35
|
-
text: string;
|
|
36
|
-
}>;
|
|
37
|
-
isError?: boolean;
|
|
38
|
-
}>;
|
|
33
|
+
}): Promise<McpResponse>;
|
|
39
34
|
export {};
|
|
40
35
|
//# sourceMappingURL=serverSecure.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serverSecure.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/serverSecure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"serverSecure.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/serverSecure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAmBxB,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,aAAa,CAAC;AAIrB,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;CAuB9B,CAAC;AAEF,KAAK,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;AAExD,wBAAsB,kBAAkB,CAAC,MAAM,EAAE;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,GAAG,OAAO,CAAC,WAAW,CAAC,CAiXvB"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { getServers
|
|
2
|
+
import { getServers } from "../../utils/config.js";
|
|
3
3
|
import { applySecureSetup, runSecureAudit, } from "../../core/secure.js";
|
|
4
4
|
import { setupFirewall, addFirewallRule, removeFirewallRule, getFirewallStatus, COOLIFY_PORTS, } from "../../core/firewall.js";
|
|
5
5
|
import { setDomain, removeDomain, getDomain, checkDns, } from "../../core/domain.js";
|
|
6
|
+
import { resolveServerForMcp, mcpSuccess, mcpError, } from "../utils.js";
|
|
7
|
+
import { requireCoolifyMode } from "../../utils/modeGuard.js";
|
|
6
8
|
import { getErrorMessage } from "../../utils/errorMapper.js";
|
|
7
9
|
export const serverSecureSchema = {
|
|
8
10
|
action: z.enum([
|
|
@@ -16,45 +18,27 @@ export const serverSecureSchema = {
|
|
|
16
18
|
domain: z.string().optional().describe("Domain name. Required for domain-set and domain-check."),
|
|
17
19
|
ssl: z.boolean().default(true).describe("Enable SSL (https) for domain. Default: true."),
|
|
18
20
|
};
|
|
19
|
-
function resolveServer(params, servers) {
|
|
20
|
-
if (params.server) {
|
|
21
|
-
return findServer(params.server);
|
|
22
|
-
}
|
|
23
|
-
if (servers.length === 1) {
|
|
24
|
-
return servers[0];
|
|
25
|
-
}
|
|
26
|
-
return undefined;
|
|
27
|
-
}
|
|
28
21
|
export async function handleServerSecure(params) {
|
|
29
22
|
try {
|
|
30
23
|
const servers = getServers();
|
|
31
24
|
if (servers.length === 0) {
|
|
32
|
-
return
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
suggested_actions: [{ command: "quicklify init", reason: "Deploy a server first" }],
|
|
36
|
-
}) }],
|
|
37
|
-
isError: true,
|
|
38
|
-
};
|
|
25
|
+
return mcpError("No servers found", undefined, [
|
|
26
|
+
{ command: "quicklify init", reason: "Deploy a server first" },
|
|
27
|
+
]);
|
|
39
28
|
}
|
|
40
|
-
const server =
|
|
29
|
+
const server = resolveServerForMcp(params, servers);
|
|
41
30
|
if (!server) {
|
|
42
31
|
if (params.server) {
|
|
43
|
-
return {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
32
|
+
return mcpError(`Server not found: ${params.server}`, `Available servers: ${servers.map((s) => s.name).join(", ")}`);
|
|
33
|
+
}
|
|
34
|
+
return mcpError("Multiple servers found. Specify which server to use.", `Available: ${servers.map((s) => s.name).join(", ")}`);
|
|
35
|
+
}
|
|
36
|
+
const domainActions = ["domain-set", "domain-remove", "domain-check", "domain-info"];
|
|
37
|
+
if (domainActions.includes(params.action)) {
|
|
38
|
+
const modeError = requireCoolifyMode(server, params.action);
|
|
39
|
+
if (modeError) {
|
|
40
|
+
return mcpError(modeError, "Domain management requires Coolify. Use SSH for bare server DNS configuration.");
|
|
50
41
|
}
|
|
51
|
-
return {
|
|
52
|
-
content: [{ type: "text", text: JSON.stringify({
|
|
53
|
-
error: "Multiple servers found. Specify which server to use.",
|
|
54
|
-
available_servers: servers.map((s) => ({ name: s.name, ip: s.ip })),
|
|
55
|
-
}) }],
|
|
56
|
-
isError: true,
|
|
57
|
-
};
|
|
58
42
|
}
|
|
59
43
|
switch (params.action) {
|
|
60
44
|
case "secure-setup": {
|
|
@@ -109,21 +93,19 @@ export async function handleServerSecure(params) {
|
|
|
109
93
|
const suggestedActions = result.score < 100
|
|
110
94
|
? [{ command: `server_secure { action: 'secure-setup', server: '${server.name}' }`, reason: "Improve security score" }]
|
|
111
95
|
: [{ command: `server_secure { action: 'firewall-status', server: '${server.name}' }`, reason: "Check firewall configuration" }];
|
|
112
|
-
return {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}) }],
|
|
126
|
-
};
|
|
96
|
+
return mcpSuccess({
|
|
97
|
+
server: server.name,
|
|
98
|
+
ip: server.ip,
|
|
99
|
+
score: result.score,
|
|
100
|
+
maxScore: 100,
|
|
101
|
+
checks: {
|
|
102
|
+
passwordAuth: result.audit.passwordAuth,
|
|
103
|
+
rootLogin: result.audit.rootLogin,
|
|
104
|
+
fail2ban: result.audit.fail2ban,
|
|
105
|
+
sshPort: result.audit.sshPort,
|
|
106
|
+
},
|
|
107
|
+
suggested_actions: suggestedActions,
|
|
108
|
+
});
|
|
127
109
|
}
|
|
128
110
|
case "firewall-setup": {
|
|
129
111
|
const result = await setupFirewall(server.ip);
|
|
@@ -138,27 +120,19 @@ export async function handleServerSecure(params) {
|
|
|
138
120
|
isError: true,
|
|
139
121
|
};
|
|
140
122
|
}
|
|
141
|
-
return {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}) }],
|
|
151
|
-
};
|
|
123
|
+
return mcpSuccess({
|
|
124
|
+
success: true,
|
|
125
|
+
server: server.name,
|
|
126
|
+
ip: server.ip,
|
|
127
|
+
message: `UFW enabled with Coolify ports (${COOLIFY_PORTS.join(", ")}) + SSH (22)`,
|
|
128
|
+
suggested_actions: [
|
|
129
|
+
{ command: `server_secure { action: 'firewall-status', server: '${server.name}' }`, reason: "Verify firewall rules" },
|
|
130
|
+
],
|
|
131
|
+
});
|
|
152
132
|
}
|
|
153
133
|
case "firewall-add": {
|
|
154
134
|
if (params.port === undefined) {
|
|
155
|
-
return
|
|
156
|
-
content: [{ type: "text", text: JSON.stringify({
|
|
157
|
-
error: "Port is required for firewall-add action",
|
|
158
|
-
hint: "Specify a port number (1-65535)",
|
|
159
|
-
}) }],
|
|
160
|
-
isError: true,
|
|
161
|
-
};
|
|
135
|
+
return mcpError("Port is required for firewall-add action", "Specify a port number (1-65535)");
|
|
162
136
|
}
|
|
163
137
|
const result = await addFirewallRule(server.ip, params.port, params.protocol || "tcp");
|
|
164
138
|
if (!result.success) {
|
|
@@ -172,27 +146,19 @@ export async function handleServerSecure(params) {
|
|
|
172
146
|
isError: true,
|
|
173
147
|
};
|
|
174
148
|
}
|
|
175
|
-
return {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}) }],
|
|
185
|
-
};
|
|
149
|
+
return mcpSuccess({
|
|
150
|
+
success: true,
|
|
151
|
+
server: server.name,
|
|
152
|
+
ip: server.ip,
|
|
153
|
+
message: `Port ${params.port}/${params.protocol || "tcp"} opened`,
|
|
154
|
+
suggested_actions: [
|
|
155
|
+
{ command: `server_secure { action: 'firewall-status', server: '${server.name}' }`, reason: "Verify firewall rules" },
|
|
156
|
+
],
|
|
157
|
+
});
|
|
186
158
|
}
|
|
187
159
|
case "firewall-remove": {
|
|
188
160
|
if (params.port === undefined) {
|
|
189
|
-
return
|
|
190
|
-
content: [{ type: "text", text: JSON.stringify({
|
|
191
|
-
error: "Port is required for firewall-remove action",
|
|
192
|
-
hint: "Specify a port number (1-65535)",
|
|
193
|
-
}) }],
|
|
194
|
-
isError: true,
|
|
195
|
-
};
|
|
161
|
+
return mcpError("Port is required for firewall-remove action", "Specify a port number (1-65535)");
|
|
196
162
|
}
|
|
197
163
|
const result = await removeFirewallRule(server.ip, params.port, params.protocol || "tcp");
|
|
198
164
|
if (!result.success) {
|
|
@@ -207,18 +173,16 @@ export async function handleServerSecure(params) {
|
|
|
207
173
|
isError: true,
|
|
208
174
|
};
|
|
209
175
|
}
|
|
210
|
-
return {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
}) }],
|
|
221
|
-
};
|
|
176
|
+
return mcpSuccess({
|
|
177
|
+
success: true,
|
|
178
|
+
server: server.name,
|
|
179
|
+
ip: server.ip,
|
|
180
|
+
message: `Port ${params.port}/${params.protocol || "tcp"} closed`,
|
|
181
|
+
...(result.warning ? { warning: result.warning } : {}),
|
|
182
|
+
suggested_actions: [
|
|
183
|
+
{ command: `server_secure { action: 'firewall-status', server: '${server.name}' }`, reason: "Verify firewall rules" },
|
|
184
|
+
],
|
|
185
|
+
});
|
|
222
186
|
}
|
|
223
187
|
case "firewall-status": {
|
|
224
188
|
const result = await getFirewallStatus(server.ip);
|
|
@@ -236,26 +200,18 @@ export async function handleServerSecure(params) {
|
|
|
236
200
|
const suggestedActions = !result.status.active
|
|
237
201
|
? [{ command: `server_secure { action: 'firewall-setup', server: '${server.name}' }`, reason: "Enable firewall" }]
|
|
238
202
|
: [{ command: `server_secure { action: 'firewall-add', server: '${server.name}', port: 3000 }`, reason: "Open additional ports if needed" }];
|
|
239
|
-
return {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}) }],
|
|
248
|
-
};
|
|
203
|
+
return mcpSuccess({
|
|
204
|
+
server: server.name,
|
|
205
|
+
ip: server.ip,
|
|
206
|
+
active: result.status.active,
|
|
207
|
+
rules: result.status.rules,
|
|
208
|
+
ruleCount: result.status.rules.length,
|
|
209
|
+
suggested_actions: suggestedActions,
|
|
210
|
+
});
|
|
249
211
|
}
|
|
250
212
|
case "domain-set": {
|
|
251
213
|
if (!params.domain) {
|
|
252
|
-
return
|
|
253
|
-
content: [{ type: "text", text: JSON.stringify({
|
|
254
|
-
error: "Domain is required for domain-set action",
|
|
255
|
-
hint: "Specify a domain name (e.g., coolify.example.com)",
|
|
256
|
-
}) }],
|
|
257
|
-
isError: true,
|
|
258
|
-
};
|
|
214
|
+
return mcpError("Domain is required for domain-set action", "Specify a domain name (e.g., coolify.example.com)");
|
|
259
215
|
}
|
|
260
216
|
const result = await setDomain(server.ip, params.domain, params.ssl ?? true);
|
|
261
217
|
if (!result.success) {
|
|
@@ -270,19 +226,17 @@ export async function handleServerSecure(params) {
|
|
|
270
226
|
};
|
|
271
227
|
}
|
|
272
228
|
const protocol = (params.ssl ?? true) ? "https" : "http";
|
|
273
|
-
return {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
}) }],
|
|
285
|
-
};
|
|
229
|
+
return mcpSuccess({
|
|
230
|
+
success: true,
|
|
231
|
+
server: server.name,
|
|
232
|
+
ip: server.ip,
|
|
233
|
+
message: `Domain set to ${params.domain}`,
|
|
234
|
+
url: `${protocol}://${params.domain}`,
|
|
235
|
+
suggested_actions: [
|
|
236
|
+
{ command: `server_secure { action: 'domain-check', server: '${server.name}', domain: '${params.domain}' }`, reason: "Verify DNS points to this server" },
|
|
237
|
+
{ command: `server_info { action: 'health', server: '${server.name}' }`, reason: "Verify Coolify is accessible" },
|
|
238
|
+
],
|
|
239
|
+
});
|
|
286
240
|
}
|
|
287
241
|
case "domain-remove": {
|
|
288
242
|
const result = await removeDomain(server.ip);
|
|
@@ -297,28 +251,20 @@ export async function handleServerSecure(params) {
|
|
|
297
251
|
isError: true,
|
|
298
252
|
};
|
|
299
253
|
}
|
|
300
|
-
return {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
}) }],
|
|
311
|
-
};
|
|
254
|
+
return mcpSuccess({
|
|
255
|
+
success: true,
|
|
256
|
+
server: server.name,
|
|
257
|
+
ip: server.ip,
|
|
258
|
+
message: "Domain removed. Coolify reset to default.",
|
|
259
|
+
url: `http://${server.ip}:8000`,
|
|
260
|
+
suggested_actions: [
|
|
261
|
+
{ command: `server_info { action: 'health', server: '${server.name}' }`, reason: "Verify Coolify is accessible" },
|
|
262
|
+
],
|
|
263
|
+
});
|
|
312
264
|
}
|
|
313
265
|
case "domain-check": {
|
|
314
266
|
if (!params.domain) {
|
|
315
|
-
return
|
|
316
|
-
content: [{ type: "text", text: JSON.stringify({
|
|
317
|
-
error: "Domain is required for domain-check action",
|
|
318
|
-
hint: "Specify a domain name to check DNS for",
|
|
319
|
-
}) }],
|
|
320
|
-
isError: true,
|
|
321
|
-
};
|
|
267
|
+
return mcpError("Domain is required for domain-check action", "Specify a domain name to check DNS for");
|
|
322
268
|
}
|
|
323
269
|
const result = await checkDns(server.ip, params.domain);
|
|
324
270
|
if (result.error) {
|
|
@@ -333,19 +279,17 @@ export async function handleServerSecure(params) {
|
|
|
333
279
|
isError: true,
|
|
334
280
|
};
|
|
335
281
|
}
|
|
336
|
-
return {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
}) }],
|
|
348
|
-
};
|
|
282
|
+
return mcpSuccess({
|
|
283
|
+
server: server.name,
|
|
284
|
+
ip: server.ip,
|
|
285
|
+
domain: params.domain,
|
|
286
|
+
resolvedIp: result.resolvedIp,
|
|
287
|
+
match: result.match,
|
|
288
|
+
...(result.hint ? { hint: result.hint } : {}),
|
|
289
|
+
suggested_actions: result.match
|
|
290
|
+
? [{ command: `server_secure { action: 'domain-set', server: '${server.name}', domain: '${params.domain}' }`, reason: "Set this domain as Coolify FQDN" }]
|
|
291
|
+
: [{ command: `server_secure { action: 'domain-info', server: '${server.name}' }`, reason: "Check current domain setting" }],
|
|
292
|
+
});
|
|
349
293
|
}
|
|
350
294
|
case "domain-info": {
|
|
351
295
|
const result = await getDomain(server.ip);
|
|
@@ -374,23 +318,18 @@ export async function handleServerSecure(params) {
|
|
|
374
318
|
reason: "Set a custom domain",
|
|
375
319
|
});
|
|
376
320
|
}
|
|
377
|
-
return {
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
}) }],
|
|
385
|
-
};
|
|
321
|
+
return mcpSuccess({
|
|
322
|
+
server: server.name,
|
|
323
|
+
ip: server.ip,
|
|
324
|
+
fqdn: result.fqdn,
|
|
325
|
+
message: result.fqdn ? `Current domain: ${result.fqdn}` : `No custom domain set. Default: http://${server.ip}:8000`,
|
|
326
|
+
suggested_actions: domainSuggestedActions,
|
|
327
|
+
});
|
|
386
328
|
}
|
|
387
329
|
}
|
|
388
330
|
}
|
|
389
331
|
catch (error) {
|
|
390
|
-
return
|
|
391
|
-
content: [{ type: "text", text: JSON.stringify({ error: getErrorMessage(error) }) }],
|
|
392
|
-
isError: true,
|
|
393
|
-
};
|
|
332
|
+
return mcpError(getErrorMessage(error));
|
|
394
333
|
}
|
|
395
334
|
}
|
|
396
335
|
//# sourceMappingURL=serverSecure.js.map
|