@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.
Files changed (72) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +59 -3
  3. package/gemini-extension.json +1 -1
  4. package/package.json +1 -1
  5. package/server.json +2 -2
  6. package/skills/headless/SKILL.md +247 -36
  7. package/skills/headless/connect/SKILL.md +103 -0
  8. package/skills/headless/{entry → connect}/bootstrap.mjs +8 -3
  9. package/skills/headless/connect/tools/antigravity.md +54 -0
  10. package/skills/headless/connect/tools/claude-code.md +46 -0
  11. package/skills/headless/connect/tools/codex.md +48 -0
  12. package/skills/headless/connect/tools/cursor.md +109 -0
  13. package/skills/headless/connect/tools/devin.md +50 -0
  14. package/skills/headless/connect/tools/vscode.md +57 -0
  15. package/skills/headless/report.schema.json +149 -0
  16. package/skills/headless/run-log.mjs +662 -0
  17. package/skills/headless/steps/01-check-state/SKILL.md +193 -0
  18. package/skills/headless/steps/02-refine/SKILL.md +206 -0
  19. package/skills/headless/steps/03-provision/SKILL.md +62 -0
  20. package/skills/headless/steps/03-provision/ecommerce/SKILL.md +133 -0
  21. package/skills/headless/steps/03-provision/webapp/SKILL.md +154 -0
  22. package/skills/headless/steps/03-provision/wordpress/SKILL.md +100 -0
  23. package/skills/headless/steps/04-content-model/SKILL.md +150 -0
  24. package/skills/headless/steps/04-content-model/ecommerce/SKILL.md +75 -0
  25. package/skills/headless/steps/04-content-model/wordpress/SKILL.md +178 -0
  26. package/skills/headless/steps/05-design/SKILL.md +455 -0
  27. package/skills/headless/steps/05-design/logo-kit.mjs +201 -0
  28. package/skills/headless/steps/06-frontend/SKILL.md +131 -0
  29. package/skills/headless/steps/07-validate/SKILL.md +53 -0
  30. package/skills/headless/steps/08-deploy/SKILL.md +171 -0
  31. package/skills/headless/steps/09-done/SKILL.md +151 -0
  32. package/src/core/runtime.js +1 -1
  33. package/src/core/runtime.ts +1 -1
  34. package/src/core/skills.js +164 -24
  35. package/src/core/skills.ts +164 -24
  36. package/src/core/tools/all.js +142 -1
  37. package/src/core/tools/all.ts +142 -1
  38. package/src/core/tools/hosting.js +142 -1
  39. package/src/core/tools/hosting.ts +142 -1
  40. package/src/servers/agency-hosting.js +1 -1
  41. package/src/servers/agency-hosting.ts +1 -1
  42. package/src/servers/agent-readiness.js +1 -1
  43. package/src/servers/agent-readiness.ts +1 -1
  44. package/src/servers/all.js +1 -1
  45. package/src/servers/all.ts +1 -1
  46. package/src/servers/billing.js +1 -1
  47. package/src/servers/billing.ts +1 -1
  48. package/src/servers/dns.js +1 -1
  49. package/src/servers/dns.ts +1 -1
  50. package/src/servers/domains.js +1 -1
  51. package/src/servers/domains.ts +1 -1
  52. package/src/servers/ecommerce.js +1 -1
  53. package/src/servers/ecommerce.ts +1 -1
  54. package/src/servers/horizons.js +1 -1
  55. package/src/servers/horizons.ts +1 -1
  56. package/src/servers/hosting.js +1 -1
  57. package/src/servers/hosting.ts +1 -1
  58. package/src/servers/mail.js +1 -1
  59. package/src/servers/mail.ts +1 -1
  60. package/src/servers/reach.js +1 -1
  61. package/src/servers/reach.ts +1 -1
  62. package/src/servers/vps.js +1 -1
  63. package/src/servers/vps.ts +1 -1
  64. package/src/servers/wordpress.js +1 -1
  65. package/src/servers/wordpress.ts +1 -1
  66. package/types.d.ts +97 -1
  67. package/skills/headless/entry/skill.md +0 -79
  68. package/skills/headless/references/DATABASE.md +0 -49
  69. package/skills/headless/references/DEPLOYMENT.md +0 -34
  70. package/skills/headless/references/SETUP.md +0 -35
  71. package/skills/headless/references/STORE.md +0 -52
  72. 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 (399 total)
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` — 62 operations for hosting
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. For a WordPress
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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hostinger-api-mcp",
3
- "version": "3.2.1",
3
+ "version": "3.3.0",
4
4
  "description": "Hostinger API — manage domains, DNS, hosting, VPS, billing and more from Gemini CLI.",
5
5
  "mcpServers": {
6
6
  "hostinger": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hostinger/mcp",
3
- "version": "3.2.1",
3
+ "version": "3.3.0",
4
4
  "mcpName": "io.github.hostinger/hostinger-api-mcp",
5
5
  "description": "MCP server for Hostinger API",
6
6
  "repository": {
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.2.1",
9
+ "version": "3.3.0",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "@hostinger/mcp",
14
- "version": "3.2.1",
14
+ "version": "3.3.0",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  },
@@ -1,56 +1,267 @@
1
1
  ---
2
2
  name: hostinger-headless
3
- description: "Build, connect, or iterate on a website hosted on Hostinger — provision hosting and a domain, optionally seed an ecommerce store with a real hosted checkout or a WordPress content backend (headless CMS/blog), build the frontend, deploy, and verify. Requires an authenticated Hostinger MCP session (see entry/skill.md). Triggers: build me a site on Hostinger, deploy this to Hostinger, connect this project to Hostinger, add a store to my Hostinger site, add a blog to my Hostinger site, update my Hostinger site."
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
- This skill turns a prompt into a live website on Hostinger. Its job is to own the full run: check the account, provision hosting and a domain, seed the backend (an ecommerce store when the intent calls for selling), build the frontend, deploy it, and verify the result.
8
+ ## Context
9
9
 
10
- The frontend is built ad-hoc to the user's intent — there is no template library. The backend pieces are real Hostinger products: web hosting (static or Node.js), domains and DNS, Hostinger Ecommerce with its public Storefront API and hosted checkout, and WordPress as a headless CMS/blog backend read through the public WP REST API.
10
+ You are an AI coding agent. The user pasted a short prompt that points you here — something like:
11
11
 
12
- ## Preconditions
12
+ > Build a Headless site for `example.com` using hostinger.com/ai/skill.md
13
13
 
14
- 1. An authenticated Hostinger MCP session — the entry skill's bootstrap handled this. If MCP tools fail with auth errors, send the user back through `entry/skill.md`.
15
- 2. The Hostinger MCP operations for **hosting** (plus **ecommerce** when the run involves a store, and **wordpress** when it involves a content backend). Operation availability varies per user — product groups can be toggled in the Hostinger Connector. When search cannot find a needed operation, ask the user to enable that product group (or configure the scoped binary, e.g. `hostinger-hosting-mcp`) rather than improvising around it.
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
- ## Resolving the operation
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
- Resolve by intent first, disk second — never let an empty directory override what the user is asking for. Check `iterate` first (it's decided by an unambiguous on-disk signal):
20
+ ### The domain parameter
21
21
 
22
- - `iterate` — a `.hostinger/site.json` is present in the project: the site is already deployed through this skill and the user wants changes. Reuse the recorded domain/site details; apply only the delta the new intent needs (edit frontend → redeploy; add a store → run `references/STORE.md` then redeploy). Never re-provision an existing site.
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
- If signals conflict, ask the user — don't guess.
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
- ## The run
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
- 1. **Discovery** — from the prompt (and the project on disk for connect/iterate), infer: does this run need a store (any buy/sell/product intent → yes)? Does it need owner-managed content — a blog, news, or anything the owner edits without a redeploy (→ WordPress backend; static copy that rarely changes does not qualify)? What brand, copy, and structure does the site need? What stack fits — plain static HTML/CSS/JS for simple sites (default), a static-output framework build, or a Node.js app when SSR or server code is genuinely required? Prefer static: it deploys fastest and has no build-failure surface. Ask the user only what you cannot infer.
31
- 2. **Setup** (`references/SETUP.md`) — plan check, then provision the website on a free subdomain (or the user's own domain) and wait until it's ready.
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
- Run non-interactively wherever possible. The exceptions that must involve the user: the paid-plan confirmation, anything that costs money (a domain purchase, a new subscription), and picking between genuinely equal options the prompt doesn't decide.
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
- ## Paths
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
- | What | Path |
44
- | --- | --- |
45
- | Plan check + website/domain provisioning | `references/SETUP.md` |
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
- ## Where the how comes from
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
- The inputSchema returned by search is authoritative for request shapes — read it before calling. Two live sources supersede anything written here when they disagree:
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
- - The ecommerce operation `ecommerce_miscellaneous_custom-storefront-setup-instructions` returns the current storefront integration guide from the server — execute it at the start of any store run.
56
- - The Hostinger API reference at https://developers.hostinger.com describes every endpoint behind the operations.
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
- const MCP = [bin('npx'), '-y', '@hostinger/mcp@latest'];
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: false });
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: false });
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) => {