helipod-mcp 0.5.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/http.js +14 -15
- package/dist/index.js +14 -15
- package/dist/stdio.js +14 -15
- package/package.json +1 -1
- package/skills/helipod-vps/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -198,7 +198,7 @@ Pick your agents when asked (or pass `-a codex cursor gemini-cli opencode -y`).
|
|
|
198
198
|
| Email | status, plan (buy, renew, change, inbox add-ons, with dry runs), send, sent log, sending domains, templates, contacts, segments, topics, broadcasts, suppressions, webhooks, inbox |
|
|
199
199
|
| Account | wallet and transactions, invoices, monthly statements, notifications, project activity, support tickets |
|
|
200
200
|
| AI | models and prices, balance, usage, metrics, AI keys (list, revoke), top-up and auto top-up |
|
|
201
|
-
| Other | `
|
|
201
|
+
| Other | `helipod_api_get` to read any other documented endpoint (read only) |
|
|
202
202
|
|
|
203
203
|
Each tool is marked read-only, write or destructive, so clients can ask before running the risky ones. Calls that cost money support a dry run, and the server tells the agent to show the price and wait for your OK.
|
|
204
204
|
|
package/dist/http.js
CHANGED
|
@@ -35673,7 +35673,7 @@ function register(server, api2, defs) {
|
|
|
35673
35673
|
annotations: {
|
|
35674
35674
|
title: d.title,
|
|
35675
35675
|
readOnlyHint: d.kind === "read",
|
|
35676
|
-
destructiveHint: d.kind
|
|
35676
|
+
destructiveHint: d.kind !== "read",
|
|
35677
35677
|
idempotentHint: d.kind === "read" || !!d.idempotent,
|
|
35678
35678
|
openWorldHint: true
|
|
35679
35679
|
}
|
|
@@ -36861,7 +36861,7 @@ var emailTools = [
|
|
|
36861
36861
|
name: "email_status",
|
|
36862
36862
|
title: "Email status",
|
|
36863
36863
|
kind: "read",
|
|
36864
|
-
description: "Email service of the key's project: plan, usage today and this month, limits, counts.",
|
|
36864
|
+
description: "Email service of the key's project: plan, usage today and this month, limits, counts. activated false = email is not set up yet: start it with buy_email_plan.",
|
|
36865
36865
|
input: { projectId },
|
|
36866
36866
|
run: (a, api2) => api2.email("GET", "/status", { project: a.projectId })
|
|
36867
36867
|
}),
|
|
@@ -36885,7 +36885,7 @@ var emailTools = [
|
|
|
36885
36885
|
name: "buy_email_plan",
|
|
36886
36886
|
title: "Buy email plan",
|
|
36887
36887
|
kind: "write",
|
|
36888
|
-
description: `Start an email plan for the project (a free plan activates without charge). ${MONEY} The dry run's mode says purchase, activate_free or already_active.`,
|
|
36888
|
+
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.`,
|
|
36889
36889
|
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: dryRun3, idempotencyKey: idem2 },
|
|
36890
36890
|
run: (a, api2) => api2.email("POST", "/plan", {
|
|
36891
36891
|
project: a.projectId,
|
|
@@ -37958,16 +37958,14 @@ var aiTools = [
|
|
|
37958
37958
|
var API_PREFIXES = ["/containers/", "/databases", "/vps", "/backup/", "/domains", "/account/", "/ai/"];
|
|
37959
37959
|
var generalTools = [
|
|
37960
37960
|
defineTool({
|
|
37961
|
-
name: "
|
|
37962
|
-
title: "
|
|
37963
|
-
kind: "
|
|
37964
|
-
description: "
|
|
37961
|
+
name: "helipod_api_get",
|
|
37962
|
+
title: "Read any Helipod API endpoint",
|
|
37963
|
+
kind: "read",
|
|
37964
|
+
description: "GET an endpoint of the Helipod public API that has no dedicated read tool (Helipod API reference: https://docs.helipod.io/docs/helipod). api=core for the Container, Database, VPS, Domain, Account and AI APIs (paths like /vps/{id}/backup/runs, /account/wallet, /ai/usage), api=email for the Email API (paths like /broadcasts). Read only: it never changes anything.",
|
|
37965
37965
|
input: {
|
|
37966
37966
|
api: exports_external.enum(["core", "email"]),
|
|
37967
|
-
|
|
37968
|
-
|
|
37969
|
-
query: exports_external.record(exports_external.string(), exports_external.string()).optional(),
|
|
37970
|
-
body: exports_external.record(exports_external.string(), exports_external.any()).optional()
|
|
37967
|
+
path: exports_external.string().regex(/^\/[A-Za-z0-9/_.\-:]*$/).describe("Path after the base URL, e.g. /vps/abc/backup/runs"),
|
|
37968
|
+
query: exports_external.record(exports_external.string(), exports_external.string()).optional()
|
|
37971
37969
|
},
|
|
37972
37970
|
run: (a, api2) => {
|
|
37973
37971
|
if (a.path.includes(".."))
|
|
@@ -37975,23 +37973,24 @@ var generalTools = [
|
|
|
37975
37973
|
if (a.api === "core") {
|
|
37976
37974
|
if (!API_PREFIXES.some((p) => a.path.startsWith(p)))
|
|
37977
37975
|
throw new Error(`Core API paths start with one of: ${API_PREFIXES.join(", ")}`);
|
|
37978
|
-
return api2.api(
|
|
37976
|
+
return api2.api("GET", a.path, { query: a.query });
|
|
37979
37977
|
}
|
|
37980
|
-
return api2.email(
|
|
37978
|
+
return api2.email("GET", a.path, { query: a.query });
|
|
37981
37979
|
}
|
|
37982
37980
|
})
|
|
37983
37981
|
];
|
|
37984
37982
|
|
|
37985
37983
|
// src/server.ts
|
|
37986
|
-
var VERSION = "0.5.
|
|
37984
|
+
var VERSION = "0.5.2";
|
|
37987
37985
|
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.
|
|
37988
37986
|
- 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) cover the AI gateway.
|
|
37989
37987
|
- 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): 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.
|
|
37990
37988
|
- Destructive tools (delete, terminate, reinstall, rollback, restore a backup, replace DNS, revoke a key, remove an SSH key or port forward, send a broadcast, execute_database_sql): confirm with the user and name what will be lost. Before execute_database_sql, run classify_database_sql.
|
|
37989
|
+
- Email: when a project has no email yet (email_status shows activated false) or its plan ended, start it with buy_email_plan (dryRun first; the FREE plan costs nothing, still confirm). That also sets email up for the project; then add and verify a sending domain.
|
|
37991
37990
|
- Databases: get_database_connection returns a password; put it in a secret variable (DATABASE_URL) instead of code or chat.
|
|
37992
37991
|
- Deploys and VPS actions run in the background: poll get_deployment / get_vps until they settle; on a failed deploy read get_deployment_logs.
|
|
37993
37992
|
- Never print secrets (passwords, secret variable values, secret files) unless the user asks for them. Domain owner details are personal data: use only what the user gave.
|
|
37994
|
-
- Errors come back as { status, code, error }: 401/403 means the key lacks access (keys choose products and projects in Settings → API keys; wallet, invoices, tickets and AI money need a whole-account key), 402 means plan limit or low balance.
|
|
37993
|
+
- Errors come back as { status, code, error }: 401/403 means the key lacks access (keys choose products and projects in Settings → API keys; wallet, invoices, tickets and AI money need a whole-account key: with a sign-in, reconnect and choose Whole account), 402 means plan limit or low balance.
|
|
37995
37994
|
Docs: https://docs.helipod.io`;
|
|
37996
37995
|
var ALL_TOOLS = [...containerTools, ...databaseTools, ...vpsTools, ...domainTools, ...emailTools, ...accountTools, ...aiTools, ...generalTools];
|
|
37997
37996
|
function createHelipodServer(config2) {
|
package/dist/index.js
CHANGED
|
@@ -34818,7 +34818,7 @@ function register(server, api2, defs) {
|
|
|
34818
34818
|
annotations: {
|
|
34819
34819
|
title: d.title,
|
|
34820
34820
|
readOnlyHint: d.kind === "read",
|
|
34821
|
-
destructiveHint: d.kind
|
|
34821
|
+
destructiveHint: d.kind !== "read",
|
|
34822
34822
|
idempotentHint: d.kind === "read" || !!d.idempotent,
|
|
34823
34823
|
openWorldHint: true
|
|
34824
34824
|
}
|
|
@@ -36006,7 +36006,7 @@ var emailTools = [
|
|
|
36006
36006
|
name: "email_status",
|
|
36007
36007
|
title: "Email status",
|
|
36008
36008
|
kind: "read",
|
|
36009
|
-
description: "Email service of the key's project: plan, usage today and this month, limits, counts.",
|
|
36009
|
+
description: "Email service of the key's project: plan, usage today and this month, limits, counts. activated false = email is not set up yet: start it with buy_email_plan.",
|
|
36010
36010
|
input: { projectId },
|
|
36011
36011
|
run: (a, api2) => api2.email("GET", "/status", { project: a.projectId })
|
|
36012
36012
|
}),
|
|
@@ -36030,7 +36030,7 @@ var emailTools = [
|
|
|
36030
36030
|
name: "buy_email_plan",
|
|
36031
36031
|
title: "Buy email plan",
|
|
36032
36032
|
kind: "write",
|
|
36033
|
-
description: `Start an email plan for the project (a free plan activates without charge). ${MONEY} The dry run's mode says purchase, activate_free or already_active.`,
|
|
36033
|
+
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.`,
|
|
36034
36034
|
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: dryRun3, idempotencyKey: idem2 },
|
|
36035
36035
|
run: (a, api2) => api2.email("POST", "/plan", {
|
|
36036
36036
|
project: a.projectId,
|
|
@@ -37103,16 +37103,14 @@ var aiTools = [
|
|
|
37103
37103
|
var API_PREFIXES = ["/containers/", "/databases", "/vps", "/backup/", "/domains", "/account/", "/ai/"];
|
|
37104
37104
|
var generalTools = [
|
|
37105
37105
|
defineTool({
|
|
37106
|
-
name: "
|
|
37107
|
-
title: "
|
|
37108
|
-
kind: "
|
|
37109
|
-
description: "
|
|
37106
|
+
name: "helipod_api_get",
|
|
37107
|
+
title: "Read any Helipod API endpoint",
|
|
37108
|
+
kind: "read",
|
|
37109
|
+
description: "GET an endpoint of the Helipod public API that has no dedicated read tool (Helipod API reference: https://docs.helipod.io/docs/helipod). api=core for the Container, Database, VPS, Domain, Account and AI APIs (paths like /vps/{id}/backup/runs, /account/wallet, /ai/usage), api=email for the Email API (paths like /broadcasts). Read only: it never changes anything.",
|
|
37110
37110
|
input: {
|
|
37111
37111
|
api: exports_external.enum(["core", "email"]),
|
|
37112
|
-
|
|
37113
|
-
|
|
37114
|
-
query: exports_external.record(exports_external.string(), exports_external.string()).optional(),
|
|
37115
|
-
body: exports_external.record(exports_external.string(), exports_external.any()).optional()
|
|
37112
|
+
path: exports_external.string().regex(/^\/[A-Za-z0-9/_.\-:]*$/).describe("Path after the base URL, e.g. /vps/abc/backup/runs"),
|
|
37113
|
+
query: exports_external.record(exports_external.string(), exports_external.string()).optional()
|
|
37116
37114
|
},
|
|
37117
37115
|
run: (a, api2) => {
|
|
37118
37116
|
if (a.path.includes(".."))
|
|
@@ -37120,23 +37118,24 @@ var generalTools = [
|
|
|
37120
37118
|
if (a.api === "core") {
|
|
37121
37119
|
if (!API_PREFIXES.some((p) => a.path.startsWith(p)))
|
|
37122
37120
|
throw new Error(`Core API paths start with one of: ${API_PREFIXES.join(", ")}`);
|
|
37123
|
-
return api2.api(
|
|
37121
|
+
return api2.api("GET", a.path, { query: a.query });
|
|
37124
37122
|
}
|
|
37125
|
-
return api2.email(
|
|
37123
|
+
return api2.email("GET", a.path, { query: a.query });
|
|
37126
37124
|
}
|
|
37127
37125
|
})
|
|
37128
37126
|
];
|
|
37129
37127
|
|
|
37130
37128
|
// src/server.ts
|
|
37131
|
-
var VERSION = "0.5.
|
|
37129
|
+
var VERSION = "0.5.2";
|
|
37132
37130
|
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.
|
|
37133
37131
|
- 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) cover the AI gateway.
|
|
37134
37132
|
- 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): 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.
|
|
37135
37133
|
- Destructive tools (delete, terminate, reinstall, rollback, restore a backup, replace DNS, revoke a key, remove an SSH key or port forward, send a broadcast, execute_database_sql): confirm with the user and name what will be lost. Before execute_database_sql, run classify_database_sql.
|
|
37134
|
+
- Email: when a project has no email yet (email_status shows activated false) or its plan ended, start it with buy_email_plan (dryRun first; the FREE plan costs nothing, still confirm). That also sets email up for the project; then add and verify a sending domain.
|
|
37136
37135
|
- Databases: get_database_connection returns a password; put it in a secret variable (DATABASE_URL) instead of code or chat.
|
|
37137
37136
|
- Deploys and VPS actions run in the background: poll get_deployment / get_vps until they settle; on a failed deploy read get_deployment_logs.
|
|
37138
37137
|
- Never print secrets (passwords, secret variable values, secret files) unless the user asks for them. Domain owner details are personal data: use only what the user gave.
|
|
37139
|
-
- Errors come back as { status, code, error }: 401/403 means the key lacks access (keys choose products and projects in Settings → API keys; wallet, invoices, tickets and AI money need a whole-account key), 402 means plan limit or low balance.
|
|
37138
|
+
- Errors come back as { status, code, error }: 401/403 means the key lacks access (keys choose products and projects in Settings → API keys; wallet, invoices, tickets and AI money need a whole-account key: with a sign-in, reconnect and choose Whole account), 402 means plan limit or low balance.
|
|
37140
37139
|
Docs: https://docs.helipod.io`;
|
|
37141
37140
|
var ALL_TOOLS = [...containerTools, ...databaseTools, ...vpsTools, ...domainTools, ...emailTools, ...accountTools, ...aiTools, ...generalTools];
|
|
37142
37141
|
function createHelipodServer(config2) {
|
package/dist/stdio.js
CHANGED
|
@@ -34925,7 +34925,7 @@ function register(server, api2, defs) {
|
|
|
34925
34925
|
annotations: {
|
|
34926
34926
|
title: d.title,
|
|
34927
34927
|
readOnlyHint: d.kind === "read",
|
|
34928
|
-
destructiveHint: d.kind
|
|
34928
|
+
destructiveHint: d.kind !== "read",
|
|
34929
34929
|
idempotentHint: d.kind === "read" || !!d.idempotent,
|
|
34930
34930
|
openWorldHint: true
|
|
34931
34931
|
}
|
|
@@ -36113,7 +36113,7 @@ var emailTools = [
|
|
|
36113
36113
|
name: "email_status",
|
|
36114
36114
|
title: "Email status",
|
|
36115
36115
|
kind: "read",
|
|
36116
|
-
description: "Email service of the key's project: plan, usage today and this month, limits, counts.",
|
|
36116
|
+
description: "Email service of the key's project: plan, usage today and this month, limits, counts. activated false = email is not set up yet: start it with buy_email_plan.",
|
|
36117
36117
|
input: { projectId },
|
|
36118
36118
|
run: (a, api2) => api2.email("GET", "/status", { project: a.projectId })
|
|
36119
36119
|
}),
|
|
@@ -36137,7 +36137,7 @@ var emailTools = [
|
|
|
36137
36137
|
name: "buy_email_plan",
|
|
36138
36138
|
title: "Buy email plan",
|
|
36139
36139
|
kind: "write",
|
|
36140
|
-
description: `Start an email plan for the project (a free plan activates without charge). ${MONEY} The dry run's mode says purchase, activate_free or already_active.`,
|
|
36140
|
+
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.`,
|
|
36141
36141
|
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: dryRun3, idempotencyKey: idem2 },
|
|
36142
36142
|
run: (a, api2) => api2.email("POST", "/plan", {
|
|
36143
36143
|
project: a.projectId,
|
|
@@ -37210,16 +37210,14 @@ var aiTools = [
|
|
|
37210
37210
|
var API_PREFIXES = ["/containers/", "/databases", "/vps", "/backup/", "/domains", "/account/", "/ai/"];
|
|
37211
37211
|
var generalTools = [
|
|
37212
37212
|
defineTool({
|
|
37213
|
-
name: "
|
|
37214
|
-
title: "
|
|
37215
|
-
kind: "
|
|
37216
|
-
description: "
|
|
37213
|
+
name: "helipod_api_get",
|
|
37214
|
+
title: "Read any Helipod API endpoint",
|
|
37215
|
+
kind: "read",
|
|
37216
|
+
description: "GET an endpoint of the Helipod public API that has no dedicated read tool (Helipod API reference: https://docs.helipod.io/docs/helipod). api=core for the Container, Database, VPS, Domain, Account and AI APIs (paths like /vps/{id}/backup/runs, /account/wallet, /ai/usage), api=email for the Email API (paths like /broadcasts). Read only: it never changes anything.",
|
|
37217
37217
|
input: {
|
|
37218
37218
|
api: exports_external.enum(["core", "email"]),
|
|
37219
|
-
|
|
37220
|
-
|
|
37221
|
-
query: exports_external.record(exports_external.string(), exports_external.string()).optional(),
|
|
37222
|
-
body: exports_external.record(exports_external.string(), exports_external.any()).optional()
|
|
37219
|
+
path: exports_external.string().regex(/^\/[A-Za-z0-9/_.\-:]*$/).describe("Path after the base URL, e.g. /vps/abc/backup/runs"),
|
|
37220
|
+
query: exports_external.record(exports_external.string(), exports_external.string()).optional()
|
|
37223
37221
|
},
|
|
37224
37222
|
run: (a, api2) => {
|
|
37225
37223
|
if (a.path.includes(".."))
|
|
@@ -37227,23 +37225,24 @@ var generalTools = [
|
|
|
37227
37225
|
if (a.api === "core") {
|
|
37228
37226
|
if (!API_PREFIXES.some((p) => a.path.startsWith(p)))
|
|
37229
37227
|
throw new Error(`Core API paths start with one of: ${API_PREFIXES.join(", ")}`);
|
|
37230
|
-
return api2.api(
|
|
37228
|
+
return api2.api("GET", a.path, { query: a.query });
|
|
37231
37229
|
}
|
|
37232
|
-
return api2.email(
|
|
37230
|
+
return api2.email("GET", a.path, { query: a.query });
|
|
37233
37231
|
}
|
|
37234
37232
|
})
|
|
37235
37233
|
];
|
|
37236
37234
|
|
|
37237
37235
|
// src/server.ts
|
|
37238
|
-
var VERSION = "0.5.
|
|
37236
|
+
var VERSION = "0.5.2";
|
|
37239
37237
|
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.
|
|
37240
37238
|
- 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) cover the AI gateway.
|
|
37241
37239
|
- 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): 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.
|
|
37242
37240
|
- Destructive tools (delete, terminate, reinstall, rollback, restore a backup, replace DNS, revoke a key, remove an SSH key or port forward, send a broadcast, execute_database_sql): confirm with the user and name what will be lost. Before execute_database_sql, run classify_database_sql.
|
|
37241
|
+
- Email: when a project has no email yet (email_status shows activated false) or its plan ended, start it with buy_email_plan (dryRun first; the FREE plan costs nothing, still confirm). That also sets email up for the project; then add and verify a sending domain.
|
|
37243
37242
|
- Databases: get_database_connection returns a password; put it in a secret variable (DATABASE_URL) instead of code or chat.
|
|
37244
37243
|
- Deploys and VPS actions run in the background: poll get_deployment / get_vps until they settle; on a failed deploy read get_deployment_logs.
|
|
37245
37244
|
- Never print secrets (passwords, secret variable values, secret files) unless the user asks for them. Domain owner details are personal data: use only what the user gave.
|
|
37246
|
-
- Errors come back as { status, code, error }: 401/403 means the key lacks access (keys choose products and projects in Settings → API keys; wallet, invoices, tickets and AI money need a whole-account key), 402 means plan limit or low balance.
|
|
37245
|
+
- Errors come back as { status, code, error }: 401/403 means the key lacks access (keys choose products and projects in Settings → API keys; wallet, invoices, tickets and AI money need a whole-account key: with a sign-in, reconnect and choose Whole account), 402 means plan limit or low balance.
|
|
37247
37246
|
Docs: https://docs.helipod.io`;
|
|
37248
37247
|
var ALL_TOOLS = [...containerTools, ...databaseTools, ...vpsTools, ...domainTools, ...emailTools, ...accountTools, ...aiTools, ...generalTools];
|
|
37249
37248
|
function createHelipodServer(config2) {
|
package/package.json
CHANGED
|
@@ -25,4 +25,4 @@ Follow the `helipod` skill rules. A VPS is prepaid per period: creating one char
|
|
|
25
25
|
- Billing: `get_vps_renewal_options` → `renew_vps`; `upgrade_vps` to a larger plan (charges the difference, restarts); `toggle_vps_auto_renew`.
|
|
26
26
|
- Terminate: `terminate_vps` is permanent, no refund: confirm explicitly.
|
|
27
27
|
|
|
28
|
-
Backups (paid add-on)
|
|
28
|
+
Backups (paid add-on) have dedicated tools; to read anything else use `helipod_api_get` with paths from https://docs.helipod.io/docs/vps-api
|