hostinger-api-mcp 3.29.0 → 3.30.1
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 +22 -0
- package/README.md +9 -40
- package/gemini-extension.json +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
- package/skills/headless/VERSION +2 -2
- package/skills/headless/connect/SKILL.md +13 -6
- package/skills/headless/connect/tools/antigravity.md +2 -2
- package/skills/headless/connect/tools/claude-code.md +2 -2
- package/skills/headless/connect/tools/codex.md +4 -4
- package/skills/headless/connect/tools/cursor.md +5 -5
- package/skills/headless/connect/tools/devin.md +4 -4
- package/skills/headless/connect/tools/vscode.md +4 -4
- package/skills/headless/steps/03-provision/ecommerce/SKILL.md +1 -1
- package/skills/headless/steps/08-deploy/SKILL.md +1 -1
- package/skills/maintain-wordpress/SKILL.md +1 -1
- package/skills/troubleshoot-website/SKILL.md +1 -1
- package/src/core/runtime.js +96 -0
- package/src/core/runtime.ts +96 -0
- package/src/core/skills.js +33 -33
- package/src/core/skills.ts +33 -33
- package/src/core/tools/all.js +78 -4
- package/src/core/tools/all.ts +78 -4
- package/src/core/tools/hosting.js +78 -4
- package/src/core/tools/hosting.ts +78 -4
- 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
- package/types.d.ts +29 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,28 @@ Generated at release time from the diff between the previous and current
|
|
|
4
4
|
build. Tool changes are listed individually; everything else is summarised
|
|
5
5
|
by area.
|
|
6
6
|
|
|
7
|
+
## v3.30.1 — 2026-11-05
|
|
8
|
+
|
|
9
|
+
### Also in this release
|
|
10
|
+
|
|
11
|
+
- Bundled agent skills: 10 files
|
|
12
|
+
- Other files: `src/core/skills.js`, `src/core/skills.ts`
|
|
13
|
+
|
|
14
|
+
## v3.30.0 — 2026-11-05
|
|
15
|
+
|
|
16
|
+
### Operations
|
|
17
|
+
|
|
18
|
+
- Added `hosting_php_update` — Update website PHP version, extensions and options
|
|
19
|
+
- Hid 4 operations from search (they still run through `execute`): `hosting_php_reset-extensions`, `hosting_php_update-extensions`, `hosting_php_update-options`, `hosting_php_update-version`
|
|
20
|
+
|
|
21
|
+
### Also in this release
|
|
22
|
+
|
|
23
|
+
- Documentation: `README.md`
|
|
24
|
+
- Bundled agent skills: `skills/headless/VERSION`, `skills/maintain-wordpress/SKILL.md`, `skills/troubleshoot-website/SKILL.md`
|
|
25
|
+
- Request handling and authentication: `src/core/runtime.js`, `src/core/runtime.ts`
|
|
26
|
+
- Other files: `src/core/skills.js`, `src/core/skills.ts`
|
|
27
|
+
- Build and packaging: `types.d.ts`
|
|
28
|
+
|
|
7
29
|
## v3.29.0 — 2026-11-05
|
|
8
30
|
|
|
9
31
|
### Also in this release
|
package/README.md
CHANGED
|
@@ -69,7 +69,7 @@ pnpm update -g @hostinger/mcp
|
|
|
69
69
|
|
|
70
70
|
This package installs the following MCP server commands:
|
|
71
71
|
|
|
72
|
-
- `hostinger-api-mcp` — unified server over every operation (
|
|
72
|
+
- `hostinger-api-mcp` — unified server over every operation (409 total)
|
|
73
73
|
- `hostinger-agency-hosting-mcp` — 43 operations for agency-hosting
|
|
74
74
|
- `hostinger-agent-readiness-mcp` — 4 operations for agent-readiness
|
|
75
75
|
- `hostinger-billing-mcp` — 10 operations for billing
|
|
@@ -78,7 +78,7 @@ This package installs the following MCP server commands:
|
|
|
78
78
|
- `hostinger-ecommerce-mcp` — 30 operations for ecommerce
|
|
79
79
|
- `hostinger-gpu-mcp` — 5 operations for gpu
|
|
80
80
|
- `hostinger-horizons-mcp` — 7 operations for horizons
|
|
81
|
-
- `hostinger-hosting-mcp` —
|
|
81
|
+
- `hostinger-hosting-mcp` — 54 operations for hosting
|
|
82
82
|
- `hostinger-mail-mcp` — 39 operations for mail
|
|
83
83
|
- `hostinger-reach-mcp` — 71 operations for reach
|
|
84
84
|
- `hostinger-vps-mcp` — 68 operations for vps
|
|
@@ -1960,6 +1960,13 @@ Clear a website's server cache (the hosting server's page cache) and Hostinger C
|
|
|
1960
1960
|
- **Method**: `custom`
|
|
1961
1961
|
- **Path**: `custom`
|
|
1962
1962
|
|
|
1963
|
+
#### hosting_php_update
|
|
1964
|
+
|
|
1965
|
+
Change a website's PHP version, extensions and php.ini options in one call. Pass only what to change, at least one of version, resetExtensions, extensions and options. Steps run in the order version, resetExtensions, extensions, options, and the call stops at the first failure. applied lists the steps that ran. When a step fails, the call returns an error whose text is the same JSON: failed names the step and why, and skipped lists the ones not attempted; a multi-execute batch stops there too. WARNING: changing the version resets the website's extensions (PHP 8.0 and later) and its options to their defaults, so pass the extensions and options to keep in the same call; they are applied after the version. Option values above the plan limit are capped silently: read the applied values back with hosting_php_get, which also lists the available versions, extensions and options. Works for Shared and Cloud hosting websites.
|
|
1966
|
+
|
|
1967
|
+
- **Method**: `custom`
|
|
1968
|
+
- **Path**: `custom`
|
|
1969
|
+
|
|
1963
1970
|
#### hosting_websites_list-domains
|
|
1964
1971
|
|
|
1965
1972
|
List the extra domains of a website: its parked (alias) domains, which show the same site under another domain name, and its subdomains (e.g. blog.example.com), with each one's root directory. parked items have domain (a domain name or an IP address) and type (domain or ip); subdomains items have domain (the full name), subdomain (the prefix) and root_directory. A list that cannot be read comes back as { error } and the other is still returned. To add or remove one use hosting_websites_add-domain or hosting_websites_remove-domain. Works for Shared and Cloud hosting websites.
|
|
@@ -2441,15 +2448,6 @@ or specific order IDs for more targeted results.
|
|
|
2441
2448
|
- **Method**: `GET`
|
|
2442
2449
|
- **Path**: `/api/hosting/v1/orders`
|
|
2443
2450
|
|
|
2444
|
-
#### hosting_php_reset-extensions
|
|
2445
|
-
|
|
2446
|
-
Resets all PHP extensions of the website to their default state.
|
|
2447
|
-
|
|
2448
|
-
Use it to recover from extension conflicts or restore the original configuration.
|
|
2449
|
-
|
|
2450
|
-
- **Method**: `PATCH`
|
|
2451
|
-
- **Path**: `/api/hosting/v1/accounts/{username}/websites/{domain}/php/extensions/reset`
|
|
2452
|
-
|
|
2453
2451
|
#### hosting_php_get
|
|
2454
2452
|
|
|
2455
2453
|
Returns the full PHP configuration for the website: current version, available versions
|
|
@@ -2470,35 +2468,6 @@ Use it to debug PHP issues or inspect the complete PHP environment of the websit
|
|
|
2470
2468
|
- **Method**: `GET`
|
|
2471
2469
|
- **Path**: `/api/hosting/v1/accounts/{username}/websites/{domain}/php/php-info`
|
|
2472
2470
|
|
|
2473
|
-
#### hosting_php_update-extensions
|
|
2474
|
-
|
|
2475
|
-
Enables or disables PHP extensions (modules) for the website.
|
|
2476
|
-
|
|
2477
|
-
Use the Get PHP details endpoint to check the current extension states before changing them.
|
|
2478
|
-
|
|
2479
|
-
- **Method**: `PATCH`
|
|
2480
|
-
- **Path**: `/api/hosting/v1/accounts/{username}/websites/{domain}/php/extensions`
|
|
2481
|
-
|
|
2482
|
-
#### hosting_php_update-options
|
|
2483
|
-
|
|
2484
|
-
Updates PHP options for the website (e.g. `memory_limit`, `max_execution_time`, `upload_max_filesize`).
|
|
2485
|
-
Only provide the options you want to change, inside the `options` object.
|
|
2486
|
-
|
|
2487
|
-
Values above the account plan limit are silently capped to that limit, so the request can succeed
|
|
2488
|
-
with a smaller applied value. Call the Get PHP details endpoint afterwards to read the applied value.
|
|
2489
|
-
|
|
2490
|
-
- **Method**: `PATCH`
|
|
2491
|
-
- **Path**: `/api/hosting/v1/accounts/{username}/websites/{domain}/php/options`
|
|
2492
|
-
|
|
2493
|
-
#### hosting_php_update-version
|
|
2494
|
-
|
|
2495
|
-
Changes the PHP version of the website.
|
|
2496
|
-
|
|
2497
|
-
Use the Get PHP details endpoint to see the versions available for the website.
|
|
2498
|
-
|
|
2499
|
-
- **Method**: `PATCH`
|
|
2500
|
-
- **Path**: `/api/hosting/v1/accounts/{username}/websites/{domain}/php/version`
|
|
2501
|
-
|
|
2502
2471
|
#### hosting_redirects_list-website
|
|
2503
2472
|
|
|
2504
2473
|
Returns a paginated list of redirects configured for the selected website.
|
package/gemini-extension.json
CHANGED
package/package.json
CHANGED
package/server.json
CHANGED
|
@@ -17,12 +17,12 @@
|
|
|
17
17
|
"url": "https://github.com/hostinger/api-mcp-server",
|
|
18
18
|
"source": "github"
|
|
19
19
|
},
|
|
20
|
-
"version": "3.
|
|
20
|
+
"version": "3.30.1",
|
|
21
21
|
"packages": [
|
|
22
22
|
{
|
|
23
23
|
"registryType": "npm",
|
|
24
24
|
"identifier": "@hostinger/mcp",
|
|
25
|
-
"version": "3.
|
|
25
|
+
"version": "3.30.1",
|
|
26
26
|
"transport": {
|
|
27
27
|
"type": "stdio"
|
|
28
28
|
},
|
package/skills/headless/VERSION
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
version=3.
|
|
2
|
-
commit=
|
|
1
|
+
version=3.30.1
|
|
2
|
+
commit=4d02050e3406
|
|
3
3
|
built=2026-11-05
|
|
@@ -107,8 +107,8 @@ hostinger-api-mcp --login
|
|
|
107
107
|
hostinger-api-mcp --logout
|
|
108
108
|
|
|
109
109
|
# Without a global install:
|
|
110
|
-
npx --yes --package=@hostinger/mcp@latest hostinger-api-mcp --login
|
|
111
|
-
npx --yes --package=@hostinger/mcp@latest hostinger-api-mcp --logout
|
|
110
|
+
npx --yes --prefix="$HOME" --package=@hostinger/mcp@latest hostinger-api-mcp --login
|
|
111
|
+
npx --yes --prefix="$HOME" --package=@hostinger/mcp@latest hostinger-api-mcp --logout
|
|
112
112
|
```
|
|
113
113
|
|
|
114
114
|
Credentials live in `~/.config/hostinger-mcp/credentials.json` (macOS/Linux) or `%APPDATA%\hostinger-mcp\credentials.json` (Windows) and are shared by every Hostinger MCP binary. OAuth works only when the tool runs the server over its default local (stdio) transport, which is what every registration below uses; `--http` needs `HOSTINGER_API_TOKEN`.
|
|
@@ -127,8 +127,8 @@ one group says nothing about the other:
|
|
|
127
127
|
|
|
128
128
|
| Group | Operations | Comes from | Needed by |
|
|
129
129
|
|---|---|---|---|
|
|
130
|
-
| **Hosting** | `hosting_*` (websites, deploy, build report), `wordpress_*` | `hostinger` (`npx -y @hostinger/mcp@latest`), or the scoped servers such as `hostinger-hosting` + `hostinger-wordpress` | every build |
|
|
131
|
-
| **Ecommerce** | `ecommerce_*` (stores, products, shipping, payments) | **only** `hostinger-ecommerce` (`npx --package=@hostinger/mcp@latest hostinger-ecommerce-mcp`), or the Ecommerce MCP in the Hostinger Connector. Neither `hostinger` nor the scoped hosting servers include it | Ecommerce backends (chosen later, in refine) |
|
|
130
|
+
| **Hosting** | `hosting_*` (websites, deploy, build report), `wordpress_*` | `hostinger` (`npx -y --prefix="$HOME" @hostinger/mcp@latest`), or the scoped servers such as `hostinger-hosting` + `hostinger-wordpress` | every build |
|
|
131
|
+
| **Ecommerce** | `ecommerce_*` (stores, products, shipping, payments) | **only** `hostinger-ecommerce` (`npx --prefix="$HOME" --package=@hostinger/mcp@latest hostinger-ecommerce-mcp`), or the Ecommerce MCP in the Hostinger Connector. Neither `hostinger` nor the scoped hosting servers include it | Ecommerce backends (chosen later, in refine) |
|
|
132
132
|
|
|
133
133
|
Check each group on its own, right here at connect, before anything else:
|
|
134
134
|
|
|
@@ -148,8 +148,8 @@ Most coding tools load MCP servers only when they start, so a server registered
|
|
|
148
148
|
until the tool restarts. When either tool group above is missing:
|
|
149
149
|
|
|
150
150
|
1. **Register the missing servers** in the tool's MCP config, as the tool route below shows: `hostinger`
|
|
151
|
-
(`npx -y @hostinger/mcp@latest`) if the hosting group is missing, and `hostinger-ecommerce`
|
|
152
|
-
(`npx --package=@hostinger/mcp@latest hostinger-ecommerce-mcp`) if the ecommerce group is missing.
|
|
151
|
+
(`npx -y --prefix="$HOME" @hostinger/mcp@latest`) if the hosting group is missing, and `hostinger-ecommerce`
|
|
152
|
+
(`npx --prefix="$HOME" --package=@hostinger/mcp@latest hostinger-ecommerce-mcp`) if the ecommerce group is missing.
|
|
153
153
|
Skip a server that is already registered under its name. When neither group is there, register
|
|
154
154
|
both: the backend isn't chosen until refine, and one restart then covers every backend.
|
|
155
155
|
2. **Write `connect.json`** (Phase 3) before you stop. The skill folder from Phase 1 stays in place,
|
|
@@ -163,6 +163,13 @@ until the tool restarts. When either tool group above is missing:
|
|
|
163
163
|
|
|
164
164
|
If a tool loads new servers without a restart (VS Code), use them right away and skip steps 3–4.
|
|
165
165
|
|
|
166
|
+
**Every `npx` command and registration keeps `--prefix` set to the user's home folder.** The tool
|
|
167
|
+
starts the server, and you run commands, in the user's project, often a cloned repository or
|
|
168
|
+
template. Without `--prefix`, npm reads the `.npmrc` there, and whoever wrote it can point npx at
|
|
169
|
+
another registry or run their own code. In shell commands write `--prefix="$HOME"` (the shell expands
|
|
170
|
+
it when you register). In JSON or TOML configs replace `<home>` with the home folder's absolute path
|
|
171
|
+
(`echo $HOME`, e.g. `/Users/me` or `C:\\Users\\me`). Never drop the flag or leave `<home>` in place.
|
|
172
|
+
|
|
166
173
|
| Tool | Route |
|
|
167
174
|
|-------------|---------------------------------|
|
|
168
175
|
| Claude Code | `connect/tools/claude-code.md` |
|
|
@@ -26,11 +26,11 @@ no tokens to handle:
|
|
|
26
26
|
"mcpServers": {
|
|
27
27
|
"hostinger": {
|
|
28
28
|
"command": "npx",
|
|
29
|
-
"args": ["-y", "@hostinger/mcp@latest"]
|
|
29
|
+
"args": ["-y", "--prefix=<home>", "@hostinger/mcp@latest"]
|
|
30
30
|
},
|
|
31
31
|
"hostinger-ecommerce": {
|
|
32
32
|
"command": "npx",
|
|
33
|
-
"args": ["--package=@hostinger/mcp@latest", "hostinger-ecommerce-mcp"]
|
|
33
|
+
"args": ["--prefix=<home>", "--package=@hostinger/mcp@latest", "hostinger-ecommerce-mcp"]
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -25,8 +25,8 @@ in, so they reuse the cached sign-in (`~/.config/hostinger-mcp/credentials.json`
|
|
|
25
25
|
`HOSTINGER_API_TOKEN`) and there are no tokens to handle:
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
claude mcp add hostinger --scope user -- npx -y @hostinger/mcp@latest # hosting group missing
|
|
29
|
-
claude mcp add hostinger-ecommerce --scope user -- npx --package=@hostinger/mcp@latest hostinger-ecommerce-mcp # ecommerce group missing
|
|
28
|
+
claude mcp add hostinger --scope user -- npx -y --prefix="$HOME" @hostinger/mcp@latest # hosting group missing
|
|
29
|
+
claude mcp add hostinger-ecommerce --scope user -- npx --prefix="$HOME" --package=@hostinger/mcp@latest hostinger-ecommerce-mcp # ecommerce group missing
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
Claude Code loads MCP servers only at startup, so follow *register, restart, resume* in
|
|
@@ -19,8 +19,8 @@ sign-in (`~/.config/hostinger-mcp/credentials.json`, or `HOSTINGER_API_TOKEN`) a
|
|
|
19
19
|
to handle:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
codex mcp add hostinger -- npx -y @hostinger/mcp@latest
|
|
23
|
-
codex mcp add hostinger-ecommerce -- npx --package=@hostinger/mcp@latest hostinger-ecommerce-mcp
|
|
22
|
+
codex mcp add hostinger -- npx -y --prefix="$HOME" @hostinger/mcp@latest
|
|
23
|
+
codex mcp add hostinger-ecommerce -- npx --prefix="$HOME" --package=@hostinger/mcp@latest hostinger-ecommerce-mcp
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
or add them to `~/.codex/config.toml`:
|
|
@@ -28,11 +28,11 @@ or add them to `~/.codex/config.toml`:
|
|
|
28
28
|
```toml
|
|
29
29
|
[mcp_servers.hostinger]
|
|
30
30
|
command = "npx"
|
|
31
|
-
args = ["-y", "@hostinger/mcp@latest"]
|
|
31
|
+
args = ["-y", "--prefix=<home>", "@hostinger/mcp@latest"]
|
|
32
32
|
|
|
33
33
|
[mcp_servers.hostinger-ecommerce]
|
|
34
34
|
command = "npx"
|
|
35
|
-
args = ["--package=@hostinger/mcp@latest", "hostinger-ecommerce-mcp"]
|
|
35
|
+
args = ["--prefix=<home>", "--package=@hostinger/mcp@latest", "hostinger-ecommerce-mcp"]
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
Codex loads MCP servers only when it starts, so follow *register, restart, resume* in
|
|
@@ -19,7 +19,7 @@ The Hostinger MCP is the npm package `@hostinger/mcp`. You do **not** need a glo
|
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
21
|
# Verify the package/binary is reachable
|
|
22
|
-
npx --yes --package=@hostinger/mcp@latest hostinger-api-mcp --version
|
|
22
|
+
npx --yes --prefix="$HOME" --package=@hostinger/mcp@latest hostinger-api-mcp --version
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
### Option B — global install
|
|
@@ -49,11 +49,11 @@ OAuth can run:
|
|
|
49
49
|
"mcpServers": {
|
|
50
50
|
"hostinger": {
|
|
51
51
|
"command": "npx",
|
|
52
|
-
"args": ["--yes", "--package=@hostinger/mcp@latest", "hostinger-api-mcp"]
|
|
52
|
+
"args": ["--yes", "--prefix=<home>", "--package=@hostinger/mcp@latest", "hostinger-api-mcp"]
|
|
53
53
|
},
|
|
54
54
|
"hostinger-ecommerce": {
|
|
55
55
|
"command": "npx",
|
|
56
|
-
"args": ["--yes", "--package=@hostinger/mcp@latest", "hostinger-ecommerce-mcp"]
|
|
56
|
+
"args": ["--yes", "--prefix=<home>", "--package=@hostinger/mcp@latest", "hostinger-ecommerce-mcp"]
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
}
|
|
@@ -74,7 +74,7 @@ If the connect bootstrap already emitted `logged_in` / `success`, credentials ar
|
|
|
74
74
|
Otherwise run the login command. It registers a dynamic OAuth client (once per machine), **opens the user's browser** to Hostinger's authorization page, listens on a localhost callback, stores tokens, and exits:
|
|
75
75
|
|
|
76
76
|
```bash
|
|
77
|
-
npx --yes --package=@hostinger/mcp@latest hostinger-api-mcp --login
|
|
77
|
+
npx --yes --prefix="$HOME" --package=@hostinger/mcp@latest hostinger-api-mcp --login
|
|
78
78
|
```
|
|
79
79
|
|
|
80
80
|
(With a global install: `hostinger-api-mcp --login`.)
|
|
@@ -95,7 +95,7 @@ They are shared across every Hostinger MCP binary. Expired access tokens refresh
|
|
|
95
95
|
To sign out later:
|
|
96
96
|
|
|
97
97
|
```bash
|
|
98
|
-
npx --yes --package=@hostinger/mcp@latest hostinger-api-mcp --logout
|
|
98
|
+
npx --yes --prefix="$HOME" --package=@hostinger/mcp@latest hostinger-api-mcp --logout
|
|
99
99
|
```
|
|
100
100
|
|
|
101
101
|
**API token (optional, CI / scripts):** set `HOSTINGER_API_TOKEN` in the environment before launching Cursor. When present it always wins and no OAuth code runs. Do not commit the token.
|
|
@@ -21,18 +21,18 @@ tokens to handle.
|
|
|
21
21
|
- **Devin CLI:**
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
devin mcp add hostinger -- npx -y @hostinger/mcp@latest
|
|
25
|
-
devin mcp add hostinger-ecommerce -- npx --package=@hostinger/mcp@latest hostinger-ecommerce-mcp
|
|
24
|
+
devin mcp add hostinger -- npx -y --prefix="$HOME" @hostinger/mcp@latest
|
|
25
|
+
devin mcp add hostinger-ecommerce -- npx --prefix="$HOME" --package=@hostinger/mcp@latest hostinger-ecommerce-mcp
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
- **Devin app:** Settings → MCP Marketplace → **Add Your Own**, transport **STDIO**, once per server:
|
|
29
29
|
|
|
30
30
|
```json
|
|
31
|
-
{ "command": "npx", "args": ["-y", "@hostinger/mcp@latest"] }
|
|
31
|
+
{ "command": "npx", "args": ["-y", "--prefix=<home>", "@hostinger/mcp@latest"] }
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
```json
|
|
35
|
-
{ "command": "npx", "args": ["--package=@hostinger/mcp@latest", "hostinger-ecommerce-mcp"] }
|
|
35
|
+
{ "command": "npx", "args": ["--prefix=<home>", "--package=@hostinger/mcp@latest", "hostinger-ecommerce-mcp"] }
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
If the tools still aren't in this session, follow *register, restart, resume* in `connect/SKILL.md`:
|
|
@@ -26,12 +26,12 @@ no tokens to handle. Add them to `.vscode/mcp.json` (workspace) or your user `se
|
|
|
26
26
|
"hostinger": {
|
|
27
27
|
"type": "stdio",
|
|
28
28
|
"command": "npx",
|
|
29
|
-
"args": ["-y", "@hostinger/mcp@latest"]
|
|
29
|
+
"args": ["-y", "--prefix=<home>", "@hostinger/mcp@latest"]
|
|
30
30
|
},
|
|
31
31
|
"hostinger-ecommerce": {
|
|
32
32
|
"type": "stdio",
|
|
33
33
|
"command": "npx",
|
|
34
|
-
"args": ["--package=@hostinger/mcp@latest", "hostinger-ecommerce-mcp"]
|
|
34
|
+
"args": ["--prefix=<home>", "--package=@hostinger/mcp@latest", "hostinger-ecommerce-mcp"]
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
}
|
|
@@ -40,8 +40,8 @@ no tokens to handle. Add them to `.vscode/mcp.json` (workspace) or your user `se
|
|
|
40
40
|
Or add them in two commands:
|
|
41
41
|
|
|
42
42
|
```bash
|
|
43
|
-
code --add-mcp '{"name":"hostinger","command":"npx","args":["-y","@hostinger/mcp@latest"]}'
|
|
44
|
-
code --add-mcp '{"name":"hostinger-ecommerce","command":"npx","args":["--package=@hostinger/mcp@latest","hostinger-ecommerce-mcp"]}'
|
|
43
|
+
code --add-mcp '{"name":"hostinger","command":"npx","args":["-y","--prefix=<home>","@hostinger/mcp@latest"]}'
|
|
44
|
+
code --add-mcp '{"name":"hostinger-ecommerce","command":"npx","args":["--prefix=<home>","--package=@hostinger/mcp@latest","hostinger-ecommerce-mcp"]}'
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
VS Code picks up new servers and their tools become available right away, with no editor restart.
|
|
@@ -22,7 +22,7 @@ Provision a **Hostinger Ecommerce** backend for `<domain>` and prove it is ready
|
|
|
22
22
|
> aren't (for example, a tool connected before connect registered both servers), register it now. The
|
|
23
23
|
> command for each tool is in its `connect/tools/<tool>.md`; for Claude Code:
|
|
24
24
|
> ```bash
|
|
25
|
-
> claude mcp add hostinger-ecommerce --scope user -- npx --package=@hostinger/mcp@latest hostinger-ecommerce-mcp
|
|
25
|
+
> claude mcp add hostinger-ecommerce --scope user -- npx --prefix="$HOME" --package=@hostinger/mcp@latest hostinger-ecommerce-mcp
|
|
26
26
|
> ```
|
|
27
27
|
> (Or enable the **Ecommerce** MCP in the Hostinger Connector.) A newly added MCP server only loads
|
|
28
28
|
> after a restart, so pause the run with *register, restart, resume* from `connect/SKILL.md`: save
|
|
@@ -15,7 +15,7 @@ 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
|
-
> `npx --yes --package=@hostinger/mcp@latest hostinger-api-mcp`).
|
|
18
|
+
> `npx --yes --prefix="$HOME" --package=@hostinger/mcp@latest hostinger-api-mcp`).
|
|
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:
|
|
@@ -65,7 +65,7 @@ When a site breaks: stop the run, deactivate the plugin updated last with `wordp
|
|
|
65
65
|
|
|
66
66
|
- Page cache: `wordpress_litespeed-cache_show-lite-speed-status`; purge after design or content changes.
|
|
67
67
|
- Object cache: `wordpress_object-cache_show-memcached-status`, then `wordpress_object-cache_toggle-memcached` with `enabled: true` — the usual quick speed-up.
|
|
68
|
-
- PHP version: `hosting_php_get` is large (around 25 KB), so read it only when the user asks about PHP. PHP 8.x is markedly faster than 7.x; confirm plugin compatibility before `hosting_php_update
|
|
68
|
+
- PHP version: `hosting_php_get` is large (around 25 KB), so read it only when the user asks about PHP. PHP 8.x is markedly faster than 7.x; confirm plugin compatibility before switching with `hosting_php_update` (`version`). The switch resets extensions and options to their defaults, so pass the custom ones from `hosting_php_get` in the same call.
|
|
69
69
|
- wp-admin: `wordpress_login_create-links` returns temporary one-click login links. Give them to the user only; never store or reuse them.
|
|
70
70
|
- Hostinger's own plugins update with `wordpress_plugins_update-hostinger` (`slug`).
|
|
71
71
|
|
|
@@ -68,7 +68,7 @@ Batch `hosting_get-deployment` (the latest build with its log, failure analysis
|
|
|
68
68
|
|
|
69
69
|
### PHP
|
|
70
70
|
|
|
71
|
-
`hosting_php_get` returns every extension and option (around 25 KB), so call it only for PHP problems. `hosting_php_update
|
|
71
|
+
`hosting_php_get` returns every extension and option (around 25 KB), so call it only for PHP problems. `hosting_php_update` changes the version, extensions and options in one call. Switching the version resets the extensions and options to their defaults, so pass the ones to keep in the same call. Option values are silently capped at the plan maximum (`max` in `hosting_php_get`), so read the applied value back. Agency: `agency-hosting_php_list-options-for-website`, then `agency-hosting_php_replace-website-options` — a full replace, so send every custom option that should stay.
|
|
72
72
|
|
|
73
73
|
### Agency Plan sites
|
|
74
74
|
|
package/src/core/runtime.js
CHANGED
|
@@ -304,6 +304,8 @@ class MCPServer {
|
|
|
304
304
|
return await this.handleHostingWebsitesUpdateSettings(params);
|
|
305
305
|
case 'hosting_cache_clear':
|
|
306
306
|
return await this.handleHostingCacheClear(params);
|
|
307
|
+
case 'hosting_php_update':
|
|
308
|
+
return await this.handleHostingPhpUpdate(params);
|
|
307
309
|
case 'hosting_websites_list-domains':
|
|
308
310
|
return await this.handleHostingWebsitesListDomains(params);
|
|
309
311
|
case 'hosting_websites_add-domain':
|
|
@@ -1605,6 +1607,100 @@ class MCPServer {
|
|
|
1605
1607
|
return { domain, cleared: scope, directory, response };
|
|
1606
1608
|
}
|
|
1607
1609
|
|
|
1610
|
+
// Application order, and how each step maps to its operation.
|
|
1611
|
+
hosting_phpUpdate_steps = [
|
|
1612
|
+
{ setting: 'version', run: (target, value) => this.callOperation('hosting_php_update-version', { ...target, version: value }) },
|
|
1613
|
+
{ setting: 'resetExtensions', run: (target) => this.callOperation('hosting_php_reset-extensions', target) },
|
|
1614
|
+
{ setting: 'extensions', run: (target, value) => this.callOperation('hosting_php_update-extensions', { ...target, ...this.hosting_phpUpdate_extensionLists(value) }) },
|
|
1615
|
+
{ setting: 'options', run: (target, value) => this.callOperation('hosting_php_update-options', { ...target, options: value }) },
|
|
1616
|
+
];
|
|
1617
|
+
|
|
1618
|
+
// The enable and disable lists to send: only the non-empty ones.
|
|
1619
|
+
hosting_phpUpdate_extensionLists(extensions) {
|
|
1620
|
+
const lists = {};
|
|
1621
|
+
for (const key of ['enable', 'disable']) {
|
|
1622
|
+
if (Array.isArray(extensions[key]) && extensions[key].length > 0) {
|
|
1623
|
+
lists[key] = extensions[key];
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
return lists;
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1629
|
+
hosting_phpUpdate_validate(params) {
|
|
1630
|
+
// Models send null for fields they leave unset.
|
|
1631
|
+
const given = (name) => params[name] !== undefined && params[name] !== null;
|
|
1632
|
+
|
|
1633
|
+
if (given('version') && (typeof params.version !== 'string' || params.version.trim() === '')) {
|
|
1634
|
+
throw new Error('version must be a non-empty string when provided');
|
|
1635
|
+
}
|
|
1636
|
+
if (given('resetExtensions') && typeof params.resetExtensions !== 'boolean') {
|
|
1637
|
+
throw new Error('resetExtensions must be a boolean when provided');
|
|
1638
|
+
}
|
|
1639
|
+
if (given('extensions')) {
|
|
1640
|
+
const extensions = params.extensions;
|
|
1641
|
+
const list = (value) => value === undefined || value === null || (Array.isArray(value) && value.every((name) => typeof name === 'string' && name !== ''));
|
|
1642
|
+
const valid = typeof extensions === 'object' && !Array.isArray(extensions)
|
|
1643
|
+
&& list(extensions.enable) && list(extensions.disable)
|
|
1644
|
+
&& Object.keys(this.hosting_phpUpdate_extensionLists(extensions)).length > 0;
|
|
1645
|
+
if (!valid) {
|
|
1646
|
+
throw new Error('extensions must be an object with a non-empty enable or disable list of extension names');
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
if (given('options')) {
|
|
1650
|
+
const options = params.options;
|
|
1651
|
+
const valid = typeof options === 'object' && !Array.isArray(options) && Object.keys(options).length > 0
|
|
1652
|
+
&& Object.values(options).every(value => typeof value === 'string' || (typeof value === 'number' && Number.isInteger(value)));
|
|
1653
|
+
if (!valid) {
|
|
1654
|
+
throw new Error('options must be a non-empty object of option names to string or integer values');
|
|
1655
|
+
}
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
async handleHostingPhpUpdate(params) {
|
|
1660
|
+
const { domain: requestedDomain } = params;
|
|
1661
|
+
this.hosting_phpUpdate_validate(params);
|
|
1662
|
+
|
|
1663
|
+
// resetExtensions: false asks for nothing, like null.
|
|
1664
|
+
const requested = this.hosting_phpUpdate_steps.filter(step => step.setting === 'resetExtensions'
|
|
1665
|
+
? params.resetExtensions === true
|
|
1666
|
+
: params[step.setting] !== undefined && params[step.setting] !== null);
|
|
1667
|
+
if (requested.length === 0) {
|
|
1668
|
+
throw new Error('Pass at least one of version, resetExtensions, extensions, options');
|
|
1669
|
+
}
|
|
1670
|
+
if (!requestedDomain || typeof requestedDomain !== 'string') {
|
|
1671
|
+
throw new Error('domain is required and must be a string');
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1674
|
+
const { username, domain } = await this.findWebsite(requestedDomain);
|
|
1675
|
+
const target = { username, domain };
|
|
1676
|
+
|
|
1677
|
+
const applied = {};
|
|
1678
|
+
let failed = null;
|
|
1679
|
+
const skipped = [];
|
|
1680
|
+
for (const step of requested) {
|
|
1681
|
+
const value = params[step.setting];
|
|
1682
|
+
if (failed) {
|
|
1683
|
+
skipped.push(step.setting);
|
|
1684
|
+
continue;
|
|
1685
|
+
}
|
|
1686
|
+
try {
|
|
1687
|
+
await step.run(target, value);
|
|
1688
|
+
// What was sent: for extensions, only the non-empty lists.
|
|
1689
|
+
applied[step.setting] = step.setting === 'extensions' ? this.hosting_phpUpdate_extensionLists(value) : value;
|
|
1690
|
+
} catch (error) {
|
|
1691
|
+
failed = { setting: step.setting, error: this.formatToolError(error) };
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
const result = { domain, applied, failed, skipped };
|
|
1696
|
+
// A failed step is a tool error carrying the same JSON, so execute reports it and a
|
|
1697
|
+
// multi-execute batch stops at this step.
|
|
1698
|
+
if (failed) {
|
|
1699
|
+
throw new Error(JSON.stringify(result));
|
|
1700
|
+
}
|
|
1701
|
+
return result;
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1608
1704
|
// A 404 means the domain is not a website on the account, which fails the whole call; any other
|
|
1609
1705
|
// failure only fails its own list.
|
|
1610
1706
|
async hosting_websitesListDomains_section(request, pick) {
|
package/src/core/runtime.ts
CHANGED
|
@@ -336,6 +336,8 @@ class MCPServer {
|
|
|
336
336
|
return await this.handleHostingWebsitesUpdateSettings(params);
|
|
337
337
|
case 'hosting_cache_clear':
|
|
338
338
|
return await this.handleHostingCacheClear(params);
|
|
339
|
+
case 'hosting_php_update':
|
|
340
|
+
return await this.handleHostingPhpUpdate(params);
|
|
339
341
|
case 'hosting_websites_list-domains':
|
|
340
342
|
return await this.handleHostingWebsitesListDomains(params);
|
|
341
343
|
case 'hosting_websites_add-domain':
|
|
@@ -1643,6 +1645,100 @@ class MCPServer {
|
|
|
1643
1645
|
return { domain, cleared: scope, directory, response };
|
|
1644
1646
|
}
|
|
1645
1647
|
|
|
1648
|
+
// Application order, and how each step maps to its operation.
|
|
1649
|
+
private hosting_phpUpdate_steps: Array<{ setting: string; run: (target: { username: string; domain: string }, value: any) => Promise<any> }> = [
|
|
1650
|
+
{ setting: 'version', run: (target, value) => this.callOperation('hosting_php_update-version', { ...target, version: value }) },
|
|
1651
|
+
{ setting: 'resetExtensions', run: (target) => this.callOperation('hosting_php_reset-extensions', target) },
|
|
1652
|
+
{ setting: 'extensions', run: (target, value) => this.callOperation('hosting_php_update-extensions', { ...target, ...this.hosting_phpUpdate_extensionLists(value) }) },
|
|
1653
|
+
{ setting: 'options', run: (target, value) => this.callOperation('hosting_php_update-options', { ...target, options: value }) },
|
|
1654
|
+
];
|
|
1655
|
+
|
|
1656
|
+
// The enable and disable lists to send: only the non-empty ones.
|
|
1657
|
+
private hosting_phpUpdate_extensionLists(extensions: Record<string, any>): Record<string, string[]> {
|
|
1658
|
+
const lists: Record<string, string[]> = {};
|
|
1659
|
+
for (const key of ['enable', 'disable']) {
|
|
1660
|
+
if (Array.isArray(extensions[key]) && extensions[key].length > 0) {
|
|
1661
|
+
lists[key] = extensions[key];
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
return lists;
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
private hosting_phpUpdate_validate(params: Record<string, any>): void {
|
|
1668
|
+
// Models send null for fields they leave unset.
|
|
1669
|
+
const given = (name: string) => params[name] !== undefined && params[name] !== null;
|
|
1670
|
+
|
|
1671
|
+
if (given('version') && (typeof params.version !== 'string' || params.version.trim() === '')) {
|
|
1672
|
+
throw new Error('version must be a non-empty string when provided');
|
|
1673
|
+
}
|
|
1674
|
+
if (given('resetExtensions') && typeof params.resetExtensions !== 'boolean') {
|
|
1675
|
+
throw new Error('resetExtensions must be a boolean when provided');
|
|
1676
|
+
}
|
|
1677
|
+
if (given('extensions')) {
|
|
1678
|
+
const extensions = params.extensions;
|
|
1679
|
+
const list = (value: any) => value === undefined || value === null || (Array.isArray(value) && value.every((name: any) => typeof name === 'string' && name !== ''));
|
|
1680
|
+
const valid = typeof extensions === 'object' && !Array.isArray(extensions)
|
|
1681
|
+
&& list(extensions.enable) && list(extensions.disable)
|
|
1682
|
+
&& Object.keys(this.hosting_phpUpdate_extensionLists(extensions)).length > 0;
|
|
1683
|
+
if (!valid) {
|
|
1684
|
+
throw new Error('extensions must be an object with a non-empty enable or disable list of extension names');
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
if (given('options')) {
|
|
1688
|
+
const options = params.options;
|
|
1689
|
+
const valid = typeof options === 'object' && !Array.isArray(options) && Object.keys(options).length > 0
|
|
1690
|
+
&& Object.values(options).every(value => typeof value === 'string' || (typeof value === 'number' && Number.isInteger(value)));
|
|
1691
|
+
if (!valid) {
|
|
1692
|
+
throw new Error('options must be a non-empty object of option names to string or integer values');
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
private async handleHostingPhpUpdate(params: Record<string, any>): Promise<any> {
|
|
1698
|
+
const { domain: requestedDomain } = params;
|
|
1699
|
+
this.hosting_phpUpdate_validate(params);
|
|
1700
|
+
|
|
1701
|
+
// resetExtensions: false asks for nothing, like null.
|
|
1702
|
+
const requested = this.hosting_phpUpdate_steps.filter(step => step.setting === 'resetExtensions'
|
|
1703
|
+
? params.resetExtensions === true
|
|
1704
|
+
: params[step.setting] !== undefined && params[step.setting] !== null);
|
|
1705
|
+
if (requested.length === 0) {
|
|
1706
|
+
throw new Error('Pass at least one of version, resetExtensions, extensions, options');
|
|
1707
|
+
}
|
|
1708
|
+
if (!requestedDomain || typeof requestedDomain !== 'string') {
|
|
1709
|
+
throw new Error('domain is required and must be a string');
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
const { username, domain } = await this.findWebsite(requestedDomain);
|
|
1713
|
+
const target = { username, domain };
|
|
1714
|
+
|
|
1715
|
+
const applied: Record<string, any> = {};
|
|
1716
|
+
let failed: { setting: string; error: string } | null = null;
|
|
1717
|
+
const skipped: string[] = [];
|
|
1718
|
+
for (const step of requested) {
|
|
1719
|
+
const value = params[step.setting];
|
|
1720
|
+
if (failed) {
|
|
1721
|
+
skipped.push(step.setting);
|
|
1722
|
+
continue;
|
|
1723
|
+
}
|
|
1724
|
+
try {
|
|
1725
|
+
await step.run(target, value);
|
|
1726
|
+
// What was sent: for extensions, only the non-empty lists.
|
|
1727
|
+
applied[step.setting] = step.setting === 'extensions' ? this.hosting_phpUpdate_extensionLists(value) : value;
|
|
1728
|
+
} catch (error) {
|
|
1729
|
+
failed = { setting: step.setting, error: this.formatToolError(error) };
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1733
|
+
const result = { domain, applied, failed, skipped };
|
|
1734
|
+
// A failed step is a tool error carrying the same JSON, so execute reports it and a
|
|
1735
|
+
// multi-execute batch stops at this step.
|
|
1736
|
+
if (failed) {
|
|
1737
|
+
throw new Error(JSON.stringify(result));
|
|
1738
|
+
}
|
|
1739
|
+
return result;
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1646
1742
|
// A 404 means the domain is not a website on the account, which fails the whole call; any other
|
|
1647
1743
|
// failure only fails its own list.
|
|
1648
1744
|
private async hosting_websitesListDomains_section(request: Promise<any>, pick: (item: any) => any): Promise<any> {
|