@selfhost.dev/mcp-server 0.3.0 → 0.4.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/README.md +147 -24
- package/dist/auth.d.ts +1 -1
- package/dist/auth.js +3 -3
- package/dist/client.js +1 -1
- package/dist/config.js +1 -1
- package/dist/index.js +29 -4
- package/dist/index.js.map +1 -1
- package/dist/rate-limiter.js +1 -1
- package/dist/tools/billing.js +14 -14
- package/dist/tools/credentials.js +1 -1
- package/dist/tools/database-users.js +9 -9
- package/dist/tools/deployment-domains.d.ts +2 -0
- package/dist/tools/deployment-domains.js +128 -0
- package/dist/tools/deployment-domains.js.map +1 -0
- package/dist/tools/deployment-notifications.d.ts +2 -0
- package/dist/tools/deployment-notifications.js +74 -0
- package/dist/tools/deployment-notifications.js.map +1 -0
- package/dist/tools/deployments.d.ts +2 -0
- package/dist/tools/deployments.js +302 -0
- package/dist/tools/deployments.js.map +1 -0
- package/dist/tools/env-vars.d.ts +2 -0
- package/dist/tools/env-vars.js +121 -0
- package/dist/tools/env-vars.js.map +1 -0
- package/dist/tools/github.d.ts +2 -0
- package/dist/tools/github.js +106 -0
- package/dist/tools/github.js.map +1 -0
- package/dist/tools/hetzner.js +13 -13
- package/dist/tools/instances.js +11 -11
- package/dist/tools/pgbouncer.js +4 -4
- package/dist/tools/pitr.js +16 -16
- package/dist/tools/project-databases.d.ts +2 -0
- package/dist/tools/project-databases.js +169 -0
- package/dist/tools/project-databases.js.map +1 -0
- package/dist/tools/project-services.d.ts +2 -0
- package/dist/tools/project-services.js +93 -0
- package/dist/tools/project-services.js.map +1 -0
- package/dist/tools/projects.d.ts +2 -0
- package/dist/tools/projects.js +141 -0
- package/dist/tools/projects.js.map +1 -0
- package/dist/tools/scaling.js +13 -13
- package/dist/types/models.js +1 -1
- package/dist/types/tiers.js +31 -1
- package/dist/types/tiers.js.map +1 -1
- package/package.json +10 -3
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { apiRequest } from "../client.js";
|
|
3
|
+
import { session } from "../session.js";
|
|
4
|
+
/**
|
|
5
|
+
* Project databases (CoolifyDatabase) - Postgres/Redis/MySQL/MongoDB instances
|
|
6
|
+
* attached to a project, provisioned via Coolify. Distinct from the AWS/Hetzner
|
|
7
|
+
* *managed instances* (`list_instances`/`create_instance`) - these live inside a
|
|
8
|
+
* PaaS project and share its server.
|
|
9
|
+
*
|
|
10
|
+
* Endpoints:
|
|
11
|
+
* - GET /api/v1/platform/projects/:pid/databases
|
|
12
|
+
* - POST /api/v1/platform/projects/:pid/databases/:db_type (202 - async provisioning)
|
|
13
|
+
* - DELETE /api/v1/platform/projects/:pid/databases/:database_pid (202; body {name} must match)
|
|
14
|
+
*
|
|
15
|
+
* The project must be `active` before creating a database (409 otherwise).
|
|
16
|
+
*/
|
|
17
|
+
const PROJECTS_BASE = "/api/v1/platform/projects";
|
|
18
|
+
const DB_TYPES = ["postgres", "redis", "mysql", "mongodb"];
|
|
19
|
+
// Coolify password rule: 8+ chars, no spaces or shell-dangerous chars.
|
|
20
|
+
const PASSWORD_RE = /^[A-Za-z0-9!@#%^*()_+\-=\[\]{}:,.?/~]+$/;
|
|
21
|
+
const DEFAULT_PORTS = { postgres: 5432, redis: 6379, mysql: 3306, mongodb: 27017 };
|
|
22
|
+
const NO_ORG = "No active organization. Call `list_organizations` then `select_organization` first.";
|
|
23
|
+
function hasOrg() {
|
|
24
|
+
return session.getActiveOrgId() !== null;
|
|
25
|
+
}
|
|
26
|
+
function dbTypePath(t) {
|
|
27
|
+
return t === "postgres" ? "postgresql" : t;
|
|
28
|
+
}
|
|
29
|
+
function checkPassword(label, v) {
|
|
30
|
+
if (!v)
|
|
31
|
+
return `${label} is required for this database type.`;
|
|
32
|
+
if (v.length < 8)
|
|
33
|
+
return `${label} must be at least 8 characters.`;
|
|
34
|
+
if (!PASSWORD_RE.test(v))
|
|
35
|
+
return `${label} contains invalid characters (no spaces or \` $ ; | & < > \\ ' ").`;
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
export function registerProjectDatabaseTools(server) {
|
|
39
|
+
server.tool("list_project_databases", "List the databases attached to a project (Postgres/Redis/MySQL/MongoDB provisioned via Coolify, NOT AWS managed instances). Returns pid, name, db_type, status (active | inactive | creating | failed | unknown), is_public, and public_port. Passwords are never returned here.", {
|
|
40
|
+
project_pid: z.string().min(1),
|
|
41
|
+
}, async ({ project_pid }) => {
|
|
42
|
+
if (!hasOrg())
|
|
43
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
44
|
+
const result = await apiRequest(`${PROJECTS_BASE}/${project_pid}/databases`, {
|
|
45
|
+
toolName: "list_project_databases",
|
|
46
|
+
});
|
|
47
|
+
if (!result.success) {
|
|
48
|
+
return { content: [{ type: "text", text: `Failed to list project databases (${result.statusCode}): ${result.message}` }] };
|
|
49
|
+
}
|
|
50
|
+
return { content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }] };
|
|
51
|
+
});
|
|
52
|
+
server.tool("create_project_database", "Create a database inside a project (provisioned via Coolify; returns 202, status starts `creating` - poll `list_project_databases`). The project must be `active`. Provide the type-specific credentials (see fields). Passwords must be 8+ chars with no spaces or shell-dangerous chars. `is_public` is REQUIRED and has no default: ASK THE USER whether the database should be publicly reachable on a port (convenient for external clients but exposes it to the internet) or kept private to the project (safer). Do not assume.", {
|
|
53
|
+
project_pid: z.string().min(1),
|
|
54
|
+
db_type: z.enum(DB_TYPES).describe("postgres | redis | mysql | mongodb"),
|
|
55
|
+
name: z.string().min(1).max(255),
|
|
56
|
+
is_public: z.boolean().describe("Required choice (ask the user, do not assume): true = expose on a public port (internet-reachable); false = private to the project."),
|
|
57
|
+
public_port: z.number().int().min(1024).max(65535).optional().describe("Public port when is_public (defaults: pg 5432, redis 6379, mysql 3306, mongo 27017)"),
|
|
58
|
+
// postgres
|
|
59
|
+
postgres_user: z.string().max(255).optional(),
|
|
60
|
+
postgres_password: z.string().optional(),
|
|
61
|
+
postgres_db: z.string().max(255).optional(),
|
|
62
|
+
// redis
|
|
63
|
+
redis_password: z.string().optional(),
|
|
64
|
+
// mysql
|
|
65
|
+
mysql_user: z.string().max(255).optional(),
|
|
66
|
+
mysql_password: z.string().optional(),
|
|
67
|
+
mysql_database: z.string().max(255).optional(),
|
|
68
|
+
mysql_root_password: z.string().optional(),
|
|
69
|
+
// mongodb
|
|
70
|
+
mongo_initdb_root_username: z.string().max(255).optional(),
|
|
71
|
+
mongo_initdb_root_password: z.string().optional(),
|
|
72
|
+
mongo_initdb_database: z.string().max(255).optional(),
|
|
73
|
+
}, async (args) => {
|
|
74
|
+
if (!hasOrg())
|
|
75
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
76
|
+
const dbType = args.db_type;
|
|
77
|
+
const isPublic = args.is_public;
|
|
78
|
+
const body = { name: args.name, is_public: isPublic };
|
|
79
|
+
if (isPublic)
|
|
80
|
+
body.public_port = args.public_port ?? DEFAULT_PORTS[dbType];
|
|
81
|
+
let err = null;
|
|
82
|
+
switch (dbType) {
|
|
83
|
+
case "postgres":
|
|
84
|
+
err = checkPassword("postgres_password", args.postgres_password);
|
|
85
|
+
if (!err && !args.postgres_user)
|
|
86
|
+
err = "postgres_user is required.";
|
|
87
|
+
if (!err && !args.postgres_db)
|
|
88
|
+
err = "postgres_db is required.";
|
|
89
|
+
if (!err) {
|
|
90
|
+
body.postgres_user = args.postgres_user;
|
|
91
|
+
body.postgres_password = args.postgres_password;
|
|
92
|
+
body.postgres_db = args.postgres_db;
|
|
93
|
+
body.instant_deploy = true;
|
|
94
|
+
}
|
|
95
|
+
break;
|
|
96
|
+
case "redis":
|
|
97
|
+
err = checkPassword("redis_password", args.redis_password);
|
|
98
|
+
if (!err) {
|
|
99
|
+
body.redis_password = args.redis_password;
|
|
100
|
+
body.instant_deploy = true;
|
|
101
|
+
}
|
|
102
|
+
break;
|
|
103
|
+
case "mysql":
|
|
104
|
+
err = checkPassword("mysql_password", args.mysql_password) || checkPassword("mysql_root_password", args.mysql_root_password);
|
|
105
|
+
if (!err && !args.mysql_user)
|
|
106
|
+
err = "mysql_user is required.";
|
|
107
|
+
if (!err && !args.mysql_database)
|
|
108
|
+
err = "mysql_database is required.";
|
|
109
|
+
if (!err) {
|
|
110
|
+
body.mysql_user = args.mysql_user;
|
|
111
|
+
body.mysql_password = args.mysql_password;
|
|
112
|
+
body.mysql_database = args.mysql_database;
|
|
113
|
+
body.mysql_root_password = args.mysql_root_password;
|
|
114
|
+
body.instant_deploy = true;
|
|
115
|
+
}
|
|
116
|
+
break;
|
|
117
|
+
case "mongodb":
|
|
118
|
+
err = checkPassword("mongo_initdb_root_password", args.mongo_initdb_root_password);
|
|
119
|
+
if (!err && !args.mongo_initdb_root_username)
|
|
120
|
+
err = "mongo_initdb_root_username is required.";
|
|
121
|
+
if (!err && !args.mongo_initdb_database)
|
|
122
|
+
err = "mongo_initdb_database is required.";
|
|
123
|
+
if (!err) {
|
|
124
|
+
body.mongo_initdb_root_username = args.mongo_initdb_root_username;
|
|
125
|
+
body.mongo_initdb_root_password = args.mongo_initdb_root_password;
|
|
126
|
+
body.mongo_initdb_database = args.mongo_initdb_database;
|
|
127
|
+
}
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
if (err)
|
|
131
|
+
return { content: [{ type: "text", text: err }] };
|
|
132
|
+
const result = await apiRequest(`${PROJECTS_BASE}/${args.project_pid}/databases/${dbTypePath(dbType)}`, {
|
|
133
|
+
method: "POST",
|
|
134
|
+
body,
|
|
135
|
+
toolName: "create_project_database",
|
|
136
|
+
});
|
|
137
|
+
if (!result.success) {
|
|
138
|
+
return { content: [{ type: "text", text: `Failed to create database (${result.statusCode}): ${result.message}` }] };
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
content: [
|
|
142
|
+
{ type: "text", text: `Database \`${args.name}\` (${dbType}) provisioning started. Poll \`list_project_databases\` until status is \`active\`.` },
|
|
143
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
144
|
+
],
|
|
145
|
+
};
|
|
146
|
+
});
|
|
147
|
+
server.tool("delete_project_database", "Delete a project database. The exact current `name` must be supplied and match (a safety check, 422 otherwise). Returns 202 (async tear-down). Irreversible.", {
|
|
148
|
+
project_pid: z.string().min(1),
|
|
149
|
+
database_pid: z.string().min(1),
|
|
150
|
+
name: z.string().min(1).describe("Exact current database name - must match"),
|
|
151
|
+
confirm: z.boolean().describe("Must be true. Permanently destroys the database and its data."),
|
|
152
|
+
}, async ({ project_pid, database_pid, name, confirm }) => {
|
|
153
|
+
if (!hasOrg())
|
|
154
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
155
|
+
if (!confirm) {
|
|
156
|
+
return { content: [{ type: "text", text: `⚠️ About to DELETE database \`${name}\` (${database_pid}) - all its data is destroyed. No undo.\n\nCall again with confirm=true to proceed.` }] };
|
|
157
|
+
}
|
|
158
|
+
const result = await apiRequest(`${PROJECTS_BASE}/${project_pid}/databases/${database_pid}`, {
|
|
159
|
+
method: "DELETE",
|
|
160
|
+
body: { name },
|
|
161
|
+
toolName: "delete_project_database",
|
|
162
|
+
});
|
|
163
|
+
if (!result.success) {
|
|
164
|
+
return { content: [{ type: "text", text: `Failed to delete database (${result.statusCode}): ${result.message}` }] };
|
|
165
|
+
}
|
|
166
|
+
return { content: [{ type: "text", text: "Database deletion queued." }] };
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=project-databases.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-databases.js","sourceRoot":"","sources":["../../src/tools/project-databases.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { apiRequest } from "../client.js";
|
|
3
|
+
import { session } from "../session.js";
|
|
4
|
+
/**
|
|
5
|
+
* Project services (CoolifyService) - pre-packaged service templates deployed
|
|
6
|
+
* into a project. Today the only supported template is `supabase`. There is no
|
|
7
|
+
* catalog endpoint; the supported set is fixed server-side.
|
|
8
|
+
*
|
|
9
|
+
* Endpoints:
|
|
10
|
+
* - GET /api/v1/platform/projects/:pid/services
|
|
11
|
+
* - POST /api/v1/platform/projects/:pid/services/:template_type (202 - async provisioning)
|
|
12
|
+
* - DELETE /api/v1/platform/projects/:pid/services/:service_pid (202; body {name} must match)
|
|
13
|
+
*
|
|
14
|
+
* The project must be `active` before creating a service (409 otherwise).
|
|
15
|
+
*/
|
|
16
|
+
const PROJECTS_BASE = "/api/v1/platform/projects";
|
|
17
|
+
const TEMPLATE_TYPES = ["supabase"];
|
|
18
|
+
const NO_ORG = "No active organization. Call `list_organizations` then `select_organization` first.";
|
|
19
|
+
function hasOrg() {
|
|
20
|
+
return session.getActiveOrgId() !== null;
|
|
21
|
+
}
|
|
22
|
+
export function registerProjectServiceTools(server) {
|
|
23
|
+
server.tool("list_project_services", "List the service-template instances deployed in a project (e.g. Supabase). Returns pid, name, template_type, status (active | inactive | creating | failed | unknown), is_public, public_port, and external_url. Credentials are not returned in the list.", {
|
|
24
|
+
project_pid: z.string().min(1),
|
|
25
|
+
}, async ({ project_pid }) => {
|
|
26
|
+
if (!hasOrg())
|
|
27
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
28
|
+
const result = await apiRequest(`${PROJECTS_BASE}/${project_pid}/services`, {
|
|
29
|
+
toolName: "list_project_services",
|
|
30
|
+
});
|
|
31
|
+
if (!result.success) {
|
|
32
|
+
return { content: [{ type: "text", text: `Failed to list project services (${result.statusCode}): ${result.message}` }] };
|
|
33
|
+
}
|
|
34
|
+
return { content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }] };
|
|
35
|
+
});
|
|
36
|
+
server.tool("create_project_service", "Deploy a service template into a project (currently only `supabase`). Returns 202, status starts `creating` - poll `list_project_services`. The project must be `active`. The dashboard password must be 8+ characters. `is_public` is REQUIRED and has no default: ASK THE USER whether the service should be publicly reachable (internet-exposed) or private to the project. Do not assume.", {
|
|
37
|
+
project_pid: z.string().min(1),
|
|
38
|
+
template_type: z.enum(TEMPLATE_TYPES).describe("Service template (only `supabase` is supported today)"),
|
|
39
|
+
name: z.string().min(1).max(255),
|
|
40
|
+
dashboard_username: z.string().min(1).max(255).describe("Supabase Studio dashboard username"),
|
|
41
|
+
dashboard_password: z.string().min(8).max(255).describe("Supabase Studio dashboard password (8+ chars)"),
|
|
42
|
+
is_public: z.boolean().describe("Required choice (ask the user, do not assume): true = expose publicly (internet-reachable); false = private to the project."),
|
|
43
|
+
public_port: z.number().int().min(1024).max(65535).optional(),
|
|
44
|
+
}, async ({ project_pid, template_type, name, dashboard_username, dashboard_password, is_public, public_port }) => {
|
|
45
|
+
if (!hasOrg())
|
|
46
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
47
|
+
const body = {
|
|
48
|
+
name,
|
|
49
|
+
dashboard_username,
|
|
50
|
+
dashboard_password,
|
|
51
|
+
instant_deploy: true,
|
|
52
|
+
is_public,
|
|
53
|
+
};
|
|
54
|
+
if (public_port !== undefined)
|
|
55
|
+
body.public_port = public_port;
|
|
56
|
+
const result = await apiRequest(`${PROJECTS_BASE}/${project_pid}/services/${template_type}`, {
|
|
57
|
+
method: "POST",
|
|
58
|
+
body,
|
|
59
|
+
toolName: "create_project_service",
|
|
60
|
+
});
|
|
61
|
+
if (!result.success) {
|
|
62
|
+
return { content: [{ type: "text", text: `Failed to create service (${result.statusCode}): ${result.message}` }] };
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
content: [
|
|
66
|
+
{ type: "text", text: `Service \`${name}\` (${template_type}) provisioning started. Poll \`list_project_services\` until status is \`active\`.` },
|
|
67
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
68
|
+
],
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
server.tool("delete_project_service", "Delete a project service. The exact current `name` must be supplied and match (a safety check, 422 otherwise). Returns 202 (async tear-down). Irreversible.", {
|
|
72
|
+
project_pid: z.string().min(1),
|
|
73
|
+
service_pid: z.string().min(1),
|
|
74
|
+
name: z.string().min(1).describe("Exact current service name - must match"),
|
|
75
|
+
confirm: z.boolean().describe("Must be true. Permanently destroys the service and its data."),
|
|
76
|
+
}, async ({ project_pid, service_pid, name, confirm }) => {
|
|
77
|
+
if (!hasOrg())
|
|
78
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
79
|
+
if (!confirm) {
|
|
80
|
+
return { content: [{ type: "text", text: `⚠️ About to DELETE service \`${name}\` (${service_pid}) - all its data is destroyed. No undo.\n\nCall again with confirm=true to proceed.` }] };
|
|
81
|
+
}
|
|
82
|
+
const result = await apiRequest(`${PROJECTS_BASE}/${project_pid}/services/${service_pid}`, {
|
|
83
|
+
method: "DELETE",
|
|
84
|
+
body: { name },
|
|
85
|
+
toolName: "delete_project_service",
|
|
86
|
+
});
|
|
87
|
+
if (!result.success) {
|
|
88
|
+
return { content: [{ type: "text", text: `Failed to delete service (${result.statusCode}): ${result.message}` }] };
|
|
89
|
+
}
|
|
90
|
+
return { content: [{ type: "text", text: "Service deletion queued." }] };
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=project-services.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-services.js","sourceRoot":"","sources":["../../src/tools/project-services.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { apiRequest } from "../client.js";
|
|
3
|
+
import { session } from "../session.js";
|
|
4
|
+
/**
|
|
5
|
+
* Projects (CoolifyProject) - the per-app container: a provisioned server +
|
|
6
|
+
* Coolify install + wildcard DNS that deployments and project databases attach
|
|
7
|
+
* to. Mounted on Rails as `resources :projects, controller: "coolify_projects"`
|
|
8
|
+
* so the URL path is `/projects` (NOT `/coolify_projects`).
|
|
9
|
+
*
|
|
10
|
+
* Endpoints:
|
|
11
|
+
* - GET /api/v1/platform/projects
|
|
12
|
+
* - GET /api/v1/platform/projects/:pid
|
|
13
|
+
* - POST /api/v1/platform/projects (202 - async provisioning)
|
|
14
|
+
* - PATCH /api/v1/platform/projects/:pid
|
|
15
|
+
* - DELETE /api/v1/platform/projects/:pid (202 - async tear-down)
|
|
16
|
+
* - GET /api/v1/platform/projects/:pid/metrics
|
|
17
|
+
*
|
|
18
|
+
* `organization_id` is required on every call and is auto-injected from the
|
|
19
|
+
* active org by the HTTP client (query for GET, body for POST/PATCH/DELETE).
|
|
20
|
+
*/
|
|
21
|
+
const PROJECTS_BASE = "/api/v1/platform/projects";
|
|
22
|
+
const DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
23
|
+
function requireOrg() {
|
|
24
|
+
return session.getActiveOrgId();
|
|
25
|
+
}
|
|
26
|
+
const NO_ORG = "No active organization. Call `list_organizations` then `select_organization` first.";
|
|
27
|
+
export function registerProjectTools(server) {
|
|
28
|
+
server.tool("list_projects", "List PaaS projects (app containers) in the active organization. Each project is a provisioned server + Coolify install that deployments and project databases attach to. Returns pid, name, status (pending | provisioning | active | failed - note `deleting`/`terminated` are filtered out server-side), public_ip, instance_domain, and timestamps. A project must reach status `active` before you can create a deployment in it.", {}, async () => {
|
|
29
|
+
if (!requireOrg())
|
|
30
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
31
|
+
const result = await apiRequest(PROJECTS_BASE, {
|
|
32
|
+
toolName: "list_projects",
|
|
33
|
+
});
|
|
34
|
+
if (!result.success) {
|
|
35
|
+
return { content: [{ type: "text", text: `Failed to list projects (${result.statusCode}): ${result.message}` }] };
|
|
36
|
+
}
|
|
37
|
+
return { content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }] };
|
|
38
|
+
});
|
|
39
|
+
server.tool("get_project", "Get one project by pid. Use this to POLL provisioning progress after `create_project`: re-call every ~5-10s until `status` becomes `active` (ready for deployments) or `failed` (provisioning errored). `status` of `deleting` or a 404 means it has been/ is being torn down. `public_ip` and `instance_domain` populate during provisioning.", {
|
|
40
|
+
project_pid: z.string().min(1).describe("Project pid, e.g. prj_01h..."),
|
|
41
|
+
}, async ({ project_pid }) => {
|
|
42
|
+
if (!requireOrg())
|
|
43
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
44
|
+
const result = await apiRequest(`${PROJECTS_BASE}/${project_pid}`, {
|
|
45
|
+
toolName: "get_project",
|
|
46
|
+
});
|
|
47
|
+
if (!result.success) {
|
|
48
|
+
return { content: [{ type: "text", text: `Failed to get project (${result.statusCode}): ${result.message}` }] };
|
|
49
|
+
}
|
|
50
|
+
return { content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }] };
|
|
51
|
+
});
|
|
52
|
+
server.tool("create_project", "Create a new PaaS project and start async server provisioning. Returns immediately (HTTP 202) with the project in status `pending` - actual provisioning (server → Coolify → DNS) takes ~2-5 minutes. Poll `get_project` until status is `active` before creating a deployment in it. Name must be unique within the org (excluding failed/terminated projects). May return 422 if the platform is at capacity for new servers - retry later.", {
|
|
53
|
+
name: z.string().min(1).max(255).describe("Project name; unique per org, <=255 chars"),
|
|
54
|
+
description: z.string().optional().describe("Optional free-text description"),
|
|
55
|
+
}, async ({ name, description }) => {
|
|
56
|
+
if (!requireOrg())
|
|
57
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
58
|
+
const project = { name };
|
|
59
|
+
if (description !== undefined && description !== "")
|
|
60
|
+
project.description = description;
|
|
61
|
+
const result = await apiRequest(PROJECTS_BASE, {
|
|
62
|
+
method: "POST",
|
|
63
|
+
body: { project },
|
|
64
|
+
toolName: "create_project",
|
|
65
|
+
});
|
|
66
|
+
if (!result.success) {
|
|
67
|
+
return { content: [{ type: "text", text: `Failed to create project (${result.statusCode}): ${result.message}` }] };
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
content: [
|
|
71
|
+
{ type: "text", text: `Project \`${name}\` created and provisioning started (status: pending). This takes ~2-5 min - poll \`get_project\` until status is \`active\` before deploying.` },
|
|
72
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
73
|
+
],
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
server.tool("update_project", "Update a project's name and/or description. Only these two fields are editable - status, IPs, and domain are server-managed. Name must remain unique within the org.", {
|
|
77
|
+
project_pid: z.string().min(1),
|
|
78
|
+
name: z.string().min(1).max(255).describe("New name (required by the backend even if unchanged)"),
|
|
79
|
+
description: z.string().nullable().optional().describe("New description; pass null to clear"),
|
|
80
|
+
}, async ({ project_pid, name, description }) => {
|
|
81
|
+
if (!requireOrg())
|
|
82
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
83
|
+
const project = { name };
|
|
84
|
+
if (description !== undefined)
|
|
85
|
+
project.description = description;
|
|
86
|
+
const result = await apiRequest(`${PROJECTS_BASE}/${project_pid}`, {
|
|
87
|
+
method: "PATCH",
|
|
88
|
+
body: { project },
|
|
89
|
+
toolName: "update_project",
|
|
90
|
+
});
|
|
91
|
+
if (!result.success) {
|
|
92
|
+
return { content: [{ type: "text", text: `Failed to update project (${result.statusCode}): ${result.message}` }] };
|
|
93
|
+
}
|
|
94
|
+
return { content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }] };
|
|
95
|
+
});
|
|
96
|
+
server.tool("delete_project", "Delete a project - tears down its provisioned server, Coolify install, DNS, and all attached deployments/databases/services. This is irreversible. Returns 202 (async tear-down; status moves to `deleting` then `terminated`). Blocked with 409 if the project is still `pending`/`provisioning`/`deleting`, or if it has an active deployment with a running container - pause active deployments first.", {
|
|
97
|
+
project_pid: z.string().min(1),
|
|
98
|
+
name: z.string().optional().describe("Project name for the confirmation message (cosmetic)"),
|
|
99
|
+
confirm: z.boolean().describe("Must be true. Permanently destroys the server and everything in the project."),
|
|
100
|
+
}, async ({ project_pid, name, confirm }) => {
|
|
101
|
+
if (!requireOrg())
|
|
102
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
103
|
+
if (!confirm) {
|
|
104
|
+
const label = name ? `\`${name}\` (${project_pid})` : project_pid;
|
|
105
|
+
return {
|
|
106
|
+
content: [{
|
|
107
|
+
type: "text",
|
|
108
|
+
text: `⚠️ About to DELETE project ${label}. This destroys the provisioned server and ALL deployments, databases, and services inside it. There is no undo.\n\nPause any active deployments first, then call again with confirm=true.`,
|
|
109
|
+
}],
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const result = await apiRequest(`${PROJECTS_BASE}/${project_pid}`, {
|
|
113
|
+
method: "DELETE",
|
|
114
|
+
toolName: "delete_project",
|
|
115
|
+
});
|
|
116
|
+
if (!result.success) {
|
|
117
|
+
return { content: [{ type: "text", text: `Failed to delete project (${result.statusCode}): ${result.message}` }] };
|
|
118
|
+
}
|
|
119
|
+
return { content: [{ type: "text", text: "Project deletion started - status will move to `deleting` then disappear once tear-down completes." }] };
|
|
120
|
+
});
|
|
121
|
+
server.tool("get_project_metrics", "Get time-series infrastructure metrics for a project (server CPU/memory/disk/network, plus per-database and per-deployment container metrics) sourced from the project's monitoring agent heartbeats. Returns `agent_status`, `last_seen_at`, and a `batches` array. Each batch has `timestamp_ms` and `metric_sets`; a metric set with no `resource` belongs to the server, otherwise `resource.pid` identifies the database/service/deployment it describes. For a 'current' snapshot use a narrow window and read the newest batch. Heartbeats land ~every 25s, so poll no faster than ~30s.", {
|
|
122
|
+
project_pid: z.string().min(1),
|
|
123
|
+
start_date: z.string().regex(DATE_RE, "YYYY-MM-DD").optional().describe("Inclusive start date YYYY-MM-DD (default: 24h ago)"),
|
|
124
|
+
end_date: z.string().regex(DATE_RE, "YYYY-MM-DD").optional().describe("Inclusive end date YYYY-MM-DD (default: today)"),
|
|
125
|
+
}, async ({ project_pid, start_date, end_date }) => {
|
|
126
|
+
if (!requireOrg())
|
|
127
|
+
return { content: [{ type: "text", text: NO_ORG }] };
|
|
128
|
+
if (start_date && end_date && start_date > end_date) {
|
|
129
|
+
return { content: [{ type: "text", text: "Invalid date range: start_date must be on or before end_date." }] };
|
|
130
|
+
}
|
|
131
|
+
const result = await apiRequest(`${PROJECTS_BASE}/${project_pid}/metrics`, {
|
|
132
|
+
query: { start_date, end_date },
|
|
133
|
+
toolName: "get_project_metrics",
|
|
134
|
+
});
|
|
135
|
+
if (!result.success) {
|
|
136
|
+
return { content: [{ type: "text", text: `Failed to get project metrics (${result.statusCode}): ${result.message}` }] };
|
|
137
|
+
}
|
|
138
|
+
return { content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }] };
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=projects.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projects.js","sourceRoot":"","sources":["../../src/tools/projects.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/scaling.js
CHANGED
|
@@ -2,14 +2,14 @@ import { z } from "zod";
|
|
|
2
2
|
import { apiRequest } from "../client.js";
|
|
3
3
|
import { session } from "../session.js";
|
|
4
4
|
/**
|
|
5
|
-
* Scaling
|
|
5
|
+
* Scaling - manual one-off resize + auto-scaling policies.
|
|
6
6
|
*
|
|
7
7
|
* Endpoints:
|
|
8
|
-
* - PUT /aws/v1/instances/:id/scale
|
|
9
|
-
* - GET /scaling_policies
|
|
10
|
-
* - POST /scaling_policies
|
|
11
|
-
* - PATCH /scaling_policies/:id
|
|
12
|
-
* - DELETE /scaling_policies/:id
|
|
8
|
+
* - PUT /aws/v1/instances/:id/scale - manual scale
|
|
9
|
+
* - GET /scaling_policies - list (filterable by instance)
|
|
10
|
+
* - POST /scaling_policies - create
|
|
11
|
+
* - PATCH /scaling_policies/:id - update
|
|
12
|
+
* - DELETE /scaling_policies/:id - delete
|
|
13
13
|
*
|
|
14
14
|
* Scaling-policy actions: start_instance | stop_instance | resize_instance |
|
|
15
15
|
* expand_storage | add_replica | manual_scale.
|
|
@@ -41,7 +41,7 @@ const METRIC_NAMES = [
|
|
|
41
41
|
];
|
|
42
42
|
const COMPARISON_OPERATORS = [">", "<", ">=", "<="];
|
|
43
43
|
export function registerScalingTools(server) {
|
|
44
|
-
server.tool("scale_instance", "Manual one-off resize of an instance
|
|
44
|
+
server.tool("scale_instance", "Manual one-off resize of an instance - change instance type, volume type, size, IOPS, throughput. Only fields you pass are sent (PATCH-style). Response includes `scaling_event_id` you can poll on the instance status (`resizing` / `modifying_storage` → terminal state). Storage must grow, not shrink.", {
|
|
45
45
|
instance_id: z.string().min(1),
|
|
46
46
|
target_instance_type: z.string().optional()
|
|
47
47
|
.describe("e.g. t3.medium, m6i.xlarge, r7g.4xlarge"),
|
|
@@ -68,7 +68,7 @@ export function registerScalingTools(server) {
|
|
|
68
68
|
return {
|
|
69
69
|
content: [{
|
|
70
70
|
type: "text",
|
|
71
|
-
text: "Nothing to scale
|
|
71
|
+
text: "Nothing to scale - pass at least one of target_instance_type / new_size_gb / new_iops / new_throughput / new_volume_type.",
|
|
72
72
|
}],
|
|
73
73
|
};
|
|
74
74
|
}
|
|
@@ -135,7 +135,7 @@ export function registerScalingTools(server) {
|
|
|
135
135
|
metric_name: z.enum(METRIC_NAMES).optional(),
|
|
136
136
|
comparison_operator: z.enum(COMPARISON_OPERATORS).optional(),
|
|
137
137
|
threshold: z.number().optional()
|
|
138
|
-
.describe("0
|
|
138
|
+
.describe("0-100 for percentage metrics"),
|
|
139
139
|
duration_minutes: z.number().int().min(1).optional(),
|
|
140
140
|
cooldown_minutes: z.number().int().min(0).optional(),
|
|
141
141
|
// Scheduled / start-stop trigger
|
|
@@ -146,9 +146,9 @@ export function registerScalingTools(server) {
|
|
|
146
146
|
end_time: z.string().optional()
|
|
147
147
|
.describe("ISO 8601 window end"),
|
|
148
148
|
scheduled_start_time: z.string().optional()
|
|
149
|
-
.describe("HH:MM UTC
|
|
149
|
+
.describe("HH:MM UTC - only for action=start_instance"),
|
|
150
150
|
scheduled_stop_time: z.string().optional()
|
|
151
|
-
.describe("HH:MM UTC
|
|
151
|
+
.describe("HH:MM UTC - only for action=stop_instance"),
|
|
152
152
|
days_of_week: z.array(z.enum(["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"])).optional(),
|
|
153
153
|
timezone: z.string().optional().describe("Default UTC; BE supports UTC | EST | PST | GMT | CET"),
|
|
154
154
|
// Action-specific details
|
|
@@ -239,7 +239,7 @@ export function registerScalingTools(server) {
|
|
|
239
239
|
return {
|
|
240
240
|
content: [{
|
|
241
241
|
type: "text",
|
|
242
|
-
text: "No changes to apply
|
|
242
|
+
text: "No changes to apply - pass at least one field to update.",
|
|
243
243
|
}],
|
|
244
244
|
};
|
|
245
245
|
}
|
|
@@ -259,7 +259,7 @@ export function registerScalingTools(server) {
|
|
|
259
259
|
}
|
|
260
260
|
return { content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }] };
|
|
261
261
|
});
|
|
262
|
-
server.tool("delete_scaling_policy", "Delete a scaling policy. The associated instance is unaffected
|
|
262
|
+
server.tool("delete_scaling_policy", "Delete a scaling policy. The associated instance is unaffected - only the schedule / rule is removed.", {
|
|
263
263
|
policy_id: z.string().min(1),
|
|
264
264
|
confirm: z.boolean().describe("Must be true to proceed."),
|
|
265
265
|
}, async ({ policy_id, confirm }) => {
|
package/dist/types/models.js
CHANGED
package/dist/types/tiers.js
CHANGED
|
@@ -24,7 +24,7 @@ export const EXEMPT_TOOLS = new Set([
|
|
|
24
24
|
"list_regions",
|
|
25
25
|
"get_instance_types_for_region",
|
|
26
26
|
"list_storage_types",
|
|
27
|
-
// Provider / Hetzner reference data
|
|
27
|
+
// Provider / Hetzner reference data - static, no BE call
|
|
28
28
|
"list_cloud_providers",
|
|
29
29
|
"list_hetzner_locations",
|
|
30
30
|
"list_hetzner_server_types",
|
|
@@ -107,6 +107,36 @@ export const WRITE_TOOLS = new Set([
|
|
|
107
107
|
"delete_agent_token",
|
|
108
108
|
"admin_revoke_invitation",
|
|
109
109
|
"admin_grant_credits",
|
|
110
|
+
// PaaS - Projects (Module 15)
|
|
111
|
+
"create_project",
|
|
112
|
+
"update_project",
|
|
113
|
+
"delete_project",
|
|
114
|
+
// PaaS - Deployments (Module 16)
|
|
115
|
+
"create_deployment",
|
|
116
|
+
"update_deployment",
|
|
117
|
+
"update_deployment_build_config",
|
|
118
|
+
"delete_deployment",
|
|
119
|
+
"trigger_deploy",
|
|
120
|
+
"redeploy_run",
|
|
121
|
+
"rollback_run",
|
|
122
|
+
// PaaS - Custom domains (Module 17)
|
|
123
|
+
"sync_deployment_domains",
|
|
124
|
+
"add_deployment_domain",
|
|
125
|
+
"remove_deployment_domain",
|
|
126
|
+
"verify_custom_domain",
|
|
127
|
+
// PaaS - Environment variables (Module 18)
|
|
128
|
+
"set_env_vars",
|
|
129
|
+
"merge_env_vars",
|
|
130
|
+
"delete_env_var",
|
|
131
|
+
// PaaS - Project databases (Module 20)
|
|
132
|
+
"create_project_database",
|
|
133
|
+
"delete_project_database",
|
|
134
|
+
// PaaS - Project services (Module 21)
|
|
135
|
+
"create_project_service",
|
|
136
|
+
"delete_project_service",
|
|
137
|
+
// PaaS - Deployment notifications (Module 22)
|
|
138
|
+
"bind_deployment_notification_channel",
|
|
139
|
+
"unbind_deployment_notification_channel",
|
|
110
140
|
]);
|
|
111
141
|
export function categorizeOperation(toolName) {
|
|
112
142
|
if (EXEMPT_TOOLS.has(toolName))
|
package/dist/types/tiers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tiers.js","sourceRoot":"","sources":["../../src/types/tiers.ts"],"names":[],"mappings":"AAaA,MAAM,CAAC,MAAM,YAAY,GAAmD;IAC1E,IAAI,EAAE;QACJ,UAAU,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAE;QAC3C,WAAW,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE;QAC/C,aAAa,EAAE,CAAC;KACjB;IACD,OAAO,EAAE;QACP,UAAU,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,aAAa,EAAE,GAAG,EAAE;QAC7C,WAAW,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE;QAC/C,aAAa,EAAE,CAAC;KACjB;IACD,GAAG,EAAE;QACH,UAAU,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAE;QAC3C,WAAW,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAE;QAC5C,aAAa,EAAE,EAAE;KAClB;IACD,UAAU,EAAE;QACV,UAAU,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,EAAE,EAAE;QAC7C,WAAW,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAE;QAC5C,aAAa,EAAE,QAAQ;KACxB;CACF,CAAC;AAIF,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC;IAClC,cAAc;IACd,+BAA+B;IAC/B,oBAAoB;IACpB,yDAAyD;IACzD,sBAAsB;IACtB,wBAAwB;IACxB,2BAA2B;CAC5B,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC;IACjC,sBAAsB;IACtB,sBAAsB;IACtB,qBAAqB;IACrB,qBAAqB;IACrB,qBAAqB;IACrB,eAAe;IACf,eAAe;IACf,mBAAmB;IACnB,gBAAgB;IAChB,mBAAmB;IACnB,mBAAmB;IACnB,wBAAwB;IACxB,YAAY;IACZ,YAAY;IACZ,eAAe;IACf,uBAAuB;IACvB,uBAAuB;IACvB,iBAAiB;IACjB,iBAAiB;IACjB,eAAe;IACf,gBAAgB;IAChB,iBAAiB;IACjB,iBAAiB;IACjB,eAAe;IACf,gBAAgB;IAChB,iBAAiB;IACjB,kBAAkB;IAClB,eAAe;IACf,eAAe;IACf,sBAAsB;IACtB,sBAAsB;IACtB,sBAAsB;IACtB,iBAAiB;IACjB,iBAAiB;IACjB,mBAAmB;IACnB,mBAAmB;IACnB,mBAAmB;IACnB,mBAAmB;IACnB,eAAe;IACf,6BAA6B;IAC7B,6BAA6B;IAC7B,6BAA6B;IAC7B,2BAA2B;IAC3B,uBAAuB;IACvB,uBAAuB;IACvB,uBAAuB;IACvB,uBAAuB;IACvB,kBAAkB;IAClB,uBAAuB;IACvB,mBAAmB;IACnB,6BAA6B;IAC7B,sBAAsB;IACtB,sBAAsB;IACtB,sBAAsB;IACtB,+BAA+B;IAC/B,mBAAmB;IACnB,aAAa;IACb,gBAAgB;IAChB,YAAY;IACZ,0BAA0B;IAC1B,cAAc;IACd,sBAAsB;IACtB,qBAAqB;IACrB,qBAAqB;IACrB,qBAAqB;IACrB,6BAA6B;IAC7B,wBAAwB;IACxB,sBAAsB;IACtB,yBAAyB;IACzB,yBAAyB;IACzB,gBAAgB;IAChB,gBAAgB;IAChB,gBAAgB;IAChB,oBAAoB;IACpB,oBAAoB;IACpB,yBAAyB;IACzB,qBAAqB;
|
|
1
|
+
{"version":3,"file":"tiers.js","sourceRoot":"","sources":["../../src/types/tiers.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@selfhost.dev/mcp-server",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "MCP server for SelfHost.dev
|
|
3
|
+
"version": "0.4.1",
|
|
4
|
+
"description": "MCP server for SelfHost.dev - provision managed databases and deploy apps (PaaS) via natural language",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|
|
@@ -24,7 +24,14 @@
|
|
|
24
24
|
"cheap managed databases",
|
|
25
25
|
"cost efficient managed databases",
|
|
26
26
|
"SelfHost",
|
|
27
|
-
"cloudSql"
|
|
27
|
+
"cloudSql",
|
|
28
|
+
"paas",
|
|
29
|
+
"deploy",
|
|
30
|
+
"deployment",
|
|
31
|
+
"github",
|
|
32
|
+
"app hosting",
|
|
33
|
+
"deploy app",
|
|
34
|
+
"coolify"
|
|
28
35
|
],
|
|
29
36
|
"license": "MIT",
|
|
30
37
|
"engines": {
|