@hostinger/mcp 3.2.2 → 3.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/gemini-extension.json +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
- package/skills/headless/SKILL.md +245 -36
- package/skills/headless/connect/SKILL.md +98 -0
- package/skills/headless/{entry → connect}/bootstrap.mjs +8 -3
- package/skills/headless/connect/tools/antigravity.md +54 -0
- package/skills/headless/connect/tools/claude-code.md +46 -0
- package/skills/headless/connect/tools/codex.md +48 -0
- package/skills/headless/connect/tools/cursor.md +109 -0
- package/skills/headless/connect/tools/devin.md +50 -0
- package/skills/headless/connect/tools/vscode.md +57 -0
- package/skills/headless/report.schema.json +149 -0
- package/skills/headless/run-log.mjs +662 -0
- package/skills/headless/steps/01-check-state/SKILL.md +209 -0
- package/skills/headless/steps/02-refine/SKILL.md +273 -0
- package/skills/headless/steps/03-provision/SKILL.md +117 -0
- package/skills/headless/steps/03-provision/ecommerce/SKILL.md +142 -0
- package/skills/headless/steps/03-provision/webapp/SKILL.md +154 -0
- package/skills/headless/steps/03-provision/wordpress/SKILL.md +249 -0
- package/skills/headless/steps/04-content-model/SKILL.md +228 -0
- package/skills/headless/steps/04-content-model/ecommerce/SKILL.md +75 -0
- package/skills/headless/steps/04-content-model/wordpress/SKILL.md +223 -0
- package/skills/headless/steps/04-content-model/wordpress/woocommerce.md +153 -0
- package/skills/headless/steps/05-design/SKILL.md +464 -0
- package/skills/headless/steps/05-design/logo-kit.mjs +201 -0
- package/skills/headless/steps/06-frontend/SKILL.md +160 -0
- package/skills/headless/steps/07-validate/SKILL.md +56 -0
- package/skills/headless/steps/08-deploy/SKILL.md +179 -0
- package/skills/headless/steps/09-done/SKILL.md +157 -0
- package/src/core/skills.js +171 -24
- package/src/core/skills.ts +171 -24
- package/src/servers/agency-hosting.js +1 -1
- package/src/servers/agency-hosting.ts +1 -1
- package/src/servers/agent-readiness.js +1 -1
- package/src/servers/agent-readiness.ts +1 -1
- package/src/servers/all.js +1 -1
- package/src/servers/all.ts +1 -1
- package/src/servers/billing.js +1 -1
- package/src/servers/billing.ts +1 -1
- package/src/servers/dns.js +1 -1
- package/src/servers/dns.ts +1 -1
- package/src/servers/domains.js +1 -1
- package/src/servers/domains.ts +1 -1
- package/src/servers/ecommerce.js +1 -1
- package/src/servers/ecommerce.ts +1 -1
- package/src/servers/horizons.js +1 -1
- package/src/servers/horizons.ts +1 -1
- package/src/servers/hosting.js +1 -1
- package/src/servers/hosting.ts +1 -1
- package/src/servers/mail.js +1 -1
- package/src/servers/mail.ts +1 -1
- package/src/servers/reach.js +1 -1
- package/src/servers/reach.ts +1 -1
- package/src/servers/vps.js +1 -1
- package/src/servers/vps.ts +1 -1
- package/src/servers/wordpress.js +1 -1
- package/src/servers/wordpress.ts +1 -1
- package/skills/headless/entry/skill.md +0 -79
- package/skills/headless/references/DATABASE.md +0 -49
- package/skills/headless/references/DEPLOYMENT.md +0 -34
- package/skills/headless/references/SETUP.md +0 -35
- package/skills/headless/references/STORE.md +0 -52
- package/skills/headless/references/WORDPRESS.md +0 -51
|
@@ -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.
|
|
7
|
+
startServer({ name: 'hostinger-agency-hosting-mcp', version: '3.3.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.
|
|
7
|
+
startServer({ name: 'hostinger-agency-hosting-mcp', version: '3.3.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.
|
|
6
|
+
startServer({ name: 'hostinger-agent-readiness-mcp', version: '3.3.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.
|
|
6
|
+
startServer({ name: 'hostinger-agent-readiness-mcp', version: '3.3.1', tools });
|
package/src/servers/all.js
CHANGED
|
@@ -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.
|
|
8
|
+
startServer({ name: 'hostinger-api-mcp', version: '3.3.1', tools, instructions, skills });
|
package/src/servers/all.ts
CHANGED
|
@@ -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.
|
|
8
|
+
startServer({ name: 'hostinger-api-mcp', version: '3.3.1', tools, instructions, skills });
|
package/src/servers/billing.js
CHANGED
package/src/servers/billing.ts
CHANGED
package/src/servers/dns.js
CHANGED
package/src/servers/dns.ts
CHANGED
package/src/servers/domains.js
CHANGED
package/src/servers/domains.ts
CHANGED
package/src/servers/ecommerce.js
CHANGED
package/src/servers/ecommerce.ts
CHANGED
package/src/servers/horizons.js
CHANGED
package/src/servers/horizons.ts
CHANGED
package/src/servers/hosting.js
CHANGED
|
@@ -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.
|
|
7
|
+
startServer({ name: 'hostinger-hosting-mcp', version: '3.3.1', tools, instructions });
|
package/src/servers/hosting.ts
CHANGED
|
@@ -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.
|
|
7
|
+
startServer({ name: 'hostinger-hosting-mcp', version: '3.3.1', tools, instructions });
|
package/src/servers/mail.js
CHANGED
package/src/servers/mail.ts
CHANGED
package/src/servers/reach.js
CHANGED
package/src/servers/reach.ts
CHANGED
package/src/servers/vps.js
CHANGED
package/src/servers/vps.ts
CHANGED
package/src/servers/wordpress.js
CHANGED
package/src/servers/wordpress.ts
CHANGED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: hostinger-headless-entry
|
|
3
|
-
description: "Build a complete website on Hostinger from a single prompt — hosting, domain, and (optionally) a store with real checkout or a blog/CMS the owner edits in WordPress. The deterministic first steps — verifying the Hostinger MCP server and signing in — are handled by a single bootstrap script; the agent then installs the full skill and hands the run to it. Triggers: build me a site, create a website, make me a website, online store, I want to sell X, start a business online, launch a site, ecommerce, portfolio, blog, business website, sell online, online shop, add a blog to my site, connect this project to Hostinger, host this on Hostinger, deploy this to Hostinger."
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Hostinger Headless Skill — cold-start entry
|
|
7
|
-
|
|
8
|
-
You are a coding agent, and this is a skill for you to execute. Follow the phases below in order — do not summarize them. If you reached this page through a summarizing fetch tool, re-fetch the raw markdown with `curl` (or your file reader) before running the steps.
|
|
9
|
-
|
|
10
|
-
This entry gets a cold environment to the point where the real skill can run, then hands off:
|
|
11
|
-
|
|
12
|
-
1. Bootstrap (deterministic, scripted). A single script verifies the Hostinger MCP server is reachable and handles sign-in, so the run starts from a known-good, authenticated state. You just run it and relay its events.
|
|
13
|
-
2. Hand off (agentic). Install the skill, then open `headless/SKILL.md` and follow it — it resolves the operation (create / connect / iterate) and owns the whole build.
|
|
14
|
-
|
|
15
|
-
Three starting points come through here, all handled the same way — run the bootstrap, then hand off:
|
|
16
|
-
|
|
17
|
-
- new — a prompt with no project (empty CWD)
|
|
18
|
-
- connect — an existing frontend not yet on Hostinger
|
|
19
|
-
- iterate — a project already deployed to Hostinger (`.hostinger/site.json` present)
|
|
20
|
-
|
|
21
|
-
The bootstrap only verifies the MCP and signs you in, so it is safe to run in every case (an existing session just reports `logged_in`).
|
|
22
|
-
|
|
23
|
-
## Phase 0 — Node (the one manual prerequisite)
|
|
24
|
-
|
|
25
|
-
The Hostinger MCP server requires Node ≥ 20. Check it:
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
node -v
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
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:
|
|
32
|
-
|
|
33
|
-
- macOS: `brew install node` (or `nvm install 22 && nvm use 22`)
|
|
34
|
-
- Linux: `nvm install 22 && nvm use 22` (or your distro's Node 20+ package)
|
|
35
|
-
- Windows: `winget install OpenJS.NodeJS.LTS` (or download from nodejs.org)
|
|
36
|
-
|
|
37
|
-
## Phase 1 — Run the bootstrap (deterministic)
|
|
38
|
-
|
|
39
|
-
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.
|
|
40
|
-
|
|
41
|
-
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.
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
# macOS/Linux:
|
|
45
|
-
curl -fsSL -O https://raw.githubusercontent.com/hostinger/api-mcp-server/main/skills/headless/entry/bootstrap.mjs
|
|
46
|
-
# Windows PowerShell:
|
|
47
|
-
iwr https://raw.githubusercontent.com/hostinger/api-mcp-server/main/skills/headless/entry/bootstrap.mjs -OutFile bootstrap.mjs
|
|
48
|
-
|
|
49
|
-
node bootstrap.mjs
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
### Relay these events
|
|
53
|
-
|
|
54
|
-
The script emits one JSON object per line:
|
|
55
|
-
|
|
56
|
-
| Event | What to do |
|
|
57
|
-
| --- | --- |
|
|
58
|
-
| `mcp_ok` | MCP server reachable — continue. |
|
|
59
|
-
| `logged_in` | Already authenticated (env token or a previous sign-in) — continue. |
|
|
60
|
-
| `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. |
|
|
61
|
-
| `success` | Bootstrap done — continue to Phase 2. |
|
|
62
|
-
| `mcp_unreachable` / `login_failed` (with `detail`) | Stop and show the user the `detail`. Do not improvise a parallel setup by hand. |
|
|
63
|
-
|
|
64
|
-
If the environment has a `HOSTINGER_API_TOKEN` set (for example CI), the bootstrap reports `logged_in` immediately — no browser needed.
|
|
65
|
-
|
|
66
|
-
## Phase 2 — Install the skill and hand off
|
|
67
|
-
|
|
68
|
-
Install the Hostinger skills locally so your agent reads files directly with no network calls:
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
npx skills add hostinger/api-mcp-server --yes
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
If the installer is unavailable, fetch the files directly instead — the full set is listed in the skill folder at `https://github.com/hostinger/api-mcp-server/tree/main/skills/headless`.
|
|
75
|
-
|
|
76
|
-
Then open `headless/SKILL.md` and follow it. That skill owns the rest of the run — it resolves the operation (create / connect / iterate), checks the account has a usable hosting plan, provisions the website and domain, seeds the store when commerce is requested, sets up a WordPress content backend when the owner needs to edit content themselves, builds, deploys, and verifies.
|
|
77
|
-
|
|
78
|
-
- Don't provision hosting, create stores, install WordPress, or deploy by hand here — the skill does all of that (`references/SETUP.md`, `references/DEPLOYMENT.md`, `references/STORE.md`, `references/WORDPRESS.md`). This entry stops at signed in.
|
|
79
|
-
- You're already authenticated from Phase 1, so every Hostinger MCP tool call will work without prompting again.
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# Database and runtime — MySQL hosts, env vars, and what to poll
|
|
2
|
-
|
|
3
|
-
Use this when the app needs MySQL, or when a deploy "succeeded" but the app cannot reach its database. Everything here uses the **hosting** MCP operations; Agency Plan differences are at the end.
|
|
4
|
-
|
|
5
|
-
## 1. Create the database
|
|
6
|
-
|
|
7
|
-
1. `hosting_databases_create` on the site's `username` with a database name, a user and a password you generate — name and user are prefixed with the account username automatically.
|
|
8
|
-
2. Read the full, prefixed `name` and `user` back from `hosting_databases_list`; every other database operation wants the full name.
|
|
9
|
-
3. Do not print the password to the user once it is stored, and never commit it.
|
|
10
|
-
|
|
11
|
-
## 2. Which host the app connects to
|
|
12
|
-
|
|
13
|
-
| Where the code runs | Host | Port | Why |
|
|
14
|
-
| --- | --- | --- | --- |
|
|
15
|
-
| PHP on the website | `localhost` or `127.0.0.1` | 3306 | `localhost` uses the MySQL socket; both are granted |
|
|
16
|
-
| Node.js on the website | `127.0.0.1` | 3306 | `localhost` may resolve to IPv6 `::1`, and not every database user has that grant |
|
|
17
|
-
| Outside Hostinger (a laptop, another server) | the `host` from `hosting_databases_list` (`srvNNNN.hstgr.io`) | 3306 | needs `hosting_databases_create-remote-connection` for that client's IP first — never `%`, it opens the database to every address on the internet |
|
|
18
|
-
|
|
19
|
-
Do not put the remote `host` into the deployed app — it has no grant for connections that come from the server itself.
|
|
20
|
-
|
|
21
|
-
## 3. Hand credentials to the app
|
|
22
|
-
|
|
23
|
-
- **Node.js:** environment variables via `hosting_nodejs_replace-environment-variables`. Conventional keys: `DB_HOST=127.0.0.1`, `DB_PORT=3306`, `DB_NAME`, `DB_USER`, `DB_PASSWORD`, plus `DATABASE_URL=mysql://USER:PASSWORD@127.0.0.1:3306/NAME` for ORMs that want one string — URL-encode `USER` and `PASSWORD` there (`encodeURIComponent`), or a password containing `@`, `:`, `/` or `#` breaks the URL. The call is a **full replace**: list the current keys with `hosting_nodejs_list-environment-variables` (values come back masked as `********` — never copy those), then send the complete set with real values. Saving restarts the process; frameworks that bake variables into the build (Next.js, `NEXT_PUBLIC_*`) need a new `hosting_nodejs_start-build` afterwards.
|
|
24
|
-
- **PHP:** a config file on the server that the app reads (its own `config.php`, WordPress's `wp-config.php`). Ship it with the deploy, keep it out of git.
|
|
25
|
-
- **Never** in client-side JavaScript, in a committed `.env`, or in chat replies.
|
|
26
|
-
|
|
27
|
-
## 4. What is asynchronous, and what to poll
|
|
28
|
-
|
|
29
|
-
| You called | Poll this until | Typical wait |
|
|
30
|
-
| --- | --- | --- |
|
|
31
|
-
| `hosting_websites_create` | `hosting_websites_list-setups` with the domain reports `status: completed` | up to a few minutes |
|
|
32
|
-
| `hosting_deploy` of a Node.js app | `hosting_get-deployment` reports a `completed` or `failed` build | minutes |
|
|
33
|
-
| `hosting_nodejs_start-build` (hosted server, which has no `hosting_deploy`) | `hosting_nodejs_build` state is `completed` or `failed` | minutes |
|
|
34
|
-
| `wordpress_installations_install`, plugin/theme/core jobs | `wordpress_installations_list` lists the install | 1–2 minutes |
|
|
35
|
-
| `hosting_databases_repair`, `hosting_websites_delete` | nothing to poll — runs in the background | minutes |
|
|
36
|
-
| `agency-hosting_website-setups_create` | `agency-hosting_website-setups_status` with `setup_uuid` is `completed` | minutes |
|
|
37
|
-
|
|
38
|
-
Poll with backoff (a few seconds, then tens of seconds). A queued response is not a failure, and re-sending the write does not speed it up.
|
|
39
|
-
|
|
40
|
-
## 5. When the app is up but broken
|
|
41
|
-
|
|
42
|
-
- Build failed: `hosting_get-deployment` returns the logs and a diagnosis together (hosted server: `hosting_nodejs_build-logs` for the raw log, `hosting_nodejs_analyse-failed-build` for a diagnosis).
|
|
43
|
-
- Build passed, app errors: `hosting_nodejs_runtime-logs` with a `period` such as `1h`; entries before `last_deployed_at` belong to the previous deploy.
|
|
44
|
-
- `Access denied for user 'x'@'::1'`: the app used `localhost` from Node.js — set `DB_HOST` to `127.0.0.1`.
|
|
45
|
-
- PHP limits (memory, upload size): `hosting_php_get`, then `hosting_php_update-options`.
|
|
46
|
-
|
|
47
|
-
## Agency Plan websites (`agency-hosting_*`)
|
|
48
|
-
|
|
49
|
-
`agency-hosting_databases_create-website` creates the database and its single user; the user is granted on `localhost`, so the PHP app connects to `localhost`. Deploys are synchronous there — `agency-hosting_deploy-php-application` returns when the site is live. Other jobs (SSL, backups) show up in `agency-hosting_websites_list-processes`.
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# Deployment — getting the build live
|
|
2
|
-
|
|
3
|
-
Match the deploy method to what the project actually is — this is the single most common failure point.
|
|
4
|
-
|
|
5
|
-
On the local `hostinger-api-mcp` server one operation does every deploy: `hosting_deploy` with `domain` and `path` (the project directory; it detects the type, packs the files itself; it skips `node_modules`, `.git` and `.env` files, reporting the `.env` ones as `skippedFiles` (set their values with `hosting_nodejs_replace-environment-variables`); it does not read `.gitignore`, so keep build output out of the directory) or `git: { repository, branch }` with `type: "static"` or `"nodejs"` (a new site is not yet detected as Node.js). It reads files from this machine, so the hosted server (`mcp.hostinger.com`) does not have it: there, upload the files and deploy from the upload as described in the `deploy-to-hosting` skill ("Without the local deploy operations"). Agency Plan sites deploy through the Agency operations listed there as well.
|
|
6
|
-
|
|
7
|
-
## Static site → `hosting_deploy` (detected as `static`)
|
|
8
|
-
|
|
9
|
-
For pre-built files only: plain HTML/CSS/JS, or the **build output** of a framework (run the build locally first, then pass the output directory as `path`).
|
|
10
|
-
|
|
11
|
-
- `index.html` must be at the **root** of that directory — not nested inside a folder.
|
|
12
|
-
- Deployment is effectively immediate — verify right after.
|
|
13
|
-
|
|
14
|
-
## Node.js app → `hosting_deploy` (detected as `nodejs`)
|
|
15
|
-
|
|
16
|
-
For anything that needs a server or a server-side build (Express, Next.js, NestJS, SSR frameworks). Pass the project's **source** directory, not the output: the install and build run on Hostinger.
|
|
17
|
-
|
|
18
|
-
- The call returns a `buildUuid` and the build runs on the server. Track it with `hosting_get-deployment` (`domain`) until `build.state` is `completed` or `failed`; on failure the response carries the logs and an analysis — fix, and deploy again. Poll with backoff: builds take minutes, not seconds.
|
|
19
|
-
- When the framework, output directory or entry file is detected wrong, pass `appType`, `outputDirectory`, `buildScript` or `entryFile` to `hosting_deploy`. A TypeScript or other compiled server app always needs `entryFile` set to the built file (for example `dist/server.js`).
|
|
20
|
-
|
|
21
|
-
## WordPress → `hosting_deploy` with `type: "wordpress-site"` / plugin & theme directories
|
|
22
|
-
|
|
23
|
-
Only when the user explicitly wants a WordPress *site* migrated or themed. A site import takes the site directory plus `databaseDump` (a `.sql` file) and can run for several minutes; a plugin or theme directory is detected from its header (`activate: true` activates a theme). (WordPress as a headless content backend behind an agent-built frontend is a different flow — that's `WORDPRESS.md`, installed fresh via the API, not imported here.)
|
|
24
|
-
|
|
25
|
-
## Verify (every deploy)
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
curl -s -o /dev/null -w "%{http_code}\n" https://YOURDOMAIN/
|
|
29
|
-
curl -s https://YOURDOMAIN/ | grep -o "SOME_REAL_HEADLINE_TEXT"
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
Replace the grep target with copy you actually rendered — a 200 alone can be a placeholder page. A freshly created site may serve a default page for a short while; if content doesn't match, clear the cache (`hosting_cache_clear-website`) and retry before assuming the deploy failed. For store runs, also run the checkout verification in `STORE.md`.
|
|
33
|
-
|
|
34
|
-
When the site is live, report the URL and remind the user the site is managed from hPanel (https://hpanel.hostinger.com).
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# Setup — plan check and website provisioning
|
|
2
|
-
|
|
3
|
-
Everything here uses the **hosting** MCP operations. If they're missing, ask the user to enable the Websites product group in the Hostinger Connector (or use the `hostinger-hosting-mcp` scoped binary).
|
|
4
|
-
|
|
5
|
-
## 1. Plan check (gate — run this first)
|
|
6
|
-
|
|
7
|
-
A website can only be created on an active hosting plan.
|
|
8
|
-
|
|
9
|
-
1. `hosting_websites_list` — if it returns websites, the account has a working plan; note any existing `order_id` and `username` for step 2.
|
|
10
|
-
2. Otherwise `hosting_orders_list` — look for an order in a usable state. A fresh order that has never hosted a website still works; note its `order_id`.
|
|
11
|
-
3. Agency Plan orders are not in that list: check `agency-hosting_orders_list` too. An active Agency order is a usable plan — create the website with `agency-hosting_website-setups_create` and poll `agency-hosting_website-setups_status` until `completed` (it returns the `website_uid`), then deploy with the Agency operations in the `deploy-to-hosting` skill.
|
|
12
|
-
4. If there is no usable order: **stop and tell the user** that an active Hostinger hosting plan is required to deploy, link https://www.hostinger.com/web-hosting, and offer to continue building the site locally in the meantime. When they confirm the purchase, re-run this check.
|
|
13
|
-
|
|
14
|
-
Never purchase a plan, domain, or any paid item without the user explicitly approving that specific purchase.
|
|
15
|
-
|
|
16
|
-
## 2. Choose the domain
|
|
17
|
-
|
|
18
|
-
- **Default: free subdomain.** `hosting_domains_generate-free-subdomain` returns a `*.hostingersite.com` domain. No verification needed. Tell the user a custom domain can be connected later.
|
|
19
|
-
- **User-owned domain:** `hosting_domains_verify-ownership` first. If not accessible, relay the TXT record it returns, remind them propagation can take ~10 minutes, and re-verify before continuing.
|
|
20
|
-
- **New domain purchase:** only on explicit request — check availability with `domains_availability_check`, state the price, and get an explicit yes before `domains_portfolio_purchase` (needs the domains product group).
|
|
21
|
-
|
|
22
|
-
## 3. Create the website and wait for it
|
|
23
|
-
|
|
24
|
-
Generating a subdomain does **not** create a website — deploying straight to it fails with `No website found for domain`. The working sequence:
|
|
25
|
-
|
|
26
|
-
1. `hosting_websites_create { domain, order_id }` — `datacenter_code` is required only for the first website on a brand-new plan (pick the first entry from `hosting_datacenters_list`).
|
|
27
|
-
2. **Poll** `hosting_websites_list-setups` filtered by the domain every 10–15 s until `status` is `completed`. The site shows up in `hosting_websites_list` before its setup finishes, and uploads, deploys and database calls return 404 or 409 until then. Creation takes up to a few minutes — don't fail fast.
|
|
28
|
-
3. Note the site's `username` — deployment and database operations are keyed on it.
|
|
29
|
-
|
|
30
|
-
If the domain already has a website (an `iterate` run, or the user pointed at an existing site), skip creation entirely.
|
|
31
|
-
|
|
32
|
-
## 4. Optional extras (only when the run needs them)
|
|
33
|
-
|
|
34
|
-
- **Database:** when the app needs MySQL, follow `DATABASE.md` — creating it, which host each runtime connects to (Node.js must use `127.0.0.1`), and handing the credentials to the app without hard-coding them.
|
|
35
|
-
- **DNS records:** the DNS operations (`dns_records_update` etc.) for custom-domain records; take a snapshot (`dns_snapshots_list` context) before destructive changes.
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
# Store — Hostinger Ecommerce with a custom storefront
|
|
2
|
-
|
|
3
|
-
**Primary source:** execute `ecommerce_miscellaneous_custom-storefront-setup-instructions` at the start of every store run — it returns the current, server-maintained integration guide, and it supersedes this file wherever they disagree. This file carries the essentials so the run can be planned before that call, and a fallback when the ecommerce operations aren't enabled.
|
|
4
|
-
|
|
5
|
-
## Mental model
|
|
6
|
-
|
|
7
|
-
Two API surfaces — don't mix them:
|
|
8
|
-
|
|
9
|
-
| Surface | Base URL | Auth | Use for |
|
|
10
|
-
| --- | --- | --- | --- |
|
|
11
|
-
| Storefront Core V2 | `https://api-ecommerce.hostinger.com/v2` | none (public, open CORS) | read products/variants, checkout — called from the browser |
|
|
12
|
-
| Management (MCP tools) | Hostinger API | authenticated | create stores/products/shipping/payments |
|
|
13
|
-
|
|
14
|
-
- A **store** (`store_*`) has **sales channels** (`scha_*`). The Storefront API is keyed on the **`sales_channel_id`** of a `custom`-type channel — not the store id. Managed channels (e.g. `quick-link`) cannot be used here, and only `custom` channels are API-creatable.
|
|
15
|
-
- **Prices are integers in minor units** (`2900` = €29.00 → divide by `10^decimal_digits`) and live on **variants**, not products.
|
|
16
|
-
- **Security boundary:** storefront reads and checkout are public and run client-side — **never embed a Hostinger API token in the storefront**. Only the management/hosting side (MCP tools) is authenticated.
|
|
17
|
-
|
|
18
|
-
## Backend setup (management tools)
|
|
19
|
-
|
|
20
|
-
1. Resolve the `custom` sales channel: `ecommerce_stores_list` → `ecommerce_sales-channels_list`. If a `custom` channel already exists, confirm with the user that it's the one to use; otherwise add one to the existing store with `ecommerce_sales-channels_create`, or create a store with `ecommerce_stores_create` (with a `custom` sales channel) when no suitable store exists. Set the channel `url` to the storefront's public domain at creation when it's already known.
|
|
21
|
-
2. For checkout to work the store needs all three: ≥ 1 product, ≥ 1 payment method, ≥ 1 shipping zone. Payment, shipping, and currency are store-level — check `ecommerce_stores_metadata` (`has_payment_methods` and `has_shipping` must be `true`; the same response carries `default_currency` with `code`, `decimal_digits`, `template` — read it here rather than guessing). Products are **per sales channel** — verify by listing products for the resolved channel on the Storefront API and confirming the list is non-empty. Seed what's missing with `ecommerce_products_create-physical` / `ecommerce_products_create-digital`, `ecommerce_payments_enable-manual-method`, and `ecommerce_shipping_set-store` (price `0` = free shipping) — confirming with the user before writing to a store that already has real data.
|
|
22
|
-
3. After deploy, point the channel at the live site: `ecommerce_sales-channels_update { store_id, sales_channel_id, url }`.
|
|
23
|
-
|
|
24
|
-
If the ecommerce operations aren't available, ask the user to enable the Ecommerce product group in the Hostinger Connector — or to provide the `sales_channel_id` directly, after which the public endpoints suffice for the frontend work.
|
|
25
|
-
|
|
26
|
-
## Frontend contract
|
|
27
|
-
|
|
28
|
-
The OpenAPI schema for the Storefront API is at `https://api-ecommerce.hostinger.com/v2/docs.json` — fetch it for exact endpoint shapes. Non-obvious rules the schema won't spell out:
|
|
29
|
-
|
|
30
|
-
- **Fetch the catalog at runtime, not build time** — client-side fetch on page load (CORS is open). Baking products into a static build makes the site stale on the first catalog edit. (SSR / Node.js hosting may fetch it server-side per request.)
|
|
31
|
-
- Each variant has a **`prices[]` array** (one entry per currency) — read `prices[0].amount` / `prices[0].sale_amount` (minor units) and `prices[0].currency` (which carries `decimal_digits` and the `template` whose `$1` placeholder you replace when formatting). There is **no** top-level `amount` on a variant.
|
|
32
|
-
- Product detail resolves by **product id** only; a slug returns 404 (map slug→id from the list endpoint). `limit` max is 100 on list endpoints (else 400).
|
|
33
|
-
- Filter variants with `product_ids[]=...`; the unfiltered variant list is eventually-consistent right after catalog edits.
|
|
34
|
-
- Cart lives in the site (e.g. `localStorage`): persist only `variant_id` + `quantity`, resolve display data from the live catalog — never a saved copy — then send everything in one checkout call:
|
|
35
|
-
|
|
36
|
-
```
|
|
37
|
-
POST /channels/{sales_channel_id}/checkout
|
|
38
|
-
{ "items":[{ "variant_id":"variant_01...", "quantity":1 }],
|
|
39
|
-
"success_url":"https://YOURDOMAIN/checkout/success/",
|
|
40
|
-
"cancel_url":"https://YOURDOMAIN/checkout/cancel/",
|
|
41
|
-
"locale":"en" }
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
`success_url`/`cancel_url` are required — build them from `window.location.origin` and make sure both pages exist. The response is `{ url, cart_token }`; redirect the browser to `url` (Hostinger's hosted checkout).
|
|
45
|
-
|
|
46
|
-
A multi-step cart alternative exists (`POST /channels/{sales_channel_id}/carts`, `PATCH /carts/{cart_id}`, `POST /carts/{cart_id}/line-items`, `PUT /carts/{cart_id}/shipping-method`, `POST /carts/{cart_id}/complete`) — the single checkout call suffices for a simple buy flow.
|
|
47
|
-
|
|
48
|
-
## Verify
|
|
49
|
-
|
|
50
|
-
- A `POST` to the checkout endpoint returns a `url` — test it directly with curl before calling the run done.
|
|
51
|
-
- The `success_url`/`cancel_url` pages return 200 (`curl -s -o /dev/null -w "%{http_code}" https://YOURDOMAIN/checkout/success/`).
|
|
52
|
-
- Open the live site, add to cart, and confirm the redirect to `https://checkout.hostinger.com`.
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
# WordPress — headless CMS and blog backend
|
|
2
|
-
|
|
3
|
-
Use WordPress when the site has **owner-managed content**: a blog, news, articles, or any content the owner must edit without a developer or a redeploy. The frontend stays agent-built and is deployed like any other run; WordPress runs separately as the content backend, and the owner writes in wp-admin.
|
|
4
|
-
|
|
5
|
-
**When NOT to use this:** static copy that rarely changes (an about page, a services list, a brochure site) — bake that into the frontend. Installing WordPress for content the owner will never edit adds a moving part for nothing. Any buy/sell intent is `STORE.md`, not this file.
|
|
6
|
-
|
|
7
|
-
Everything in Setup uses the **hosting** and **wordpress** MCP operation groups; ask the user to enable them in the Hostinger Connector if operations are missing.
|
|
8
|
-
|
|
9
|
-
## Mental model
|
|
10
|
-
|
|
11
|
-
Two surfaces, like the store recipe:
|
|
12
|
-
|
|
13
|
-
| Surface | Base URL | Auth | Use for |
|
|
14
|
-
| --- | --- | --- | --- |
|
|
15
|
-
| WP REST API | `https://CMS_DOMAIN/wp-json/wp/v2` | none for published content (open CORS) | frontend reads: posts, pages, media, categories |
|
|
16
|
-
| Management (MCP tools + wp-admin) | Hostinger API / wp-admin | authenticated | install WP, plugins, cache; the owner writes content |
|
|
17
|
-
|
|
18
|
-
- Published content is publicly readable and the REST API allows cross-origin browser reads — a static frontend on another domain fetches it directly at runtime.
|
|
19
|
-
- Drafts, previews, and **writes need authentication** (WP application passwords). Never put credentials of any kind in the frontend; a public site only needs the anonymous read path.
|
|
20
|
-
|
|
21
|
-
## Setup (management tools)
|
|
22
|
-
|
|
23
|
-
1. **Check for an existing installation first**: `wordpress_installations_list` filtered by the site's username/domain. Reuse a valid install when the user agrees — never overwrite one silently.
|
|
24
|
-
2. **Choose where WordPress lives.** Default: a dedicated subdomain of the site, e.g. `cms.<domain>` — create it with `hosting_domains_create-website-subdomain` so the main domain stays free for the frontend. A separate free-subdomain website (per `SETUP.md`) also works when the plan allows another website.
|
|
25
|
-
3. **Install**: `wordpress_installations_install` on that domain. The call only queues the job — **poll** `wordpress_installations_list` until the installation appears (typically 1–2 minutes). Don't proceed on the queued response alone.
|
|
26
|
-
4. **Hand the owner their editor**: mint a one-click wp-admin link with `wordpress_login_create-links` and show it to the user. Content authoring happens in wp-admin — the skill does not seed posts (there is no anonymous write path, by design). The fresh install ships with a sample post, which is enough to build and verify the frontend against.
|
|
27
|
-
5. **Caching** (recommended before finishing): enable the object cache with `wordpress_object-cache_toggle-memcached`; after config changes, purge with `wordpress_litespeed-cache_purge-lite-speed`.
|
|
28
|
-
|
|
29
|
-
## Frontend contract
|
|
30
|
-
|
|
31
|
-
All paths relative to `https://CMS_DOMAIN/wp-json/wp/v2`. Non-obvious rules:
|
|
32
|
-
|
|
33
|
-
- **Fetch at runtime, not build time** — content changes whenever the owner publishes; baking it into a static build defeats the purpose. Client-side fetch on page load is fine (CORS is open).
|
|
34
|
-
- List posts with `/posts?per_page=10&_embed` — `_embed` inlines featured images (`_embedded['wp:featuredmedia'][0].source_url`), authors, and terms; without it you get IDs that need extra requests.
|
|
35
|
-
- Post bodies are **rendered HTML**: use `title.rendered` / `content.rendered` / `excerpt.rendered` and render them as HTML — do not treat them as plain text and do not try to restyle their inner markup beyond CSS.
|
|
36
|
-
- Single post by slug: `/posts?slug=my-post` — returns an **array** (take the first element); there is no direct slug path.
|
|
37
|
-
- Pagination comes from the `X-WP-Total` / `X-WP-TotalPages` response headers, not the body.
|
|
38
|
-
- Only **published** content is returned anonymously. An empty list is a normal state — the frontend must render it gracefully, not error.
|
|
39
|
-
- SEO is the frontend's job: page titles, meta tags, and the sitemap come from the frontend build, not from WordPress plugins.
|
|
40
|
-
|
|
41
|
-
## Verify
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
curl -s -o /dev/null -w "%{http_code}\n" "https://CMS_DOMAIN/wp-json/wp/v2/posts?per_page=1"
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
Expect 200 with a JSON array. Then confirm the deployed frontend renders the sample post (or a clean empty state), and show the user two links: the live site and the wp-admin login for writing content.
|
|
48
|
-
|
|
49
|
-
## Record
|
|
50
|
-
|
|
51
|
-
Add `"cms_domain"` to `.hostinger/site.json` (see `SKILL.md` §Record) so iterate runs know a WordPress backend exists and reuse it instead of installing again.
|