@selfhost.dev/mcp-server 0.2.0 → 0.4.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.
Files changed (36) hide show
  1. package/README.md +123 -22
  2. package/dist/index.js +31 -3
  3. package/dist/index.js.map +1 -1
  4. package/dist/tools/auth.js +0 -11
  5. package/dist/tools/auth.js.map +1 -1
  6. package/dist/tools/deployment-domains.d.ts +2 -0
  7. package/dist/tools/deployment-domains.js +128 -0
  8. package/dist/tools/deployment-domains.js.map +1 -0
  9. package/dist/tools/deployment-notifications.d.ts +2 -0
  10. package/dist/tools/deployment-notifications.js +74 -0
  11. package/dist/tools/deployment-notifications.js.map +1 -0
  12. package/dist/tools/deployments.d.ts +2 -0
  13. package/dist/tools/deployments.js +302 -0
  14. package/dist/tools/deployments.js.map +1 -0
  15. package/dist/tools/env-vars.d.ts +2 -0
  16. package/dist/tools/env-vars.js +121 -0
  17. package/dist/tools/env-vars.js.map +1 -0
  18. package/dist/tools/github.d.ts +2 -0
  19. package/dist/tools/github.js +106 -0
  20. package/dist/tools/github.js.map +1 -0
  21. package/dist/tools/hetzner.d.ts +2 -0
  22. package/dist/tools/hetzner.js +263 -0
  23. package/dist/tools/hetzner.js.map +1 -0
  24. package/dist/tools/instances.js +1 -1
  25. package/dist/tools/project-databases.d.ts +2 -0
  26. package/dist/tools/project-databases.js +169 -0
  27. package/dist/tools/project-databases.js.map +1 -0
  28. package/dist/tools/project-services.d.ts +2 -0
  29. package/dist/tools/project-services.js +94 -0
  30. package/dist/tools/project-services.js.map +1 -0
  31. package/dist/tools/projects.d.ts +2 -0
  32. package/dist/tools/projects.js +141 -0
  33. package/dist/tools/projects.js.map +1 -0
  34. package/dist/types/tiers.js +37 -1
  35. package/dist/types/tiers.js.map +1 -1
  36. package/package.json +10 -3
@@ -0,0 +1,263 @@
1
+ import { z } from "zod";
2
+ import { apiRequest } from "../client.js";
3
+ import { session } from "../session.js";
4
+ /**
5
+ * Hetzner Cloud — Postgres-only provisioning.
6
+ *
7
+ * Backend endpoints (added in selfhost-dev/selfhost PR #983):
8
+ * - POST /hetzner/v1/instances — provision
9
+ * - GET /hetzner/v1/instances/:pid — read
10
+ * - GET /hetzner/v1/instances/:pid/status — provisioning progress
11
+ * - DELETE /hetzner/v1/instances/:pid — destroy
12
+ *
13
+ * Limitations vs AWS today:
14
+ * - Postgres only (no MySQL, no MongoDB)
15
+ * - No list endpoint — callers must keep track of `pid` after create
16
+ * - No start / stop / reboot / update / fork
17
+ * - No scaling, no PITR, no PgBouncer, no database-user management
18
+ *
19
+ * Locations + server types are hardcoded here to mirror the Rails CLI
20
+ * registry. When the backend ships discovery endpoints we'll switch these
21
+ * tools over.
22
+ */
23
+ function resolveOrgId(organization_id) {
24
+ return organization_id || session.getActiveOrgId();
25
+ }
26
+ const noOrgMessage = "No organization selected. Call `select_organization` first or pass an organization_id.";
27
+ // --- Static reference data ---------------------------------------------------
28
+ const CLOUD_PROVIDERS = [
29
+ {
30
+ id: "aws",
31
+ name: "Amazon Web Services (AWS)",
32
+ capabilities: "Full lifecycle: create / list / start / stop / reboot / update / fork / delete; multi-AZ; replicas; auto-scaling; scheduled scaling; PITR; PgBouncer; database users; alerts; backup policies.",
33
+ create_tool: "create_instance",
34
+ list_tool: "list_instances",
35
+ notes: "Production-ready. Use for any workload that needs HA, replicas, or any of the lifecycle ops above. Available in 20+ AWS regions.",
36
+ },
37
+ {
38
+ id: "hetzner",
39
+ name: "Hetzner Cloud",
40
+ capabilities: "Provisioning only: create / read / status / delete. No start / stop / reboot / update / fork; no scaling; no PITR; no PgBouncer; no database users; no alerts.",
41
+ create_tool: "create_hetzner_instance",
42
+ list_tool: null,
43
+ notes: "Cheaper than AWS for Postgres workloads but BE feature surface is currently limited. Use only when the user explicitly asks for Hetzner. Postgres only.",
44
+ },
45
+ ];
46
+ const HETZNER_LOCATIONS = [
47
+ { code: "fsn1", name: "Falkenstein", country: "Germany", continent: "Europe" },
48
+ { code: "nbg1", name: "Nuremberg", country: "Germany", continent: "Europe" },
49
+ { code: "hel1", name: "Helsinki", country: "Finland", continent: "Europe" },
50
+ { code: "ash", name: "Ashburn, VA", country: "United States", continent: "North America" },
51
+ { code: "sin", name: "Singapore", country: "Singapore", continent: "Asia" },
52
+ ];
53
+ const HETZNER_SERVER_TYPES = [
54
+ { code: "cpx11", vcpu: 2, memory_gb: 2, disk_gb: 40, cpu_family: "AMD" },
55
+ { code: "cpx21", vcpu: 3, memory_gb: 4, disk_gb: 80, cpu_family: "AMD" },
56
+ { code: "cpx22", vcpu: 4, memory_gb: 4, disk_gb: 80, cpu_family: "AMD" },
57
+ { code: "cpx31", vcpu: 4, memory_gb: 8, disk_gb: 160, cpu_family: "AMD" },
58
+ { code: "cpx42", vcpu: 8, memory_gb: 16, disk_gb: 240, cpu_family: "AMD" },
59
+ { code: "cpx51", vcpu: 16, memory_gb: 32, disk_gb: 360, cpu_family: "AMD" },
60
+ ];
61
+ // --- Schemas -----------------------------------------------------------------
62
+ const cidrRangeSchema = z.object({
63
+ cidr: z.string().min(1).describe("CIDR range, e.g. 10.0.0.0/24"),
64
+ name: z.string().optional().describe("Friendly label"),
65
+ port: z.number().int().optional().describe("Port allowed by this rule (default: 5432)"),
66
+ description: z.string().optional(),
67
+ });
68
+ const LOCATION_CODES = HETZNER_LOCATIONS.map((l) => l.code);
69
+ const SERVER_TYPE_CODES = HETZNER_SERVER_TYPES.map((s) => s.code);
70
+ // --- Registration ------------------------------------------------------------
71
+ export function registerHetznerTools(server) {
72
+ // ----- Provider discovery -------------------------------------------------
73
+ server.tool("list_cloud_providers", "List the cloud providers SelfHost can provision Postgres on. Call this whenever the user expresses an intent to create a database — present the options and ask which one they want before choosing the create tool. The response includes capabilities and the specific create tool for each provider.", {}, async () => {
74
+ return {
75
+ content: [
76
+ { type: "text", text: JSON.stringify(CLOUD_PROVIDERS, null, 2) },
77
+ ],
78
+ };
79
+ });
80
+ server.tool("list_hetzner_locations", "List the Hetzner Cloud locations (datacenters) available for provisioning. Returns an array of `{code, name, country, continent}`. The `code` is what `create_hetzner_instance` expects for its `region` param. Ask the user which one they want before creating.", {}, async () => {
81
+ return {
82
+ content: [
83
+ { type: "text", text: JSON.stringify(HETZNER_LOCATIONS, null, 2) },
84
+ ],
85
+ };
86
+ });
87
+ server.tool("list_hetzner_server_types", "List the Hetzner Cloud server types available for Postgres. Returns an array of `{code, vcpu, memory_gb, disk_gb, cpu_family}`. The `code` is what `create_hetzner_instance` expects for its `server_type` param. Note: `disk_gb` is the server's local disk; the database storage is a separately-attached Hetzner Volume sized via the `storage_size` param at create time.", {}, async () => {
88
+ return {
89
+ content: [
90
+ { type: "text", text: JSON.stringify(HETZNER_SERVER_TYPES, null, 2) },
91
+ ],
92
+ };
93
+ });
94
+ // ----- Provisioning -------------------------------------------------------
95
+ server.tool("create_hetzner_instance", `Provision a new Postgres database on Hetzner Cloud.
96
+
97
+ RECOMMENDED FLOW:
98
+ 1. Call \`list_cloud_providers\` and ask the user which provider they want.
99
+ 2. If Hetzner: call \`list_hetzner_locations\` and let the user pick a region.
100
+ 3. Call \`list_hetzner_server_types\` and let the user pick a size.
101
+ 4. Confirm storage_size (separate Hetzner Volume, in GB).
102
+ 5. Then call this tool.
103
+
104
+ IMPORTANT:
105
+ - The password returned in the response is shown ONCE. Save it immediately — there's no way to retrieve it.
106
+ - Hetzner integration is currently provision/delete only. After creation, use \`get_hetzner_instance_status\` to poll provisioning progress, and \`get_hetzner_instance\` to read details. To remove it, use \`delete_hetzner_instance\`.
107
+ - Provisioning takes ~5-10 minutes (network + firewall + SSH key + server + volume + load balancer + Ansible/autobase playbook + Cloudflare DNS).`, {
108
+ organization_id: z.string().optional()
109
+ .describe("Organization PID (defaults to active org)"),
110
+ name: z.string().min(1).max(63)
111
+ .describe("Instance name (used for DNS host)"),
112
+ region: z.enum(LOCATION_CODES)
113
+ .describe("Hetzner location code — call list_hetzner_locations to see options"),
114
+ server_type: z.enum(SERVER_TYPE_CODES)
115
+ .describe("Hetzner server type — call list_hetzner_server_types to see options"),
116
+ storage_size: z.number().int().min(10).max(10240)
117
+ .describe("Database storage size in GB (Hetzner Volume, separate from server local disk)"),
118
+ db_version: z.string().optional()
119
+ .describe("Postgres version (default: 18)"),
120
+ high_availability: z.boolean().optional()
121
+ .describe("Provision a 3-node cluster with a load balancer (extra ~€5/mo). Default: false (single-node, public IP only)"),
122
+ public_access: z.boolean().optional()
123
+ .describe("Expose port 5432 to the internet (default: true). Combine with allowed_cidr_ranges to restrict."),
124
+ backup_enabled: z.boolean().optional()
125
+ .describe("Enable automated backups (default: true)"),
126
+ username: z.string().regex(/^[a-z_][a-z0-9_]{0,30}$/i).optional()
127
+ .describe("Database username (default: postgres)"),
128
+ delete_protection: z.boolean().optional()
129
+ .describe("Prevent accidental deletion (recommended for production)"),
130
+ allowed_cidr_ranges: z.array(cidrRangeSchema).max(24).optional()
131
+ .describe("IP whitelist on port 5432 (max 24 ranges). Merged with the internal 10.0.0.0/16 rule."),
132
+ }, async (params) => {
133
+ const orgId = resolveOrgId(params.organization_id);
134
+ if (!orgId) {
135
+ return { content: [{ type: "text", text: noOrgMessage }] };
136
+ }
137
+ const body = {
138
+ organization_id: orgId,
139
+ name: params.name,
140
+ region: params.region,
141
+ server_type: params.server_type,
142
+ storage_size: params.storage_size,
143
+ };
144
+ if (params.db_version !== undefined)
145
+ body.db_version = params.db_version;
146
+ if (params.high_availability !== undefined)
147
+ body.high_availability = params.high_availability;
148
+ if (params.public_access !== undefined)
149
+ body.public_access = params.public_access;
150
+ if (params.backup_enabled !== undefined)
151
+ body.backup_enabled = params.backup_enabled;
152
+ if (params.username !== undefined)
153
+ body.username = params.username;
154
+ if (params.delete_protection !== undefined)
155
+ body.delete_protection = params.delete_protection;
156
+ if (params.allowed_cidr_ranges !== undefined)
157
+ body.allowed_cidr_ranges = params.allowed_cidr_ranges;
158
+ const result = await apiRequest("/hetzner/v1/instances", {
159
+ method: "POST",
160
+ body,
161
+ toolName: "create_hetzner_instance",
162
+ skipOrgInjection: true,
163
+ });
164
+ if (!result.success) {
165
+ return {
166
+ content: [{
167
+ type: "text",
168
+ text: `Failed to create Hetzner instance (${result.statusCode}): ${result.message}`,
169
+ }],
170
+ };
171
+ }
172
+ const data = result.data;
173
+ const lines = [
174
+ "Hetzner instance provisioning started!",
175
+ "",
176
+ `PID: ${data.pid}`,
177
+ ];
178
+ if (data.host)
179
+ lines.push(`Host: ${data.host}`);
180
+ if (data.username)
181
+ lines.push(`Username: ${data.username}`);
182
+ if (data.password) {
183
+ lines.push(`Password: ${data.password}`);
184
+ lines.push("");
185
+ lines.push("⚠️ SAVE THIS PASSWORD NOW — it cannot be retrieved again.");
186
+ }
187
+ lines.push("");
188
+ lines.push(`Poll provisioning progress with \`get_hetzner_instance_status\` (pid: ${data.pid}). Provisioning typically takes 5–10 minutes.`);
189
+ return {
190
+ content: [
191
+ { type: "text", text: lines.join("\n") },
192
+ { type: "text", text: JSON.stringify(data, null, 2) },
193
+ ],
194
+ };
195
+ });
196
+ server.tool("get_hetzner_instance", "Get details for a single Hetzner instance by PID. Returns the full record including name, region, server_type, storage_size, high_availability, public_access, host (DNS name), and creation timestamps.", {
197
+ pid: z.string().min(1).describe("Hetzner instance PID (returned by create_hetzner_instance)"),
198
+ }, async ({ pid }) => {
199
+ const result = await apiRequest(`/hetzner/v1/instances/${pid}`, {
200
+ toolName: "get_hetzner_instance",
201
+ skipOrgInjection: true,
202
+ });
203
+ if (!result.success) {
204
+ return {
205
+ content: [{
206
+ type: "text",
207
+ text: `Failed to get Hetzner instance (${result.statusCode}): ${result.message}`,
208
+ }],
209
+ };
210
+ }
211
+ return { content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }] };
212
+ });
213
+ server.tool("get_hetzner_instance_status", "Poll the provisioning progress of a Hetzner instance. Returns `{pid, status, progress: {step_name: 'completed' | 'pending', ...}}`. Use this after `create_hetzner_instance` until `status` is terminal (e.g. `running` or `failed`). Steps include network, firewall, ssh_key, server, volume, load_balancer (HA only), ansible, finalize.", {
214
+ pid: z.string().min(1),
215
+ }, async ({ pid }) => {
216
+ const result = await apiRequest(`/hetzner/v1/instances/${pid}/status`, {
217
+ toolName: "get_hetzner_instance_status",
218
+ skipOrgInjection: true,
219
+ });
220
+ if (!result.success) {
221
+ return {
222
+ content: [{
223
+ type: "text",
224
+ text: `Failed to get Hetzner instance status (${result.statusCode}): ${result.message}`,
225
+ }],
226
+ };
227
+ }
228
+ return { content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }] };
229
+ });
230
+ server.tool("delete_hetzner_instance", "Delete a Hetzner instance and all associated resources (server, volume, firewall, network, load balancer if HA, DNS record). IRREVERSIBLE — there's no `start` / `stop` on Hetzner; deletion is the only way to remove an instance.", {
231
+ pid: z.string().min(1),
232
+ confirm: z.boolean().describe("Must be true to proceed. ALL DATA on this instance will be permanently lost."),
233
+ }, async ({ pid, confirm }) => {
234
+ if (!confirm) {
235
+ return {
236
+ content: [{
237
+ type: "text",
238
+ text: `⚠️ About to DELETE Hetzner instance ${pid}.\n\nThis action is IRREVERSIBLE. Server, volume, firewall, network, load balancer, and DNS records will all be removed. All data will be lost.\n\nCall again with confirm=true to proceed.`,
239
+ }],
240
+ };
241
+ }
242
+ const result = await apiRequest(`/hetzner/v1/instances/${pid}`, {
243
+ method: "DELETE",
244
+ toolName: "delete_hetzner_instance",
245
+ skipOrgInjection: true,
246
+ });
247
+ if (!result.success) {
248
+ return {
249
+ content: [{
250
+ type: "text",
251
+ text: `Failed to delete Hetzner instance (${result.statusCode}): ${result.message}`,
252
+ }],
253
+ };
254
+ }
255
+ return {
256
+ content: [
257
+ { type: "text", text: `Hetzner instance ${pid} delete requested. Resources are being torn down.` },
258
+ { type: "text", text: JSON.stringify(result.data, null, 2) },
259
+ ],
260
+ };
261
+ });
262
+ }
263
+ //# sourceMappingURL=hetzner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hetzner.js","sourceRoot":"","sources":["../../src/tools/hetzner.ts"],"names":[],"mappings":"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"}
@@ -179,7 +179,7 @@ Returns an itemized cost breakdown including compute, storage, markup, and add-o
179
179
  return { content: [{ type: "text", text: lines.join("\n") }] };
180
180
  });
181
181
  // --- Instance lifecycle tools ---
182
- server.tool("create_instance", `Create a new database instance. This is the core provisioning tool.
182
+ server.tool("create_instance", `Create a new database instance on AWS. This is the core AWS provisioning tool. For Hetzner Cloud, use \`create_hetzner_instance\` instead — call \`list_cloud_providers\` first to confirm which provider the user wants.
183
183
 
184
184
  RECOMMENDED FLOW (follow this before calling create_instance):
185
185
  1. Ask the user: host on SelfHost's cloud (platform-managed) or their own AWS account (BYOC)?
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerProjectDatabaseTools(server: McpServer): void;
@@ -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` defaults to true, which exposes the database on `public_port` - set it false to keep the DB internal to the project.", {
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().optional().describe("Expose the DB on a public port (default true)"),
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 ?? true;
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":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC;;;;;;;;;;;;GAYG;AAEH,MAAM,aAAa,GAAG,2BAA2B,CAAC;AAClD,MAAM,QAAQ,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,CAAU,CAAC;AAGpE,uEAAuE;AACvE,MAAM,WAAW,GAAG,yCAAyC,CAAC;AAC9D,MAAM,aAAa,GAA2B,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAE3G,MAAM,MAAM,GACV,qFAAqF,CAAC;AAExF,SAAS,MAAM;IACb,OAAO,OAAO,CAAC,cAAc,EAAE,KAAK,IAAI,CAAC;AAC3C,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,aAAa,CAAC,KAAa,EAAE,CAAqB;IACzD,IAAI,CAAC,CAAC;QAAE,OAAO,GAAG,KAAK,sCAAsC,CAAC;IAC9D,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,GAAG,KAAK,iCAAiC,CAAC;IACnE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,GAAG,KAAK,oEAAoE,CAAC;IAC9G,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,MAAiB;IAC5D,MAAM,CAAC,IAAI,CACT,wBAAwB,EACxB,kRAAkR,EAClR;QACE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;KAC/B,EACD,KAAK,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE;QACxB,IAAI,CAAC,MAAM,EAAE;YAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;QACpE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAU,GAAG,aAAa,IAAI,WAAW,YAAY,EAAE;YACpF,QAAQ,EAAE,wBAAwB;SACnC,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,qCAAqC,MAAM,CAAC,UAAU,MAAM,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;QAC7H,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACrF,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,yBAAyB,EACzB,gaAAga,EACha;QACE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9B,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,oCAAoC,CAAC;QACxE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;QAChC,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+CAA+C,CAAC;QAC3F,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qFAAqF,CAAC;QAC7J,WAAW;QACX,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;QAC7C,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QACxC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;QAC3C,QAAQ;QACR,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QACrC,QAAQ;QACR,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;QAC1C,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QACrC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;QAC9C,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC1C,UAAU;QACV,0BAA0B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;QAC1D,0BAA0B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QACjD,qBAAqB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;KACtD,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC,MAAM,EAAE;YAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;QACpE,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC;QACxC,MAAM,IAAI,GAA4B,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;QAC/E,IAAI,QAAQ;YAAE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;QAE3E,IAAI,GAAG,GAAkB,IAAI,CAAC;QAC9B,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,UAAU;gBACb,GAAG,GAAG,aAAa,CAAC,mBAAmB,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC;gBACjE,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa;oBAAE,GAAG,GAAG,4BAA4B,CAAC;gBACpE,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW;oBAAE,GAAG,GAAG,0BAA0B,CAAC;gBAChE,IAAI,CAAC,GAAG,EAAE,CAAC;oBACT,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;oBACxC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,CAAC;oBAChD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;oBACpC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;gBAC7B,CAAC;gBACD,MAAM;YACR,KAAK,OAAO;gBACV,GAAG,GAAG,aAAa,CAAC,gBAAgB,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;gBAC3D,IAAI,CAAC,GAAG,EAAE,CAAC;oBACT,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC;oBAC1C,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;gBAC7B,CAAC;gBACD,MAAM;YACR,KAAK,OAAO;gBACV,GAAG,GAAG,aAAa,CAAC,gBAAgB,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,aAAa,CAAC,qBAAqB,EAAE,IAAI,CAAC,mBAAmB,CAAC,CAAC;gBAC7H,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU;oBAAE,GAAG,GAAG,yBAAyB,CAAC;gBAC9D,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc;oBAAE,GAAG,GAAG,6BAA6B,CAAC;gBACtE,IAAI,CAAC,GAAG,EAAE,CAAC;oBACT,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;oBAClC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC;oBAC1C,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC;oBAC1C,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,mBAAmB,CAAC;oBACpD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;gBAC7B,CAAC;gBACD,MAAM;YACR,KAAK,SAAS;gBACZ,GAAG,GAAG,aAAa,CAAC,4BAA4B,EAAE,IAAI,CAAC,0BAA0B,CAAC,CAAC;gBACnF,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,0BAA0B;oBAAE,GAAG,GAAG,yCAAyC,CAAC;gBAC9F,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,qBAAqB;oBAAE,GAAG,GAAG,oCAAoC,CAAC;gBACpF,IAAI,CAAC,GAAG,EAAE,CAAC;oBACT,IAAI,CAAC,0BAA0B,GAAG,IAAI,CAAC,0BAA0B,CAAC;oBAClE,IAAI,CAAC,0BAA0B,GAAG,IAAI,CAAC,0BAA0B,CAAC;oBAClE,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC,qBAAqB,CAAC;gBAC1D,CAAC;gBACD,MAAM;QACV,CAAC;QACD,IAAI,GAAG;YAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;QAE3D,MAAM,MAAM,GAAG,MAAM,UAAU,CAAU,GAAG,aAAa,IAAI,IAAI,CAAC,WAAW,cAAc,UAAU,CAAC,MAAM,CAAC,EAAE,EAAE;YAC/G,MAAM,EAAE,MAAM;YACd,IAAI;YACJ,QAAQ,EAAE,yBAAyB;SACpC,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,8BAA8B,MAAM,CAAC,UAAU,MAAM,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;QACtH,CAAC;QACD,OAAO;YACL,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,IAAI,CAAC,IAAI,OAAO,MAAM,qFAAqF,EAAE;gBACjJ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;aAC7D;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,yBAAyB,EACzB,8JAA8J,EAC9J;QACE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9B,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,0CAA0C,CAAC;QAC5E,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,+DAA+D,CAAC;KAC/F,EACD,KAAK,EAAE,EAAE,WAAW,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE;QACrD,IAAI,CAAC,MAAM,EAAE;YAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;QACpE,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,kCAAkC,IAAI,OAAO,YAAY,qFAAqF,EAAE,CAAC,EAAE,CAAC;QAC/L,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,UAAU,CAAU,GAAG,aAAa,IAAI,WAAW,cAAc,YAAY,EAAE,EAAE;YACpG,MAAM,EAAE,QAAQ;YAChB,IAAI,EAAE,EAAE,IAAI,EAAE;YACd,QAAQ,EAAE,yBAAyB;SACpC,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,8BAA8B,MAAM,CAAC,UAAU,MAAM,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;QACtH,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,2BAA2B,EAAE,CAAC,EAAE,CAAC;IAC5E,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerProjectServiceTools(server: McpServer): void;
@@ -0,0 +1,94 @@
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.", {
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().optional().describe("Expose publicly (default true)"),
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
+ };
53
+ if (is_public !== undefined)
54
+ body.is_public = is_public;
55
+ if (public_port !== undefined)
56
+ body.public_port = public_port;
57
+ const result = await apiRequest(`${PROJECTS_BASE}/${project_pid}/services/${template_type}`, {
58
+ method: "POST",
59
+ body,
60
+ toolName: "create_project_service",
61
+ });
62
+ if (!result.success) {
63
+ return { content: [{ type: "text", text: `Failed to create service (${result.statusCode}): ${result.message}` }] };
64
+ }
65
+ return {
66
+ content: [
67
+ { type: "text", text: `Service \`${name}\` (${template_type}) provisioning started. Poll \`list_project_services\` until status is \`active\`.` },
68
+ { type: "text", text: JSON.stringify(result.data, null, 2) },
69
+ ],
70
+ };
71
+ });
72
+ 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.", {
73
+ project_pid: z.string().min(1),
74
+ service_pid: z.string().min(1),
75
+ name: z.string().min(1).describe("Exact current service name - must match"),
76
+ confirm: z.boolean().describe("Must be true. Permanently destroys the service and its data."),
77
+ }, async ({ project_pid, service_pid, name, confirm }) => {
78
+ if (!hasOrg())
79
+ return { content: [{ type: "text", text: NO_ORG }] };
80
+ if (!confirm) {
81
+ 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.` }] };
82
+ }
83
+ const result = await apiRequest(`${PROJECTS_BASE}/${project_pid}/services/${service_pid}`, {
84
+ method: "DELETE",
85
+ body: { name },
86
+ toolName: "delete_project_service",
87
+ });
88
+ if (!result.success) {
89
+ return { content: [{ type: "text", text: `Failed to delete service (${result.statusCode}): ${result.message}` }] };
90
+ }
91
+ return { content: [{ type: "text", text: "Service deletion queued." }] };
92
+ });
93
+ }
94
+ //# 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,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerProjectTools(server: McpServer): void;