helipod-mcp 0.5.8 → 0.5.9
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 +41 -7
- package/dist/index.js +41 -7
- package/dist/stdio.js +41 -7
- package/package.json +1 -1
package/dist/http.js
CHANGED
|
@@ -35582,10 +35582,12 @@ var EMPTY_COMPLETION_RESULT = {
|
|
|
35582
35582
|
class HelipodError extends Error {
|
|
35583
35583
|
status;
|
|
35584
35584
|
code;
|
|
35585
|
-
|
|
35585
|
+
details;
|
|
35586
|
+
constructor(status, code, message, details) {
|
|
35586
35587
|
super(message);
|
|
35587
35588
|
this.status = status;
|
|
35588
35589
|
this.code = code;
|
|
35590
|
+
this.details = details;
|
|
35589
35591
|
this.name = "HelipodError";
|
|
35590
35592
|
}
|
|
35591
35593
|
}
|
|
@@ -35681,7 +35683,8 @@ class HelipodClient {
|
|
|
35681
35683
|
if (!res.ok || json2?.success === false) {
|
|
35682
35684
|
const retry = res.headers.get("retry-after");
|
|
35683
35685
|
const msg = json2?.error ?? (text.slice(0, 300) || res.statusText);
|
|
35684
|
-
|
|
35686
|
+
const details = json2?.details && typeof json2.details === "object" && !Array.isArray(json2.details) ? json2.details : undefined;
|
|
35687
|
+
throw new HelipodError(res.status, json2?.code, retry ? `${msg} (retry after ${retry}s)` : String(msg), details);
|
|
35685
35688
|
}
|
|
35686
35689
|
return json2 && "data" in json2 ? json2.data : json2;
|
|
35687
35690
|
}
|
|
@@ -35713,7 +35716,7 @@ function register(server, api2, defs) {
|
|
|
35713
35716
|
const err = e instanceof HelipodError ? e : new HelipodError(0, "CLIENT_ERROR", String(e?.message ?? e));
|
|
35714
35717
|
return {
|
|
35715
35718
|
isError: true,
|
|
35716
|
-
content: [{ type: "text", text: JSON.stringify({ status: err.status, code: err.code ?? null, error: err.message }, null, 2) }]
|
|
35719
|
+
content: [{ type: "text", text: JSON.stringify({ status: err.status, code: err.code ?? null, error: err.message, ...err.details ? { details: err.details } : {} }, null, 2) }]
|
|
35717
35720
|
};
|
|
35718
35721
|
}
|
|
35719
35722
|
});
|
|
@@ -35847,18 +35850,48 @@ var containerTools = [
|
|
|
35847
35850
|
input: { serviceId: id("Service") },
|
|
35848
35851
|
run: (a, api2) => api2.api("GET", `${C}/services/${a.serviceId}`)
|
|
35849
35852
|
}),
|
|
35853
|
+
defineTool({
|
|
35854
|
+
name: "get_git_connections",
|
|
35855
|
+
title: "Git connections",
|
|
35856
|
+
kind: "read",
|
|
35857
|
+
description: "Whether the user connected GitHub (sign-in + the Helipod GitHub App, with the accounts it is installed on) and GitLab, plus connectUrl: the Helipod page where the user connects them. Check this before deploying from a private repo. Connecting needs the user in a browser: give them connectUrl, never try to connect yourself.",
|
|
35858
|
+
input: {},
|
|
35859
|
+
run: (_a3, api2) => api2.api("GET", `${C}/git/connections`)
|
|
35860
|
+
}),
|
|
35861
|
+
defineTool({
|
|
35862
|
+
name: "list_git_repos",
|
|
35863
|
+
title: "List Git repositories",
|
|
35864
|
+
kind: "read",
|
|
35865
|
+
description: "Repositories the user's connected GitHub App installations (host github, default) or GitLab account (host gitlab) can reach: fullName, url, private, defaultBranch, newest first. Pass one url to create_service as repo. Not connected: 409 with details.connectUrl for the user.",
|
|
35866
|
+
input: {
|
|
35867
|
+
host: exports_external.enum(["github", "gitlab"]).optional().describe("github (default) or gitlab"),
|
|
35868
|
+
installationId: exports_external.number().int().positive().optional().describe("Only this GitHub installation (id from get_git_connections)"),
|
|
35869
|
+
search: exports_external.string().max(200).optional().describe("Filter by part of owner/name"),
|
|
35870
|
+
limit: exports_external.number().int().min(1).max(100).optional().describe("Default 50"),
|
|
35871
|
+
offset: exports_external.number().int().min(0).optional()
|
|
35872
|
+
},
|
|
35873
|
+
run: (a, api2) => api2.api("GET", `${C}/git/repos`, {
|
|
35874
|
+
query: {
|
|
35875
|
+
host: a.host,
|
|
35876
|
+
installationId: a.installationId !== undefined ? String(a.installationId) : undefined,
|
|
35877
|
+
search: a.search,
|
|
35878
|
+
limit: a.limit !== undefined ? String(a.limit) : undefined,
|
|
35879
|
+
offset: a.offset !== undefined ? String(a.offset) : undefined
|
|
35880
|
+
}
|
|
35881
|
+
})
|
|
35882
|
+
}),
|
|
35850
35883
|
defineTool({
|
|
35851
35884
|
name: "create_service",
|
|
35852
35885
|
title: "Create service",
|
|
35853
35886
|
kind: "write",
|
|
35854
|
-
description: "Create a service from a container image, a
|
|
35887
|
+
description: "Create a service from a container image, a Git repository or an inline Dockerfile, and (unless deploy=false) start its first deploy. Private GitHub / GitLab repos work once connected (get_git_connections, list_git_repos); such services also redeploy on every push. A private repo that is not connected is refused (409 GITHUB_NOT_CONNECTED / GITLAB_NOT_CONNECTED / REPO_NOT_ACCESSIBLE, nothing created): give the user details.connectUrl and retry after they connect. COSTS MONEY once deployed (billed daily from the wallet): call with dryRun=true first, show the dailyCost to the user and get their OK.",
|
|
35855
35888
|
input: {
|
|
35856
35889
|
environmentId: id("Environment"),
|
|
35857
35890
|
name: exports_external.string().regex(/^[A-Za-z][A-Za-z0-9_-]{0,39}$/).describe("Service name (letters, digits, _ -; starts with a letter). Also used in references like ${{name.KEY}}"),
|
|
35858
35891
|
image: exports_external.string().optional().describe("Container image, e.g. nginx:alpine or ghcr.io/acme/app:1.2"),
|
|
35859
35892
|
registryUsername: exports_external.string().optional().describe("Private registry user (with registryPassword)"),
|
|
35860
35893
|
registryPassword: exports_external.string().optional().describe("Private registry password or token"),
|
|
35861
|
-
repo: exports_external.string().optional().describe("
|
|
35894
|
+
repo: exports_external.string().optional().describe("Git repository: https URL or owner/name for GitHub (instead of image). Private repos need a connected GitHub / GitLab (list_git_repos)"),
|
|
35862
35895
|
branch: exports_external.string().optional().describe("Git branch (default main)"),
|
|
35863
35896
|
rootDirectory: exports_external.string().optional().describe("Monorepo: folder to build, e.g. apps/web"),
|
|
35864
35897
|
dockerfile: exports_external.string().optional().describe("Inline Dockerfile content (instead of image/repo)"),
|
|
@@ -38180,7 +38213,7 @@ var generalTools = [
|
|
|
38180
38213
|
];
|
|
38181
38214
|
|
|
38182
38215
|
// src/server.ts
|
|
38183
|
-
var VERSION = "0.5.
|
|
38216
|
+
var VERSION = "0.5.9";
|
|
38184
38217
|
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.
|
|
38185
38218
|
- 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.
|
|
38186
38219
|
- 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.
|
|
@@ -38190,9 +38223,10 @@ var INSTRUCTIONS = `Helipod is a cloud platform (Indonesia): containers, managed
|
|
|
38190
38223
|
- Databases: get_database_connection returns a password; put it in a secret variable (DATABASE_URL) instead of code or chat.
|
|
38191
38224
|
- Migrate (free): create_vps_import returns a one-time command for the USER to run as root on their old server (never run it yourself); before the first restore_vps_import, show fetchedIp and ask the user to confirm it is their server.
|
|
38192
38225
|
- Images from generate_ai_image are deleted after 7 days: tell the user and have them download the ones they keep.
|
|
38226
|
+
- Deploying from Git: public repos need nothing. For a private repo check get_git_connections / list_git_repos first; when GitHub or GitLab is not connected (or a call returns 409 GITHUB_NOT_CONNECTED / GITLAB_NOT_CONNECTED / REPO_NOT_ACCESSIBLE), give the user details.connectUrl to open in their browser and try again after they confirm. Never ask for a GitHub token.
|
|
38193
38227
|
- Deploys and VPS actions run in the background: poll get_deployment / get_vps until they settle; on a failed deploy read get_deployment_logs.
|
|
38194
38228
|
- 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.
|
|
38195
|
-
- 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.
|
|
38229
|
+
- Errors come back as { status, code, error, details? }: 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.
|
|
38196
38230
|
Docs: https://docs.helipod.io`;
|
|
38197
38231
|
var ALL_TOOLS = [...containerTools, ...databaseTools, ...vpsTools, ...domainTools, ...emailTools, ...accountTools, ...aiTools, ...generalTools];
|
|
38198
38232
|
function createHelipodServer(config2) {
|
package/dist/index.js
CHANGED
|
@@ -34727,10 +34727,12 @@ var EMPTY_COMPLETION_RESULT = {
|
|
|
34727
34727
|
class HelipodError extends Error {
|
|
34728
34728
|
status;
|
|
34729
34729
|
code;
|
|
34730
|
-
|
|
34730
|
+
details;
|
|
34731
|
+
constructor(status, code, message, details) {
|
|
34731
34732
|
super(message);
|
|
34732
34733
|
this.status = status;
|
|
34733
34734
|
this.code = code;
|
|
34735
|
+
this.details = details;
|
|
34734
34736
|
this.name = "HelipodError";
|
|
34735
34737
|
}
|
|
34736
34738
|
}
|
|
@@ -34826,7 +34828,8 @@ class HelipodClient {
|
|
|
34826
34828
|
if (!res.ok || json2?.success === false) {
|
|
34827
34829
|
const retry = res.headers.get("retry-after");
|
|
34828
34830
|
const msg = json2?.error ?? (text.slice(0, 300) || res.statusText);
|
|
34829
|
-
|
|
34831
|
+
const details = json2?.details && typeof json2.details === "object" && !Array.isArray(json2.details) ? json2.details : undefined;
|
|
34832
|
+
throw new HelipodError(res.status, json2?.code, retry ? `${msg} (retry after ${retry}s)` : String(msg), details);
|
|
34830
34833
|
}
|
|
34831
34834
|
return json2 && "data" in json2 ? json2.data : json2;
|
|
34832
34835
|
}
|
|
@@ -34858,7 +34861,7 @@ function register(server, api2, defs) {
|
|
|
34858
34861
|
const err = e instanceof HelipodError ? e : new HelipodError(0, "CLIENT_ERROR", String(e?.message ?? e));
|
|
34859
34862
|
return {
|
|
34860
34863
|
isError: true,
|
|
34861
|
-
content: [{ type: "text", text: JSON.stringify({ status: err.status, code: err.code ?? null, error: err.message }, null, 2) }]
|
|
34864
|
+
content: [{ type: "text", text: JSON.stringify({ status: err.status, code: err.code ?? null, error: err.message, ...err.details ? { details: err.details } : {} }, null, 2) }]
|
|
34862
34865
|
};
|
|
34863
34866
|
}
|
|
34864
34867
|
});
|
|
@@ -34992,18 +34995,48 @@ var containerTools = [
|
|
|
34992
34995
|
input: { serviceId: id("Service") },
|
|
34993
34996
|
run: (a, api2) => api2.api("GET", `${C}/services/${a.serviceId}`)
|
|
34994
34997
|
}),
|
|
34998
|
+
defineTool({
|
|
34999
|
+
name: "get_git_connections",
|
|
35000
|
+
title: "Git connections",
|
|
35001
|
+
kind: "read",
|
|
35002
|
+
description: "Whether the user connected GitHub (sign-in + the Helipod GitHub App, with the accounts it is installed on) and GitLab, plus connectUrl: the Helipod page where the user connects them. Check this before deploying from a private repo. Connecting needs the user in a browser: give them connectUrl, never try to connect yourself.",
|
|
35003
|
+
input: {},
|
|
35004
|
+
run: (_a3, api2) => api2.api("GET", `${C}/git/connections`)
|
|
35005
|
+
}),
|
|
35006
|
+
defineTool({
|
|
35007
|
+
name: "list_git_repos",
|
|
35008
|
+
title: "List Git repositories",
|
|
35009
|
+
kind: "read",
|
|
35010
|
+
description: "Repositories the user's connected GitHub App installations (host github, default) or GitLab account (host gitlab) can reach: fullName, url, private, defaultBranch, newest first. Pass one url to create_service as repo. Not connected: 409 with details.connectUrl for the user.",
|
|
35011
|
+
input: {
|
|
35012
|
+
host: exports_external.enum(["github", "gitlab"]).optional().describe("github (default) or gitlab"),
|
|
35013
|
+
installationId: exports_external.number().int().positive().optional().describe("Only this GitHub installation (id from get_git_connections)"),
|
|
35014
|
+
search: exports_external.string().max(200).optional().describe("Filter by part of owner/name"),
|
|
35015
|
+
limit: exports_external.number().int().min(1).max(100).optional().describe("Default 50"),
|
|
35016
|
+
offset: exports_external.number().int().min(0).optional()
|
|
35017
|
+
},
|
|
35018
|
+
run: (a, api2) => api2.api("GET", `${C}/git/repos`, {
|
|
35019
|
+
query: {
|
|
35020
|
+
host: a.host,
|
|
35021
|
+
installationId: a.installationId !== undefined ? String(a.installationId) : undefined,
|
|
35022
|
+
search: a.search,
|
|
35023
|
+
limit: a.limit !== undefined ? String(a.limit) : undefined,
|
|
35024
|
+
offset: a.offset !== undefined ? String(a.offset) : undefined
|
|
35025
|
+
}
|
|
35026
|
+
})
|
|
35027
|
+
}),
|
|
34995
35028
|
defineTool({
|
|
34996
35029
|
name: "create_service",
|
|
34997
35030
|
title: "Create service",
|
|
34998
35031
|
kind: "write",
|
|
34999
|
-
description: "Create a service from a container image, a
|
|
35032
|
+
description: "Create a service from a container image, a Git repository or an inline Dockerfile, and (unless deploy=false) start its first deploy. Private GitHub / GitLab repos work once connected (get_git_connections, list_git_repos); such services also redeploy on every push. A private repo that is not connected is refused (409 GITHUB_NOT_CONNECTED / GITLAB_NOT_CONNECTED / REPO_NOT_ACCESSIBLE, nothing created): give the user details.connectUrl and retry after they connect. COSTS MONEY once deployed (billed daily from the wallet): call with dryRun=true first, show the dailyCost to the user and get their OK.",
|
|
35000
35033
|
input: {
|
|
35001
35034
|
environmentId: id("Environment"),
|
|
35002
35035
|
name: exports_external.string().regex(/^[A-Za-z][A-Za-z0-9_-]{0,39}$/).describe("Service name (letters, digits, _ -; starts with a letter). Also used in references like ${{name.KEY}}"),
|
|
35003
35036
|
image: exports_external.string().optional().describe("Container image, e.g. nginx:alpine or ghcr.io/acme/app:1.2"),
|
|
35004
35037
|
registryUsername: exports_external.string().optional().describe("Private registry user (with registryPassword)"),
|
|
35005
35038
|
registryPassword: exports_external.string().optional().describe("Private registry password or token"),
|
|
35006
|
-
repo: exports_external.string().optional().describe("
|
|
35039
|
+
repo: exports_external.string().optional().describe("Git repository: https URL or owner/name for GitHub (instead of image). Private repos need a connected GitHub / GitLab (list_git_repos)"),
|
|
35007
35040
|
branch: exports_external.string().optional().describe("Git branch (default main)"),
|
|
35008
35041
|
rootDirectory: exports_external.string().optional().describe("Monorepo: folder to build, e.g. apps/web"),
|
|
35009
35042
|
dockerfile: exports_external.string().optional().describe("Inline Dockerfile content (instead of image/repo)"),
|
|
@@ -37325,7 +37358,7 @@ var generalTools = [
|
|
|
37325
37358
|
];
|
|
37326
37359
|
|
|
37327
37360
|
// src/server.ts
|
|
37328
|
-
var VERSION = "0.5.
|
|
37361
|
+
var VERSION = "0.5.9";
|
|
37329
37362
|
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.
|
|
37330
37363
|
- 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.
|
|
37331
37364
|
- 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.
|
|
@@ -37335,9 +37368,10 @@ var INSTRUCTIONS = `Helipod is a cloud platform (Indonesia): containers, managed
|
|
|
37335
37368
|
- Databases: get_database_connection returns a password; put it in a secret variable (DATABASE_URL) instead of code or chat.
|
|
37336
37369
|
- Migrate (free): create_vps_import returns a one-time command for the USER to run as root on their old server (never run it yourself); before the first restore_vps_import, show fetchedIp and ask the user to confirm it is their server.
|
|
37337
37370
|
- Images from generate_ai_image are deleted after 7 days: tell the user and have them download the ones they keep.
|
|
37371
|
+
- Deploying from Git: public repos need nothing. For a private repo check get_git_connections / list_git_repos first; when GitHub or GitLab is not connected (or a call returns 409 GITHUB_NOT_CONNECTED / GITLAB_NOT_CONNECTED / REPO_NOT_ACCESSIBLE), give the user details.connectUrl to open in their browser and try again after they confirm. Never ask for a GitHub token.
|
|
37338
37372
|
- Deploys and VPS actions run in the background: poll get_deployment / get_vps until they settle; on a failed deploy read get_deployment_logs.
|
|
37339
37373
|
- 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.
|
|
37340
|
-
- 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.
|
|
37374
|
+
- Errors come back as { status, code, error, details? }: 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.
|
|
37341
37375
|
Docs: https://docs.helipod.io`;
|
|
37342
37376
|
var ALL_TOOLS = [...containerTools, ...databaseTools, ...vpsTools, ...domainTools, ...emailTools, ...accountTools, ...aiTools, ...generalTools];
|
|
37343
37377
|
function createHelipodServer(config2) {
|
package/dist/stdio.js
CHANGED
|
@@ -34834,10 +34834,12 @@ var EMPTY_COMPLETION_RESULT = {
|
|
|
34834
34834
|
class HelipodError extends Error {
|
|
34835
34835
|
status;
|
|
34836
34836
|
code;
|
|
34837
|
-
|
|
34837
|
+
details;
|
|
34838
|
+
constructor(status, code, message, details) {
|
|
34838
34839
|
super(message);
|
|
34839
34840
|
this.status = status;
|
|
34840
34841
|
this.code = code;
|
|
34842
|
+
this.details = details;
|
|
34841
34843
|
this.name = "HelipodError";
|
|
34842
34844
|
}
|
|
34843
34845
|
}
|
|
@@ -34933,7 +34935,8 @@ class HelipodClient {
|
|
|
34933
34935
|
if (!res.ok || json2?.success === false) {
|
|
34934
34936
|
const retry = res.headers.get("retry-after");
|
|
34935
34937
|
const msg = json2?.error ?? (text.slice(0, 300) || res.statusText);
|
|
34936
|
-
|
|
34938
|
+
const details = json2?.details && typeof json2.details === "object" && !Array.isArray(json2.details) ? json2.details : undefined;
|
|
34939
|
+
throw new HelipodError(res.status, json2?.code, retry ? `${msg} (retry after ${retry}s)` : String(msg), details);
|
|
34937
34940
|
}
|
|
34938
34941
|
return json2 && "data" in json2 ? json2.data : json2;
|
|
34939
34942
|
}
|
|
@@ -34965,7 +34968,7 @@ function register(server, api2, defs) {
|
|
|
34965
34968
|
const err = e instanceof HelipodError ? e : new HelipodError(0, "CLIENT_ERROR", String(e?.message ?? e));
|
|
34966
34969
|
return {
|
|
34967
34970
|
isError: true,
|
|
34968
|
-
content: [{ type: "text", text: JSON.stringify({ status: err.status, code: err.code ?? null, error: err.message }, null, 2) }]
|
|
34971
|
+
content: [{ type: "text", text: JSON.stringify({ status: err.status, code: err.code ?? null, error: err.message, ...err.details ? { details: err.details } : {} }, null, 2) }]
|
|
34969
34972
|
};
|
|
34970
34973
|
}
|
|
34971
34974
|
});
|
|
@@ -35099,18 +35102,48 @@ var containerTools = [
|
|
|
35099
35102
|
input: { serviceId: id("Service") },
|
|
35100
35103
|
run: (a, api2) => api2.api("GET", `${C}/services/${a.serviceId}`)
|
|
35101
35104
|
}),
|
|
35105
|
+
defineTool({
|
|
35106
|
+
name: "get_git_connections",
|
|
35107
|
+
title: "Git connections",
|
|
35108
|
+
kind: "read",
|
|
35109
|
+
description: "Whether the user connected GitHub (sign-in + the Helipod GitHub App, with the accounts it is installed on) and GitLab, plus connectUrl: the Helipod page where the user connects them. Check this before deploying from a private repo. Connecting needs the user in a browser: give them connectUrl, never try to connect yourself.",
|
|
35110
|
+
input: {},
|
|
35111
|
+
run: (_a3, api2) => api2.api("GET", `${C}/git/connections`)
|
|
35112
|
+
}),
|
|
35113
|
+
defineTool({
|
|
35114
|
+
name: "list_git_repos",
|
|
35115
|
+
title: "List Git repositories",
|
|
35116
|
+
kind: "read",
|
|
35117
|
+
description: "Repositories the user's connected GitHub App installations (host github, default) or GitLab account (host gitlab) can reach: fullName, url, private, defaultBranch, newest first. Pass one url to create_service as repo. Not connected: 409 with details.connectUrl for the user.",
|
|
35118
|
+
input: {
|
|
35119
|
+
host: exports_external.enum(["github", "gitlab"]).optional().describe("github (default) or gitlab"),
|
|
35120
|
+
installationId: exports_external.number().int().positive().optional().describe("Only this GitHub installation (id from get_git_connections)"),
|
|
35121
|
+
search: exports_external.string().max(200).optional().describe("Filter by part of owner/name"),
|
|
35122
|
+
limit: exports_external.number().int().min(1).max(100).optional().describe("Default 50"),
|
|
35123
|
+
offset: exports_external.number().int().min(0).optional()
|
|
35124
|
+
},
|
|
35125
|
+
run: (a, api2) => api2.api("GET", `${C}/git/repos`, {
|
|
35126
|
+
query: {
|
|
35127
|
+
host: a.host,
|
|
35128
|
+
installationId: a.installationId !== undefined ? String(a.installationId) : undefined,
|
|
35129
|
+
search: a.search,
|
|
35130
|
+
limit: a.limit !== undefined ? String(a.limit) : undefined,
|
|
35131
|
+
offset: a.offset !== undefined ? String(a.offset) : undefined
|
|
35132
|
+
}
|
|
35133
|
+
})
|
|
35134
|
+
}),
|
|
35102
35135
|
defineTool({
|
|
35103
35136
|
name: "create_service",
|
|
35104
35137
|
title: "Create service",
|
|
35105
35138
|
kind: "write",
|
|
35106
|
-
description: "Create a service from a container image, a
|
|
35139
|
+
description: "Create a service from a container image, a Git repository or an inline Dockerfile, and (unless deploy=false) start its first deploy. Private GitHub / GitLab repos work once connected (get_git_connections, list_git_repos); such services also redeploy on every push. A private repo that is not connected is refused (409 GITHUB_NOT_CONNECTED / GITLAB_NOT_CONNECTED / REPO_NOT_ACCESSIBLE, nothing created): give the user details.connectUrl and retry after they connect. COSTS MONEY once deployed (billed daily from the wallet): call with dryRun=true first, show the dailyCost to the user and get their OK.",
|
|
35107
35140
|
input: {
|
|
35108
35141
|
environmentId: id("Environment"),
|
|
35109
35142
|
name: exports_external.string().regex(/^[A-Za-z][A-Za-z0-9_-]{0,39}$/).describe("Service name (letters, digits, _ -; starts with a letter). Also used in references like ${{name.KEY}}"),
|
|
35110
35143
|
image: exports_external.string().optional().describe("Container image, e.g. nginx:alpine or ghcr.io/acme/app:1.2"),
|
|
35111
35144
|
registryUsername: exports_external.string().optional().describe("Private registry user (with registryPassword)"),
|
|
35112
35145
|
registryPassword: exports_external.string().optional().describe("Private registry password or token"),
|
|
35113
|
-
repo: exports_external.string().optional().describe("
|
|
35146
|
+
repo: exports_external.string().optional().describe("Git repository: https URL or owner/name for GitHub (instead of image). Private repos need a connected GitHub / GitLab (list_git_repos)"),
|
|
35114
35147
|
branch: exports_external.string().optional().describe("Git branch (default main)"),
|
|
35115
35148
|
rootDirectory: exports_external.string().optional().describe("Monorepo: folder to build, e.g. apps/web"),
|
|
35116
35149
|
dockerfile: exports_external.string().optional().describe("Inline Dockerfile content (instead of image/repo)"),
|
|
@@ -37432,7 +37465,7 @@ var generalTools = [
|
|
|
37432
37465
|
];
|
|
37433
37466
|
|
|
37434
37467
|
// src/server.ts
|
|
37435
|
-
var VERSION = "0.5.
|
|
37468
|
+
var VERSION = "0.5.9";
|
|
37436
37469
|
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.
|
|
37437
37470
|
- 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.
|
|
37438
37471
|
- 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.
|
|
@@ -37442,9 +37475,10 @@ var INSTRUCTIONS = `Helipod is a cloud platform (Indonesia): containers, managed
|
|
|
37442
37475
|
- Databases: get_database_connection returns a password; put it in a secret variable (DATABASE_URL) instead of code or chat.
|
|
37443
37476
|
- Migrate (free): create_vps_import returns a one-time command for the USER to run as root on their old server (never run it yourself); before the first restore_vps_import, show fetchedIp and ask the user to confirm it is their server.
|
|
37444
37477
|
- Images from generate_ai_image are deleted after 7 days: tell the user and have them download the ones they keep.
|
|
37478
|
+
- Deploying from Git: public repos need nothing. For a private repo check get_git_connections / list_git_repos first; when GitHub or GitLab is not connected (or a call returns 409 GITHUB_NOT_CONNECTED / GITLAB_NOT_CONNECTED / REPO_NOT_ACCESSIBLE), give the user details.connectUrl to open in their browser and try again after they confirm. Never ask for a GitHub token.
|
|
37445
37479
|
- Deploys and VPS actions run in the background: poll get_deployment / get_vps until they settle; on a failed deploy read get_deployment_logs.
|
|
37446
37480
|
- 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.
|
|
37447
|
-
- 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.
|
|
37481
|
+
- Errors come back as { status, code, error, details? }: 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.
|
|
37448
37482
|
Docs: https://docs.helipod.io`;
|
|
37449
37483
|
var ALL_TOOLS = [...containerTools, ...databaseTools, ...vpsTools, ...domainTools, ...emailTools, ...accountTools, ...aiTools, ...generalTools];
|
|
37450
37484
|
function createHelipodServer(config2) {
|
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.9",
|
|
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": {
|