helipod-mcp 0.5.9 → 0.5.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/http.js +47 -31
- package/dist/index.js +47 -31
- package/dist/stdio.js +47 -31
- package/package.json +1 -1
package/dist/http.js
CHANGED
|
@@ -36281,6 +36281,10 @@ var period = exports_external.enum(["monthly", "3month", "6month", "yearly"]);
|
|
|
36281
36281
|
var pointId = exports_external.string().describe("Restore point id (from list_vps_restore_points)");
|
|
36282
36282
|
var backupPath = exports_external.string().max(1024).describe("Absolute path inside the backup, e.g. /etc/nginx or /var/www/index.html");
|
|
36283
36283
|
var migrationId = exports_external.string().describe("Migration id (from list_vps_migrations)");
|
|
36284
|
+
var dryRun2 = exports_external.boolean().optional().describe("true = return the price (IDR) and the wallet balance after it; nothing is charged or changed");
|
|
36285
|
+
var idempotencyKey = exports_external.string().regex(/^[A-Za-z0-9_.:-]{8,128}$/).optional().describe("Idempotency-Key for the real call. Generated when omitted; pass the same value when retrying so it is never charged twice");
|
|
36286
|
+
var DRY = "dryRun=true returns the price and walletBalanceAfter without charging or changing anything.";
|
|
36287
|
+
var dryQuery = (d) => ({ dryRun: d ? "true" : undefined });
|
|
36284
36288
|
var vpsTools = [
|
|
36285
36289
|
defineTool({
|
|
36286
36290
|
name: "list_vps_plans",
|
|
@@ -36310,7 +36314,7 @@ var vpsTools = [
|
|
|
36310
36314
|
name: "create_vps",
|
|
36311
36315
|
title: "Create VPS",
|
|
36312
36316
|
kind: "write",
|
|
36313
|
-
description:
|
|
36317
|
+
description: `Order a server. COSTS MONEY right away (the whole billing period is charged from the wallet; refunded if provisioning fails). Call with dryRun=true first, show the price and the wallet after it, and get the user's explicit OK. ${DRY} autoRenew=false creates it with auto-renew off (renew it with renew_vps). Provisioning takes a few minutes: poll get_vps.`,
|
|
36314
36318
|
input: {
|
|
36315
36319
|
projectId: exports_external.string().uuid(),
|
|
36316
36320
|
planId: exports_external.string(),
|
|
@@ -36318,9 +36322,12 @@ var vpsTools = [
|
|
|
36318
36322
|
osType: exports_external.string().describe("From the plan's osTemplates, e.g. ubuntu"),
|
|
36319
36323
|
osVersion: exports_external.string().describe("e.g. 24.04"),
|
|
36320
36324
|
rootPassword: password,
|
|
36321
|
-
billingPeriod: period.optional().describe("Default monthly")
|
|
36325
|
+
billingPeriod: period.optional().describe("Default monthly"),
|
|
36326
|
+
autoRenew: exports_external.boolean().optional().describe("false = no automatic renewal from the wallet (default true)"),
|
|
36327
|
+
dryRun: dryRun2,
|
|
36328
|
+
idempotencyKey
|
|
36322
36329
|
},
|
|
36323
|
-
run: (
|
|
36330
|
+
run: ({ dryRun: dryRun3, idempotencyKey: idempotencyKey2, ...body }, api2) => api2.api("POST", "/vps", { body, query: dryQuery(dryRun3), idempotencyKey: purchaseKey(dryRun3, idempotencyKey2) })
|
|
36324
36331
|
}),
|
|
36325
36332
|
defineTool({
|
|
36326
36333
|
name: "vps_power",
|
|
@@ -36374,17 +36381,17 @@ var vpsTools = [
|
|
|
36374
36381
|
name: "renew_vps",
|
|
36375
36382
|
title: "Renew VPS",
|
|
36376
36383
|
kind: "write",
|
|
36377
|
-
description:
|
|
36378
|
-
input: { vpsId, billingPeriod: period },
|
|
36379
|
-
run: (a, api2) => api2.api("POST", `/vps/${a.vpsId}/renew`, { body: { billingPeriod: a.billingPeriod } })
|
|
36384
|
+
description: `Extend a server's paid period. COSTS MONEY: call with dryRun=true first, show the price and the wallet after it, and get the user's OK. ${DRY}`,
|
|
36385
|
+
input: { vpsId, billingPeriod: period, dryRun: dryRun2, idempotencyKey },
|
|
36386
|
+
run: (a, api2) => api2.api("POST", `/vps/${a.vpsId}/renew`, { body: { billingPeriod: a.billingPeriod }, query: dryQuery(a.dryRun), idempotencyKey: purchaseKey(a.dryRun, a.idempotencyKey) })
|
|
36380
36387
|
}),
|
|
36381
36388
|
defineTool({
|
|
36382
36389
|
name: "upgrade_vps",
|
|
36383
36390
|
title: "Upgrade VPS plan",
|
|
36384
36391
|
kind: "write",
|
|
36385
|
-
description:
|
|
36386
|
-
input: { vpsId, planId: exports_external.string() },
|
|
36387
|
-
run: (a, api2) => api2.api("POST", `/vps/${a.vpsId}/upgrade`, { body: { planId: a.planId } })
|
|
36392
|
+
description: `Move a server to a larger plan in the same family and region. COSTS MONEY (the difference for the days left) and restarts the server. planId must be one listed by get_vps_upgrade_options. Call with dryRun=true first and get the user's OK. ${DRY} Servers with providerCode 2 only.`,
|
|
36393
|
+
input: { vpsId, planId: exports_external.string(), dryRun: dryRun2, idempotencyKey },
|
|
36394
|
+
run: (a, api2) => api2.api("POST", `/vps/${a.vpsId}/upgrade`, { body: { planId: a.planId }, query: dryQuery(a.dryRun), idempotencyKey: purchaseKey(a.dryRun, a.idempotencyKey) })
|
|
36388
36395
|
}),
|
|
36389
36396
|
defineTool({
|
|
36390
36397
|
name: "get_vps_upgrade_options",
|
|
@@ -36411,11 +36418,20 @@ var vpsTools = [
|
|
|
36411
36418
|
input: { vpsId, range: exports_external.enum(["1h", "6h", "24h", "7d", "30d"]).optional() },
|
|
36412
36419
|
run: (a, api2) => api2.api("GET", `/vps/${a.vpsId}/metrics`, { query: { range: a.range } })
|
|
36413
36420
|
}),
|
|
36421
|
+
defineTool({
|
|
36422
|
+
name: "set_vps_auto_renew",
|
|
36423
|
+
title: "Set VPS auto-renew",
|
|
36424
|
+
kind: "write",
|
|
36425
|
+
idempotent: true,
|
|
36426
|
+
description: "Turn auto-renew on or off (sets the value, safe to repeat). With it off, the server is only renewed by renew_vps and expires otherwise.",
|
|
36427
|
+
input: { vpsId, autoRenew: exports_external.boolean() },
|
|
36428
|
+
run: (a, api2) => api2.api("POST", `/vps/${a.vpsId}/auto-renew`, { body: { autoRenew: a.autoRenew } })
|
|
36429
|
+
}),
|
|
36414
36430
|
defineTool({
|
|
36415
36431
|
name: "toggle_vps_auto_renew",
|
|
36416
36432
|
title: "Toggle VPS auto-renew",
|
|
36417
36433
|
kind: "write",
|
|
36418
|
-
description: "Flip auto-renew
|
|
36434
|
+
description: "Flip auto-renew to the other value; the response gives the new one. Prefer set_vps_auto_renew to reach a given state.",
|
|
36419
36435
|
input: { vpsId },
|
|
36420
36436
|
run: (a, api2) => api2.api("POST", `/vps/${a.vpsId}/auto-renew-toggle`)
|
|
36421
36437
|
}),
|
|
@@ -36744,8 +36760,8 @@ var vpsTools = [
|
|
|
36744
36760
|
// src/tools/domains.ts
|
|
36745
36761
|
var domainId = exports_external.number().int().positive().describe("Domain id (number, from list_my_domains)");
|
|
36746
36762
|
var hostId = exports_external.number().int().positive().describe("Child nameserver id (from list_child_nameservers)");
|
|
36747
|
-
var
|
|
36748
|
-
var
|
|
36763
|
+
var dryRun3 = exports_external.boolean().optional().describe("true = return the exact price (IDR, VAT included) and the wallet balance after it; nothing is charged or registered");
|
|
36764
|
+
var DRY2 = "dryRun=true returns the price and walletBalanceAfter without charging or changing anything.";
|
|
36749
36765
|
var record3 = exports_external.object({
|
|
36750
36766
|
name: exports_external.string().describe('"@" for the domain itself, or the part before the domain, e.g. "www" or "_dmarc.mail". A full name like "www.example.com" is accepted and stored as "www"'),
|
|
36751
36767
|
type: exports_external.enum(["A", "AAAA", "MX", "MXE", "CNAME", "SPF", "TXT"]),
|
|
@@ -36821,12 +36837,12 @@ var domainTools = [
|
|
|
36821
36837
|
name: "register_domain",
|
|
36822
36838
|
title: "Register domain",
|
|
36823
36839
|
kind: "write",
|
|
36824
|
-
description: `Register a domain for 1 year. COSTS MONEY from the wallet. Check search_domain, and that the owner details are complete (check_registrant / update_registrant). ${
|
|
36840
|
+
description: `Register a domain for 1 year. COSTS MONEY from the wallet. Check search_domain, and that the owner details are complete (check_registrant / update_registrant). ${DRY2} The dry run includes WHOIS privacy when whoisProtection is true.`,
|
|
36825
36841
|
input: {
|
|
36826
36842
|
name: exports_external.string().describe("Full domain, e.g. tokosaya.id"),
|
|
36827
36843
|
nameservers: exports_external.array(exports_external.string()).min(2).max(5).optional(),
|
|
36828
36844
|
whoisProtection: exports_external.boolean().optional(),
|
|
36829
|
-
dryRun:
|
|
36845
|
+
dryRun: dryRun3
|
|
36830
36846
|
},
|
|
36831
36847
|
run: (a, api2) => api2.api("POST", "/domains/register", { body: { name: a.name, period: 1, nameservers: a.nameservers, whoisProtection: a.whoisProtection }, query: { dryRun: a.dryRun ? "true" : undefined } })
|
|
36832
36848
|
}),
|
|
@@ -36834,16 +36850,16 @@ var domainTools = [
|
|
|
36834
36850
|
name: "transfer_domain",
|
|
36835
36851
|
title: "Transfer domain in",
|
|
36836
36852
|
kind: "write",
|
|
36837
|
-
description: `Transfer a domain from another registrar (adds 1 year). COSTS MONEY from the wallet. Needs the domain's auth code. ${
|
|
36838
|
-
input: { name: exports_external.string(), authCode: exports_external.string(), nameservers: exports_external.array(exports_external.string()).min(2).max(5).optional(), dryRun:
|
|
36853
|
+
description: `Transfer a domain from another registrar (adds 1 year). COSTS MONEY from the wallet. Needs the domain's auth code. ${DRY2}`,
|
|
36854
|
+
input: { name: exports_external.string(), authCode: exports_external.string(), nameservers: exports_external.array(exports_external.string()).min(2).max(5).optional(), dryRun: dryRun3 },
|
|
36839
36855
|
run: (a, api2) => api2.api("POST", "/domains/transfer", { body: { name: a.name, authCode: a.authCode, period: 1, nameservers: a.nameservers }, query: { dryRun: a.dryRun ? "true" : undefined } })
|
|
36840
36856
|
}),
|
|
36841
36857
|
defineTool({
|
|
36842
36858
|
name: "renew_domain",
|
|
36843
36859
|
title: "Renew domain",
|
|
36844
36860
|
kind: "write",
|
|
36845
|
-
description: `Renew a domain for 1 year (plus WHOIS privacy when it is on). COSTS MONEY from the wallet. ${
|
|
36846
|
-
input: { domainId, dryRun:
|
|
36861
|
+
description: `Renew a domain for 1 year (plus WHOIS privacy when it is on). COSTS MONEY from the wallet. ${DRY2}`,
|
|
36862
|
+
input: { domainId, dryRun: dryRun3 },
|
|
36847
36863
|
run: (a, api2) => api2.api("POST", `/domains/${a.domainId}/renew`, { body: { period: 1 }, query: { dryRun: a.dryRun ? "true" : undefined } })
|
|
36848
36864
|
}),
|
|
36849
36865
|
defineTool({
|
|
@@ -37006,7 +37022,7 @@ var message = exports_external.object({
|
|
|
37006
37022
|
variables: exports_external.record(exports_external.string(), exports_external.string()).optional(),
|
|
37007
37023
|
idempotencyKey: exports_external.string().max(128).optional()
|
|
37008
37024
|
});
|
|
37009
|
-
var
|
|
37025
|
+
var dryRun4 = exports_external.boolean().optional().describe("true = return the price (IDR) and the wallet balance after it; nothing is charged or changed");
|
|
37010
37026
|
var idem2 = exports_external.string().regex(/^[A-Za-z0-9_.:-]{8,128}$/).optional().describe("Idempotency-Key for the real purchase. Generated when omitted; pass the same value when retrying so it is never charged twice");
|
|
37011
37027
|
var MONEY = "COSTS MONEY from the wallet. dryRun=true returns the charge (IDR) and walletBalanceAfter without charging or changing anything.";
|
|
37012
37028
|
var planCode = exports_external.string().min(1).max(50).describe("Plan code from list_email_plans");
|
|
@@ -37042,7 +37058,7 @@ var emailTools = [
|
|
|
37042
37058
|
title: "Buy email plan",
|
|
37043
37059
|
kind: "write",
|
|
37044
37060
|
description: `Start an email plan for the project (a free plan activates without charge). Works for a project with no email yet: the real call also sets email up (result.setup). ${MONEY} The dry run's mode says purchase, activate_free or already_active.`,
|
|
37045
|
-
input: { projectId, planCode, months: exports_external.union([exports_external.literal(1), exports_external.literal(3), exports_external.literal(6), exports_external.literal(12)]).optional().describe("Billing cycle, default 1"), dryRun:
|
|
37061
|
+
input: { projectId, planCode, months: exports_external.union([exports_external.literal(1), exports_external.literal(3), exports_external.literal(6), exports_external.literal(12)]).optional().describe("Billing cycle, default 1"), dryRun: dryRun4, idempotencyKey: idem2 },
|
|
37046
37062
|
run: (a, api2) => api2.email("POST", "/plan", {
|
|
37047
37063
|
project: a.projectId,
|
|
37048
37064
|
body: { planCode: a.planCode, months: a.months },
|
|
@@ -37055,7 +37071,7 @@ var emailTools = [
|
|
|
37055
37071
|
title: "Renew email plan",
|
|
37056
37072
|
kind: "write",
|
|
37057
37073
|
description: `Renew the project's ended or expiring email plan (409 PLAN_ACTIVE while one is still running and cannot be extended). Repeats the last plan and cycle unless planCode / months are given. ${MONEY}`,
|
|
37058
|
-
input: { projectId, planCode: planCode.optional(), months: exports_external.union([exports_external.literal(1), exports_external.literal(3), exports_external.literal(6), exports_external.literal(12)]).optional(), dryRun:
|
|
37074
|
+
input: { projectId, planCode: planCode.optional(), months: exports_external.union([exports_external.literal(1), exports_external.literal(3), exports_external.literal(6), exports_external.literal(12)]).optional(), dryRun: dryRun4, idempotencyKey: idem2 },
|
|
37059
37075
|
run: (a, api2) => api2.email("POST", "/plan/renew", {
|
|
37060
37076
|
project: a.projectId,
|
|
37061
37077
|
body: { planCode: a.planCode, months: a.months },
|
|
@@ -37068,7 +37084,7 @@ var emailTools = [
|
|
|
37068
37084
|
title: "Change email plan",
|
|
37069
37085
|
kind: "write",
|
|
37070
37086
|
description: `Move the active email plan to another plan. An upgrade applies now and charges the prorated difference to the same end date; a downgrade is scheduled for the next cycle (no refund). ${MONEY}`,
|
|
37071
|
-
input: { projectId, planCode, dryRun:
|
|
37087
|
+
input: { projectId, planCode, dryRun: dryRun4, idempotencyKey: idem2 },
|
|
37072
37088
|
run: (a, api2) => api2.email("POST", "/plan/change", {
|
|
37073
37089
|
project: a.projectId,
|
|
37074
37090
|
body: { planCode: a.planCode },
|
|
@@ -37085,7 +37101,7 @@ var emailTools = [
|
|
|
37085
37101
|
projectId,
|
|
37086
37102
|
extraMailboxes: exports_external.number().int().min(0).max(50).describe("Total extra mailboxes wanted (0-50)"),
|
|
37087
37103
|
extraStorageGb: exports_external.number().int().min(0).max(1000).describe("Total extra inbox storage in GB (0-1000)"),
|
|
37088
|
-
dryRun:
|
|
37104
|
+
dryRun: dryRun4,
|
|
37089
37105
|
idempotencyKey: idem2
|
|
37090
37106
|
},
|
|
37091
37107
|
run: (a, api2) => api2.email("POST", "/plan/addons", {
|
|
@@ -37655,7 +37671,7 @@ var emailTools = [
|
|
|
37655
37671
|
// src/tools/databases.ts
|
|
37656
37672
|
var databaseId = exports_external.string().uuid().describe("Database id (from list_databases)");
|
|
37657
37673
|
var environmentId = exports_external.string().uuid().describe("Environment id (from list_projects). Omit for the primary (production) branch.");
|
|
37658
|
-
var
|
|
37674
|
+
var dryRun5 = exports_external.boolean().optional().describe("true = only check and show the result or price; nothing changes");
|
|
37659
37675
|
var databaseTools = [
|
|
37660
37676
|
defineTool({
|
|
37661
37677
|
name: "list_database_plans",
|
|
@@ -37749,7 +37765,7 @@ var databaseTools = [
|
|
|
37749
37765
|
minCu: exports_external.number().min(0.25).max(10).optional(),
|
|
37750
37766
|
maxCu: exports_external.number().min(0.25).max(10).optional(),
|
|
37751
37767
|
suspendTimeoutSeconds: exports_external.number().int().min(0).max(604800).optional().describe("0 = never suspend, or 60-604800"),
|
|
37752
|
-
dryRun:
|
|
37768
|
+
dryRun: dryRun5
|
|
37753
37769
|
},
|
|
37754
37770
|
run: (a, api2) => api2.api("PATCH", `/databases/${a.databaseId}/settings`, {
|
|
37755
37771
|
body: { minCu: a.minCu, maxCu: a.maxCu, suspendTimeoutSeconds: a.suspendTimeoutSeconds },
|
|
@@ -37761,7 +37777,7 @@ var databaseTools = [
|
|
|
37761
37777
|
title: "Upgrade database plan / top up",
|
|
37762
37778
|
kind: "write",
|
|
37763
37779
|
description: "Buy a paid plan or top up credits. COSTS MONEY from the wallet: call with dryRun first, show price and wallet balance after, and get the user's explicit OK.",
|
|
37764
|
-
input: { databaseId, plan: exports_external.string().describe("Plan code (e.g. STARTER) or id from list_database_plans"), dryRun:
|
|
37780
|
+
input: { databaseId, plan: exports_external.string().describe("Plan code (e.g. STARTER) or id from list_database_plans"), dryRun: dryRun5, idempotencyKey: exports_external.string().max(128).optional() },
|
|
37765
37781
|
run: (a, api2) => api2.api("POST", `/databases/${a.databaseId}/upgrade`, { body: { plan: a.plan }, query: { dryRun: a.dryRun ? "true" : undefined }, idempotencyKey: a.idempotencyKey })
|
|
37766
37782
|
}),
|
|
37767
37783
|
defineTool({
|
|
@@ -38019,7 +38035,7 @@ var accountTools = [
|
|
|
38019
38035
|
var projectId2 = exports_external.string().uuid().optional().describe("Limit to one project (a project key is always limited to its own)");
|
|
38020
38036
|
var keyId = exports_external.string().uuid().optional().describe("Limit to one AI key (id from list_ai_keys)");
|
|
38021
38037
|
var model = exports_external.string().max(100).optional().describe("Limit to one model id");
|
|
38022
|
-
var
|
|
38038
|
+
var dryRun6 = exports_external.boolean().optional().describe("true = only check and show the result; nothing is charged or changed");
|
|
38023
38039
|
var ACCOUNT_KEY2 = "Needs a whole-account key (a key limited to one project gets 403 ACCOUNT_KEY_REQUIRED).";
|
|
38024
38040
|
var imageProject = exports_external.string().uuid().optional().describe("Project the images belong to (required with a whole-account key; a project key uses its own)");
|
|
38025
38041
|
var INLINE_MAX_BYTES = 1500000;
|
|
@@ -38104,7 +38120,7 @@ var aiTools = [
|
|
|
38104
38120
|
n: exports_external.number().int().min(1).max(10).optional().describe("Images in this request (up to the model's maxN; default 1)"),
|
|
38105
38121
|
images: exports_external.array(exports_external.string().url().startsWith("https://")).max(10).optional().describe("Reference images as https:// links (only models with refImages > 0)"),
|
|
38106
38122
|
projectId: imageProject,
|
|
38107
|
-
dryRun:
|
|
38123
|
+
dryRun: dryRun6,
|
|
38108
38124
|
wait: exports_external.number().int().min(0).max(55).optional().describe("Seconds to wait for the result (default 50; 0 = return the id at once)"),
|
|
38109
38125
|
idempotencyKey: exports_external.string().regex(/^[A-Za-z0-9_.:-]{8,128}$/).optional().describe("Idempotency-Key for the real request. Generated when omitted; pass the same value when retrying so it is never charged twice")
|
|
38110
38126
|
},
|
|
@@ -38154,7 +38170,7 @@ var aiTools = [
|
|
|
38154
38170
|
input: {
|
|
38155
38171
|
packId: exports_external.string().min(1).max(64).optional(),
|
|
38156
38172
|
amount: exports_external.number().min(1).max(1e9).optional().describe("IDR"),
|
|
38157
|
-
dryRun:
|
|
38173
|
+
dryRun: dryRun6,
|
|
38158
38174
|
idempotencyKey: exports_external.string().regex(/^[A-Za-z0-9_.:-]{8,128}$/).optional().describe("Idempotency-Key for the real top-up. Generated when omitted; pass the same value when retrying so it is never charged twice")
|
|
38159
38175
|
},
|
|
38160
38176
|
run: (a, api2) => {
|
|
@@ -38177,7 +38193,7 @@ var aiTools = [
|
|
|
38177
38193
|
enabled: exports_external.boolean(),
|
|
38178
38194
|
threshold: exports_external.number().min(1).optional().describe("Top up when the AI balance is below this (IDR)"),
|
|
38179
38195
|
amount: exports_external.number().min(1).optional().describe("How much to top up each time (IDR)"),
|
|
38180
|
-
dryRun:
|
|
38196
|
+
dryRun: dryRun6
|
|
38181
38197
|
},
|
|
38182
38198
|
run: (a, api2) => api2.api("PUT", "/ai/auto-topup", {
|
|
38183
38199
|
body: { enabled: a.enabled, threshold: a.threshold, amount: a.amount },
|
|
@@ -38213,7 +38229,7 @@ var generalTools = [
|
|
|
38213
38229
|
];
|
|
38214
38230
|
|
|
38215
38231
|
// src/server.ts
|
|
38216
|
-
var VERSION = "0.5.
|
|
38232
|
+
var VERSION = "0.5.10";
|
|
38217
38233
|
var INSTRUCTIONS = `Helipod is a cloud platform (Indonesia): containers, managed Postgres databases, VPS, domains, email and an AI gateway, billed from a prepaid wallet in Rupiah.
|
|
38218
38234
|
- Start with list_projects to find projects and environment ids. Account tools (get_wallet, invoices, statements, notifications, get_project_activity, support tickets) cover the account; AI tools (list_ai_models, get_ai_overview, get_ai_usage, AI keys, top-ups, generate_ai_image) cover the AI gateway.
|
|
38219
38235
|
- Anything that costs money (create/deploy/scale services, resize volumes, upgrade a database plan, create/renew/upgrade VPS, VPS backups, register/renew/transfer domains, email plans and inbox add-ons, AI top-ups and auto top-up, generating images): call it with dryRun=true first (or the price lookup when it has no dry run), tell the user the cost in IDR and the wallet balance after, and wait for an explicit yes before the real call. Never treat silence or an earlier general OK as a yes.
|
package/dist/index.js
CHANGED
|
@@ -35426,6 +35426,10 @@ var period = exports_external.enum(["monthly", "3month", "6month", "yearly"]);
|
|
|
35426
35426
|
var pointId = exports_external.string().describe("Restore point id (from list_vps_restore_points)");
|
|
35427
35427
|
var backupPath = exports_external.string().max(1024).describe("Absolute path inside the backup, e.g. /etc/nginx or /var/www/index.html");
|
|
35428
35428
|
var migrationId = exports_external.string().describe("Migration id (from list_vps_migrations)");
|
|
35429
|
+
var dryRun2 = exports_external.boolean().optional().describe("true = return the price (IDR) and the wallet balance after it; nothing is charged or changed");
|
|
35430
|
+
var idempotencyKey = exports_external.string().regex(/^[A-Za-z0-9_.:-]{8,128}$/).optional().describe("Idempotency-Key for the real call. Generated when omitted; pass the same value when retrying so it is never charged twice");
|
|
35431
|
+
var DRY = "dryRun=true returns the price and walletBalanceAfter without charging or changing anything.";
|
|
35432
|
+
var dryQuery = (d) => ({ dryRun: d ? "true" : undefined });
|
|
35429
35433
|
var vpsTools = [
|
|
35430
35434
|
defineTool({
|
|
35431
35435
|
name: "list_vps_plans",
|
|
@@ -35455,7 +35459,7 @@ var vpsTools = [
|
|
|
35455
35459
|
name: "create_vps",
|
|
35456
35460
|
title: "Create VPS",
|
|
35457
35461
|
kind: "write",
|
|
35458
|
-
description:
|
|
35462
|
+
description: `Order a server. COSTS MONEY right away (the whole billing period is charged from the wallet; refunded if provisioning fails). Call with dryRun=true first, show the price and the wallet after it, and get the user's explicit OK. ${DRY} autoRenew=false creates it with auto-renew off (renew it with renew_vps). Provisioning takes a few minutes: poll get_vps.`,
|
|
35459
35463
|
input: {
|
|
35460
35464
|
projectId: exports_external.string().uuid(),
|
|
35461
35465
|
planId: exports_external.string(),
|
|
@@ -35463,9 +35467,12 @@ var vpsTools = [
|
|
|
35463
35467
|
osType: exports_external.string().describe("From the plan's osTemplates, e.g. ubuntu"),
|
|
35464
35468
|
osVersion: exports_external.string().describe("e.g. 24.04"),
|
|
35465
35469
|
rootPassword: password,
|
|
35466
|
-
billingPeriod: period.optional().describe("Default monthly")
|
|
35470
|
+
billingPeriod: period.optional().describe("Default monthly"),
|
|
35471
|
+
autoRenew: exports_external.boolean().optional().describe("false = no automatic renewal from the wallet (default true)"),
|
|
35472
|
+
dryRun: dryRun2,
|
|
35473
|
+
idempotencyKey
|
|
35467
35474
|
},
|
|
35468
|
-
run: (
|
|
35475
|
+
run: ({ dryRun: dryRun3, idempotencyKey: idempotencyKey2, ...body }, api2) => api2.api("POST", "/vps", { body, query: dryQuery(dryRun3), idempotencyKey: purchaseKey(dryRun3, idempotencyKey2) })
|
|
35469
35476
|
}),
|
|
35470
35477
|
defineTool({
|
|
35471
35478
|
name: "vps_power",
|
|
@@ -35519,17 +35526,17 @@ var vpsTools = [
|
|
|
35519
35526
|
name: "renew_vps",
|
|
35520
35527
|
title: "Renew VPS",
|
|
35521
35528
|
kind: "write",
|
|
35522
|
-
description:
|
|
35523
|
-
input: { vpsId, billingPeriod: period },
|
|
35524
|
-
run: (a, api2) => api2.api("POST", `/vps/${a.vpsId}/renew`, { body: { billingPeriod: a.billingPeriod } })
|
|
35529
|
+
description: `Extend a server's paid period. COSTS MONEY: call with dryRun=true first, show the price and the wallet after it, and get the user's OK. ${DRY}`,
|
|
35530
|
+
input: { vpsId, billingPeriod: period, dryRun: dryRun2, idempotencyKey },
|
|
35531
|
+
run: (a, api2) => api2.api("POST", `/vps/${a.vpsId}/renew`, { body: { billingPeriod: a.billingPeriod }, query: dryQuery(a.dryRun), idempotencyKey: purchaseKey(a.dryRun, a.idempotencyKey) })
|
|
35525
35532
|
}),
|
|
35526
35533
|
defineTool({
|
|
35527
35534
|
name: "upgrade_vps",
|
|
35528
35535
|
title: "Upgrade VPS plan",
|
|
35529
35536
|
kind: "write",
|
|
35530
|
-
description:
|
|
35531
|
-
input: { vpsId, planId: exports_external.string() },
|
|
35532
|
-
run: (a, api2) => api2.api("POST", `/vps/${a.vpsId}/upgrade`, { body: { planId: a.planId } })
|
|
35537
|
+
description: `Move a server to a larger plan in the same family and region. COSTS MONEY (the difference for the days left) and restarts the server. planId must be one listed by get_vps_upgrade_options. Call with dryRun=true first and get the user's OK. ${DRY} Servers with providerCode 2 only.`,
|
|
35538
|
+
input: { vpsId, planId: exports_external.string(), dryRun: dryRun2, idempotencyKey },
|
|
35539
|
+
run: (a, api2) => api2.api("POST", `/vps/${a.vpsId}/upgrade`, { body: { planId: a.planId }, query: dryQuery(a.dryRun), idempotencyKey: purchaseKey(a.dryRun, a.idempotencyKey) })
|
|
35533
35540
|
}),
|
|
35534
35541
|
defineTool({
|
|
35535
35542
|
name: "get_vps_upgrade_options",
|
|
@@ -35556,11 +35563,20 @@ var vpsTools = [
|
|
|
35556
35563
|
input: { vpsId, range: exports_external.enum(["1h", "6h", "24h", "7d", "30d"]).optional() },
|
|
35557
35564
|
run: (a, api2) => api2.api("GET", `/vps/${a.vpsId}/metrics`, { query: { range: a.range } })
|
|
35558
35565
|
}),
|
|
35566
|
+
defineTool({
|
|
35567
|
+
name: "set_vps_auto_renew",
|
|
35568
|
+
title: "Set VPS auto-renew",
|
|
35569
|
+
kind: "write",
|
|
35570
|
+
idempotent: true,
|
|
35571
|
+
description: "Turn auto-renew on or off (sets the value, safe to repeat). With it off, the server is only renewed by renew_vps and expires otherwise.",
|
|
35572
|
+
input: { vpsId, autoRenew: exports_external.boolean() },
|
|
35573
|
+
run: (a, api2) => api2.api("POST", `/vps/${a.vpsId}/auto-renew`, { body: { autoRenew: a.autoRenew } })
|
|
35574
|
+
}),
|
|
35559
35575
|
defineTool({
|
|
35560
35576
|
name: "toggle_vps_auto_renew",
|
|
35561
35577
|
title: "Toggle VPS auto-renew",
|
|
35562
35578
|
kind: "write",
|
|
35563
|
-
description: "Flip auto-renew
|
|
35579
|
+
description: "Flip auto-renew to the other value; the response gives the new one. Prefer set_vps_auto_renew to reach a given state.",
|
|
35564
35580
|
input: { vpsId },
|
|
35565
35581
|
run: (a, api2) => api2.api("POST", `/vps/${a.vpsId}/auto-renew-toggle`)
|
|
35566
35582
|
}),
|
|
@@ -35889,8 +35905,8 @@ var vpsTools = [
|
|
|
35889
35905
|
// src/tools/domains.ts
|
|
35890
35906
|
var domainId = exports_external.number().int().positive().describe("Domain id (number, from list_my_domains)");
|
|
35891
35907
|
var hostId = exports_external.number().int().positive().describe("Child nameserver id (from list_child_nameservers)");
|
|
35892
|
-
var
|
|
35893
|
-
var
|
|
35908
|
+
var dryRun3 = exports_external.boolean().optional().describe("true = return the exact price (IDR, VAT included) and the wallet balance after it; nothing is charged or registered");
|
|
35909
|
+
var DRY2 = "dryRun=true returns the price and walletBalanceAfter without charging or changing anything.";
|
|
35894
35910
|
var record3 = exports_external.object({
|
|
35895
35911
|
name: exports_external.string().describe('"@" for the domain itself, or the part before the domain, e.g. "www" or "_dmarc.mail". A full name like "www.example.com" is accepted and stored as "www"'),
|
|
35896
35912
|
type: exports_external.enum(["A", "AAAA", "MX", "MXE", "CNAME", "SPF", "TXT"]),
|
|
@@ -35966,12 +35982,12 @@ var domainTools = [
|
|
|
35966
35982
|
name: "register_domain",
|
|
35967
35983
|
title: "Register domain",
|
|
35968
35984
|
kind: "write",
|
|
35969
|
-
description: `Register a domain for 1 year. COSTS MONEY from the wallet. Check search_domain, and that the owner details are complete (check_registrant / update_registrant). ${
|
|
35985
|
+
description: `Register a domain for 1 year. COSTS MONEY from the wallet. Check search_domain, and that the owner details are complete (check_registrant / update_registrant). ${DRY2} The dry run includes WHOIS privacy when whoisProtection is true.`,
|
|
35970
35986
|
input: {
|
|
35971
35987
|
name: exports_external.string().describe("Full domain, e.g. tokosaya.id"),
|
|
35972
35988
|
nameservers: exports_external.array(exports_external.string()).min(2).max(5).optional(),
|
|
35973
35989
|
whoisProtection: exports_external.boolean().optional(),
|
|
35974
|
-
dryRun:
|
|
35990
|
+
dryRun: dryRun3
|
|
35975
35991
|
},
|
|
35976
35992
|
run: (a, api2) => api2.api("POST", "/domains/register", { body: { name: a.name, period: 1, nameservers: a.nameservers, whoisProtection: a.whoisProtection }, query: { dryRun: a.dryRun ? "true" : undefined } })
|
|
35977
35993
|
}),
|
|
@@ -35979,16 +35995,16 @@ var domainTools = [
|
|
|
35979
35995
|
name: "transfer_domain",
|
|
35980
35996
|
title: "Transfer domain in",
|
|
35981
35997
|
kind: "write",
|
|
35982
|
-
description: `Transfer a domain from another registrar (adds 1 year). COSTS MONEY from the wallet. Needs the domain's auth code. ${
|
|
35983
|
-
input: { name: exports_external.string(), authCode: exports_external.string(), nameservers: exports_external.array(exports_external.string()).min(2).max(5).optional(), dryRun:
|
|
35998
|
+
description: `Transfer a domain from another registrar (adds 1 year). COSTS MONEY from the wallet. Needs the domain's auth code. ${DRY2}`,
|
|
35999
|
+
input: { name: exports_external.string(), authCode: exports_external.string(), nameservers: exports_external.array(exports_external.string()).min(2).max(5).optional(), dryRun: dryRun3 },
|
|
35984
36000
|
run: (a, api2) => api2.api("POST", "/domains/transfer", { body: { name: a.name, authCode: a.authCode, period: 1, nameservers: a.nameservers }, query: { dryRun: a.dryRun ? "true" : undefined } })
|
|
35985
36001
|
}),
|
|
35986
36002
|
defineTool({
|
|
35987
36003
|
name: "renew_domain",
|
|
35988
36004
|
title: "Renew domain",
|
|
35989
36005
|
kind: "write",
|
|
35990
|
-
description: `Renew a domain for 1 year (plus WHOIS privacy when it is on). COSTS MONEY from the wallet. ${
|
|
35991
|
-
input: { domainId, dryRun:
|
|
36006
|
+
description: `Renew a domain for 1 year (plus WHOIS privacy when it is on). COSTS MONEY from the wallet. ${DRY2}`,
|
|
36007
|
+
input: { domainId, dryRun: dryRun3 },
|
|
35992
36008
|
run: (a, api2) => api2.api("POST", `/domains/${a.domainId}/renew`, { body: { period: 1 }, query: { dryRun: a.dryRun ? "true" : undefined } })
|
|
35993
36009
|
}),
|
|
35994
36010
|
defineTool({
|
|
@@ -36151,7 +36167,7 @@ var message = exports_external.object({
|
|
|
36151
36167
|
variables: exports_external.record(exports_external.string(), exports_external.string()).optional(),
|
|
36152
36168
|
idempotencyKey: exports_external.string().max(128).optional()
|
|
36153
36169
|
});
|
|
36154
|
-
var
|
|
36170
|
+
var dryRun4 = exports_external.boolean().optional().describe("true = return the price (IDR) and the wallet balance after it; nothing is charged or changed");
|
|
36155
36171
|
var idem2 = exports_external.string().regex(/^[A-Za-z0-9_.:-]{8,128}$/).optional().describe("Idempotency-Key for the real purchase. Generated when omitted; pass the same value when retrying so it is never charged twice");
|
|
36156
36172
|
var MONEY = "COSTS MONEY from the wallet. dryRun=true returns the charge (IDR) and walletBalanceAfter without charging or changing anything.";
|
|
36157
36173
|
var planCode = exports_external.string().min(1).max(50).describe("Plan code from list_email_plans");
|
|
@@ -36187,7 +36203,7 @@ var emailTools = [
|
|
|
36187
36203
|
title: "Buy email plan",
|
|
36188
36204
|
kind: "write",
|
|
36189
36205
|
description: `Start an email plan for the project (a free plan activates without charge). Works for a project with no email yet: the real call also sets email up (result.setup). ${MONEY} The dry run's mode says purchase, activate_free or already_active.`,
|
|
36190
|
-
input: { projectId, planCode, months: exports_external.union([exports_external.literal(1), exports_external.literal(3), exports_external.literal(6), exports_external.literal(12)]).optional().describe("Billing cycle, default 1"), dryRun:
|
|
36206
|
+
input: { projectId, planCode, months: exports_external.union([exports_external.literal(1), exports_external.literal(3), exports_external.literal(6), exports_external.literal(12)]).optional().describe("Billing cycle, default 1"), dryRun: dryRun4, idempotencyKey: idem2 },
|
|
36191
36207
|
run: (a, api2) => api2.email("POST", "/plan", {
|
|
36192
36208
|
project: a.projectId,
|
|
36193
36209
|
body: { planCode: a.planCode, months: a.months },
|
|
@@ -36200,7 +36216,7 @@ var emailTools = [
|
|
|
36200
36216
|
title: "Renew email plan",
|
|
36201
36217
|
kind: "write",
|
|
36202
36218
|
description: `Renew the project's ended or expiring email plan (409 PLAN_ACTIVE while one is still running and cannot be extended). Repeats the last plan and cycle unless planCode / months are given. ${MONEY}`,
|
|
36203
|
-
input: { projectId, planCode: planCode.optional(), months: exports_external.union([exports_external.literal(1), exports_external.literal(3), exports_external.literal(6), exports_external.literal(12)]).optional(), dryRun:
|
|
36219
|
+
input: { projectId, planCode: planCode.optional(), months: exports_external.union([exports_external.literal(1), exports_external.literal(3), exports_external.literal(6), exports_external.literal(12)]).optional(), dryRun: dryRun4, idempotencyKey: idem2 },
|
|
36204
36220
|
run: (a, api2) => api2.email("POST", "/plan/renew", {
|
|
36205
36221
|
project: a.projectId,
|
|
36206
36222
|
body: { planCode: a.planCode, months: a.months },
|
|
@@ -36213,7 +36229,7 @@ var emailTools = [
|
|
|
36213
36229
|
title: "Change email plan",
|
|
36214
36230
|
kind: "write",
|
|
36215
36231
|
description: `Move the active email plan to another plan. An upgrade applies now and charges the prorated difference to the same end date; a downgrade is scheduled for the next cycle (no refund). ${MONEY}`,
|
|
36216
|
-
input: { projectId, planCode, dryRun:
|
|
36232
|
+
input: { projectId, planCode, dryRun: dryRun4, idempotencyKey: idem2 },
|
|
36217
36233
|
run: (a, api2) => api2.email("POST", "/plan/change", {
|
|
36218
36234
|
project: a.projectId,
|
|
36219
36235
|
body: { planCode: a.planCode },
|
|
@@ -36230,7 +36246,7 @@ var emailTools = [
|
|
|
36230
36246
|
projectId,
|
|
36231
36247
|
extraMailboxes: exports_external.number().int().min(0).max(50).describe("Total extra mailboxes wanted (0-50)"),
|
|
36232
36248
|
extraStorageGb: exports_external.number().int().min(0).max(1000).describe("Total extra inbox storage in GB (0-1000)"),
|
|
36233
|
-
dryRun:
|
|
36249
|
+
dryRun: dryRun4,
|
|
36234
36250
|
idempotencyKey: idem2
|
|
36235
36251
|
},
|
|
36236
36252
|
run: (a, api2) => api2.email("POST", "/plan/addons", {
|
|
@@ -36800,7 +36816,7 @@ var emailTools = [
|
|
|
36800
36816
|
// src/tools/databases.ts
|
|
36801
36817
|
var databaseId = exports_external.string().uuid().describe("Database id (from list_databases)");
|
|
36802
36818
|
var environmentId = exports_external.string().uuid().describe("Environment id (from list_projects). Omit for the primary (production) branch.");
|
|
36803
|
-
var
|
|
36819
|
+
var dryRun5 = exports_external.boolean().optional().describe("true = only check and show the result or price; nothing changes");
|
|
36804
36820
|
var databaseTools = [
|
|
36805
36821
|
defineTool({
|
|
36806
36822
|
name: "list_database_plans",
|
|
@@ -36894,7 +36910,7 @@ var databaseTools = [
|
|
|
36894
36910
|
minCu: exports_external.number().min(0.25).max(10).optional(),
|
|
36895
36911
|
maxCu: exports_external.number().min(0.25).max(10).optional(),
|
|
36896
36912
|
suspendTimeoutSeconds: exports_external.number().int().min(0).max(604800).optional().describe("0 = never suspend, or 60-604800"),
|
|
36897
|
-
dryRun:
|
|
36913
|
+
dryRun: dryRun5
|
|
36898
36914
|
},
|
|
36899
36915
|
run: (a, api2) => api2.api("PATCH", `/databases/${a.databaseId}/settings`, {
|
|
36900
36916
|
body: { minCu: a.minCu, maxCu: a.maxCu, suspendTimeoutSeconds: a.suspendTimeoutSeconds },
|
|
@@ -36906,7 +36922,7 @@ var databaseTools = [
|
|
|
36906
36922
|
title: "Upgrade database plan / top up",
|
|
36907
36923
|
kind: "write",
|
|
36908
36924
|
description: "Buy a paid plan or top up credits. COSTS MONEY from the wallet: call with dryRun first, show price and wallet balance after, and get the user's explicit OK.",
|
|
36909
|
-
input: { databaseId, plan: exports_external.string().describe("Plan code (e.g. STARTER) or id from list_database_plans"), dryRun:
|
|
36925
|
+
input: { databaseId, plan: exports_external.string().describe("Plan code (e.g. STARTER) or id from list_database_plans"), dryRun: dryRun5, idempotencyKey: exports_external.string().max(128).optional() },
|
|
36910
36926
|
run: (a, api2) => api2.api("POST", `/databases/${a.databaseId}/upgrade`, { body: { plan: a.plan }, query: { dryRun: a.dryRun ? "true" : undefined }, idempotencyKey: a.idempotencyKey })
|
|
36911
36927
|
}),
|
|
36912
36928
|
defineTool({
|
|
@@ -37164,7 +37180,7 @@ var accountTools = [
|
|
|
37164
37180
|
var projectId2 = exports_external.string().uuid().optional().describe("Limit to one project (a project key is always limited to its own)");
|
|
37165
37181
|
var keyId = exports_external.string().uuid().optional().describe("Limit to one AI key (id from list_ai_keys)");
|
|
37166
37182
|
var model = exports_external.string().max(100).optional().describe("Limit to one model id");
|
|
37167
|
-
var
|
|
37183
|
+
var dryRun6 = exports_external.boolean().optional().describe("true = only check and show the result; nothing is charged or changed");
|
|
37168
37184
|
var ACCOUNT_KEY2 = "Needs a whole-account key (a key limited to one project gets 403 ACCOUNT_KEY_REQUIRED).";
|
|
37169
37185
|
var imageProject = exports_external.string().uuid().optional().describe("Project the images belong to (required with a whole-account key; a project key uses its own)");
|
|
37170
37186
|
var INLINE_MAX_BYTES = 1500000;
|
|
@@ -37249,7 +37265,7 @@ var aiTools = [
|
|
|
37249
37265
|
n: exports_external.number().int().min(1).max(10).optional().describe("Images in this request (up to the model's maxN; default 1)"),
|
|
37250
37266
|
images: exports_external.array(exports_external.string().url().startsWith("https://")).max(10).optional().describe("Reference images as https:// links (only models with refImages > 0)"),
|
|
37251
37267
|
projectId: imageProject,
|
|
37252
|
-
dryRun:
|
|
37268
|
+
dryRun: dryRun6,
|
|
37253
37269
|
wait: exports_external.number().int().min(0).max(55).optional().describe("Seconds to wait for the result (default 50; 0 = return the id at once)"),
|
|
37254
37270
|
idempotencyKey: exports_external.string().regex(/^[A-Za-z0-9_.:-]{8,128}$/).optional().describe("Idempotency-Key for the real request. Generated when omitted; pass the same value when retrying so it is never charged twice")
|
|
37255
37271
|
},
|
|
@@ -37299,7 +37315,7 @@ var aiTools = [
|
|
|
37299
37315
|
input: {
|
|
37300
37316
|
packId: exports_external.string().min(1).max(64).optional(),
|
|
37301
37317
|
amount: exports_external.number().min(1).max(1e9).optional().describe("IDR"),
|
|
37302
|
-
dryRun:
|
|
37318
|
+
dryRun: dryRun6,
|
|
37303
37319
|
idempotencyKey: exports_external.string().regex(/^[A-Za-z0-9_.:-]{8,128}$/).optional().describe("Idempotency-Key for the real top-up. Generated when omitted; pass the same value when retrying so it is never charged twice")
|
|
37304
37320
|
},
|
|
37305
37321
|
run: (a, api2) => {
|
|
@@ -37322,7 +37338,7 @@ var aiTools = [
|
|
|
37322
37338
|
enabled: exports_external.boolean(),
|
|
37323
37339
|
threshold: exports_external.number().min(1).optional().describe("Top up when the AI balance is below this (IDR)"),
|
|
37324
37340
|
amount: exports_external.number().min(1).optional().describe("How much to top up each time (IDR)"),
|
|
37325
|
-
dryRun:
|
|
37341
|
+
dryRun: dryRun6
|
|
37326
37342
|
},
|
|
37327
37343
|
run: (a, api2) => api2.api("PUT", "/ai/auto-topup", {
|
|
37328
37344
|
body: { enabled: a.enabled, threshold: a.threshold, amount: a.amount },
|
|
@@ -37358,7 +37374,7 @@ var generalTools = [
|
|
|
37358
37374
|
];
|
|
37359
37375
|
|
|
37360
37376
|
// src/server.ts
|
|
37361
|
-
var VERSION = "0.5.
|
|
37377
|
+
var VERSION = "0.5.10";
|
|
37362
37378
|
var INSTRUCTIONS = `Helipod is a cloud platform (Indonesia): containers, managed Postgres databases, VPS, domains, email and an AI gateway, billed from a prepaid wallet in Rupiah.
|
|
37363
37379
|
- Start with list_projects to find projects and environment ids. Account tools (get_wallet, invoices, statements, notifications, get_project_activity, support tickets) cover the account; AI tools (list_ai_models, get_ai_overview, get_ai_usage, AI keys, top-ups, generate_ai_image) cover the AI gateway.
|
|
37364
37380
|
- Anything that costs money (create/deploy/scale services, resize volumes, upgrade a database plan, create/renew/upgrade VPS, VPS backups, register/renew/transfer domains, email plans and inbox add-ons, AI top-ups and auto top-up, generating images): call it with dryRun=true first (or the price lookup when it has no dry run), tell the user the cost in IDR and the wallet balance after, and wait for an explicit yes before the real call. Never treat silence or an earlier general OK as a yes.
|
package/dist/stdio.js
CHANGED
|
@@ -35533,6 +35533,10 @@ var period = exports_external.enum(["monthly", "3month", "6month", "yearly"]);
|
|
|
35533
35533
|
var pointId = exports_external.string().describe("Restore point id (from list_vps_restore_points)");
|
|
35534
35534
|
var backupPath = exports_external.string().max(1024).describe("Absolute path inside the backup, e.g. /etc/nginx or /var/www/index.html");
|
|
35535
35535
|
var migrationId = exports_external.string().describe("Migration id (from list_vps_migrations)");
|
|
35536
|
+
var dryRun2 = exports_external.boolean().optional().describe("true = return the price (IDR) and the wallet balance after it; nothing is charged or changed");
|
|
35537
|
+
var idempotencyKey = exports_external.string().regex(/^[A-Za-z0-9_.:-]{8,128}$/).optional().describe("Idempotency-Key for the real call. Generated when omitted; pass the same value when retrying so it is never charged twice");
|
|
35538
|
+
var DRY = "dryRun=true returns the price and walletBalanceAfter without charging or changing anything.";
|
|
35539
|
+
var dryQuery = (d) => ({ dryRun: d ? "true" : undefined });
|
|
35536
35540
|
var vpsTools = [
|
|
35537
35541
|
defineTool({
|
|
35538
35542
|
name: "list_vps_plans",
|
|
@@ -35562,7 +35566,7 @@ var vpsTools = [
|
|
|
35562
35566
|
name: "create_vps",
|
|
35563
35567
|
title: "Create VPS",
|
|
35564
35568
|
kind: "write",
|
|
35565
|
-
description:
|
|
35569
|
+
description: `Order a server. COSTS MONEY right away (the whole billing period is charged from the wallet; refunded if provisioning fails). Call with dryRun=true first, show the price and the wallet after it, and get the user's explicit OK. ${DRY} autoRenew=false creates it with auto-renew off (renew it with renew_vps). Provisioning takes a few minutes: poll get_vps.`,
|
|
35566
35570
|
input: {
|
|
35567
35571
|
projectId: exports_external.string().uuid(),
|
|
35568
35572
|
planId: exports_external.string(),
|
|
@@ -35570,9 +35574,12 @@ var vpsTools = [
|
|
|
35570
35574
|
osType: exports_external.string().describe("From the plan's osTemplates, e.g. ubuntu"),
|
|
35571
35575
|
osVersion: exports_external.string().describe("e.g. 24.04"),
|
|
35572
35576
|
rootPassword: password,
|
|
35573
|
-
billingPeriod: period.optional().describe("Default monthly")
|
|
35577
|
+
billingPeriod: period.optional().describe("Default monthly"),
|
|
35578
|
+
autoRenew: exports_external.boolean().optional().describe("false = no automatic renewal from the wallet (default true)"),
|
|
35579
|
+
dryRun: dryRun2,
|
|
35580
|
+
idempotencyKey
|
|
35574
35581
|
},
|
|
35575
|
-
run: (
|
|
35582
|
+
run: ({ dryRun: dryRun3, idempotencyKey: idempotencyKey2, ...body }, api2) => api2.api("POST", "/vps", { body, query: dryQuery(dryRun3), idempotencyKey: purchaseKey(dryRun3, idempotencyKey2) })
|
|
35576
35583
|
}),
|
|
35577
35584
|
defineTool({
|
|
35578
35585
|
name: "vps_power",
|
|
@@ -35626,17 +35633,17 @@ var vpsTools = [
|
|
|
35626
35633
|
name: "renew_vps",
|
|
35627
35634
|
title: "Renew VPS",
|
|
35628
35635
|
kind: "write",
|
|
35629
|
-
description:
|
|
35630
|
-
input: { vpsId, billingPeriod: period },
|
|
35631
|
-
run: (a, api2) => api2.api("POST", `/vps/${a.vpsId}/renew`, { body: { billingPeriod: a.billingPeriod } })
|
|
35636
|
+
description: `Extend a server's paid period. COSTS MONEY: call with dryRun=true first, show the price and the wallet after it, and get the user's OK. ${DRY}`,
|
|
35637
|
+
input: { vpsId, billingPeriod: period, dryRun: dryRun2, idempotencyKey },
|
|
35638
|
+
run: (a, api2) => api2.api("POST", `/vps/${a.vpsId}/renew`, { body: { billingPeriod: a.billingPeriod }, query: dryQuery(a.dryRun), idempotencyKey: purchaseKey(a.dryRun, a.idempotencyKey) })
|
|
35632
35639
|
}),
|
|
35633
35640
|
defineTool({
|
|
35634
35641
|
name: "upgrade_vps",
|
|
35635
35642
|
title: "Upgrade VPS plan",
|
|
35636
35643
|
kind: "write",
|
|
35637
|
-
description:
|
|
35638
|
-
input: { vpsId, planId: exports_external.string() },
|
|
35639
|
-
run: (a, api2) => api2.api("POST", `/vps/${a.vpsId}/upgrade`, { body: { planId: a.planId } })
|
|
35644
|
+
description: `Move a server to a larger plan in the same family and region. COSTS MONEY (the difference for the days left) and restarts the server. planId must be one listed by get_vps_upgrade_options. Call with dryRun=true first and get the user's OK. ${DRY} Servers with providerCode 2 only.`,
|
|
35645
|
+
input: { vpsId, planId: exports_external.string(), dryRun: dryRun2, idempotencyKey },
|
|
35646
|
+
run: (a, api2) => api2.api("POST", `/vps/${a.vpsId}/upgrade`, { body: { planId: a.planId }, query: dryQuery(a.dryRun), idempotencyKey: purchaseKey(a.dryRun, a.idempotencyKey) })
|
|
35640
35647
|
}),
|
|
35641
35648
|
defineTool({
|
|
35642
35649
|
name: "get_vps_upgrade_options",
|
|
@@ -35663,11 +35670,20 @@ var vpsTools = [
|
|
|
35663
35670
|
input: { vpsId, range: exports_external.enum(["1h", "6h", "24h", "7d", "30d"]).optional() },
|
|
35664
35671
|
run: (a, api2) => api2.api("GET", `/vps/${a.vpsId}/metrics`, { query: { range: a.range } })
|
|
35665
35672
|
}),
|
|
35673
|
+
defineTool({
|
|
35674
|
+
name: "set_vps_auto_renew",
|
|
35675
|
+
title: "Set VPS auto-renew",
|
|
35676
|
+
kind: "write",
|
|
35677
|
+
idempotent: true,
|
|
35678
|
+
description: "Turn auto-renew on or off (sets the value, safe to repeat). With it off, the server is only renewed by renew_vps and expires otherwise.",
|
|
35679
|
+
input: { vpsId, autoRenew: exports_external.boolean() },
|
|
35680
|
+
run: (a, api2) => api2.api("POST", `/vps/${a.vpsId}/auto-renew`, { body: { autoRenew: a.autoRenew } })
|
|
35681
|
+
}),
|
|
35666
35682
|
defineTool({
|
|
35667
35683
|
name: "toggle_vps_auto_renew",
|
|
35668
35684
|
title: "Toggle VPS auto-renew",
|
|
35669
35685
|
kind: "write",
|
|
35670
|
-
description: "Flip auto-renew
|
|
35686
|
+
description: "Flip auto-renew to the other value; the response gives the new one. Prefer set_vps_auto_renew to reach a given state.",
|
|
35671
35687
|
input: { vpsId },
|
|
35672
35688
|
run: (a, api2) => api2.api("POST", `/vps/${a.vpsId}/auto-renew-toggle`)
|
|
35673
35689
|
}),
|
|
@@ -35996,8 +36012,8 @@ var vpsTools = [
|
|
|
35996
36012
|
// src/tools/domains.ts
|
|
35997
36013
|
var domainId = exports_external.number().int().positive().describe("Domain id (number, from list_my_domains)");
|
|
35998
36014
|
var hostId = exports_external.number().int().positive().describe("Child nameserver id (from list_child_nameservers)");
|
|
35999
|
-
var
|
|
36000
|
-
var
|
|
36015
|
+
var dryRun3 = exports_external.boolean().optional().describe("true = return the exact price (IDR, VAT included) and the wallet balance after it; nothing is charged or registered");
|
|
36016
|
+
var DRY2 = "dryRun=true returns the price and walletBalanceAfter without charging or changing anything.";
|
|
36001
36017
|
var record3 = exports_external.object({
|
|
36002
36018
|
name: exports_external.string().describe('"@" for the domain itself, or the part before the domain, e.g. "www" or "_dmarc.mail". A full name like "www.example.com" is accepted and stored as "www"'),
|
|
36003
36019
|
type: exports_external.enum(["A", "AAAA", "MX", "MXE", "CNAME", "SPF", "TXT"]),
|
|
@@ -36073,12 +36089,12 @@ var domainTools = [
|
|
|
36073
36089
|
name: "register_domain",
|
|
36074
36090
|
title: "Register domain",
|
|
36075
36091
|
kind: "write",
|
|
36076
|
-
description: `Register a domain for 1 year. COSTS MONEY from the wallet. Check search_domain, and that the owner details are complete (check_registrant / update_registrant). ${
|
|
36092
|
+
description: `Register a domain for 1 year. COSTS MONEY from the wallet. Check search_domain, and that the owner details are complete (check_registrant / update_registrant). ${DRY2} The dry run includes WHOIS privacy when whoisProtection is true.`,
|
|
36077
36093
|
input: {
|
|
36078
36094
|
name: exports_external.string().describe("Full domain, e.g. tokosaya.id"),
|
|
36079
36095
|
nameservers: exports_external.array(exports_external.string()).min(2).max(5).optional(),
|
|
36080
36096
|
whoisProtection: exports_external.boolean().optional(),
|
|
36081
|
-
dryRun:
|
|
36097
|
+
dryRun: dryRun3
|
|
36082
36098
|
},
|
|
36083
36099
|
run: (a, api2) => api2.api("POST", "/domains/register", { body: { name: a.name, period: 1, nameservers: a.nameservers, whoisProtection: a.whoisProtection }, query: { dryRun: a.dryRun ? "true" : undefined } })
|
|
36084
36100
|
}),
|
|
@@ -36086,16 +36102,16 @@ var domainTools = [
|
|
|
36086
36102
|
name: "transfer_domain",
|
|
36087
36103
|
title: "Transfer domain in",
|
|
36088
36104
|
kind: "write",
|
|
36089
|
-
description: `Transfer a domain from another registrar (adds 1 year). COSTS MONEY from the wallet. Needs the domain's auth code. ${
|
|
36090
|
-
input: { name: exports_external.string(), authCode: exports_external.string(), nameservers: exports_external.array(exports_external.string()).min(2).max(5).optional(), dryRun:
|
|
36105
|
+
description: `Transfer a domain from another registrar (adds 1 year). COSTS MONEY from the wallet. Needs the domain's auth code. ${DRY2}`,
|
|
36106
|
+
input: { name: exports_external.string(), authCode: exports_external.string(), nameservers: exports_external.array(exports_external.string()).min(2).max(5).optional(), dryRun: dryRun3 },
|
|
36091
36107
|
run: (a, api2) => api2.api("POST", "/domains/transfer", { body: { name: a.name, authCode: a.authCode, period: 1, nameservers: a.nameservers }, query: { dryRun: a.dryRun ? "true" : undefined } })
|
|
36092
36108
|
}),
|
|
36093
36109
|
defineTool({
|
|
36094
36110
|
name: "renew_domain",
|
|
36095
36111
|
title: "Renew domain",
|
|
36096
36112
|
kind: "write",
|
|
36097
|
-
description: `Renew a domain for 1 year (plus WHOIS privacy when it is on). COSTS MONEY from the wallet. ${
|
|
36098
|
-
input: { domainId, dryRun:
|
|
36113
|
+
description: `Renew a domain for 1 year (plus WHOIS privacy when it is on). COSTS MONEY from the wallet. ${DRY2}`,
|
|
36114
|
+
input: { domainId, dryRun: dryRun3 },
|
|
36099
36115
|
run: (a, api2) => api2.api("POST", `/domains/${a.domainId}/renew`, { body: { period: 1 }, query: { dryRun: a.dryRun ? "true" : undefined } })
|
|
36100
36116
|
}),
|
|
36101
36117
|
defineTool({
|
|
@@ -36258,7 +36274,7 @@ var message = exports_external.object({
|
|
|
36258
36274
|
variables: exports_external.record(exports_external.string(), exports_external.string()).optional(),
|
|
36259
36275
|
idempotencyKey: exports_external.string().max(128).optional()
|
|
36260
36276
|
});
|
|
36261
|
-
var
|
|
36277
|
+
var dryRun4 = exports_external.boolean().optional().describe("true = return the price (IDR) and the wallet balance after it; nothing is charged or changed");
|
|
36262
36278
|
var idem2 = exports_external.string().regex(/^[A-Za-z0-9_.:-]{8,128}$/).optional().describe("Idempotency-Key for the real purchase. Generated when omitted; pass the same value when retrying so it is never charged twice");
|
|
36263
36279
|
var MONEY = "COSTS MONEY from the wallet. dryRun=true returns the charge (IDR) and walletBalanceAfter without charging or changing anything.";
|
|
36264
36280
|
var planCode = exports_external.string().min(1).max(50).describe("Plan code from list_email_plans");
|
|
@@ -36294,7 +36310,7 @@ var emailTools = [
|
|
|
36294
36310
|
title: "Buy email plan",
|
|
36295
36311
|
kind: "write",
|
|
36296
36312
|
description: `Start an email plan for the project (a free plan activates without charge). Works for a project with no email yet: the real call also sets email up (result.setup). ${MONEY} The dry run's mode says purchase, activate_free or already_active.`,
|
|
36297
|
-
input: { projectId, planCode, months: exports_external.union([exports_external.literal(1), exports_external.literal(3), exports_external.literal(6), exports_external.literal(12)]).optional().describe("Billing cycle, default 1"), dryRun:
|
|
36313
|
+
input: { projectId, planCode, months: exports_external.union([exports_external.literal(1), exports_external.literal(3), exports_external.literal(6), exports_external.literal(12)]).optional().describe("Billing cycle, default 1"), dryRun: dryRun4, idempotencyKey: idem2 },
|
|
36298
36314
|
run: (a, api2) => api2.email("POST", "/plan", {
|
|
36299
36315
|
project: a.projectId,
|
|
36300
36316
|
body: { planCode: a.planCode, months: a.months },
|
|
@@ -36307,7 +36323,7 @@ var emailTools = [
|
|
|
36307
36323
|
title: "Renew email plan",
|
|
36308
36324
|
kind: "write",
|
|
36309
36325
|
description: `Renew the project's ended or expiring email plan (409 PLAN_ACTIVE while one is still running and cannot be extended). Repeats the last plan and cycle unless planCode / months are given. ${MONEY}`,
|
|
36310
|
-
input: { projectId, planCode: planCode.optional(), months: exports_external.union([exports_external.literal(1), exports_external.literal(3), exports_external.literal(6), exports_external.literal(12)]).optional(), dryRun:
|
|
36326
|
+
input: { projectId, planCode: planCode.optional(), months: exports_external.union([exports_external.literal(1), exports_external.literal(3), exports_external.literal(6), exports_external.literal(12)]).optional(), dryRun: dryRun4, idempotencyKey: idem2 },
|
|
36311
36327
|
run: (a, api2) => api2.email("POST", "/plan/renew", {
|
|
36312
36328
|
project: a.projectId,
|
|
36313
36329
|
body: { planCode: a.planCode, months: a.months },
|
|
@@ -36320,7 +36336,7 @@ var emailTools = [
|
|
|
36320
36336
|
title: "Change email plan",
|
|
36321
36337
|
kind: "write",
|
|
36322
36338
|
description: `Move the active email plan to another plan. An upgrade applies now and charges the prorated difference to the same end date; a downgrade is scheduled for the next cycle (no refund). ${MONEY}`,
|
|
36323
|
-
input: { projectId, planCode, dryRun:
|
|
36339
|
+
input: { projectId, planCode, dryRun: dryRun4, idempotencyKey: idem2 },
|
|
36324
36340
|
run: (a, api2) => api2.email("POST", "/plan/change", {
|
|
36325
36341
|
project: a.projectId,
|
|
36326
36342
|
body: { planCode: a.planCode },
|
|
@@ -36337,7 +36353,7 @@ var emailTools = [
|
|
|
36337
36353
|
projectId,
|
|
36338
36354
|
extraMailboxes: exports_external.number().int().min(0).max(50).describe("Total extra mailboxes wanted (0-50)"),
|
|
36339
36355
|
extraStorageGb: exports_external.number().int().min(0).max(1000).describe("Total extra inbox storage in GB (0-1000)"),
|
|
36340
|
-
dryRun:
|
|
36356
|
+
dryRun: dryRun4,
|
|
36341
36357
|
idempotencyKey: idem2
|
|
36342
36358
|
},
|
|
36343
36359
|
run: (a, api2) => api2.email("POST", "/plan/addons", {
|
|
@@ -36907,7 +36923,7 @@ var emailTools = [
|
|
|
36907
36923
|
// src/tools/databases.ts
|
|
36908
36924
|
var databaseId = exports_external.string().uuid().describe("Database id (from list_databases)");
|
|
36909
36925
|
var environmentId = exports_external.string().uuid().describe("Environment id (from list_projects). Omit for the primary (production) branch.");
|
|
36910
|
-
var
|
|
36926
|
+
var dryRun5 = exports_external.boolean().optional().describe("true = only check and show the result or price; nothing changes");
|
|
36911
36927
|
var databaseTools = [
|
|
36912
36928
|
defineTool({
|
|
36913
36929
|
name: "list_database_plans",
|
|
@@ -37001,7 +37017,7 @@ var databaseTools = [
|
|
|
37001
37017
|
minCu: exports_external.number().min(0.25).max(10).optional(),
|
|
37002
37018
|
maxCu: exports_external.number().min(0.25).max(10).optional(),
|
|
37003
37019
|
suspendTimeoutSeconds: exports_external.number().int().min(0).max(604800).optional().describe("0 = never suspend, or 60-604800"),
|
|
37004
|
-
dryRun:
|
|
37020
|
+
dryRun: dryRun5
|
|
37005
37021
|
},
|
|
37006
37022
|
run: (a, api2) => api2.api("PATCH", `/databases/${a.databaseId}/settings`, {
|
|
37007
37023
|
body: { minCu: a.minCu, maxCu: a.maxCu, suspendTimeoutSeconds: a.suspendTimeoutSeconds },
|
|
@@ -37013,7 +37029,7 @@ var databaseTools = [
|
|
|
37013
37029
|
title: "Upgrade database plan / top up",
|
|
37014
37030
|
kind: "write",
|
|
37015
37031
|
description: "Buy a paid plan or top up credits. COSTS MONEY from the wallet: call with dryRun first, show price and wallet balance after, and get the user's explicit OK.",
|
|
37016
|
-
input: { databaseId, plan: exports_external.string().describe("Plan code (e.g. STARTER) or id from list_database_plans"), dryRun:
|
|
37032
|
+
input: { databaseId, plan: exports_external.string().describe("Plan code (e.g. STARTER) or id from list_database_plans"), dryRun: dryRun5, idempotencyKey: exports_external.string().max(128).optional() },
|
|
37017
37033
|
run: (a, api2) => api2.api("POST", `/databases/${a.databaseId}/upgrade`, { body: { plan: a.plan }, query: { dryRun: a.dryRun ? "true" : undefined }, idempotencyKey: a.idempotencyKey })
|
|
37018
37034
|
}),
|
|
37019
37035
|
defineTool({
|
|
@@ -37271,7 +37287,7 @@ var accountTools = [
|
|
|
37271
37287
|
var projectId2 = exports_external.string().uuid().optional().describe("Limit to one project (a project key is always limited to its own)");
|
|
37272
37288
|
var keyId = exports_external.string().uuid().optional().describe("Limit to one AI key (id from list_ai_keys)");
|
|
37273
37289
|
var model = exports_external.string().max(100).optional().describe("Limit to one model id");
|
|
37274
|
-
var
|
|
37290
|
+
var dryRun6 = exports_external.boolean().optional().describe("true = only check and show the result; nothing is charged or changed");
|
|
37275
37291
|
var ACCOUNT_KEY2 = "Needs a whole-account key (a key limited to one project gets 403 ACCOUNT_KEY_REQUIRED).";
|
|
37276
37292
|
var imageProject = exports_external.string().uuid().optional().describe("Project the images belong to (required with a whole-account key; a project key uses its own)");
|
|
37277
37293
|
var INLINE_MAX_BYTES = 1500000;
|
|
@@ -37356,7 +37372,7 @@ var aiTools = [
|
|
|
37356
37372
|
n: exports_external.number().int().min(1).max(10).optional().describe("Images in this request (up to the model's maxN; default 1)"),
|
|
37357
37373
|
images: exports_external.array(exports_external.string().url().startsWith("https://")).max(10).optional().describe("Reference images as https:// links (only models with refImages > 0)"),
|
|
37358
37374
|
projectId: imageProject,
|
|
37359
|
-
dryRun:
|
|
37375
|
+
dryRun: dryRun6,
|
|
37360
37376
|
wait: exports_external.number().int().min(0).max(55).optional().describe("Seconds to wait for the result (default 50; 0 = return the id at once)"),
|
|
37361
37377
|
idempotencyKey: exports_external.string().regex(/^[A-Za-z0-9_.:-]{8,128}$/).optional().describe("Idempotency-Key for the real request. Generated when omitted; pass the same value when retrying so it is never charged twice")
|
|
37362
37378
|
},
|
|
@@ -37406,7 +37422,7 @@ var aiTools = [
|
|
|
37406
37422
|
input: {
|
|
37407
37423
|
packId: exports_external.string().min(1).max(64).optional(),
|
|
37408
37424
|
amount: exports_external.number().min(1).max(1e9).optional().describe("IDR"),
|
|
37409
|
-
dryRun:
|
|
37425
|
+
dryRun: dryRun6,
|
|
37410
37426
|
idempotencyKey: exports_external.string().regex(/^[A-Za-z0-9_.:-]{8,128}$/).optional().describe("Idempotency-Key for the real top-up. Generated when omitted; pass the same value when retrying so it is never charged twice")
|
|
37411
37427
|
},
|
|
37412
37428
|
run: (a, api2) => {
|
|
@@ -37429,7 +37445,7 @@ var aiTools = [
|
|
|
37429
37445
|
enabled: exports_external.boolean(),
|
|
37430
37446
|
threshold: exports_external.number().min(1).optional().describe("Top up when the AI balance is below this (IDR)"),
|
|
37431
37447
|
amount: exports_external.number().min(1).optional().describe("How much to top up each time (IDR)"),
|
|
37432
|
-
dryRun:
|
|
37448
|
+
dryRun: dryRun6
|
|
37433
37449
|
},
|
|
37434
37450
|
run: (a, api2) => api2.api("PUT", "/ai/auto-topup", {
|
|
37435
37451
|
body: { enabled: a.enabled, threshold: a.threshold, amount: a.amount },
|
|
@@ -37465,7 +37481,7 @@ var generalTools = [
|
|
|
37465
37481
|
];
|
|
37466
37482
|
|
|
37467
37483
|
// src/server.ts
|
|
37468
|
-
var VERSION = "0.5.
|
|
37484
|
+
var VERSION = "0.5.10";
|
|
37469
37485
|
var INSTRUCTIONS = `Helipod is a cloud platform (Indonesia): containers, managed Postgres databases, VPS, domains, email and an AI gateway, billed from a prepaid wallet in Rupiah.
|
|
37470
37486
|
- Start with list_projects to find projects and environment ids. Account tools (get_wallet, invoices, statements, notifications, get_project_activity, support tickets) cover the account; AI tools (list_ai_models, get_ai_overview, get_ai_usage, AI keys, top-ups, generate_ai_image) cover the AI gateway.
|
|
37471
37487
|
- Anything that costs money (create/deploy/scale services, resize volumes, upgrade a database plan, create/renew/upgrade VPS, VPS backups, register/renew/transfer domains, email plans and inbox add-ons, AI top-ups and auto top-up, generating images): call it with dryRun=true first (or the price lookup when it has no dry run), tell the user the cost in IDR and the wallet balance after, and wait for an explicit yes before the real call. Never treat silence or an earlier general OK as a yes.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "helipod-mcp",
|
|
3
3
|
"mcpName": "io.helipod/helipod",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.10",
|
|
5
5
|
"description": "MCP server for Helipod: containers, databases, VPS, domains and email from Claude Code, Codex, Cursor and other AI tools.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|