hostinger-api-mcp 3.30.0 → 3.30.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/CHANGELOG.md +18 -0
- package/README.md +4 -1
- package/gemini-extension.json +2 -1
- package/package.json +1 -1
- package/server.json +2 -2
- package/skills/headless/SKILL.md +7 -5
- package/skills/headless/VERSION +3 -3
- package/skills/headless/connect/SKILL.md +34 -10
- package/skills/headless/connect/bootstrap.mjs +25 -14
- package/skills/headless/connect/launch.mjs +42 -0
- package/skills/headless/connect/launch.sh +23 -0
- package/skills/headless/connect/tools/antigravity.md +5 -5
- package/skills/headless/connect/tools/claude-code.md +3 -3
- package/skills/headless/connect/tools/codex.md +7 -7
- package/skills/headless/connect/tools/cursor.md +9 -9
- package/skills/headless/connect/tools/devin.md +5 -5
- package/skills/headless/connect/tools/vscode.md +7 -7
- package/skills/headless/hostinger-mcp.mjs +4 -9
- package/skills/headless/steps/03-provision/ecommerce/SKILL.md +2 -2
- package/skills/headless/steps/03-provision/webapp/SKILL.md +1 -1
- package/skills/headless/steps/03-provision/wordpress/SKILL.md +2 -2
- package/skills/headless/steps/04-content-model/wordpress/SKILL.md +1 -1
- package/skills/headless/steps/08-deploy/SKILL.md +3 -3
- package/src/core/oauth.js +14 -4
- package/src/core/oauth.ts +14 -4
- package/src/core/runtime.js +6 -0
- package/src/core/runtime.ts +6 -0
- package/src/core/skills.js +59 -45
- package/src/core/skills.ts +59 -45
- package/src/servers/agency-hosting.js +1 -1
- package/src/servers/agency-hosting.ts +1 -1
- package/src/servers/agent-readiness.js +1 -1
- package/src/servers/agent-readiness.ts +1 -1
- package/src/servers/all.js +1 -1
- package/src/servers/all.ts +1 -1
- package/src/servers/billing.js +1 -1
- package/src/servers/billing.ts +1 -1
- package/src/servers/dns.js +1 -1
- package/src/servers/dns.ts +1 -1
- package/src/servers/domains.js +1 -1
- package/src/servers/domains.ts +1 -1
- package/src/servers/ecommerce.js +1 -1
- package/src/servers/ecommerce.ts +1 -1
- package/src/servers/gpu.js +1 -1
- package/src/servers/gpu.ts +1 -1
- package/src/servers/horizons.js +1 -1
- package/src/servers/horizons.ts +1 -1
- package/src/servers/hosting.js +1 -1
- package/src/servers/hosting.ts +1 -1
- package/src/servers/mail.js +1 -1
- package/src/servers/mail.ts +1 -1
- package/src/servers/reach.js +1 -1
- package/src/servers/reach.ts +1 -1
- package/src/servers/vps.js +1 -1
- package/src/servers/vps.ts +1 -1
- package/src/servers/wordpress.js +1 -1
- package/src/servers/wordpress.ts +1 -1
|
@@ -64,7 +64,7 @@ All operations below go through the Hostinger connector (`execute`).
|
|
|
64
64
|
(if `<new>/` already exists, stop and ask instead of moving into it),
|
|
65
65
|
update the domain in `brief.md`, and tell the user the new domain.
|
|
66
66
|
Admin credentials are generated by the platform; never ask the user for a password.
|
|
67
|
-
3. Don't wait here. At the join, `node <skill>/wait.mjs setup <domain>` (see *Waiting on Hostinger* in
|
|
67
|
+
3. Don't wait here. At the join, `cd "$HOME" && node <skill>/wait.mjs setup <domain>` (see *Waiting on Hostinger* in
|
|
68
68
|
the top-level `SKILL.md`) returns once the setup is `completed`, usually at once by then. A `failed`
|
|
69
69
|
setup → stop, point at hPanel.
|
|
70
70
|
|
|
@@ -95,7 +95,7 @@ install WordPress straight into its `/cms` directory. This is the onboarding han
|
|
|
95
95
|
generated database counts against the plan's limit.
|
|
96
96
|
3. The call is **asynchronous** — a success response only means the install job was **queued**. This is
|
|
97
97
|
the *fire*: record `provision.in_progress` and return to prepare work. At the join,
|
|
98
|
-
`node <skill>/wait.mjs cms <domain> <username>` returns the `/cms` install row (`directory: "cms"`,
|
|
98
|
+
`cd "$HOME" && node <skill>/wait.mjs cms <domain> <username>` returns the `/cms` install row (`directory: "cms"`,
|
|
99
99
|
valid) once it exists, usually within 1–2 minutes of the install.
|
|
100
100
|
|
|
101
101
|
## Step 3 — Verify (all must pass)
|
|
@@ -78,7 +78,7 @@ else is refused, with the field named.
|
|
|
78
78
|
## Step 2 — Run the push
|
|
79
79
|
|
|
80
80
|
```bash
|
|
81
|
-
node <skill>/push-content.mjs <domain>
|
|
81
|
+
cd "$HOME" && node <skill>/push-content.mjs <domain>
|
|
82
82
|
```
|
|
83
83
|
|
|
84
84
|
It mints the token itself (never printed), removes WordPress's "Hello world!" post and "Sample Page",
|
|
@@ -15,13 +15,13 @@ This is an **instance-barrier** step: run it only after `provision.status == "co
|
|
|
15
15
|
> **Connected to the hosted server (`mcp.hostinger.com`)?** Its `hosting_deploy` deploys Git
|
|
16
16
|
> repositories only and cannot read a local `path`. Run this step through the local
|
|
17
17
|
> `hostinger-api-mcp` server instead (see the connect step:
|
|
18
|
-
>
|
|
18
|
+
> `<command> <launcher>`).
|
|
19
19
|
|
|
20
20
|
> **With a shell and the Hostinger CLI installed**, the same deploy is one command, with the build
|
|
21
21
|
> settings passed exactly as the table below says. Run it from the project, since it links the current directory:
|
|
22
22
|
> `cd ~/.hostinger/<domain>/src && hostinger up --domain <domain> --type nodejs --app-type <appType> --output-directory <dir> --build-script build --node-version 22 --package-manager npm --yes --format json`.
|
|
23
23
|
> It uploads, builds, waits and returns `data.buildUuid` and `data.buildState`; add `--no-wait` to
|
|
24
|
-
> return at once and wait with `node <skill>/wait.mjs build <domain> <uuid>`. Then continue at
|
|
24
|
+
> return at once and wait with `cd "$HOME" && node <skill>/wait.mjs build <domain> <uuid>`. Then continue at
|
|
25
25
|
> "Verify" below. Recent CLI versions see that the site is headless (`data.headless: true`) and
|
|
26
26
|
> deploy only its Node.js frontend, leaving `/cms` alone; still pass the settings above.
|
|
27
27
|
|
|
@@ -156,7 +156,7 @@ keeps the root from serving 403 (see the rule above).
|
|
|
156
156
|
Wait for it in one command (see *Waiting on Hostinger* in the top-level `SKILL.md`):
|
|
157
157
|
|
|
158
158
|
```bash
|
|
159
|
-
node <skill>/wait.mjs build <domain> <buildUuid>
|
|
159
|
+
cd "$HOME" && node <skill>/wait.mjs build <domain> <buildUuid>
|
|
160
160
|
```
|
|
161
161
|
|
|
162
162
|
It waits for `hosting_get-deployment` to report the build `completed`, then for `https://<domain>/` to
|
package/src/core/oauth.js
CHANGED
|
@@ -85,11 +85,21 @@ function parseIssuer(raw) {
|
|
|
85
85
|
return u.origin;
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
// Keeps the absolute PATH entries outside any node_modules folder. npx run in a project puts its
|
|
89
|
+
// node_modules/.bin (and each parent's) first on PATH, and a relative entry resolves against the project,
|
|
90
|
+
// so either would let the project supply xdg-open.
|
|
91
|
+
export function safePath(value, delimiter = path.delimiter) {
|
|
92
|
+
return value
|
|
93
|
+
.split(delimiter)
|
|
94
|
+
.filter((p) => path.isAbsolute(p) && !p.split(/[\\/]/).includes("node_modules"))
|
|
95
|
+
.join(delimiter);
|
|
96
|
+
}
|
|
97
|
+
|
|
88
98
|
// No shell: the URL is a single argv entry, never parsed by sh or cmd.
|
|
89
|
-
//
|
|
90
|
-
//
|
|
99
|
+
// rundll32 and macOS open are launched by absolute path, so neither a PATH entry nor (on Windows,
|
|
100
|
+
// which looks a bare name up in the working directory first) a planted copy can stand in for them.
|
|
91
101
|
export function browserCommand(platform, url, systemRoot = process.env.SystemRoot) {
|
|
92
|
-
if (platform === "darwin") return ["open", [url]];
|
|
102
|
+
if (platform === "darwin") return ["/usr/bin/open", [url]];
|
|
93
103
|
if (platform === "win32") {
|
|
94
104
|
return [
|
|
95
105
|
path.win32.join(systemRoot || "C:\\Windows", "System32", "rundll32.exe"),
|
|
@@ -435,7 +445,7 @@ export class OAuthProvider {
|
|
|
435
445
|
"[OAuth] If the browser does not open, copy the URL above into one manually.\n\n",
|
|
436
446
|
);
|
|
437
447
|
const [cmd, args] = browserCommand(process.platform, url);
|
|
438
|
-
execFile(cmd, args, (err) => {
|
|
448
|
+
execFile(cmd, args, { cwd: os.homedir(), env: { ...process.env, PATH: safePath(process.env.PATH ?? "") } }, (err) => {
|
|
439
449
|
if (err) {
|
|
440
450
|
process.stderr.write(
|
|
441
451
|
`[OAuth] Could not auto-launch browser: ${err.message}\n`,
|
package/src/core/oauth.ts
CHANGED
|
@@ -88,11 +88,21 @@ function parseIssuer(raw: string): string {
|
|
|
88
88
|
return u.origin;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
// Keeps the absolute PATH entries outside any node_modules folder. npx run in a project puts its
|
|
92
|
+
// node_modules/.bin (and each parent's) first on PATH, and a relative entry resolves against the project,
|
|
93
|
+
// so either would let the project supply xdg-open.
|
|
94
|
+
export function safePath(value: string, delimiter: string = path.delimiter): string {
|
|
95
|
+
return value
|
|
96
|
+
.split(delimiter)
|
|
97
|
+
.filter((p) => path.isAbsolute(p) && !p.split(/[\\/]/).includes('node_modules'))
|
|
98
|
+
.join(delimiter);
|
|
99
|
+
}
|
|
100
|
+
|
|
91
101
|
// No shell: the URL is a single argv entry, never parsed by sh or cmd.
|
|
92
|
-
//
|
|
93
|
-
//
|
|
102
|
+
// rundll32 and macOS open are launched by absolute path, so neither a PATH entry nor (on Windows,
|
|
103
|
+
// which looks a bare name up in the working directory first) a planted copy can stand in for them.
|
|
94
104
|
export function browserCommand(platform: string, url: string, systemRoot = process.env.SystemRoot): [string, string[]] {
|
|
95
|
-
if (platform === 'darwin') return ['open', [url]];
|
|
105
|
+
if (platform === 'darwin') return ['/usr/bin/open', [url]];
|
|
96
106
|
if (platform === 'win32') {
|
|
97
107
|
return [
|
|
98
108
|
path.win32.join(systemRoot || 'C:\\Windows', 'System32', 'rundll32.exe'),
|
|
@@ -396,7 +406,7 @@ export class OAuthProvider {
|
|
|
396
406
|
process.stderr.write(`\n[OAuth] Opening browser for sign-in:\n ${url}\n`);
|
|
397
407
|
process.stderr.write('[OAuth] If the browser does not open, copy the URL above into one manually.\n\n');
|
|
398
408
|
const [cmd, args] = browserCommand(process.platform, url);
|
|
399
|
-
execFile(cmd, args, (err) => {
|
|
409
|
+
execFile(cmd, args, { cwd: os.homedir(), env: { ...process.env, PATH: safePath(process.env.PATH ?? '') } }, (err) => {
|
|
400
410
|
if (err) {
|
|
401
411
|
process.stderr.write(`[OAuth] Could not auto-launch browser: ${err.message}\n`);
|
|
402
412
|
}
|
package/src/core/runtime.js
CHANGED
|
@@ -4109,6 +4109,12 @@ class MCPServer {
|
|
|
4109
4109
|
}
|
|
4110
4110
|
|
|
4111
4111
|
export async function startServer({ name, version, tools, instructions, skills }) {
|
|
4112
|
+
// The headless skill's launcher starts this server from the home folder (npx run in the project would
|
|
4113
|
+
// put the project's node_modules/.bin first on PATH) and names the project here, so relative paths in
|
|
4114
|
+
// tool arguments still resolve against it. Everything that runs from PATH is resolved by now.
|
|
4115
|
+
if (process.env.MCP_PROJECT_DIR) {
|
|
4116
|
+
try { process.chdir(process.env.MCP_PROJECT_DIR); } catch { /* stay in the home folder */ }
|
|
4117
|
+
}
|
|
4112
4118
|
const argv = minimist(process.argv.slice(2), {
|
|
4113
4119
|
string: ['host'],
|
|
4114
4120
|
boolean: ['stdio', 'http', 'help', 'version', 'login', 'logout'],
|
package/src/core/runtime.ts
CHANGED
|
@@ -4170,6 +4170,12 @@ class MCPServer {
|
|
|
4170
4170
|
}
|
|
4171
4171
|
|
|
4172
4172
|
export async function startServer({ name, version, tools, instructions, skills }: { name: string; version: string; tools: OpenApiTool[]; instructions?: string; skills?: Skill[] }): Promise<void> {
|
|
4173
|
+
// The headless skill's launcher starts this server from the home folder (npx run in the project would
|
|
4174
|
+
// put the project's node_modules/.bin first on PATH) and names the project here, so relative paths in
|
|
4175
|
+
// tool arguments still resolve against it. Everything that runs from PATH is resolved by now.
|
|
4176
|
+
if (process.env.MCP_PROJECT_DIR) {
|
|
4177
|
+
try { process.chdir(process.env.MCP_PROJECT_DIR); } catch { /* stay in the home folder */ }
|
|
4178
|
+
}
|
|
4173
4179
|
const argv = minimist(process.argv.slice(2), {
|
|
4174
4180
|
string: ['host'],
|
|
4175
4181
|
boolean: ['stdio', 'http', 'help', 'version', 'login', 'logout'],
|