@hostinger/mcp 3.2.1 → 3.3.0
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 +23 -0
- package/README.md +59 -3
- package/gemini-extension.json +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
- package/skills/headless/SKILL.md +247 -36
- package/skills/headless/connect/SKILL.md +103 -0
- package/skills/headless/{entry → connect}/bootstrap.mjs +8 -3
- package/skills/headless/connect/tools/antigravity.md +54 -0
- package/skills/headless/connect/tools/claude-code.md +46 -0
- package/skills/headless/connect/tools/codex.md +48 -0
- package/skills/headless/connect/tools/cursor.md +109 -0
- package/skills/headless/connect/tools/devin.md +50 -0
- package/skills/headless/connect/tools/vscode.md +57 -0
- package/skills/headless/report.schema.json +149 -0
- package/skills/headless/run-log.mjs +662 -0
- package/skills/headless/steps/01-check-state/SKILL.md +193 -0
- package/skills/headless/steps/02-refine/SKILL.md +206 -0
- package/skills/headless/steps/03-provision/SKILL.md +62 -0
- package/skills/headless/steps/03-provision/ecommerce/SKILL.md +133 -0
- package/skills/headless/steps/03-provision/webapp/SKILL.md +154 -0
- package/skills/headless/steps/03-provision/wordpress/SKILL.md +100 -0
- package/skills/headless/steps/04-content-model/SKILL.md +150 -0
- package/skills/headless/steps/04-content-model/ecommerce/SKILL.md +75 -0
- package/skills/headless/steps/04-content-model/wordpress/SKILL.md +178 -0
- package/skills/headless/steps/05-design/SKILL.md +455 -0
- package/skills/headless/steps/05-design/logo-kit.mjs +201 -0
- package/skills/headless/steps/06-frontend/SKILL.md +131 -0
- package/skills/headless/steps/07-validate/SKILL.md +53 -0
- package/skills/headless/steps/08-deploy/SKILL.md +171 -0
- package/skills/headless/steps/09-done/SKILL.md +151 -0
- package/src/core/runtime.js +1 -1
- package/src/core/runtime.ts +1 -1
- package/src/core/skills.js +164 -24
- package/src/core/skills.ts +164 -24
- package/src/core/tools/all.js +142 -1
- package/src/core/tools/all.ts +142 -1
- package/src/core/tools/hosting.js +142 -1
- package/src/core/tools/hosting.ts +142 -1
- 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/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 +97 -1
- package/skills/headless/entry/skill.md +0 -79
- package/skills/headless/references/DATABASE.md +0 -49
- package/skills/headless/references/DEPLOYMENT.md +0 -34
- package/skills/headless/references/SETUP.md +0 -35
- package/skills/headless/references/STORE.md +0 -52
- package/skills/headless/references/WORDPRESS.md +0 -51
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,29 @@ 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.3.0 — 2026-10-19
|
|
8
|
+
|
|
9
|
+
### Also in this release
|
|
10
|
+
|
|
11
|
+
- Bundled agent skills: 33 files
|
|
12
|
+
- Other files: `src/core/skills.js`, `src/core/skills.ts`
|
|
13
|
+
|
|
14
|
+
## v3.2.2 — 2026-10-19
|
|
15
|
+
|
|
16
|
+
### Operations
|
|
17
|
+
|
|
18
|
+
- Added `hosting_cdn_disable` — Disable CDN
|
|
19
|
+
- Added `hosting_cdn_enable` — Enable CDN
|
|
20
|
+
- Added `hosting_cdn_purge-cache` — Purge CDN cache
|
|
21
|
+
- Added `hosting_cdn_status` — Get CDN status
|
|
22
|
+
- Changed the description of `hosting_cache_clear-website`
|
|
23
|
+
|
|
24
|
+
### Also in this release
|
|
25
|
+
|
|
26
|
+
- Documentation: `README.md`
|
|
27
|
+
- Request handling and authentication: `src/core/runtime.js`, `src/core/runtime.ts`
|
|
28
|
+
- Build and packaging: `types.d.ts`
|
|
29
|
+
|
|
7
30
|
## v3.2.1 — 2026-10-19
|
|
8
31
|
|
|
9
32
|
### Operations
|
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 (403 total)
|
|
73
73
|
- `hostinger-agency-hosting-mcp` — 42 operations for agency-hosting
|
|
74
74
|
- `hostinger-agent-readiness-mcp` — 3 operations for agent-readiness
|
|
75
75
|
- `hostinger-billing-mcp` — 9 operations for billing
|
|
@@ -77,7 +77,7 @@ This package installs the following MCP server commands:
|
|
|
77
77
|
- `hostinger-domains-mcp` — 42 operations for domains
|
|
78
78
|
- `hostinger-ecommerce-mcp` — 29 operations for ecommerce
|
|
79
79
|
- `hostinger-horizons-mcp` — 6 operations for horizons
|
|
80
|
-
- `hostinger-hosting-mcp` —
|
|
80
|
+
- `hostinger-hosting-mcp` — 66 operations for hosting
|
|
81
81
|
- `hostinger-mail-mcp` — 38 operations for mail
|
|
82
82
|
- `hostinger-reach-mcp` — 56 operations for reach
|
|
83
83
|
- `hostinger-vps-mcp` — 67 operations for vps
|
|
@@ -1833,7 +1833,8 @@ Check deployment status, build status, build logs and why a build failed (failur
|
|
|
1833
1833
|
Permanently clears all server-side cache for the website at once. Use it when content was
|
|
1834
1834
|
updated and needs to be visible immediately, or after making major changes.
|
|
1835
1835
|
|
|
1836
|
-
Also purges the Hostinger CDN cache when CDN is enabled on the website.
|
|
1836
|
+
Also purges the Hostinger CDN cache when CDN is enabled on the website. To purge only the CDN
|
|
1837
|
+
cache and leave the server cache untouched, use `Purge CDN cache`. For a WordPress
|
|
1837
1838
|
installation living in a subdirectory, pass the directory query parameter to clear its cache.
|
|
1838
1839
|
|
|
1839
1840
|
- **Method**: `DELETE`
|
|
@@ -1861,6 +1862,61 @@ Does nothing if caching is already in the requested state.
|
|
|
1861
1862
|
- **Method**: `PATCH`
|
|
1862
1863
|
- **Path**: `/api/hosting/v1/accounts/{username}/websites/{domain}/cache/toggle`
|
|
1863
1864
|
|
|
1865
|
+
#### hosting_cdn_disable
|
|
1866
|
+
|
|
1867
|
+
Turns off the Hostinger CDN for the website domain. Once DNS propagation completes, the
|
|
1868
|
+
website content is served directly from the origin server. Repeating the call is safe; when
|
|
1869
|
+
CDN is already disabled, it applies the DNS change again.
|
|
1870
|
+
|
|
1871
|
+
Returns 422 for platform-managed domains (for example `*.hostingersite.com` and
|
|
1872
|
+
`*.app-preview.com`), where CDN cannot be disabled, even when CDN is already off. Also returns
|
|
1873
|
+
422 while the account is being moved to another server (retry after the move finishes), or
|
|
1874
|
+
when the CDN provider rejects the change. Returns 404 when the domain is not a website on the
|
|
1875
|
+
account.
|
|
1876
|
+
|
|
1877
|
+
- **Method**: `POST`
|
|
1878
|
+
- **Path**: `/api/hosting/v1/accounts/{username}/websites/{domain}/cdn/disable`
|
|
1879
|
+
|
|
1880
|
+
#### hosting_cdn_enable
|
|
1881
|
+
|
|
1882
|
+
Turns on the Hostinger CDN for the website domain, which speeds up page loads and reduces the
|
|
1883
|
+
load on the server. Works for the main domain, parked domains and subdomains of the account.
|
|
1884
|
+
|
|
1885
|
+
Enabling changes the domain's DNS records and usually takes a few seconds. After that, DNS
|
|
1886
|
+
propagation can take a few more minutes before visitors are served through the CDN.
|
|
1887
|
+
|
|
1888
|
+
Repeating the call is safe, for example after a timeout. When CDN is already enabled, it
|
|
1889
|
+
applies the DNS change again and refreshes the CDN SSL certificate.
|
|
1890
|
+
|
|
1891
|
+
Returns 422 when the account is disabled, while the account is being moved to another
|
|
1892
|
+
server (retry after the move finishes), or when the CDN provider rejects the change.
|
|
1893
|
+
Returns 404 when the domain is not a website on the account.
|
|
1894
|
+
|
|
1895
|
+
- **Method**: `POST`
|
|
1896
|
+
- **Path**: `/api/hosting/v1/accounts/{username}/websites/{domain}/cdn/enable`
|
|
1897
|
+
|
|
1898
|
+
#### hosting_cdn_purge-cache
|
|
1899
|
+
|
|
1900
|
+
Purges the website's content from the Hostinger CDN edge cache only. The origin server cache
|
|
1901
|
+
is not touched; to clear both, use `Clear website cache`.
|
|
1902
|
+
|
|
1903
|
+
Returns 422 when CDN is not enabled on the website. Returns 404 when the domain is not a
|
|
1904
|
+
website on the account.
|
|
1905
|
+
|
|
1906
|
+
- **Method**: `DELETE`
|
|
1907
|
+
- **Path**: `/api/hosting/v1/accounts/{username}/websites/{domain}/cdn/purge`
|
|
1908
|
+
|
|
1909
|
+
#### hosting_cdn_status
|
|
1910
|
+
|
|
1911
|
+
Returns whether the Hostinger CDN is enabled for the website domain. Works for the main
|
|
1912
|
+
domain, parked domains and subdomains of the account.
|
|
1913
|
+
|
|
1914
|
+
The domain must be the exact website name as listed on the account, without a `www.` prefix.
|
|
1915
|
+
Returns 404 when the domain is not a website on the account.
|
|
1916
|
+
|
|
1917
|
+
- **Method**: `GET`
|
|
1918
|
+
- **Path**: `/api/hosting/v1/accounts/{username}/websites/{domain}/cdn/status`
|
|
1919
|
+
|
|
1864
1920
|
#### hosting_cron-jobs_list
|
|
1865
1921
|
|
|
1866
1922
|
Returns the list of cron jobs configured for the specified account, including their schedule and command.
|
package/gemini-extension.json
CHANGED
package/package.json
CHANGED
package/server.json
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
"url": "https://github.com/hostinger/api-mcp-server",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "3.
|
|
9
|
+
"version": "3.3.0",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "@hostinger/mcp",
|
|
14
|
-
"version": "3.
|
|
14
|
+
"version": "3.3.0",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
},
|
package/skills/headless/SKILL.md
CHANGED
|
@@ -1,56 +1,267 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: hostinger-headless
|
|
3
|
-
description: "
|
|
3
|
+
description: "Orchestrator for the Hostinger Headless build flow — build and deploy a real website on the user's Hostinger account from a single prompt that names a domain. Holds the stage flow and the state contract, and drives each stage in sequence: connect, check state, refine, provision, content model, design, frontend, validate, deploy, done. Triggers: build a headless site for <domain>, build me a site, create a website, make me a website, deploy this to Hostinger, host this on Hostinger, connect this project to Hostinger."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Hostinger Headless
|
|
6
|
+
# Hostinger Headless — build a website with your own AI tool
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
## Context
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
You are an AI coding agent. The user pasted a short prompt that points you here — something like:
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
> Build a Headless site for `example.com` using hostinger.com/ai/skill.md
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
3. An active hosting plan (checked in Setup §1). Hostinger hosting is a paid product: if the account has no usable plan, inform the user plainly that a subscription is required, link them to https://www.hostinger.com/web-hosting, and pause until they confirm the purchase. Do not treat this as an error — it is a normal step for new accounts. Everything that doesn't need hosting (planning, building the frontend locally) can proceed while they decide.
|
|
14
|
+
Your job is to build and deploy a real website on the user's Hostinger account by following this
|
|
15
|
+
recipe and the recipes it links to — nothing more, nothing less.
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
This file is the **orchestrator**. It is public and stable: it never changes and never moves. It
|
|
18
|
+
holds the flow, the state contract, the failure policy and the guardrails.
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
### The domain parameter
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
- `connect` — a frontend project already on disk (or brought in as a zip/export/URL) that is not yet on Hostinger, with language like "deploy this / host this on Hostinger / connect this project". Emptiness of the CWD at trigger time is not a create signal when a design is brought in from elsewhere.
|
|
24
|
-
- `create` — a new site from a prompt with nothing brought in: "build me a store / portfolio / site…".
|
|
22
|
+
The pasted prompt contains exactly two things that matter:
|
|
25
23
|
|
|
26
|
-
|
|
24
|
+
- **This URL** — `hostinger.com/ai/skill.md`, the stable entry point.
|
|
25
|
+
- **A domain** — e.g. `coral-pottery-1847.hostingersite.com` (a temporary Hostinger subdomain) or
|
|
26
|
+
the user's own purchased domain. This is the single site you may touch.
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
The prompt does **not** say what kind of site to build. Do not assume or invent it. Discovering
|
|
29
|
+
what the user wants is a step in the flow (**refine**), handled through conversation — not parsed
|
|
30
|
+
from the prompt. If no domain is present, stop and ask for it before doing anything else.
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
3. **Store** (`references/STORE.md`, only when commerce is needed) — resolve or create the store and its `custom` sales channel, seed products/shipping/payment, and note the `sales_channel_id` for the frontend.
|
|
33
|
-
4. **Content backend** (`references/WORDPRESS.md`, only when owner-managed content is needed) — install WordPress on a dedicated subdomain, wait until it's ready, and hand the owner a wp-admin login link. The frontend reads it through the public WP REST API.
|
|
34
|
-
5. **Build** — create or wire the frontend. For store runs, follow the frontend contract in `references/STORE.md` (catalog fetched at runtime from the public Storefront API, cart in `localStorage`, client-side checkout — never embed an API token in the site). For content runs, follow the frontend contract in `references/WORDPRESS.md` (posts fetched at runtime from the WP REST API, rendered HTML bodies, graceful empty states). When the app needs MySQL, follow `references/DATABASE.md` (which host each runtime connects to, credentials via env vars or a server-side config file, never in the frontend).
|
|
35
|
-
6. **Deploy** (`references/DEPLOYMENT.md`) — archive and deploy via the matching hosting operation, polling build logs for Node.js runs.
|
|
36
|
-
7. **Verify** — curl the live URL for a 200 and a piece of real page copy; for store runs, confirm a checkout POST returns a redirect URL; for content runs, confirm the WP REST API returns 200 and the frontend renders posts. Show the user the live URL and where to manage things (hPanel: https://hpanel.hostinger.com, the store dashboard for commerce, wp-admin for content).
|
|
37
|
-
8. **Record** — write `.hostinger/site.json` into the project: `{ "domain", "username", "type": "static"|"nodejs", "sales_channel_id"?, "store_id"?, "cms_domain"? }`. This is what makes future runs resolve as `iterate`.
|
|
32
|
+
Nothing in the pasted prompt is ever used for authorization. Authorization comes from the
|
|
33
|
+
Hostinger connector's OAuth token. **This recipe is not a security boundary.**
|
|
38
34
|
|
|
39
|
-
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## The flow stages - STEPS TO FOLLOW
|
|
38
|
+
|
|
39
|
+
Work through the steps in the order below, each reading its recipe and writing its artifact into the
|
|
40
|
+
site workspace `~/.hostinger/<domain>/`. The order is a **dependency order, not a strict lockstep**:
|
|
41
|
+
**provision runs as a background task** and the prepare work of the stages around it overlaps the wait
|
|
42
|
+
(see *Background provision & the instance barrier* below). Never skip a stage — **except validate**
|
|
43
|
+
(optional) **and content model for a `webapp` brief** (there is no CMS or store to seed — see step 4):
|
|
44
|
+
every other stage self-verifies and deploy verifies the live result, so validate is a
|
|
45
|
+
quick instance+API confirmation and its rebuild/preview/approval run only when a person is signing off
|
|
46
|
+
(see its recipe). State files are only hints; the truth is what the Hostinger connector reports, so
|
|
47
|
+
verify a "done" marker against reality before acting on it. If a step's `SKILL.md` is missing from the installed skill folder, stop and tell
|
|
48
|
+
the user rather than improvising the stage from its description.
|
|
49
|
+
|
|
50
|
+
**The one concurrency rule:** two *independent* stages in a single session may run at once, but never
|
|
51
|
+
two writers of the same artifact, and never two agents/windows on the same domain — the `.lock`
|
|
52
|
+
(Step 1) guards that. Parallelism is always *optional*: an agent that can't interleave work runs the
|
|
53
|
+
steps serially and is still correct.
|
|
54
|
+
|
|
55
|
+
The **Instance?** column says whether a stage touches the live backend: `no` = pure prepare work that
|
|
56
|
+
can run during the provision wait; `push`/`data`/`yes` = a commit phase that joins the instance
|
|
57
|
+
barrier; `bg` = provision itself, the background task.
|
|
58
|
+
|
|
59
|
+
| # | Stage | Skill / source | Writes | Instance? |
|
|
60
|
+
|---|---|---|---|---|
|
|
61
|
+
| — | **connect** — connect the Hostinger connector, auth, active plan | `connect/SKILL.md` → `connect/tools/<tool>.md` | `connect.json` | no |
|
|
62
|
+
| 1 | **check state** — where does this domain stand? resume / switch / start over | `steps/01-check-state/SKILL.md` | `state.json` | no |
|
|
63
|
+
| 2 | **refine** — discover what the user wants, in conversation | `steps/02-refine/SKILL.md` | `brief.md` | no |
|
|
64
|
+
| 3 | **provision** — choose the backend from the brief, then provision it | `steps/03-provision/<backend>/SKILL.md` | `site.json` | **bg** — fire, then poll in the background |
|
|
65
|
+
| 4 | **content model** — define + create content/images, then push to the backend | `steps/04-content-model/<backend>/SKILL.md` | `content-model.md` | prepare: no · **push: yes** |
|
|
66
|
+
| 5 | **design** — derive design directions from the brief, pick one, write the `design.md` contract + logo | `steps/05-design/SKILL.md` | `design.md`, `brand/` | no |
|
|
67
|
+
| 6 | **frontend** — pick/confirm the framework (default Next.js SSR), implement `design.md` against the backend | `steps/06-frontend/SKILL.md` | source in `<workspace>/src/` | shell: no · **data: yes** |
|
|
68
|
+
| 7 | **validate** *(optional)* — quick instance+API confirmation; rebuild/preview/approval only when a person signs off | `steps/07-validate/SKILL.md` | — | no (local) |
|
|
69
|
+
| 8 | **deploy** — upload source, trigger the build | `steps/08-deploy/SKILL.md` | `deploy.json` | **yes** |
|
|
70
|
+
| 9 | **done** — hand over URLs, dashboard, summary, next steps (the **final report**) | `steps/09-done/SKILL.md` | — | no |
|
|
71
|
+
|
|
72
|
+
**connect** runs first — it's fetched from the public URL and runs *before* the Hostinger connector
|
|
73
|
+
exists. The nine numbered steps live under `steps/` and are read from the installed skill folder.
|
|
74
|
+
**provision** and **content model** route to a per-backend subfolder (`<backend>` = `wordpress` |
|
|
75
|
+
`ecommerce` | `webapp`), chosen from the brief. **`webapp`** is a plain Node.js app host (an empty
|
|
76
|
+
website — no CMS, no store, no `/cms`) for any app/SPA that brings its own code and data; it **skips the
|
|
77
|
+
content-model stage entirely** (there is nothing to seed — the app owns its own data) and never installs
|
|
78
|
+
WordPress. **design** turns the brief into a chosen look and writes the `design.md` contract;
|
|
79
|
+
**frontend** is a single generic step that picks the framework (guess → default Next.js SSR → confirm)
|
|
80
|
+
and implements `design.md`.
|
|
81
|
+
|
|
82
|
+
**Always end with the final report.** Whenever a run ends, give the user the final report defined
|
|
83
|
+
in `steps/09-done/SKILL.md`: an outcome paragraph, a *Steps completed* table (one row per stage that
|
|
84
|
+
ran), the links, where state lives, and any gaps. That includes runs that stop early at a dummy or
|
|
85
|
+
missing step, a failed provision, or a user pause. Every run also saves a **build report**
|
|
86
|
+
(`run-log.mjs report`, see *Run log and build report* below), on those early stops too.
|
|
87
|
+
|
|
88
|
+
**Log the run as you go.** Wrap every stage (and each phase of a split stage) in
|
|
89
|
+
`run-log.mjs stage-start` / `stage-end`, and log an event the moment something goes wrong, the user
|
|
90
|
+
corrects you, or a skill is missing or wrong — before you continue. See *Run log and build report*.
|
|
91
|
+
|
|
92
|
+
**Why this order.** connect first, so account/plan failures surface before the user spends time
|
|
93
|
+
talking. Check-state right after, so a resumed, duplicate, or brand-new run is sorted out — and the
|
|
94
|
+
user is offered the choice to continue, switch domains, or start over — before any new work begins.
|
|
95
|
+
Refinement before provisioning, because the backend cannot be chosen until the brief exists.
|
|
96
|
+
Validation before deploy, always — nothing reaches the live domain unseen.
|
|
97
|
+
|
|
98
|
+
### Background provision & the instance barrier
|
|
99
|
+
|
|
100
|
+
Provisioning is mostly *waiting*: `hosting_websites_create` returns "queued" immediately, then it's a
|
|
101
|
+
`hosting_websites_list-setups` poll every ~15 s for a few minutes. Don't block on that poll. The
|
|
102
|
+
single rule that makes the overlap safe:
|
|
103
|
+
|
|
104
|
+
> **Fire provision as a background task, then do every stage's prepare work while it settles. The
|
|
105
|
+
> moment a step must write to the live instance, it waits for provision to report `completed`
|
|
106
|
+
> (verified against `hosting_websites_list-setups`). That wait is the *instance barrier*.**
|
|
107
|
+
|
|
108
|
+
Once `brief.md` exists (it already fixes the backend choice), the lanes are:
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
refine ──▶ brief.md
|
|
112
|
+
├─▶ provision: FIRE create, record provision.in_progress ─────────┐ (bg poll)
|
|
113
|
+
├─▶ content-model PREPARE: define entities, write copy, │
|
|
114
|
+
│ generate images │
|
|
115
|
+
├─▶ design: directions → design.md + logo (from the brief) │
|
|
116
|
+
└─▶ frontend SHELL: pick framework, scaffold, implement design.md │
|
|
117
|
+
│
|
|
118
|
+
══════════════════════ instance barrier: provision.status == completed ═════╪═════
|
|
119
|
+
▼
|
|
120
|
+
├─▶ content-model PUSH: send content/media via the connector (needs the instance)
|
|
121
|
+
└─▶ frontend DATA: wire fetch/bind against the backend API URL from site.json
|
|
122
|
+
│
|
|
123
|
+
▼
|
|
124
|
+
validate ──▶ deploy (needs the provisioned target) ──▶ done
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Nothing before the barrier touches the backend, so it's safe to run in any order the agent can manage
|
|
128
|
+
— sequentially if it can't interleave. Nothing after the barrier may start until provision is
|
|
129
|
+
verifiably `completed`. If provision **fails** at the barrier (quota, `422`, a changed free
|
|
130
|
+
subdomain), the prepare artifacts (drafted content, generated images, the `src/` shell) stay valid —
|
|
131
|
+
only the commit phases wait or retry; re-run provision, then cross the barrier.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## State and artifacts
|
|
136
|
+
|
|
137
|
+
Everything for a domain — its state **and** its generated source — lives under the **site workspace
|
|
138
|
+
`~/.hostinger/<domain>/`** (resolve `~` to the home directory: `$HOME` in a shell, `os.homedir()` in
|
|
139
|
+
Node — `~/.hostinger` means `$HOME/.hostinger`). This is a **global, per-user** location, not a
|
|
140
|
+
project folder, so a build is discoverable and resumable from **any** directory — the current working
|
|
141
|
+
directory does not matter. Create the workspace if it's missing and do all of a stage's work inside
|
|
142
|
+
it (including the frontend `src/`, built and deployed from `~/.hostinger/<domain>/src/`).
|
|
143
|
+
|
|
144
|
+
**The directory name is the domain**, so the files inside it never repeat it, and `~/.hostinger/`
|
|
145
|
+
holds every site you've built — one subdirectory per domain, no collisions.
|
|
146
|
+
|
|
147
|
+
| File (under `~/.hostinger/<domain>/`) | Written by | Contains |
|
|
148
|
+
|---|---|---|
|
|
149
|
+
| `state.json` | every stage | tool, next stage, Hostinger connector version, timestamps |
|
|
150
|
+
| `connect.json` | connect | tool, account/plan readiness |
|
|
151
|
+
| `brief.md` | refine | refined brief, audience, tone, pages, must-haves |
|
|
152
|
+
| `site.json` | provision | chosen backend, username, install id, all URLs |
|
|
153
|
+
| `content-model.md` | content model | entities, fields, pages, navigation |
|
|
154
|
+
| `design.md` (+ `brand/` logo files) | design | chosen design direction: tokens, type, logo, components, per-page composition, accessibility |
|
|
155
|
+
| `src/` | frontend | the website source implementing `design.md`; framework choice is recorded in `state.json → frontend` |
|
|
156
|
+
| `deploy.json` | deploy | build id, deployed at, live URLs |
|
|
157
|
+
| `events.jsonl` | every stage, via `run-log.mjs` | append-only log of issues, user feedback, skill gaps and wins |
|
|
158
|
+
| `reports/<run>.json` + `.html`, `report.html` | done (or any early stop), via `run-log.mjs` | the build report for each run; `report.html` is the latest |
|
|
159
|
+
|
|
160
|
+
`state.json` is the minimum you must keep current. **`stage` is the *next* stage to run** (not the
|
|
161
|
+
last completed one), and it does **not** store the domain — the directory is the key. Because
|
|
162
|
+
provision runs in the background, its status lives in its own `provision` field rather than in
|
|
163
|
+
`stage`, so prepare work can advance `stage` while provision is still settling:
|
|
164
|
+
|
|
165
|
+
```json
|
|
166
|
+
{
|
|
167
|
+
"tool": "claude-code",
|
|
168
|
+
"stage": "content_model",
|
|
169
|
+
"provision": {
|
|
170
|
+
"status": "in_progress",
|
|
171
|
+
"domain": "example.com",
|
|
172
|
+
"started_at": "2026-10-08T10:00:00Z"
|
|
173
|
+
},
|
|
174
|
+
"updated_at": "2026-10-08T10:00:00Z"
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
- `provision` is **absent** until provision fires, `{"status":"in_progress", …}` while the
|
|
179
|
+
background poll runs, and `{"status":"completed", …}` once `hosting_websites_list-setups` confirms
|
|
180
|
+
it. `domain` is the poll target.
|
|
181
|
+
- Any **instance-barrier** step (content-model push, frontend data, deploy) must read
|
|
182
|
+
`provision.status == "completed"` — and re-verify it against the connector — before it runs. A
|
|
183
|
+
prepare step ignores `provision` entirely.
|
|
184
|
+
- On **resume**, `provision.status` is a hint only: re-poll `hosting_websites_list-setups` to learn
|
|
185
|
+
the truth, then update the field.
|
|
186
|
+
- `run` (the current run), `history` (one entry per stage or phase, with real start and end
|
|
187
|
+
times), and `reports_sent` / `reports_rejected` (which copy of each report reached Hostinger) are
|
|
188
|
+
written **only** by `run-log.mjs`. Leave them alone when you update `state.json` by hand.
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Run log and build report
|
|
193
|
+
|
|
194
|
+
`run-log.mjs` (next to this file) records the run while it happens and turns it into a report at the
|
|
195
|
+
end. Timestamps come from the script, so they're measured, not remembered. It needs only Node.
|
|
196
|
+
Every command is `node <skill>/run-log.mjs <domain> …`, where `<skill>` is the folder this file is
|
|
197
|
+
in. Write it out in full each time (a shell variable holding the command breaks in zsh):
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
node <skill>/run-log.mjs <domain> run-start --tool <tool> --model <model> --skill <skill version> # check-state, first thing
|
|
201
|
+
node <skill>/run-log.mjs <domain> run-update --kind resume # check-state, once the route is agreed (or redesign / iterate)
|
|
202
|
+
node <skill>/run-log.mjs <domain> stage-start frontend # before a stage
|
|
203
|
+
node <skill>/run-log.mjs <domain> stage-end frontend ok_after_retries --note "second framework tried"
|
|
204
|
+
node <skill>/run-log.mjs <domain> stage-start frontend --phase shell # split stages log each phase
|
|
205
|
+
node <skill>/run-log.mjs <domain> event issue '{"stage":"content_model","symptom":"…","cause":"…","workaround":"…","severity":"medium","resolved":true}'
|
|
206
|
+
node <skill>/run-log.mjs <domain> report --outcome live # done, or wherever the run stops
|
|
207
|
+
node <skill>/run-log.mjs <domain> report-sent <run> # after the report was sent (see below)
|
|
208
|
+
node <skill>/run-log.mjs <domain> report-rejected <run> # the send returned 422
|
|
209
|
+
node <skill>/run-log.mjs <domain> unsent # check-state: reports still to send
|
|
210
|
+
node <skill>/run-log.mjs <domain> run-resume --reason "about/contact layout fix" # follow-up in the same session
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
**Follow-ups continue the run.** When the user asks for a change after the final report in the
|
|
214
|
+
same session (a layout fix, a copy tweak, a redeploy), that work belongs to the run it follows:
|
|
215
|
+
call `run-resume`, log the feedback and the stages it re-runs as usual, then `report` again. That
|
|
216
|
+
rewrites the same `reports/<run>.json` and `.html`, so you get one report that includes the follow-up,
|
|
217
|
+
not a second report that replaces `report.html`. Use `run-start` only in a new session; check-state
|
|
218
|
+
does that.
|
|
219
|
+
|
|
220
|
+
`stage-end` results: `ok`, `ok_after_retries`, `ok_with_fixups`, `failed`, `skipped`, `stopped`.
|
|
221
|
+
Stages: `check_state`, `refine`, `provision`, `content_model`, `design`, `frontend`, `validate`,
|
|
222
|
+
`deploy`, `done` (connect has its own `connect.json`). Split stages use `--phase`: provision `fire` /
|
|
223
|
+
`join`, content model `prepare` / `push`, frontend `shell` / `data`.
|
|
224
|
+
|
|
225
|
+
**Forgot a `stage-start`?** Log it as soon as you notice, with roughly when the stage began:
|
|
226
|
+
`stage-start frontend --started-ago 6m` (or `--started-at <ISO time>`). The same flags work on a
|
|
227
|
+
`stage-end` that has no start. With neither, the script assumes the stage began when the previous one
|
|
228
|
+
ended. Either way the start is marked as estimated in the report. Never log a start and an end
|
|
229
|
+
back to back after the work is done: that records a stage that took no time. If you already did,
|
|
230
|
+
correct it with `stage-fix frontend --started-ago 6m`.
|
|
231
|
+
|
|
232
|
+
**Log an event the moment it happens**, not at the end — details are gone by then:
|
|
233
|
+
|
|
234
|
+
| Event | Log it when | Fields (required in bold) |
|
|
235
|
+
|---|---|---|
|
|
236
|
+
| `issue` | something fails, misbehaves, or needs a workaround — including your own mistakes | **stage**, **symptom**, cause, workaround, severity (`high`/`medium`/`low`), resolved, user_had_to_intervene |
|
|
237
|
+
| `feedback` | the user corrects you, rejects something, or changes scope | **stage**, **category** (e.g. `design_rejected`, `layout_bug`, `scope_add`, `wrong_assumption`), **paraphrase** |
|
|
238
|
+
| `skill_gap` | a step is dummy, missing, wrong or silent on what you needed | **skill** (path), **gap** |
|
|
239
|
+
| `good` | something worked notably well or fast | **text** |
|
|
240
|
+
|
|
241
|
+
Paraphrase the user; don't paste long quotes, file contents, credentials or personal data. Set
|
|
242
|
+
`user_had_to_intervene` when the user had to point the problem out.
|
|
40
243
|
|
|
41
|
-
|
|
244
|
+
**Tokens** go on `report --tokens '<json>'` only if your tool tells you your own usage directly
|
|
245
|
+
(`{"source":"…","requests":…,"input":…,"output":…,"cache_read":…,"cache_write":…,"est_cost_usd":…}`).
|
|
246
|
+
Otherwise leave it out and the report says `{"source":"not reported"}` (not null: the connector rejects a null `tokens`). Never read session transcripts or log
|
|
247
|
+
files to get it.
|
|
42
248
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
| Store: seed the backend + the frontend API contract | `references/STORE.md` |
|
|
47
|
-
| WordPress: headless CMS/blog backend + the frontend read contract | `references/WORDPRESS.md` |
|
|
48
|
-
| Deploy: static vs Node.js, archive rules, logs, verify | `references/DEPLOYMENT.md` |
|
|
49
|
-
| Database + runtime: MySQL host per runtime, env vars, what to poll, runtime logs | `references/DATABASE.md` |
|
|
249
|
+
The report is saved to `reports/<run>.json` and `.html`, and `report.html` in the workspace is the
|
|
250
|
+
latest. If a run never reaches its report (the window closed), the next `run-start` closes it as
|
|
251
|
+
`abandoned`, so its log still becomes a report.
|
|
50
252
|
|
|
51
|
-
|
|
253
|
+
**Send every report to Hostinger.** Sending is part of the flow, so don't ask first; tell the user in
|
|
254
|
+
one line right after the send (see `09-done`). Right after each
|
|
255
|
+
`report` (follow-ups included), read `reports/<run>.json` and pass its contents, unchanged, as the
|
|
256
|
+
arguments of the Hostinger connector tool `hosting_headless_submit-build-report`. Then record the
|
|
257
|
+
result:
|
|
52
258
|
|
|
53
|
-
|
|
259
|
+
- **Success:** `report-sent <run>`.
|
|
260
|
+
- **422** (the report doesn't match the schema the endpoint holds): `report-rejected <run>`. Don't
|
|
261
|
+
resend it.
|
|
262
|
+
- **Anything else** (network error, 5xx, the tool isn't in your connector): do nothing. The next
|
|
263
|
+
check-state sends it again.
|
|
54
264
|
|
|
55
|
-
|
|
56
|
-
|
|
265
|
+
Never edit the JSON before sending, never add account details (the connector's login identifies the
|
|
266
|
+
account), and never let a failed send block, delay or change the run. Check-state sends any
|
|
267
|
+
reports still unsent (abandoned runs, earlier failures) with `unsent`.
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hostinger-headless-connect
|
|
3
|
+
description: "Connect step for the Hostinger Headless flow — verify Node, run the bootstrap (reach the Hostinger MCP server + OAuth sign-in), then route to the matching coding-tool skill under tools/ so MCP tools and skills are available before the build steps run. Triggers: connect to Hostinger, set up the Hostinger connector, start a headless build."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Hostinger Headless Skill — connect
|
|
7
|
+
|
|
8
|
+
You are a coding agent, and this is a skill for you to execute. Follow the phases below in order.
|
|
9
|
+
|
|
10
|
+
This skill goal is to help you to connect to Hostinger via MCP. That can be done via Hostinger Connector or adding the MCP via MCP Server.
|
|
11
|
+
|
|
12
|
+
We support different coding Agentic coding tools such as Claude Code, Codex, Cursor, VS Code...and so on.
|
|
13
|
+
|
|
14
|
+
Your goal is to route those tools to their specific skill inside the tools folder ensuring the tool is fully connected.
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## Phase 0 — Node (the single one prerequisite)
|
|
18
|
+
|
|
19
|
+
The Hostinger MCP server requires Node ≥ 20. Check it:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
node -v
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
If that errors (Node not installed) or prints a version below 20, install or upgrade Node and re-check — do not try to work around it:
|
|
26
|
+
|
|
27
|
+
- macOS: `brew install node` (or `nvm install 22 && nvm use 22`)
|
|
28
|
+
- Linux: `nvm install 22 && nvm use 22` (or your distro's Node 20+ package)
|
|
29
|
+
- Windows: `winget install OpenJS.NodeJS.LTS` (or download from nodejs.org)
|
|
30
|
+
|
|
31
|
+
## Phase 1 — Run the bootstrap (deterministic)
|
|
32
|
+
|
|
33
|
+
Download the bootstrap script, then run it. It verifies the MCP server and handles sign-in, emitting one JSON event per line on stdout. Run it as a background/streaming process and relay its events to the user.
|
|
34
|
+
|
|
35
|
+
The script is safe and inspectable: it only checks the MCP server via `npx` and drives the OAuth sign-in (a browser flow with a localhost callback) — no other network calls, no filesystem writes. Read it first if your sandbox flags externally-downloaded code.
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# macOS/Linux:
|
|
39
|
+
curl -fsSL -O https://raw.githubusercontent.com/hostinger/api-mcp-server/main/skills/headless/connect/bootstrap.mjs
|
|
40
|
+
# Windows PowerShell:
|
|
41
|
+
iwr https://raw.githubusercontent.com/hostinger/api-mcp-server/main/skills/headless/connect/bootstrap.mjs -OutFile bootstrap.mjs
|
|
42
|
+
|
|
43
|
+
node bootstrap.mjs
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Relay these events
|
|
47
|
+
|
|
48
|
+
The script emits one JSON object per line:
|
|
49
|
+
|
|
50
|
+
| Event | What to do |
|
|
51
|
+
| --- |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
52
|
+
| `mcp_ok` | MCP server reachable — continue. |
|
|
53
|
+
| `logged_in` | Already authenticated (env token or a previous sign-in) — continue. |
|
|
54
|
+
| `awaiting_user` (`verificationUri`) | A browser window should have opened on the user's machine. Show the URL in plain prose and wait for the user to finish signing in. The OAuth callback lands on a localhost port, so the sign-in must be completed on this same machine. |
|
|
55
|
+
| `success` | Bootstrap done — continue to Phase 2. |
|
|
56
|
+
| `mcp_unreachable` / `login_failed` (with `detail`) | Stop and show the user the `detail`. Do not improvise a parallel setup by hand. |
|
|
57
|
+
|
|
58
|
+
If the environment has a `HOSTINGER_API_TOKEN` set (for example CI), the bootstrap reports `logged_in` immediately — no browser needed.
|
|
59
|
+
|
|
60
|
+
### Sign in or out manually
|
|
61
|
+
|
|
62
|
+
The bootstrap runs the sign-in for you. To run it directly, or to switch accounts, use the MCP's own commands. `--login` opens the browser to the Hostinger sign-in page, waits for the localhost callback, stores the credentials and exits. `--logout` revokes the stored credentials, so the next sign-in opens the browser again.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# With a global install (npm install -g @hostinger/mcp):
|
|
66
|
+
hostinger-api-mcp --login
|
|
67
|
+
hostinger-api-mcp --logout
|
|
68
|
+
|
|
69
|
+
# Without a global install:
|
|
70
|
+
npx --yes --package=@hostinger/mcp@latest hostinger-api-mcp --login
|
|
71
|
+
npx --yes --package=@hostinger/mcp@latest hostinger-api-mcp --logout
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
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 in stdio mode; `--http` needs `HOSTINGER_API_TOKEN`.
|
|
75
|
+
|
|
76
|
+
## Phase 2 - Route to the specific tool instructions
|
|
77
|
+
|
|
78
|
+
| Tool | Route |
|
|
79
|
+
|-------------|---------------------------------|
|
|
80
|
+
| Claude Code | `connect/tools/claude-code.md` |
|
|
81
|
+
| Codex | `connect/tools/codex.md` |
|
|
82
|
+
| Cursor | `connect/tools/cursor.md` |
|
|
83
|
+
| VS Code | `connect/tools/vscode.md` |
|
|
84
|
+
| Antigravity | `connect/tools/antigravity.md` |
|
|
85
|
+
| Devin | `connect/tools/devin.md` |
|
|
86
|
+
|
|
87
|
+
If the user's tool isn't listed yet, connect it the generic way (register the Hostinger MCP server
|
|
88
|
+
for that tool, or drive `npx --yes --package=@hostinger/mcp@latest hostinger-api-mcp` over stdio) and continue.
|
|
89
|
+
|
|
90
|
+
## Phase 3 - Continue to Headless Hosting steps
|
|
91
|
+
|
|
92
|
+
After evrything is verified then you can go back to `headless/SKILL.md` and follow the steps section to start the process.
|
|
93
|
+
|
|
94
|
+
> **Backend-specific MCP groups.** The base connector covers hosting + WordPress. An **Ecommerce** build
|
|
95
|
+
> also needs the separate **`hostinger-ecommerce`** MCP group (`ecommerce_*` ops) — it is not loaded by
|
|
96
|
+
> default. The provision step adds it when the brief chooses Ecommerce (see
|
|
97
|
+
> `steps/03-provision/ecommerce/SKILL.md`); adding an MCP server needs a session restart/reconnect to
|
|
98
|
+
> take effect.
|
|
99
|
+
|
|
100
|
+
## Reference Sources
|
|
101
|
+
|
|
102
|
+
- https://mcpservers.org/servers/hostinger/api-mcp-server
|
|
103
|
+
- https://www.hostinger.com/connector
|
|
@@ -21,10 +21,15 @@ const fail = (event, extra = {}) => {
|
|
|
21
21
|
const isWin = process.platform === 'win32';
|
|
22
22
|
const bin = (name) => (isWin ? `${name}.cmd` : name);
|
|
23
23
|
// Run the MCP via npx — no global install, always the latest published version.
|
|
24
|
-
|
|
24
|
+
// Use --package so npx resolves the published package, then invoke the unified binary.
|
|
25
|
+
const MCP = [bin('npx'), '-y', '--package=@hostinger/mcp@latest', 'hostinger-api-mcp'];
|
|
26
|
+
// Node >= 18.20.2 / 20.12.2 refuses to spawn a .cmd/.bat without a shell
|
|
27
|
+
// (CVE-2024-27980), so npx.cmd needs shell:true on Windows. Our args are all
|
|
28
|
+
// fixed literals, so enabling the shell introduces no injection risk.
|
|
29
|
+
const spawnShell = isWin;
|
|
25
30
|
|
|
26
31
|
function capture(cmd, args) {
|
|
27
|
-
const r = spawnSync(cmd, args, { encoding: 'utf8', shell:
|
|
32
|
+
const r = spawnSync(cmd, args, { encoding: 'utf8', shell: spawnShell });
|
|
28
33
|
return { status: r.status ?? 1, out: `${r.stdout || ''}${r.stderr || ''}`, error: r.error };
|
|
29
34
|
}
|
|
30
35
|
|
|
@@ -67,7 +72,7 @@ function existingAuth() {
|
|
|
67
72
|
// prefix — forward it so the agent can show it if the browser didn't open.
|
|
68
73
|
function login() {
|
|
69
74
|
return new Promise((resolve) => {
|
|
70
|
-
const child = spawn(MCP[0], [...MCP.slice(1), '--login'], { shell:
|
|
75
|
+
const child = spawn(MCP[0], [...MCP.slice(1), '--login'], { shell: spawnShell });
|
|
71
76
|
let diag = '';
|
|
72
77
|
let urlSent = false;
|
|
73
78
|
const collect = (chunk) => {
|