hostinger-api-mcp 3.13.0 → 3.14.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.
Files changed (42) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +25 -3
  3. package/gemini-extension.json +1 -1
  4. package/package.json +1 -1
  5. package/server.json +2 -2
  6. package/skills/headless/steps/02-refine/SKILL.md +60 -32
  7. package/skills/headless/steps/03-provision/webapp/SKILL.md +2 -0
  8. package/src/core/runtime.js +1 -1
  9. package/src/core/runtime.ts +1 -1
  10. package/src/core/skills.js +6 -6
  11. package/src/core/skills.ts +6 -6
  12. package/src/core/tools/all.js +37 -2
  13. package/src/core/tools/all.ts +37 -2
  14. package/src/core/tools/hosting.js +37 -2
  15. package/src/core/tools/hosting.ts +37 -2
  16. package/src/servers/agency-hosting.js +1 -1
  17. package/src/servers/agency-hosting.ts +1 -1
  18. package/src/servers/agent-readiness.js +1 -1
  19. package/src/servers/agent-readiness.ts +1 -1
  20. package/src/servers/all.js +1 -1
  21. package/src/servers/all.ts +1 -1
  22. package/src/servers/billing.js +1 -1
  23. package/src/servers/billing.ts +1 -1
  24. package/src/servers/dns.js +1 -1
  25. package/src/servers/dns.ts +1 -1
  26. package/src/servers/domains.js +1 -1
  27. package/src/servers/domains.ts +1 -1
  28. package/src/servers/ecommerce.js +1 -1
  29. package/src/servers/ecommerce.ts +1 -1
  30. package/src/servers/horizons.js +1 -1
  31. package/src/servers/horizons.ts +1 -1
  32. package/src/servers/hosting.js +1 -1
  33. package/src/servers/hosting.ts +1 -1
  34. package/src/servers/mail.js +1 -1
  35. package/src/servers/mail.ts +1 -1
  36. package/src/servers/reach.js +1 -1
  37. package/src/servers/reach.ts +1 -1
  38. package/src/servers/vps.js +1 -1
  39. package/src/servers/vps.ts +1 -1
  40. package/src/servers/wordpress.js +1 -1
  41. package/src/servers/wordpress.ts +1 -1
  42. package/types.d.ts +33 -1
@@ -155,10 +155,10 @@ const skills: Skill[] = [
155
155
  },
156
156
  {
157
157
  "uri": "skill://hostinger-headless/steps/02-refine/SKILL.md",
158
- "digest": "sha256:e186715938d72ad7590ffb6b36ea3a48b1ea64c4f04fe667c3b2d027631e3ad8",
159
- "size": 18861,
158
+ "digest": "sha256:44e51eee7c03239b06eb73e83aa231d92069a96e519d5642145a774ad4dcda45",
159
+ "size": 20752,
160
160
  "mimeType": "text/markdown",
161
- "text": "---\nname: headless-step-refine\ndescription: \"Step 2 (refine) of the Hostinger Headless flow. Turns the user's seed — often just a domain — into a brief through conversation: asks what they want to build (purpose, audience, tone, pages, products, must-haves; images, local files, links all welcome), then *infers* the backend that fits (WordPress, Ecommerce, WordPress + Ecommerce, WordPress + WooCommerce for a one-site content+store, or Webapp for a custom app/SPA) — it never asks the user to pick a backend or a technology; the user confirms the plan in plain language, then it writes brief.md. Hostinger Ecommerce stays the default for selling; WooCommerce is chosen only when the user explicitly asks for it or wants content and a store on one WordPress site.\"\n---\n\n# headless-step-refine\n\nFind out what the user wants to build, guess which backend fits, and write it down. This is a\n**conversation, not a form**: the pasted prompt names a domain and nothing else, so everything about\nthe site comes from talking to the user.\n\n**Keep it short.** The only thing you must know is *what they are building* — enough to guess the\nbackend. Every other question is optional: the more the user gives, the better the site, but never\nhold the build hostage to refinement. Fill gaps with sensible defaults and say so in the brief. A\nskipped question tool is not the user passing on a question; see *When you ask the user* in the\ntop-level `SKILL.md`.\n\n> **Never ask the user to choose a backend or a technology.** Don't ask \"WordPress or Ecommerce?\",\n> don't present WordPress/Ecommerce/WooCommerce/Webapp as options, and don't surface the backend in a\n> multiple-choice UI. Open with **\"What do you want to build?\"** and infer the backend yourself in\n> Step 4 from what they describe (and whether they sell). The backend is a technical decision the flow\n> makes *for* the user — they confirm the **plan** (what the site is and does), not the plumbing. The\n> only exception is when the user *volunteers* a backend (\"build it on WordPress\", \"use WooCommerce\"):\n> then honour their choice and note it in the brief.\n\n**In:** the domain (the workspace directory name), plus anything the user already shared.\n**Out:** `~/.hostinger/<domain>/brief.md`.\n\nNothing in this step touches Hostinger. It only asks, decides and writes.\n\n---\n\n## Step 1 — Read the workspace, then the resume check\n\nRead everything already in `~/.hostinger/<domain>/` (`state.json`, `connect.json`, any notes, images\nor files the user dropped there) — it all counts as input.\n\nIf `brief.md` already exists for this domain, **don't overwrite it**. Show the user a three-line\nsummary (what the site is, its pages, the suggested backend) and ask: *keep it, or change\nsomething?* Keep → go to Step 6. Change → edit only what they asked for, then re-confirm (Step 5). A\nskipped tool result is not Keep; see *When you ask the user* in the top-level `SKILL.md`.\n\nIf the site is already provisioned (`site.json` exists), the backend is **fixed** — never change the\nSuggested backend on a provisioned site. Explain that switching backends means a new domain.\n\n## Step 2 — Gather what you already have\n\nBefore asking anything, collect what the user has already given you, so you don't ask for it again:\n\n- **Inspect the directory the command was run in** — this is the biggest signal for the build mode\n (Step 3). Look for an existing **frontend / webapp / commerce project**: a `package.json`, a\n framework config (`next.config.*`, `astro.config.*`, `vite.config.*`, `svelte.config.*`, `nuxt.*`),\n a `src/` or `app/` tree, `index.html`, a storefront/cart, etc. A real project here usually means the\n user **already has their own frontend** and mainly needs a Hostinger backend to wire it to — lean\n toward \"bring your own frontend\" in Step 3. If the folder has nothing site-like, assume they don't\n and lean toward \"agent builds it\".\n- Anything in the pasted prompt beyond the domain (a sentence, a link, a screenshot).\n- Files in the current project that look like site material (copy, logos, product lists, images).\n- What the agent already knows about the user from local memory or this conversation (a prior build,\n stack preferences, a frontend they always use).\n- The domain name itself — a hint only (`coral-pottery.com` suggests pottery), never a conclusion.\n\n## Step 3 — Ask\n\nIf Step 2 already answers *what are you building* and *will they sell*, skip the Round 1–3 questions\nbelow, but still ask **Build mode** before moving on.\n\nOtherwise open with one line and **wait for the user's answer**: *\"Tell me what you want to build — a\nsentence is enough. Links, screenshots or files help too. Skip anything you don't want to answer.\"*\n\n> **\"What do you want to build?\" is an OPEN question — ask it in plain prose and wait.** Never turn it\n> into a multiple-choice list of pre-baked site ideas (\"Coffee shop / Travel blog / Portfolio …\"):\n> that puts words in the user's mouth and defeats the point of asking. Let them describe it in their\n> own words. The structured question UI is only for genuinely *choice-shaped* follow-ups (selling\n> yes/no, which pages, tone adjectives, the build mode) — not for the opening question, and never for\n> the backend.\n\nAsk in **short rounds of 2–3 questions**, and adapt each round to the previous answers. If your tool\nhas a structured question UI (multiple choice with an \"other\" field), use it for the choice-shaped\nfollow-up questions (pages, selling yes/no, tone) — **never for the opening \"what do you want to\nbuild?\" and never for the backend** (that's your decision, not theirs). **At most 3 rounds**, and\nstop early as soon as you can guess the backend and the user seems done — \"just build it\" or \"you\ndecide\" means *use defaults*, not *ask again*. A skipped tool result is not their answer: re-ask\nthat round in plain text, as *When you ask the user* in the top-level `SKILL.md` says. The re-ask\nrepeats the round; it doesn't count toward the 3.\n\n**Round 1 — what it is (the only required round):**\n\n1. **What are you building?** The business or project, and what the site is for.\n2. **Will you sell anything on it?** Physical products, digital products, services with checkout —\n or nothing. *This decides the backend.* Skip it only when the answer is already unmistakable\n (\"an online shop for my candles\", \"my personal blog\"); when in doubt, ask.\n3. **Who is it for?** The audience, and how they'll find the site. *(optional)*\n\n**Round 2 — what goes on it (optional, adapt to Round 1):**\n\n- **Content they'll publish over time** — blog posts, articles, news, recipes, portfolio pieces,\n case studies? How often? Or is it a handful of pages that rarely change?\n- **Pages** — propose a page list from what you know and ask them to add or remove.\n- If they sell: **what and how many** — a rough product count, categories, whether products have\n variants (size, colour), and the shipping regions.\n\n**Round 3 — how it should feel (optional, skip what you already know):**\n\nThis is the round that captures **all design input** — the design step reads it from `brief.md` to derive\nthe design directions, so it is **not** asked again later; gather it here:\n\n- **Reference & look** — a **site they like (URL)** and what to take from it, plus a few adjectives for\n the vibe. Screenshots welcome.\n- **Colours & brand** — brand/accent colours, logo, fonts, existing copy, photos. Note where they live.\n- **Must-haves and no-gos** — contact form, newsletter, bookings, languages, things to avoid.\n\nIf the user asks for something outside the scope (user accounts, member areas, bookings with a\ncalendar backend, user-generated content), say plainly that the headless flow doesn't support it yet\nand record it under **Out of scope** — don't promise it.\n\n> **A contact form *is* supported (WordPress backends).** If the user wants one, keep it in\n> **Must-haves** and name it \"Contact form\". Provision installs **Contact Form 7** on `/cms` and the\n> frontend wires a contact page whose form emails the site owner through WordPress's built-in\n> `wp_mail()` — no third-party service and no API keys. It's **opt-in**: built only when the brief asks\n> for it. (A form that needs accounts, payments or a booking calendar is still out of scope — this is a\n> plain name/email/message enquiry form.)\n\n### Build mode — ask once (this one *is* a user choice)\n\nThe backend is your call, but **how the frontend gets built is the user's** — because most of the time\nthe user already has their own frontend and just needs a Hostinger backend to wire it to. After the\nfolder + memory inspection (Step 2), ask **one** question (a structured choice is ideal here), seeding\nthe default from what you found:\n\n- **Bring your own frontend** *(default when Step 2 found a real project in the folder)* — \"I already\n have a frontend / I'll drive the design and we vibe-code it together.\" The agent **uses the user's\n existing project in the current folder as the source**, collaborates on design/code at the user's\n direction, and wires it to the provisioned backend. There is **no agent-generated design** — the\n design step defers to the user (see the Build mode box at the top of the design step), and the frontend step builds on their project\n rather than scaffolding a new one.\n- **Agent designs and builds it** *(default when the folder has nothing site-like)* — \"Give me ideas\n — you design and code it.\" Today's flow: the design step proposes directions and the frontend step\n scaffolds and implements them.\n\nA skipped tool result is not a pick: re-ask in plain text, and use the seeded default only when the\nuser says so (see *When you ask the user* in the top-level `SKILL.md`).\n\nRecord the answer as the brief's **Build mode**. This is the one frontend/technology question you *do*\nput to the user; everything else about the stack (framework, SSR/SSG) is still inferred. The deliverable\nis the same either way — a working site on the backend; only *who drives the frontend* changes.\n\n## Step 4 — Decide the backend (your call, from the brief — not a question)\n\nFrom what the user described, **you** pick the backend that fits — this is an internal decision, never\na question put back to the user. Pick the backend that fits what the user told you:\n\n| Backend | Choose when | What it gives the owner |\n|---|---|---|\n| **WordPress** | No selling. The owner publishes and edits content: pages, blog, articles, portfolio. | Headless WordPress at `/cms` — write and edit content in wp-admin. |\n| **Ecommerce** | Selling is the point, and the rest is a few static pages (About, Contact, FAQ, policies). No ongoing blog. | Hostinger Ecommerce store — products, collections, checkout, payments, shipping, orders. |\n| **WordPress + Ecommerce** | Selling **and** regular editorial content (a blog, guides, lookbooks, recipes) the owner keeps adding to, run as **two** backends (WordPress site + separate Hostinger Ecommerce store). | Both: WordPress for content, the Ecommerce store for products and checkout. |\n| **WordPress + WooCommerce** | **Only** when the user explicitly names WooCommerce, or explicitly wants content **and** a store on **one** WordPress site (one admin, one domain). The one-site alternative to WordPress + Ecommerce. | A single headless WordPress at `/cms` with the WooCommerce plugin — products, cart, coupons and checkout (Cash on Delivery) over the WooCommerce Store API, plus WP posts/pages on the same site. |\n| **Webapp** | A custom **app, SPA or web application** that brings its own code and data — a dashboard, tool, calculator, booking app, a project the user is deploying — **not** a content site or a store. No CMS and no store engine. | A plain Node.js app host (an empty website, no `/cms`), with a MySQL database when the app needs one. The app owns all its routes and data. |\n\nRules of thumb:\n\n- **Is it an app, or a site?** A custom application the user builds/brings (its own logic, its own data,\n maybe a database) → **Webapp**. A content site or a shop → one of the three above. When the user says\n \"my app / SPA / dashboard / tool\", or hands you an existing app project to deploy, that's **Webapp**.\n- **Selling decides first (for sites).** No selling → WordPress. Selling → Ecommerce or\n WordPress + Ecommerce.\n- **Then the content.** Selling plus only a few fixed pages → Ecommerce. Selling plus content the\n owner will keep publishing → WordPress + Ecommerce.\n- **Hostinger Ecommerce is the default for selling — WooCommerce is never the default and is never\n recommended on its own.** Choose **WordPress + WooCommerce** only when the user explicitly names\n WooCommerce, or explicitly wants content **and** a store on one WordPress site (one admin, one\n domain — the one-site alternative to WordPress + Ecommerce). For every other selling case, keep\n Hostinger Ecommerce. If the user wants both content and a store but hasn't said \"one site\" or\n \"WooCommerce\", offer it as an option — don't switch to it silently.\n- **Don't add WordPress \"just in case\".** A second backend is a second admin to learn. Recommend the\n combination only when the user described ongoing content.\n- Selling a single service by enquiry (no checkout, no cart) is **not** commerce → WordPress with a\n contact page.\n- **Webapp never uses WordPress or a store.** If the user wants a custom app *and* a CMS/shop, that's two\n different sites — build the app as a Webapp and tell them the content/commerce backend is a separate\n domain.\n\n**Then set rendering** (write it in the brief's **Rendering** section): **Ecommerce → SSR required**\n(carts/search need per-request rendering — any SSR framework works; Next.js is the default, not a\nrequirement); **WordPress + WooCommerce → SSR required** (same reason — cart/checkout need per-request\nrendering); **WordPress → SSG (Astro)** if the site is mostly static and the owner is fine rebuilding\nto publish, otherwise **SSR**; **Webapp → whatever the app is** (SSR for a server app, SPA for a\nclient-only app) — it deploys as a Node.js app either way. When unsure, default to **Next.js SSR**.\n\n## Step 5 — Confirm the plan in one message\n\nSend **one** message that confirms **what you'll build** — the plan, not the plumbing. Lead with the\nsite, not the backend:\n\n- **The plan** — what it is, audience, pages, products (if any), tone. Mark anything you defaulted\n (*\"assumed: warm, minimal look\"*) so the user sees what they skipped.\n- **How it's built** — state the backend as a *consequence* in one plain line, focused on what it\n means for them day to day (\"I'll build this on WordPress, so you edit pages and posts in a normal\n WordPress admin\"), **not** as a choice you're asking them to make. Don't ask \"is WordPress OK?\" or\n offer alternatives unless it was a genuine close call *and* the difference matters to the user.\n\nEnd with *\"Good to go, or anything to change?\"* A yes (or \"go\") → write `brief.md`. A skipped tool\nresult is not a yes (see *When you ask the user* in the top-level `SKILL.md`). Changes → apply them\nand write it; don't loop back into questions. If the user *volunteers* a different backend, use\ntheirs and note it in the brief.\n\n## Step 6 — Write `brief.md` and hand off\n\nWrite `brief.md` from the template below. Fill every section from the conversation, defaulting what\nthe user skipped and tagging it `(assumed)`; leave out **Products** when nothing is sold. Use the\nuser's own words where you can. Then update `state.json`:\n`\"stage\": \"provision\"`, fresh `updated_at`.\n\nThe **Suggested backend** section is the contract with `03-provision/SKILL.md`, which routes on it.\nIts first line must be exactly one of `**WordPress**`, `**Ecommerce**`, `**WordPress + Ecommerce**`,\n`**WordPress + WooCommerce**` or `**Webapp**`, followed by an em dash and the one-line reason.\n`**WordPress + WooCommerce**` is the WordPress backend with the WooCommerce store turned on — provision\nroutes it to the `wordpress` subfolder with the store enabled (it is **not** a separate backend).\n\n## `brief.md` template\n\n```markdown\n# Brief — <domain>\n\n> Brief agreed with the user on <today>.\n\n## Purpose\n<what the site is, who runs it, what it's for — 2–3 sentences>\n\n## Audience\n<who visits, how they arrive, what device they mostly use>\n\n## Tone\n<voice in a sentence or two>\n\n## Design direction\n<look & feel in a few adjectives; **reference site(s)** the user named (URLs) and what to take from them\n(layout, structure, mood); colours / brand palette; any screenshots. This is where ALL design questions\nland — the frontend step reads this and does not re-ask. Write \"Agent's choice: <short style>\" when the\nuser didn't specify. Record in the user's own words a request to keep their current look (\"Keep the look\nwe have: <site URL | screenshots | brand guide>\") and any logo idea they describe; the design step acts\non both.>\n\n## Pages\n- **<Page>** — <one-line purpose>\n- …\n\n## Products\n<only when selling: what is sold, rough count, categories, variants, shipping regions, payments>\n\n## Content\n<what the owner will publish over time and how often — or \"A few fixed pages; no ongoing content.\">\n\n## Must-haves\n- …\n\n## Out of scope\n- …\n\n## Assets\n<logo, colours, photos, copy the user provided and where they are; \"None yet\" if none>\n\n## Suggested backend\n**<WordPress | Ecommerce | WordPress + Ecommerce | WordPress + WooCommerce | Webapp>** — <one-line reason>.\n<\"Confirmed by the user.\" or \"User chose this over the recommended <X> because <reason>.\">\n\n## Build mode\n**<Bring your own frontend | Agent designs and builds>** — <one line>. <When \"Bring your own frontend\":\nthe path to the user's existing project in the current folder (the frontend source), and how they want\nto drive design/code. When \"Agent designs and builds\": leave the design + frontend steps to run as\nnormal.> The design step and the frontend step both read this: **Bring your own frontend** → design\ndefers to the user and frontend builds on their project; **Agent designs and builds** → both run as normal.\n\n## Rendering\n**<SSR | SSG>** — <reason>. Rules: **Ecommerce requires SSR** and **WordPress + WooCommerce requires\nSSR** (carts/checkout need per-request rendering — any SSR framework works; Next.js is the default, not\na requirement); **WordPress may be SSG (Astro)** when the site is mostly static and rarely changes,\notherwise **SSR**. Default when unsure: **Next.js SSR**.\n```\n\n## Example — WordPress + Ecommerce\n\n> A ceramicist sells around 30 handmade pieces and writes a monthly studio journal.\n\n```markdown\n## Suggested backend\n**WordPress + Ecommerce** — sells ~30 products with checkout, and the owner publishes a monthly\nstudio journal they want to edit themselves.\nConfirmed by the user.\n```\n"
161
+ "text": "---\nname: headless-step-refine\ndescription: \"Step 2 (refine) of the Hostinger Headless flow. Turns the user's seed — often just a domain — into a brief through conversation: asks what they want to build (purpose, audience, tone, pages, products, must-haves; images, local files, links all welcome), then *infers* the backend that fits (WordPress, Ecommerce, WordPress + Ecommerce, WordPress + WooCommerce for a one-site content+store, or Webapp for a custom app/SPA) — it never asks the user to pick a backend or a technology; the user confirms the plan in plain language, then it writes brief.md. Hostinger Ecommerce stays the default for selling; WooCommerce is chosen only when the user explicitly asks for it or wants content and a store on one WordPress site.\"\n---\n\n# headless-step-refine\n\nFind out what the user wants to build, guess which backend fits, and write it down. This is a\n**conversation, not a form**: the pasted prompt names a domain and nothing else, so everything about\nthe site comes from talking to the user.\n\n**Keep it short.** You must know what they are building, whether they sell and whether they'll\npublish content over time — enough to guess the backend — plus, when Step 2 found a project in the folder, the\n**Existing project** confirms. Every other question is optional: the more the user gives, the better the site, but never\nhold the build hostage to refinement. Fill gaps with sensible defaults and say so in the brief. A\nskipped question tool is not the user passing on a question; see *When you ask the user* in the\ntop-level `SKILL.md`.\n\n> **Never ask the user to choose a backend or a technology.** Don't ask \"WordPress or Ecommerce?\",\n> don't present WordPress/Ecommerce/WooCommerce/Webapp as options, and don't surface the backend in a\n> multiple-choice UI. Open with **\"What do you want to build?\"** and infer the backend yourself in\n> Step 4 from what they describe (and whether they sell). The backend is a technical decision the flow\n> makes *for* the user — they confirm the **plan** (what the site is and does), not the plumbing. The\n> only exception is when the user *volunteers* a backend (\"build it on WordPress\", \"use WooCommerce\"):\n> then honour their choice and note it in the brief.\n\n**In:** the domain (the workspace directory name), plus anything the user already shared.\n**Out:** `~/.hostinger/<domain>/brief.md`.\n\nNothing in this step touches Hostinger. It only asks, decides and writes.\n\n---\n\n## Step 1 — Read the workspace, then the resume check\n\nRead everything already in `~/.hostinger/<domain>/` (`state.json`, `connect.json`, any notes, images\nor files the user dropped there) — it all counts as input.\n\nIf `brief.md` already exists for this domain, **don't overwrite it**. Show the user a three-line\nsummary (what the site is, its pages, the suggested backend) and ask: *keep it, or change\nsomething?* Keep → go to Step 6. Change → edit only what they asked for, then re-confirm (Step 5). A\nskipped tool result is not Keep; see *When you ask the user* in the top-level `SKILL.md`.\n\nIf the site is already provisioned (`site.json` exists), the backend is **fixed** — never change the\nSuggested backend on a provisioned site. Explain that switching backends means a new domain.\n\n## Step 2 — Gather what you already have\n\nBefore asking anything, collect what the user has already given you, so you don't ask for it again:\n\n- **Inspect the directory the command was run in** — this is the biggest signal for the build mode\n (Step 3). Look for an existing **frontend / webapp / commerce project**: a `package.json`, a\n framework config (`next.config.*`, `astro.config.*`, `vite.config.*`, `svelte.config.*`, `nuxt.*`),\n a `src/` or `app/` tree, `index.html`, a storefront/cart, etc. A real project here usually means the\n user **already has their own frontend** and mainly needs a Hostinger backend to wire it to — lean\n toward \"bring your own frontend\" in Step 3. That is what *Step 2 found a project in the folder*\n means everywhere below.\n- Anything in the pasted prompt beyond the domain (a sentence, a link, a screenshot).\n- Files in the current project that look like site material (copy, logos, product lists, images).\n- What the agent already knows about the user from local memory or this conversation (a prior build,\n stack preferences, a frontend they always use).\n- The domain name itself — a hint only (`coral-pottery.com` suggests pottery), never a conclusion.\n\n## Step 3 — Ask\n\nWhen Step 2 found a project in the folder, ask **Build mode** and the **Existing project** confirms\nbelow in your first message, after Round 1 when Round 1 still needs asking; they don't count toward\nthe 3 rounds, and code that answers Round 1 never skips them. Otherwise don't ask Build mode: it\ndefaults (see *Build mode* below).\n\nIf Step 2 already answers the three Round 1 questions, skip the Round 1–3 questions below. Otherwise\nopen with one line and **wait for the user's answer**: *\"Tell me what you want to build — a\nsentence is enough. Links, screenshots or files help too. Skip anything you don't want to answer.\"*\n\n> **\"What do you want to build?\" is an OPEN question — ask it in plain prose and wait.** Never turn it\n> into a multiple-choice list of pre-baked site ideas (\"Coffee shop / Travel blog / Portfolio …\"):\n> that puts words in the user's mouth and defeats the point of asking. Let them describe it in their\n> own words. The structured question UI is only for genuinely *choice-shaped* follow-ups (selling\n> yes/no, which pages, tone adjectives, the build mode) — not for the opening question, and never for\n> the backend.\n\nAsk in **short rounds of 2–3 questions**, and adapt each round to the previous answers. If your tool\nhas a structured question UI (multiple choice with an \"other\" field), use it for the choice-shaped\nfollow-up questions (pages, selling yes/no, tone) — **never for the opening \"what do you want to\nbuild?\" and never for the backend** (that's your decision, not theirs). **At most 3 rounds**, and\nstop early as soon as you can guess the backend and the user seems done — \"just build it\" or \"you\ndecide\" means *use defaults*, not *ask again*. A skipped tool result is not their answer: re-ask\nthat round in plain text, as *When you ask the user* in the top-level `SKILL.md` says. The re-ask\nrepeats the round; it doesn't count toward the 3.\n\n**Round 1 — what it is (required; these three decide the backend):**\n\n1. **What are you building?** The business or project, and what the site is for.\n2. **Will you sell anything on it?** Physical products, digital products, services with checkout —\n or nothing. Skip it only when the answer is already unmistakable (\"an online shop for my\n candles\", \"my personal blog\"); when in doubt, ask.\n3. **Will you publish content over time?** Blog posts, articles, news, recipes, portfolio pieces,\n case studies, and how often — or a handful of pages that rarely change. Skip it only when the\n answer is already unmistakable (\"my personal blog\", an app the user is deploying).\n\n**Round 2 — what goes on it (optional, adapt to Round 1):**\n\n- **Who is it for?** The audience, and how they'll find the site.\n- **Pages** — propose a page list from what you know and ask them to add or remove.\n- If they sell: **what and how many** — a rough product count, categories, whether products have\n variants (size, colour), and the shipping regions.\n\n**Round 3 — how it should feel (optional, skip what you already know):**\n\nThis is the round that captures **all design input** — the design step reads it from `brief.md` to derive\nthe design directions, so it is **not** asked again later; gather it here:\n\n- **Reference & look** — a **site they like (URL)** and what to take from it, plus a few adjectives for\n the vibe. Screenshots welcome.\n- **Colours & brand** — brand/accent colours, logo, fonts, existing copy, photos. Note where they live.\n- **Must-haves and no-gos** — contact form, newsletter, bookings, languages, things to avoid.\n\n**Existing project — when Step 2 found a project in the folder (required, in the Build mode message):**\n\nBuild mode answers the look. The code shows the rest, but the user knows what has to survive the\nmove, so ask each as a confirm of what you found, naming it, so the user only says yes or corrects you:\n\n1. **Routes that open directly** — the client-side routes you found (name them, e.g. `/stats`,\n `/settings`) must open from a typed link and survive a refresh? Ask only when the code routes in\n the browser (React Router, Vue Router, a history or hash router); a server-routed app has none.\n2. **Data** — the database and environment variable names you found (or \"none\"): is that all the\n app needs? Hostinger gives the app MySQL only: a different database (Postgres, MongoDB, a SQLite\n file) goes under **Out of scope** as a migration the user owns, not as `Database: MySQL`.\n\nRecord the routes and data in **Existing project**.\n\nIf the user asks for something outside the scope (user accounts, member areas, bookings with a\ncalendar backend, user-generated content), say plainly that the headless flow doesn't support it yet\nand record it under **Out of scope** — don't promise it.\n\n> **A contact form *is* supported (WordPress backends).** If the user wants one, keep it in\n> **Must-haves** and name it \"Contact form\". Provision installs **Contact Form 7** on `/cms` and the\n> frontend wires a contact page whose form emails the site owner through WordPress's built-in\n> `wp_mail()` — no third-party service and no API keys. It's **opt-in**: built only when the brief asks\n> for it. (A form that needs accounts, payments or a booking calendar is still out of scope — this is a\n> plain name/email/message enquiry form.)\n\n### Build mode — a user choice when the folder holds a project\n\nThe backend is your call, but **how the frontend gets built is the user's**. When Step 2 found a\nproject in the folder, ask **one** question (a structured choice is ideal here); it also settles the\napp's look:\n\n- **Bring your own frontend — keep my app's look** *(the default)* — the agent **uses the user's\n existing project in the current folder as the source**, collaborates on design/code at the user's\n direction, and wires it to the provisioned backend. There is **no agent-generated design** — the\n design step defers to the user (see the Build mode box at the top of the design step), and the\n frontend step builds on their project rather than scaffolding a new one. Write \"Keep the look we\n have: the app in this folder\" in **Design direction**.\n- **Agent designs and builds it — a new design** — the design step proposes directions and the\n frontend step scaffolds and implements them.\n\nA skipped tool result is not a pick: re-ask in plain text, and use the default only when the user\nsays so (see *When you ask the user* in the top-level `SKILL.md`).\n\nOtherwise don't ask: Build mode is **Agent designs and builds**. When the user says they have their\nown code elsewhere, ask for its path, inspect it as in Step 2, and from then on treat it as a project\nfound in the folder.\n\nRecord the answer as the brief's **Build mode**. This is the one frontend/technology question you *do*\nput to the user; everything else about the stack (framework, SSR/SSG) is still inferred. The deliverable\nis the same either way — a working site on the backend; only *who drives the frontend* changes.\n\n## Step 4 — Decide the backend (your call, from the brief — not a question)\n\nFrom what the user described, **you** pick the backend that fits — this is an internal decision, never\na question put back to the user. Pick the backend that fits what the user told you:\n\n| Backend | Choose when | What it gives the owner |\n|---|---|---|\n| **WordPress** | No selling. The owner publishes and edits content: pages, blog, articles, portfolio. | Headless WordPress at `/cms` — write and edit content in wp-admin. |\n| **Ecommerce** | Selling is the point, and the rest is a few static pages (About, Contact, FAQ, policies). No ongoing blog. | Hostinger Ecommerce store — products, collections, checkout, payments, shipping, orders. |\n| **WordPress + Ecommerce** | Selling **and** regular editorial content (a blog, guides, lookbooks, recipes) the owner keeps adding to, run as **two** backends (WordPress site + separate Hostinger Ecommerce store). | Both: WordPress for content, the Ecommerce store for products and checkout. |\n| **WordPress + WooCommerce** | **Only** when the user explicitly names WooCommerce, or explicitly wants content **and** a store on **one** WordPress site (one admin, one domain). The one-site alternative to WordPress + Ecommerce. | A single headless WordPress at `/cms` with the WooCommerce plugin — products, cart, coupons and checkout (Cash on Delivery) over the WooCommerce Store API, plus WP posts/pages on the same site. |\n| **Webapp** | A custom **app, SPA or web application** that brings its own code and data — a dashboard, tool, calculator, booking app, a project the user is deploying — **not** a content site or a store. No CMS and no store engine. | A plain Node.js app host (an empty website, no `/cms`), with a MySQL database when the app needs one. The app owns all its routes and data. |\n\nRules of thumb:\n\n- **Is it an app, or a site?** A custom application the user builds/brings (its own logic, its own data,\n maybe a database) → **Webapp**. A content site or a shop → one of the three above. When the user says\n \"my app / SPA / dashboard / tool\", or hands you an existing app project to deploy, that's **Webapp**.\n- **Selling decides first (for sites).** No selling → WordPress. Selling → Ecommerce or\n WordPress + Ecommerce.\n- **Then the content.** Selling plus only a few fixed pages → Ecommerce. Selling plus content the\n owner will keep publishing → WordPress + Ecommerce.\n- **Hostinger Ecommerce is the default for selling — WooCommerce is never the default and is never\n recommended on its own.** Choose **WordPress + WooCommerce** only when the user explicitly names\n WooCommerce, or explicitly wants content **and** a store on one WordPress site (one admin, one\n domain — the one-site alternative to WordPress + Ecommerce). For every other selling case, keep\n Hostinger Ecommerce. If the user wants both content and a store but hasn't said \"one site\" or\n \"WooCommerce\", offer it as an option — don't switch to it silently.\n- **Don't add WordPress \"just in case\".** A second backend is a second admin to learn. Recommend the\n combination only when the user described ongoing content.\n- Selling a single service by enquiry (no checkout, no cart) is **not** commerce → WordPress with a\n contact page.\n- **Webapp never uses WordPress or a store.** If the user wants a custom app *and* a CMS/shop, that's two\n different sites — build the app as a Webapp and tell them the content/commerce backend is a separate\n domain.\n\n**Then set rendering** (write it in the brief's **Rendering** section): **Ecommerce → SSR required**\n(carts/search need per-request rendering — any SSR framework works; Next.js is the default, not a\nrequirement); **WordPress + WooCommerce → SSR required** (same reason — cart/checkout need per-request\nrendering); **WordPress → SSG (Astro)** if the site is mostly static and the owner is fine rebuilding\nto publish, otherwise **SSR**; **Webapp → whatever the app is** (SSR for a server app, SPA for a\nclient-only app) — it deploys as a Node.js app either way. When unsure, default to **Next.js SSR**.\n\n## Step 5 — Confirm the plan in one message\n\nSend **one** message that confirms **what you'll build** — the plan, not the plumbing. Lead with the\nsite, not the backend:\n\n- **The plan** — what it is, audience, pages, products (if any), tone. Mark anything you defaulted\n (*\"assumed: warm, minimal look\"*) so the user sees what they skipped.\n- **Your app** *(when Step 2 found a project in the folder)* — one line: keeps its look or gets a new\n one, the routes that must open directly, and whether a database is created.\n- **How it's built** — state the backend as a *consequence* in one plain line, focused on what it\n means for them day to day (\"I'll build this on WordPress, so you edit pages and posts in a normal\n WordPress admin\"), **not** as a choice you're asking them to make. Don't ask \"is WordPress OK?\" or\n offer alternatives unless it was a genuine close call *and* the difference matters to the user.\n\nEnd with *\"Good to go, or anything to change?\"* A yes (or \"go\") → write `brief.md`. A skipped tool\nresult is not a yes (see *When you ask the user* in the top-level `SKILL.md`). Changes → apply them\nand write it; don't loop back into questions. If the user *volunteers* a different backend, use\ntheirs and note it in the brief.\n\n## Step 6 — Write `brief.md` and hand off\n\nWrite `brief.md` from the template below. Fill every section from the conversation, defaulting what\nthe user skipped and tagging it `(assumed)`; leave out **Products** when nothing is sold and\n**Existing project** unless Step 2 found a project in the folder. Use the user's own words where you\ncan. Then update `state.json`:\n`\"stage\": \"provision\"`, fresh `updated_at`.\n\nThe **Suggested backend** section is the contract with `03-provision/SKILL.md`, which routes on it.\nIts first line must be exactly one of `**WordPress**`, `**Ecommerce**`, `**WordPress + Ecommerce**`,\n`**WordPress + WooCommerce**` or `**Webapp**`, followed by an em dash and the one-line reason.\n`**WordPress + WooCommerce**` is the WordPress backend with the WooCommerce store turned on — provision\nroutes it to the `wordpress` subfolder with the store enabled (it is **not** a separate backend).\n\n## `brief.md` template\n\n```markdown\n# Brief — <domain>\n\n> Brief agreed with the user on <today>.\n\n## Purpose\n<what the site is, who runs it, what it's for — 2–3 sentences>\n\n## Audience\n<who visits, how they arrive, what device they mostly use>\n\n## Tone\n<voice in a sentence or two>\n\n## Design direction\n<look & feel in a few adjectives; **reference site(s)** the user named (URLs) and what to take from them\n(layout, structure, mood); colours / brand palette; any screenshots. This is where ALL design questions\nland — the frontend step reads this and does not re-ask. Write \"Agent's choice: <short style>\" when the\nuser didn't specify. Record in the user's own words a request to keep their current look (\"Keep the look\nwe have: <site URL | screenshots | brand guide | the app in this folder>\") and any logo idea they describe; the design step acts\non both.>\n\n## Pages\n- **<Page>** — <one-line purpose>\n- …\n\n## Products\n<only when selling: what is sold, rough count, categories, variants, shipping regions, payments>\n\n## Content\n<what the owner will publish over time and how often — or \"A few fixed pages; no ongoing content.\">\n\n## Must-haves\n- …\n\n## Out of scope\n- …\n\n## Assets\n<logo, colours, photos, copy the user provided and where they are; \"None yet\" if none>\n\n## Existing project\n<only when Step 2 found a project in the folder: its path; the framework; the client-side\nroutes that must open directly and on refresh (or \"None\"); Database: none | MySQL; the env var names\nthe app reads — names only, never values>\n\n## Suggested backend\n**<WordPress | Ecommerce | WordPress + Ecommerce | WordPress + WooCommerce | Webapp>** — <one-line reason>.\n<\"Confirmed by the user.\" or \"User chose this over the recommended <X> because <reason>.\">\n\n## Build mode\n**<Bring your own frontend | Agent designs and builds>** — <one line>. <When \"Bring your own frontend\":\nhow they want to drive design/code; the project's path is under **Existing project**. When \"Agent designs and builds\": leave the design + frontend steps to run as\nnormal.> The design step and the frontend step both read this: **Bring your own frontend** → design\ndefers to the user and frontend builds on their project; **Agent designs and builds** → both run as normal.\n\n## Rendering\n**<SSR | SSG>** — <reason>. Rules: **Ecommerce requires SSR** and **WordPress + WooCommerce requires\nSSR** (carts/checkout need per-request rendering — any SSR framework works; Next.js is the default, not\na requirement); **WordPress may be SSG (Astro)** when the site is mostly static and rarely changes,\notherwise **SSR**. Default when unsure: **Next.js SSR**.\n```\n\n## Example — WordPress + Ecommerce\n\n> A ceramicist sells around 30 handmade pieces and writes a monthly studio journal.\n\n```markdown\n## Suggested backend\n**WordPress + Ecommerce** — sells ~30 products with checkout, and the owner publishes a monthly\nstudio journal they want to edit themselves.\nConfirmed by the user.\n```\n"
162
162
  },
163
163
  {
164
164
  "uri": "skill://hostinger-headless/steps/03-provision/SKILL.md",
@@ -176,10 +176,10 @@ const skills: Skill[] = [
176
176
  },
177
177
  {
178
178
  "uri": "skill://hostinger-headless/steps/03-provision/webapp/SKILL.md",
179
- "digest": "sha256:9b7aa3f3643b20c8a270ab755fa8ce380692faab479d00296d12c06d12a8f65a",
180
- "size": 9334,
179
+ "digest": "sha256:1b4639929e9dd7dd55ec65ea674ee0b881f039efe5eec5505a690b6b5ba29372",
180
+ "size": 9491,
181
181
  "mimeType": "text/markdown",
182
- "text": "---\nname: headless-step-provision-webapp\ndescription: \"Provision a plain Node.js app host for the Hostinger Headless flow: create an empty website (no WordPress, no store engine, no /cms), optionally a MySQL database, then record it in site.json. For any webapp / SPA / app that brings its own code and data.\"\n---\n\n# headless-step-provision-webapp\n\nProvision a bare **Node.js app host** for `<domain>` and prove it is ready. This is the backend for\n**any webapp, SPA or app** that brings its own code (and, if it needs one, its own database) — there is\nno CMS and no store engine here. The site is an **empty website**: just the hosting slot that the\nfrontend step builds into and the deploy step ships to as a Node.js application. **Out:** `site.json`.\n\n> **Not WordPress, not Ecommerce.** Never provision `headless_wordpress` / `headless_ecommerce` for a\n> webapp, and never install WordPress at `/cms`. A webapp owns its own routes, data and rendering.\n\nAll website/database operations below go through the Hostinger connector (`execute`).\n\n> **Fire vs join (background provision).** Steps 1–2 up to `hosting_websites_start-setup` are the\n> **fire** half: once the setup is queued, record `provision.in_progress` and return to do prepare work\n> (see the router `../SKILL.md`). The readiness **poll** at the end of Step 2, plus Steps 3–5, are the\n> **join** half — run them when an instance-barrier step needs the backend (or immediately, if the\n> agent can't interleave). An already-`completed` site detected in Step 1 means provision is done:\n> record `provision.completed` and adopt it.\n\n## Step 1 — Detect before you create (never provision twice)\n\n1. `hosting_websites_list { \"domain\": \"<domain>\" }` — substring filter, so **exact-match** the row's\n `domain`. If a row exists, note `username`, `order_id`, `website_type`.\n2. `hosting_websites_list-setups { \"domain\": \"<domain>\" }` — exact-match the row:\n - `completed` → already provisioned → skip to Step 3 (adopt it).\n - `running` → skip to Step 2 (poll).\n - `failed` → tell the user and point them at hPanel; do **not** call start-setup again on your own.\n3. If the site exists but is a different kind (`website_type` is `headless`, or a WordPress/store site),\n stop and tell the user — this domain already hosts something else.\n\n## Step 2 — Create (only when nothing exists)\n\n1. Pick the plan: `hosting_orders_list { \"statuses\": [\"active\"] }`. One active order → use it; several\n → ask the user which.\n2. Start the setup as an **empty website** — **omit `type`** (no WordPress, no store):\n\n ```json\n { \"operation\": \"hosting_websites_start-setup\",\n \"params\": { \"order_id\": <order_id>, \"domain\": \"<domain>\" } }\n ```\n\n `domain` must be a **customer-owned** domain. For a temporary `*.hostingersite.com` subdomain,\n **omit `domain`** — the setup generates one itself and returns it in the response. Don't call a\n separate subdomain op to make one first: there's no need in this flow. (The API would also accept a\n subdomain you generated via `hosting_domains_generate-free-subdomain`, valid for 24 h from the client\n that made it — this flow just doesn't use that.) The response then carries the generated domain: if it\n differs from the workspace directory name, move `~/.hostinger/<old>/` to `~/.hostinger/<new>/`\n (if `<new>/` already exists, stop and ask instead of moving into it),\n update the domain in `brief.md`, and tell the user the new domain.\n3. Poll `hosting_websites_list-setups { \"domain\": \"<domain>\" }` every ~15 s until `completed`\n (typically under a minute; allow a few minutes). `failed` → stop, point at hPanel.\n\n## Step 3 — Database (only if the app needs one)\n\nSkip this step entirely for an app with no database (static SPA, an app that talks to an external API).\nThis is **join-half** work — it needs the live website, so run it once `provision.status == \"completed\"`.\n\n**Preferred — let the platform create the database and inject the credentials:**\n`hosting_databases_setup-website { username, domain }` creates a MySQL database, **generates the\npassword, writes `DB_HOST` / `DB_PORT` / `DB_NAME` / `DB_USER` / `DB_PASSWORD` / `DATABASE_URL` into the\nwebsite's environment variables, and restarts the app — in one call.** The password is never returned,\nso there is **nothing to persist and nothing to lose across sessions** — the app reads it from the\nenvironment. (It 422s if any of those env vars already exist; clear them first with\n`hosting_nodejs_replace-environment-variables`. Frameworks that bake vars into the build — Next.js,\n`NEXT_PUBLIC_*` — only pick up the values on the deploy build.)\n\n> **⚠️ A later `hosting_nodejs_replace-environment-variables` wipes these credentials.** That call is a\n> **full replace**, and when you list the current vars first the `DB_PASSWORD` (and `DATABASE_URL`) read\n> back **masked** (`********`) — the generated password is unknown, so you cannot resend it and the DB\n> env is lost. One rule, pick one:\n> - **(a) Set every other app env var first, and call `setup-website` last** — then nothing has to\n> replace the env again.\n> - **(b) If a later replace is unavoidable**, reset the password with\n> `hosting_databases_change-password { username, name, password }` and resend **all** of `DB_HOST`,\n> `DB_PORT`, `DB_NAME`, `DB_USER`, `DB_PASSWORD` and `DATABASE_URL` with the new password in that same\n> full replace.\n\n**Manual alternative** — only when you need a specific name/user or finer control:\n\n1. `hosting_databases_create` with a name, a user, and a password you generate — name and user are\n prefixed with the account username automatically. Read the full, prefixed `name`/`user` back from\n `hosting_databases_list`.\n2. **Which host the app connects to:** the app runs **on the website**, so Node.js connects to\n **`127.0.0.1:3306`** — never `localhost` (it can resolve to IPv6 `::1`, and not every database user\n has that grant), and never the external `host` from `hosting_databases_list` (`srvNNNN.hstgr.io`,\n which has no grant for connections from the server itself).\n3. **Set the env vars now, while you still hold the generated password.** The password is **not persisted\n anywhere** (never in `site.json`), so set `DB_HOST=127.0.0.1`, `DB_PORT=3306`, `DB_NAME`, `DB_USER`,\n `DB_PASSWORD`, plus `DATABASE_URL=mysql://USER:PASSWORD@127.0.0.1:3306/NAME` (URL-encode USER/PASSWORD)\n right here with `hosting_nodejs_replace-environment-variables` (a **full replace** — list current keys\n first; values come back masked; send the complete set with real values). Saving restarts the process;\n build-time vars need a fresh deploy (`hosting_deploy`) afterwards. **Don't defer this to deploy:** on\n a **cross-session resume** the generated password is gone, so you must **reset it** with\n `hosting_databases_change-password { username, name, password }` and set the env vars from the new one.\n4. **Never** put the password in source, a committed `.env`, client-side JavaScript, or a chat reply;\n never print it once stored.\n\n## Step 4 — Verify\n\n| Check | How | Expect |\n|---|---|---|\n| Website exists | `hosting_websites_list` exact row | the row is present, `username` known |\n| Setup finished | `hosting_websites_list-setups` exact row | `status: completed` |\n| Database reachable *(only if created)* | `hosting_databases_list { username }` | the prefixed db + user are listed |\n\n`GET https://<domain>/` returns the Hostinger default page (or 403) until the frontend is deployed —\nexpected, not a failure. There is **no `/cms` and no API** on this domain; the app itself serves every\nroute once it is deployed (Step 8).\n\nIf a check fails: retry once after ~30 s; if it still fails, stop and point the user at hPanel.\n\n## Step 5 — Record `site.json`\n\n```json\n{\n \"backend\": \"webapp\",\n \"website_type\": \"empty\",\n \"order_id\": 1007223428,\n \"username\": \"u…\",\n \"runtime\": \"nodejs\",\n \"database\": {\n \"enabled\": false,\n \"engine\": \"mysql\",\n \"name\": \"u…_appdb\",\n \"user\": \"u…_app\",\n \"host\": \"127.0.0.1\",\n \"port\": 3306\n },\n \"urls\": {\n \"site\": \"https://<domain>\"\n },\n \"provisioned_at\": \"…\",\n \"verified_at\": \"…\"\n}\n```\n\nNo passwords or tokens in `site.json` — only the non-secret connection shape (host/port/name/user). Set\n`\"database\": { \"enabled\": false }` (and drop the rest) when the app needs no database.\n\n## Deploy & content model (what happens next)\n\n- **Content model is skipped for a webapp** — there is no CMS or store to seed; the app owns its own\n data. The content-model router (`../../04-content-model/SKILL.md`) passes straight through to the\n frontend step for this backend.\n- **Deploy** is a standard Node.js application deploy, handled by `../../08-deploy/SKILL.md`: it archives\n the **source** (not the build output; exclude `node_modules/`, `.next/`, `dist/`, build output and\n `.git/`), then deploys with `hosting_deploy` (`type: \"nodejs\"`, upload + server-side `npm install` +\n build, one shot) passing the framework's `appType` + `outputDirectory` inline, and polls\n `hosting_get-deployment` until the build completes. Any supported `appType` works (Next.js, Nuxt,\n Express, NestJS, Fastify, Vite/React/Vue SPA, …). There is no `/cms` to preserve here, so the whole\n root is the app.\n"
182
+ "text": "---\nname: headless-step-provision-webapp\ndescription: \"Provision a plain Node.js app host for the Hostinger Headless flow: create an empty website (no WordPress, no store engine, no /cms), optionally a MySQL database, then record it in site.json. For any webapp / SPA / app that brings its own code and data.\"\n---\n\n# headless-step-provision-webapp\n\nProvision a bare **Node.js app host** for `<domain>` and prove it is ready. This is the backend for\n**any webapp, SPA or app** that brings its own code (and, if it needs one, its own database) — there is\nno CMS and no store engine here. The site is an **empty website**: just the hosting slot that the\nfrontend step builds into and the deploy step ships to as a Node.js application. **Out:** `site.json`.\n\n> **Not WordPress, not Ecommerce.** Never provision `headless_wordpress` / `headless_ecommerce` for a\n> webapp, and never install WordPress at `/cms`. A webapp owns its own routes, data and rendering.\n\nAll website/database operations below go through the Hostinger connector (`execute`).\n\n> **Fire vs join (background provision).** Steps 1–2 up to `hosting_websites_start-setup` are the\n> **fire** half: once the setup is queued, record `provision.in_progress` and return to do prepare work\n> (see the router `../SKILL.md`). The readiness **poll** at the end of Step 2, plus Steps 3–5, are the\n> **join** half — run them when an instance-barrier step needs the backend (or immediately, if the\n> agent can't interleave). An already-`completed` site detected in Step 1 means provision is done:\n> record `provision.completed` and adopt it.\n\n## Step 1 — Detect before you create (never provision twice)\n\n1. `hosting_websites_list { \"domain\": \"<domain>\" }` — substring filter, so **exact-match** the row's\n `domain`. If a row exists, note `username`, `order_id`, `website_type`.\n2. `hosting_websites_list-setups { \"domain\": \"<domain>\" }` — exact-match the row:\n - `completed` → already provisioned → skip to Step 3 (adopt it).\n - `running` → skip to Step 2 (poll).\n - `failed` → tell the user and point them at hPanel; do **not** call start-setup again on your own.\n3. If the site exists but is a different kind (`website_type` is `headless`, or a WordPress/store site),\n stop and tell the user — this domain already hosts something else.\n\n## Step 2 — Create (only when nothing exists)\n\n1. Pick the plan: `hosting_orders_list { \"statuses\": [\"active\"] }`. One active order → use it; several\n → ask the user which.\n2. Start the setup as an **empty website** — **omit `type`** (no WordPress, no store):\n\n ```json\n { \"operation\": \"hosting_websites_start-setup\",\n \"params\": { \"order_id\": <order_id>, \"domain\": \"<domain>\" } }\n ```\n\n `domain` must be a **customer-owned** domain. For a temporary `*.hostingersite.com` subdomain,\n **omit `domain`** — the setup generates one itself and returns it in the response. Don't call a\n separate subdomain op to make one first: there's no need in this flow. (The API would also accept a\n subdomain you generated via `hosting_domains_generate-free-subdomain`, valid for 24 h from the client\n that made it — this flow just doesn't use that.) The response then carries the generated domain: if it\n differs from the workspace directory name, move `~/.hostinger/<old>/` to `~/.hostinger/<new>/`\n (if `<new>/` already exists, stop and ask instead of moving into it),\n update the domain in `brief.md`, and tell the user the new domain.\n3. Poll `hosting_websites_list-setups { \"domain\": \"<domain>\" }` every ~15 s until `completed`\n (typically under a minute; allow a few minutes). `failed` → stop, point at hPanel.\n\n## Step 3 — Database (only if the app needs one)\n\nSkip this step entirely for an app with no database (static SPA, an app that talks to an external API).\nThe app needs one when `brief.md` → **Existing project** says **Database: MySQL**, or, for a new app,\nwhen the brief describes data the app stores itself.\nThis is **join-half** work — it needs the live website, so run it once `provision.status == \"completed\"`.\n\n**Preferred — let the platform create the database and inject the credentials:**\n`hosting_databases_setup-website { username, domain }` creates a MySQL database, **generates the\npassword, writes `DB_HOST` / `DB_PORT` / `DB_NAME` / `DB_USER` / `DB_PASSWORD` / `DATABASE_URL` into the\nwebsite's environment variables, and restarts the app — in one call.** The password is never returned,\nso there is **nothing to persist and nothing to lose across sessions** — the app reads it from the\nenvironment. (It 422s if any of those env vars already exist; clear them first with\n`hosting_nodejs_replace-environment-variables`. Frameworks that bake vars into the build — Next.js,\n`NEXT_PUBLIC_*` — only pick up the values on the deploy build.)\n\n> **⚠️ A later `hosting_nodejs_replace-environment-variables` wipes these credentials.** That call is a\n> **full replace**, and when you list the current vars first the `DB_PASSWORD` (and `DATABASE_URL`) read\n> back **masked** (`********`) — the generated password is unknown, so you cannot resend it and the DB\n> env is lost. One rule, pick one:\n> - **(a) Set every other app env var first, and call `setup-website` last** — then nothing has to\n> replace the env again.\n> - **(b) If a later replace is unavoidable**, reset the password with\n> `hosting_databases_change-password { username, name, password }` and resend **all** of `DB_HOST`,\n> `DB_PORT`, `DB_NAME`, `DB_USER`, `DB_PASSWORD` and `DATABASE_URL` with the new password in that same\n> full replace.\n\n**Manual alternative** — only when you need a specific name/user or finer control:\n\n1. `hosting_databases_create` with a name, a user, and a password you generate — name and user are\n prefixed with the account username automatically. Read the full, prefixed `name`/`user` back from\n `hosting_databases_list`.\n2. **Which host the app connects to:** the app runs **on the website**, so Node.js connects to\n **`127.0.0.1:3306`** — never `localhost` (it can resolve to IPv6 `::1`, and not every database user\n has that grant), and never the external `host` from `hosting_databases_list` (`srvNNNN.hstgr.io`,\n which has no grant for connections from the server itself).\n3. **Set the env vars now, while you still hold the generated password.** The password is **not persisted\n anywhere** (never in `site.json`), so set `DB_HOST=127.0.0.1`, `DB_PORT=3306`, `DB_NAME`, `DB_USER`,\n `DB_PASSWORD`, plus `DATABASE_URL=mysql://USER:PASSWORD@127.0.0.1:3306/NAME` (URL-encode USER/PASSWORD)\n right here with `hosting_nodejs_replace-environment-variables` (a **full replace** — list current keys\n first; values come back masked; send the complete set with real values). Saving restarts the process;\n build-time vars need a fresh deploy (`hosting_deploy`) afterwards. **Don't defer this to deploy:** on\n a **cross-session resume** the generated password is gone, so you must **reset it** with\n `hosting_databases_change-password { username, name, password }` and set the env vars from the new one.\n4. **Never** put the password in source, a committed `.env`, client-side JavaScript, or a chat reply;\n never print it once stored.\n\n## Step 4 — Verify\n\n| Check | How | Expect |\n|---|---|---|\n| Website exists | `hosting_websites_list` exact row | the row is present, `username` known |\n| Setup finished | `hosting_websites_list-setups` exact row | `status: completed` |\n| Database reachable *(only if created)* | `hosting_databases_list { username }` | the prefixed db + user are listed |\n\n`GET https://<domain>/` returns the Hostinger default page (or 403) until the frontend is deployed —\nexpected, not a failure. There is **no `/cms` and no API** on this domain; the app itself serves every\nroute once it is deployed (Step 8).\n\nIf a check fails: retry once after ~30 s; if it still fails, stop and point the user at hPanel.\n\n## Step 5 — Record `site.json`\n\n```json\n{\n \"backend\": \"webapp\",\n \"website_type\": \"empty\",\n \"order_id\": 1007223428,\n \"username\": \"u…\",\n \"runtime\": \"nodejs\",\n \"database\": {\n \"enabled\": false,\n \"engine\": \"mysql\",\n \"name\": \"u…_appdb\",\n \"user\": \"u…_app\",\n \"host\": \"127.0.0.1\",\n \"port\": 3306\n },\n \"urls\": {\n \"site\": \"https://<domain>\"\n },\n \"provisioned_at\": \"…\",\n \"verified_at\": \"…\"\n}\n```\n\nNo passwords or tokens in `site.json` — only the non-secret connection shape (host/port/name/user). Set\n`\"database\": { \"enabled\": false }` (and drop the rest) when the app needs no database.\n\n## Deploy & content model (what happens next)\n\n- **Content model is skipped for a webapp** — there is no CMS or store to seed; the app owns its own\n data. The content-model router (`../../04-content-model/SKILL.md`) passes straight through to the\n frontend step for this backend.\n- **Deploy** is a standard Node.js application deploy, handled by `../../08-deploy/SKILL.md`: it archives\n the **source** (not the build output; exclude `node_modules/`, `.next/`, `dist/`, build output and\n `.git/`), then deploys with `hosting_deploy` (`type: \"nodejs\"`, upload + server-side `npm install` +\n build, one shot) passing the framework's `appType` + `outputDirectory` inline, and polls\n `hosting_get-deployment` until the build completes. Any supported `appType` works (Next.js, Nuxt,\n Express, NestJS, Fastify, Vite/React/Vue SPA, …). There is no `/cms` to preserve here, so the whole\n root is the app.\n"
183
183
  },
184
184
  {
185
185
  "uri": "skill://hostinger-headless/steps/03-provision/wordpress/SKILL.md",
@@ -6209,6 +6209,41 @@ export default [
6209
6209
  ],
6210
6210
  "group": "hosting"
6211
6211
  },
6212
+ {
6213
+ "name": "hosting_cache_status",
6214
+ "title": "Get cache status",
6215
+ "annotations": {
6216
+ "title": "Get cache status",
6217
+ "readOnlyHint": true,
6218
+ "destructiveHint": false
6219
+ },
6220
+ "description": "Returns the caching state of the website: whether server-side caching is enabled and whether\ndevelopment (cacheless) mode is on. Works for the main domain, addon websites, parked domains\nand subdomains of the account; each reports its own settings and does not inherit them from\nits parent website.\n\n`is_enabled` is the setting changed by `Toggle website cache` and reflects a toggle\nimmediately. `is_cacheless_mode_enabled` is true while development mode is on; caching is then\nbypassed even when `is_enabled` is true. `Toggle cacheless mode` is applied in the background,\nso this flag can take a few minutes to follow it.\n\nThe domain must be the exact website name as listed on the account, without a `www.` prefix.\nReturns 404 when the domain is not a website on the account.",
6221
+ "method": "GET",
6222
+ "path": "/api/hosting/v1/accounts/{username}/websites/{domain}/cache/status",
6223
+ "inputSchema": {
6224
+ "type": "object",
6225
+ "properties": {
6226
+ "username": {
6227
+ "type": "string",
6228
+ "description": "username parameter"
6229
+ },
6230
+ "domain": {
6231
+ "type": "string",
6232
+ "description": "Domain name"
6233
+ }
6234
+ },
6235
+ "required": [
6236
+ "username",
6237
+ "domain"
6238
+ ]
6239
+ },
6240
+ "security": [
6241
+ {
6242
+ "apiToken": []
6243
+ }
6244
+ ],
6245
+ "group": "hosting"
6246
+ },
6212
6247
  {
6213
6248
  "name": "hosting_cache_toggle-cacheless",
6214
6249
  "title": "Toggle cacheless mode",
@@ -6218,7 +6253,7 @@ export default [
6218
6253
  "destructiveHint": true,
6219
6254
  "idempotentHint": true
6220
6255
  },
6221
- "description": "Turns development (cacheless) mode on or off, based on the enabled flag. When enabled, nothing\nis cached, effectively turning off all caching for the website; use it while actively developing,\ntesting changes, debugging issues, or when real-time updates must be visible. Disable it after\nfinishing development work to restore the performance benefits of caching.",
6256
+ "description": "Turns development (cacheless) mode on or off, based on the enabled flag. When enabled, nothing\nis cached, effectively turning off all caching for the website; use it while actively developing,\ntesting changes, debugging issues, or when real-time updates must be visible. Disable it after\nfinishing development work to restore the performance benefits of caching.\n\nThe change is applied in the background and can take a few minutes. Use `Get cache status` to\ncheck the current state.",
6222
6257
  "method": "PATCH",
6223
6258
  "path": "/api/hosting/v1/accounts/{username}/websites/{domain}/cacheless-mode/toggle",
6224
6259
  "inputSchema": {
@@ -6259,7 +6294,7 @@ export default [
6259
6294
  "destructiveHint": true,
6260
6295
  "idempotentHint": true
6261
6296
  },
6262
- "description": "Turns server-side caching for the website on or off, based on the enabled flag. Enable it for\nfaster page loads, reduced server load, and improved user experience; recommended for production\nwebsites. Disabling may impact performance; to temporarily bypass caching while developing or\ndebugging, prefer toggling cacheless mode instead.\n\nDoes nothing if caching is already in the requested state.",
6297
+ "description": "Turns server-side caching for the website on or off, based on the enabled flag. Enable it for\nfaster page loads, reduced server load, and improved user experience; recommended for production\nwebsites. Disabling may impact performance; to temporarily bypass caching while developing or\ndebugging, prefer toggling cacheless mode instead.\n\nDoes nothing if caching is already in the requested state. Use `Get cache status` to check the\ncurrent state.",
6263
6298
  "method": "PATCH",
6264
6299
  "path": "/api/hosting/v1/accounts/{username}/websites/{domain}/cache/toggle",
6265
6300
  "inputSchema": {
@@ -6225,6 +6225,41 @@ const tools: OpenApiTool[] = [
6225
6225
  ],
6226
6226
  "group": "hosting"
6227
6227
  },
6228
+ {
6229
+ "name": "hosting_cache_status",
6230
+ "title": "Get cache status",
6231
+ "annotations": {
6232
+ "title": "Get cache status",
6233
+ "readOnlyHint": true,
6234
+ "destructiveHint": false
6235
+ },
6236
+ "description": "Returns the caching state of the website: whether server-side caching is enabled and whether\ndevelopment (cacheless) mode is on. Works for the main domain, addon websites, parked domains\nand subdomains of the account; each reports its own settings and does not inherit them from\nits parent website.\n\n`is_enabled` is the setting changed by `Toggle website cache` and reflects a toggle\nimmediately. `is_cacheless_mode_enabled` is true while development mode is on; caching is then\nbypassed even when `is_enabled` is true. `Toggle cacheless mode` is applied in the background,\nso this flag can take a few minutes to follow it.\n\nThe domain must be the exact website name as listed on the account, without a `www.` prefix.\nReturns 404 when the domain is not a website on the account.",
6237
+ "method": "GET",
6238
+ "path": "/api/hosting/v1/accounts/{username}/websites/{domain}/cache/status",
6239
+ "inputSchema": {
6240
+ "type": "object",
6241
+ "properties": {
6242
+ "username": {
6243
+ "type": "string",
6244
+ "description": "username parameter"
6245
+ },
6246
+ "domain": {
6247
+ "type": "string",
6248
+ "description": "Domain name"
6249
+ }
6250
+ },
6251
+ "required": [
6252
+ "username",
6253
+ "domain"
6254
+ ]
6255
+ },
6256
+ "security": [
6257
+ {
6258
+ "apiToken": []
6259
+ }
6260
+ ],
6261
+ "group": "hosting"
6262
+ },
6228
6263
  {
6229
6264
  "name": "hosting_cache_toggle-cacheless",
6230
6265
  "title": "Toggle cacheless mode",
@@ -6234,7 +6269,7 @@ const tools: OpenApiTool[] = [
6234
6269
  "destructiveHint": true,
6235
6270
  "idempotentHint": true
6236
6271
  },
6237
- "description": "Turns development (cacheless) mode on or off, based on the enabled flag. When enabled, nothing\nis cached, effectively turning off all caching for the website; use it while actively developing,\ntesting changes, debugging issues, or when real-time updates must be visible. Disable it after\nfinishing development work to restore the performance benefits of caching.",
6272
+ "description": "Turns development (cacheless) mode on or off, based on the enabled flag. When enabled, nothing\nis cached, effectively turning off all caching for the website; use it while actively developing,\ntesting changes, debugging issues, or when real-time updates must be visible. Disable it after\nfinishing development work to restore the performance benefits of caching.\n\nThe change is applied in the background and can take a few minutes. Use `Get cache status` to\ncheck the current state.",
6238
6273
  "method": "PATCH",
6239
6274
  "path": "/api/hosting/v1/accounts/{username}/websites/{domain}/cacheless-mode/toggle",
6240
6275
  "inputSchema": {
@@ -6275,7 +6310,7 @@ const tools: OpenApiTool[] = [
6275
6310
  "destructiveHint": true,
6276
6311
  "idempotentHint": true
6277
6312
  },
6278
- "description": "Turns server-side caching for the website on or off, based on the enabled flag. Enable it for\nfaster page loads, reduced server load, and improved user experience; recommended for production\nwebsites. Disabling may impact performance; to temporarily bypass caching while developing or\ndebugging, prefer toggling cacheless mode instead.\n\nDoes nothing if caching is already in the requested state.",
6313
+ "description": "Turns server-side caching for the website on or off, based on the enabled flag. Enable it for\nfaster page loads, reduced server load, and improved user experience; recommended for production\nwebsites. Disabling may impact performance; to temporarily bypass caching while developing or\ndebugging, prefer toggling cacheless mode instead.\n\nDoes nothing if caching is already in the requested state. Use `Get cache status` to check the\ncurrent state.",
6279
6314
  "method": "PATCH",
6280
6315
  "path": "/api/hosting/v1/accounts/{username}/websites/{domain}/cache/toggle",
6281
6316
  "inputSchema": {
@@ -519,6 +519,41 @@ export default [
519
519
  ],
520
520
  "group": "hosting"
521
521
  },
522
+ {
523
+ "name": "hosting_cache_status",
524
+ "title": "Get cache status",
525
+ "annotations": {
526
+ "title": "Get cache status",
527
+ "readOnlyHint": true,
528
+ "destructiveHint": false
529
+ },
530
+ "description": "Returns the caching state of the website: whether server-side caching is enabled and whether\ndevelopment (cacheless) mode is on. Works for the main domain, addon websites, parked domains\nand subdomains of the account; each reports its own settings and does not inherit them from\nits parent website.\n\n`is_enabled` is the setting changed by `Toggle website cache` and reflects a toggle\nimmediately. `is_cacheless_mode_enabled` is true while development mode is on; caching is then\nbypassed even when `is_enabled` is true. `Toggle cacheless mode` is applied in the background,\nso this flag can take a few minutes to follow it.\n\nThe domain must be the exact website name as listed on the account, without a `www.` prefix.\nReturns 404 when the domain is not a website on the account.",
531
+ "method": "GET",
532
+ "path": "/api/hosting/v1/accounts/{username}/websites/{domain}/cache/status",
533
+ "inputSchema": {
534
+ "type": "object",
535
+ "properties": {
536
+ "username": {
537
+ "type": "string",
538
+ "description": "username parameter"
539
+ },
540
+ "domain": {
541
+ "type": "string",
542
+ "description": "Domain name"
543
+ }
544
+ },
545
+ "required": [
546
+ "username",
547
+ "domain"
548
+ ]
549
+ },
550
+ "security": [
551
+ {
552
+ "apiToken": []
553
+ }
554
+ ],
555
+ "group": "hosting"
556
+ },
522
557
  {
523
558
  "name": "hosting_cache_toggle-cacheless",
524
559
  "title": "Toggle cacheless mode",
@@ -528,7 +563,7 @@ export default [
528
563
  "destructiveHint": true,
529
564
  "idempotentHint": true
530
565
  },
531
- "description": "Turns development (cacheless) mode on or off, based on the enabled flag. When enabled, nothing\nis cached, effectively turning off all caching for the website; use it while actively developing,\ntesting changes, debugging issues, or when real-time updates must be visible. Disable it after\nfinishing development work to restore the performance benefits of caching.",
566
+ "description": "Turns development (cacheless) mode on or off, based on the enabled flag. When enabled, nothing\nis cached, effectively turning off all caching for the website; use it while actively developing,\ntesting changes, debugging issues, or when real-time updates must be visible. Disable it after\nfinishing development work to restore the performance benefits of caching.\n\nThe change is applied in the background and can take a few minutes. Use `Get cache status` to\ncheck the current state.",
532
567
  "method": "PATCH",
533
568
  "path": "/api/hosting/v1/accounts/{username}/websites/{domain}/cacheless-mode/toggle",
534
569
  "inputSchema": {
@@ -569,7 +604,7 @@ export default [
569
604
  "destructiveHint": true,
570
605
  "idempotentHint": true
571
606
  },
572
- "description": "Turns server-side caching for the website on or off, based on the enabled flag. Enable it for\nfaster page loads, reduced server load, and improved user experience; recommended for production\nwebsites. Disabling may impact performance; to temporarily bypass caching while developing or\ndebugging, prefer toggling cacheless mode instead.\n\nDoes nothing if caching is already in the requested state.",
607
+ "description": "Turns server-side caching for the website on or off, based on the enabled flag. Enable it for\nfaster page loads, reduced server load, and improved user experience; recommended for production\nwebsites. Disabling may impact performance; to temporarily bypass caching while developing or\ndebugging, prefer toggling cacheless mode instead.\n\nDoes nothing if caching is already in the requested state. Use `Get cache status` to check the\ncurrent state.",
573
608
  "method": "PATCH",
574
609
  "path": "/api/hosting/v1/accounts/{username}/websites/{domain}/cache/toggle",
575
610
  "inputSchema": {
@@ -535,6 +535,41 @@ const tools: OpenApiTool[] = [
535
535
  ],
536
536
  "group": "hosting"
537
537
  },
538
+ {
539
+ "name": "hosting_cache_status",
540
+ "title": "Get cache status",
541
+ "annotations": {
542
+ "title": "Get cache status",
543
+ "readOnlyHint": true,
544
+ "destructiveHint": false
545
+ },
546
+ "description": "Returns the caching state of the website: whether server-side caching is enabled and whether\ndevelopment (cacheless) mode is on. Works for the main domain, addon websites, parked domains\nand subdomains of the account; each reports its own settings and does not inherit them from\nits parent website.\n\n`is_enabled` is the setting changed by `Toggle website cache` and reflects a toggle\nimmediately. `is_cacheless_mode_enabled` is true while development mode is on; caching is then\nbypassed even when `is_enabled` is true. `Toggle cacheless mode` is applied in the background,\nso this flag can take a few minutes to follow it.\n\nThe domain must be the exact website name as listed on the account, without a `www.` prefix.\nReturns 404 when the domain is not a website on the account.",
547
+ "method": "GET",
548
+ "path": "/api/hosting/v1/accounts/{username}/websites/{domain}/cache/status",
549
+ "inputSchema": {
550
+ "type": "object",
551
+ "properties": {
552
+ "username": {
553
+ "type": "string",
554
+ "description": "username parameter"
555
+ },
556
+ "domain": {
557
+ "type": "string",
558
+ "description": "Domain name"
559
+ }
560
+ },
561
+ "required": [
562
+ "username",
563
+ "domain"
564
+ ]
565
+ },
566
+ "security": [
567
+ {
568
+ "apiToken": []
569
+ }
570
+ ],
571
+ "group": "hosting"
572
+ },
538
573
  {
539
574
  "name": "hosting_cache_toggle-cacheless",
540
575
  "title": "Toggle cacheless mode",
@@ -544,7 +579,7 @@ const tools: OpenApiTool[] = [
544
579
  "destructiveHint": true,
545
580
  "idempotentHint": true
546
581
  },
547
- "description": "Turns development (cacheless) mode on or off, based on the enabled flag. When enabled, nothing\nis cached, effectively turning off all caching for the website; use it while actively developing,\ntesting changes, debugging issues, or when real-time updates must be visible. Disable it after\nfinishing development work to restore the performance benefits of caching.",
582
+ "description": "Turns development (cacheless) mode on or off, based on the enabled flag. When enabled, nothing\nis cached, effectively turning off all caching for the website; use it while actively developing,\ntesting changes, debugging issues, or when real-time updates must be visible. Disable it after\nfinishing development work to restore the performance benefits of caching.\n\nThe change is applied in the background and can take a few minutes. Use `Get cache status` to\ncheck the current state.",
548
583
  "method": "PATCH",
549
584
  "path": "/api/hosting/v1/accounts/{username}/websites/{domain}/cacheless-mode/toggle",
550
585
  "inputSchema": {
@@ -585,7 +620,7 @@ const tools: OpenApiTool[] = [
585
620
  "destructiveHint": true,
586
621
  "idempotentHint": true
587
622
  },
588
- "description": "Turns server-side caching for the website on or off, based on the enabled flag. Enable it for\nfaster page loads, reduced server load, and improved user experience; recommended for production\nwebsites. Disabling may impact performance; to temporarily bypass caching while developing or\ndebugging, prefer toggling cacheless mode instead.\n\nDoes nothing if caching is already in the requested state.",
623
+ "description": "Turns server-side caching for the website on or off, based on the enabled flag. Enable it for\nfaster page loads, reduced server load, and improved user experience; recommended for production\nwebsites. Disabling may impact performance; to temporarily bypass caching while developing or\ndebugging, prefer toggling cacheless mode instead.\n\nDoes nothing if caching is already in the requested state. Use `Get cache status` to check the\ncurrent state.",
589
624
  "method": "PATCH",
590
625
  "path": "/api/hosting/v1/accounts/{username}/websites/{domain}/cache/toggle",
591
626
  "inputSchema": {
@@ -4,4 +4,4 @@ import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/agency-hosting.js';
5
5
  import instructions from '../core/instructions.agency-hosting.js';
6
6
 
7
- startServer({ name: 'hostinger-agency-hosting-mcp', version: '3.13.0', tools, instructions });
7
+ startServer({ name: 'hostinger-agency-hosting-mcp', version: '3.14.1', tools, instructions });
@@ -4,4 +4,4 @@ import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/agency-hosting.js';
5
5
  import instructions from '../core/instructions.agency-hosting.js';
6
6
 
7
- startServer({ name: 'hostinger-agency-hosting-mcp', version: '3.13.0', tools, instructions });
7
+ startServer({ name: 'hostinger-agency-hosting-mcp', version: '3.14.1', tools, instructions });
@@ -3,4 +3,4 @@
3
3
  import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/agent-readiness.js';
5
5
 
6
- startServer({ name: 'hostinger-agent-readiness-mcp', version: '3.13.0', tools });
6
+ startServer({ name: 'hostinger-agent-readiness-mcp', version: '3.14.1', tools });
@@ -3,4 +3,4 @@
3
3
  import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/agent-readiness.js';
5
5
 
6
- startServer({ name: 'hostinger-agent-readiness-mcp', version: '3.13.0', tools });
6
+ startServer({ name: 'hostinger-agent-readiness-mcp', version: '3.14.1', tools });
@@ -5,4 +5,4 @@ import tools from '../core/tools/all.js';
5
5
  import instructions from '../core/instructions.js';
6
6
  import skills from '../core/skills.js';
7
7
 
8
- startServer({ name: 'hostinger-api-mcp', version: '3.13.0', tools, instructions, skills });
8
+ startServer({ name: 'hostinger-api-mcp', version: '3.14.1', tools, instructions, skills });
@@ -5,4 +5,4 @@ import tools from '../core/tools/all.js';
5
5
  import instructions from '../core/instructions.js';
6
6
  import skills from '../core/skills.js';
7
7
 
8
- startServer({ name: 'hostinger-api-mcp', version: '3.13.0', tools, instructions, skills });
8
+ startServer({ name: 'hostinger-api-mcp', version: '3.14.1', tools, instructions, skills });
@@ -3,4 +3,4 @@
3
3
  import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/billing.js';
5
5
 
6
- startServer({ name: 'hostinger-billing-mcp', version: '3.13.0', tools });
6
+ startServer({ name: 'hostinger-billing-mcp', version: '3.14.1', tools });
@@ -3,4 +3,4 @@
3
3
  import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/billing.js';
5
5
 
6
- startServer({ name: 'hostinger-billing-mcp', version: '3.13.0', tools });
6
+ startServer({ name: 'hostinger-billing-mcp', version: '3.14.1', tools });
@@ -3,4 +3,4 @@
3
3
  import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/dns.js';
5
5
 
6
- startServer({ name: 'hostinger-dns-mcp', version: '3.13.0', tools });
6
+ startServer({ name: 'hostinger-dns-mcp', version: '3.14.1', tools });
@@ -3,4 +3,4 @@
3
3
  import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/dns.js';
5
5
 
6
- startServer({ name: 'hostinger-dns-mcp', version: '3.13.0', tools });
6
+ startServer({ name: 'hostinger-dns-mcp', version: '3.14.1', tools });
@@ -3,4 +3,4 @@
3
3
  import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/domains.js';
5
5
 
6
- startServer({ name: 'hostinger-domains-mcp', version: '3.13.0', tools });
6
+ startServer({ name: 'hostinger-domains-mcp', version: '3.14.1', tools });
@@ -3,4 +3,4 @@
3
3
  import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/domains.js';
5
5
 
6
- startServer({ name: 'hostinger-domains-mcp', version: '3.13.0', tools });
6
+ startServer({ name: 'hostinger-domains-mcp', version: '3.14.1', tools });
@@ -3,4 +3,4 @@
3
3
  import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/ecommerce.js';
5
5
 
6
- startServer({ name: 'hostinger-ecommerce-mcp', version: '3.13.0', tools });
6
+ startServer({ name: 'hostinger-ecommerce-mcp', version: '3.14.1', tools });
@@ -3,4 +3,4 @@
3
3
  import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/ecommerce.js';
5
5
 
6
- startServer({ name: 'hostinger-ecommerce-mcp', version: '3.13.0', tools });
6
+ startServer({ name: 'hostinger-ecommerce-mcp', version: '3.14.1', tools });
@@ -3,4 +3,4 @@
3
3
  import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/horizons.js';
5
5
 
6
- startServer({ name: 'hostinger-horizons-mcp', version: '3.13.0', tools });
6
+ startServer({ name: 'hostinger-horizons-mcp', version: '3.14.1', tools });
@@ -3,4 +3,4 @@
3
3
  import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/horizons.js';
5
5
 
6
- startServer({ name: 'hostinger-horizons-mcp', version: '3.13.0', tools });
6
+ startServer({ name: 'hostinger-horizons-mcp', version: '3.14.1', tools });
@@ -4,4 +4,4 @@ import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/hosting.js';
5
5
  import instructions from '../core/instructions.js';
6
6
 
7
- startServer({ name: 'hostinger-hosting-mcp', version: '3.13.0', tools, instructions });
7
+ startServer({ name: 'hostinger-hosting-mcp', version: '3.14.1', tools, instructions });
@@ -4,4 +4,4 @@ import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/hosting.js';
5
5
  import instructions from '../core/instructions.js';
6
6
 
7
- startServer({ name: 'hostinger-hosting-mcp', version: '3.13.0', tools, instructions });
7
+ startServer({ name: 'hostinger-hosting-mcp', version: '3.14.1', tools, instructions });
@@ -3,4 +3,4 @@
3
3
  import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/mail.js';
5
5
 
6
- startServer({ name: 'hostinger-mail-mcp', version: '3.13.0', tools });
6
+ startServer({ name: 'hostinger-mail-mcp', version: '3.14.1', tools });
@@ -3,4 +3,4 @@
3
3
  import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/mail.js';
5
5
 
6
- startServer({ name: 'hostinger-mail-mcp', version: '3.13.0', tools });
6
+ startServer({ name: 'hostinger-mail-mcp', version: '3.14.1', tools });
@@ -3,4 +3,4 @@
3
3
  import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/reach.js';
5
5
 
6
- startServer({ name: 'hostinger-reach-mcp', version: '3.13.0', tools });
6
+ startServer({ name: 'hostinger-reach-mcp', version: '3.14.1', tools });
@@ -3,4 +3,4 @@
3
3
  import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/reach.js';
5
5
 
6
- startServer({ name: 'hostinger-reach-mcp', version: '3.13.0', tools });
6
+ startServer({ name: 'hostinger-reach-mcp', version: '3.14.1', tools });
@@ -3,4 +3,4 @@
3
3
  import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/vps.js';
5
5
 
6
- startServer({ name: 'hostinger-vps-mcp', version: '3.13.0', tools });
6
+ startServer({ name: 'hostinger-vps-mcp', version: '3.14.1', tools });
@@ -3,4 +3,4 @@
3
3
  import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/vps.js';
5
5
 
6
- startServer({ name: 'hostinger-vps-mcp', version: '3.13.0', tools });
6
+ startServer({ name: 'hostinger-vps-mcp', version: '3.14.1', tools });
@@ -3,4 +3,4 @@
3
3
  import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/wordpress.js';
5
5
 
6
- startServer({ name: 'hostinger-wordpress-mcp', version: '3.13.0', tools });
6
+ startServer({ name: 'hostinger-wordpress-mcp', version: '3.14.1', tools });
@@ -3,4 +3,4 @@
3
3
  import { startServer } from '../core/runtime.js';
4
4
  import tools from '../core/tools/wordpress.js';
5
5
 
6
- startServer({ name: 'hostinger-wordpress-mcp', version: '3.13.0', tools });
6
+ startServer({ name: 'hostinger-wordpress-mcp', version: '3.14.1', tools });