hostinger-api-mcp 2.5.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/gemini-extension.json +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
- package/skills/deploy-to-hosting/SKILL.md +25 -0
- package/skills/headless/references/DATABASE.md +1 -1
- package/skills/headless/references/DEPLOYMENT.md +2 -0
- package/skills/headless/references/SETUP.md +3 -2
- package/skills/migrate-to-hosting/SKILL.md +5 -3
- package/src/core/instructions.js +1 -1
- package/src/core/instructions.ts +1 -1
- package/src/core/runtime.js +1 -1
- package/src/core/runtime.ts +1 -1
- package/src/core/skills.js +15 -15
- package/src/core/skills.ts +15 -15
- package/src/core/tools/all.js +2 -1
- package/src/core/tools/all.ts +2 -1
- package/src/core/tools/billing.js +2 -1
- package/src/core/tools/billing.ts +2 -1
- package/src/servers/agency-hosting.js +1 -1
- package/src/servers/agency-hosting.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/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,24 @@ Generated at release time from the diff between the previous and current
|
|
|
4
4
|
build. Tool changes are listed individually; everything else is summarised
|
|
5
5
|
by area.
|
|
6
6
|
|
|
7
|
+
## v2.6.0 — 2026-09-30
|
|
8
|
+
|
|
9
|
+
### Operations
|
|
10
|
+
|
|
11
|
+
- Changed the input schema of `billing_catalog_list`
|
|
12
|
+
|
|
13
|
+
### Also in this release
|
|
14
|
+
|
|
15
|
+
- Request handling and authentication: `src/core/runtime.js`, `src/core/runtime.ts`
|
|
16
|
+
|
|
17
|
+
## v2.5.1 — 2026-09-30
|
|
18
|
+
|
|
19
|
+
### Also in this release
|
|
20
|
+
|
|
21
|
+
- Bundled agent skills: 5 files
|
|
22
|
+
- Server instructions: `src/core/instructions.js`, `src/core/instructions.ts`
|
|
23
|
+
- Other files: `src/core/skills.js`, `src/core/skills.ts`
|
|
24
|
+
|
|
7
25
|
## v2.5.0 — 2026-09-30
|
|
8
26
|
|
|
9
27
|
### Also in this release
|
package/gemini-extension.json
CHANGED
package/package.json
CHANGED
package/server.json
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
"url": "https://github.com/hostinger/api-mcp-server",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "2.
|
|
9
|
+
"version": "2.6.0",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "@hostinger/mcp",
|
|
14
|
-
"version": "2.
|
|
14
|
+
"version": "2.6.0",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
},
|
|
@@ -42,6 +42,31 @@ Archive rules (name archives `name_YYYYMMDD_HHMMSS.zip`):
|
|
|
42
42
|
- **Node.js source:** no `node_modules/`, no build output (`dist/`, `.next/`, `build/`), no `.env*`, nothing matched by `.gitignore`; 50 MB at most. `git archive --format=zip -o app_20260101_120000.zip HEAD` produces exactly the committed files — mention that uncommitted changes are left out.
|
|
43
43
|
- Agency deploys are synchronous: the site is live when the call returns.
|
|
44
44
|
|
|
45
|
+
The operations in the table read the archive from this machine, so only the local `hostinger-api-mcp` server has them. On the hosted server (`mcp.hostinger.com`) `search` does not find them — upload the files yourself as below.
|
|
46
|
+
|
|
47
|
+
### Without the local deploy operations
|
|
48
|
+
|
|
49
|
+
1. Get upload credentials: `hosting_files_generate-upload-url` (`username`, `domain`); Agency: `agency-hosting_files_generate-upload-url` (`website_uid`). Both return `url`, `auth_key` and `rest_auth_key`, which authenticate the upload instead of the API token.
|
|
50
|
+
2. Upload each file with TUS, where `DEST` is its path in the website's storage:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
SIZE=$(wc -c < "$FILE" | tr -d ' ')
|
|
54
|
+
curl -sS -X POST "$URL/$DEST?override=true" -H "X-Auth: $AUTH_KEY" -H "X-Auth-Rest: $REST_AUTH_KEY" -H "Tus-Resumable: 1.0.0" -H "Upload-Length: $SIZE" -H "Upload-Offset: 0"
|
|
55
|
+
curl -sS -X PATCH "$URL/$DEST?override=true" -H "X-Auth: $AUTH_KEY" -H "X-Auth-Rest: $REST_AUTH_KEY" -H "Tus-Resumable: 1.0.0" -H "Content-Type: application/offset+octet-stream" -H "Upload-Offset: 0" --data-binary "@$FILE"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The first call returns `201`, the second `204` with an `Upload-Offset` header equal to the file size. `override=true` makes a retry safe.
|
|
59
|
+
3. Deploy from the uploaded files (`RANDOM8` is any fresh 8-character string, e.g. `$(LC_ALL=C tr -dc 'a-z0-9' < /dev/urandom | head -c 8)`):
|
|
60
|
+
|
|
61
|
+
| Project | `DEST` | Then |
|
|
62
|
+
| --- | --- | --- |
|
|
63
|
+
| Static or PHP | `site.zip` | `hosting_websites_deploy-static-site-archive` with `archive_path: "site.zip"` |
|
|
64
|
+
| Node.js | `app.zip` | `hosting_nodejs_build-settings-from-archive` with `archive_path: "app.zip"`, then `hosting_nodejs_start-build` with those settings, `source_type: "archive"` and `source_options.archive_path: "app.zip"` |
|
|
65
|
+
| WordPress plugin | every file, as `wp-content/plugins/SLUG-RANDOM8/<path in the plugin>` | `wordpress_plugins_deploy` with `slug` and `plugin_path: "SLUG-RANDOM8"` |
|
|
66
|
+
| WordPress theme | every file, as `wp-content/themes/SLUG-RANDOM8/<path in the theme>` | `wordpress_themes_deploy` with `slug`, `theme_path: "SLUG-RANDOM8"` and optional `is_activated` |
|
|
67
|
+
| Agency, extracted as-is | `.h5g/site.zip` | `agency-hosting_files_import-website-from-archive` with `archive_name: "site.zip"` |
|
|
68
|
+
| Agency `node-static` | `.h5g/RANDOM8/app.zip` | `agency-hosting_websites_build-nodejs-assets` with `archive_path: ".h5g/RANDOM8"` — the directory, not the file |
|
|
69
|
+
|
|
45
70
|
## 3. Node.js builds
|
|
46
71
|
|
|
47
72
|
`hosting_deploy-js-application` uploads the archive to the document root, detects settings from `package.json` and starts a build. Track it with `hosting_nodejs_list-builds` and `hosting_nodejs_build` (by `uuid`), polling every 10–20 s — builds take minutes.
|
|
@@ -28,7 +28,7 @@ Do not put the remote `host` into the deployed app — it has no grant for conne
|
|
|
28
28
|
|
|
29
29
|
| You called | Poll this until | Typical wait |
|
|
30
30
|
| --- | --- | --- |
|
|
31
|
-
| `hosting_websites_create` | `hosting_websites_list`
|
|
31
|
+
| `hosting_websites_create` | `hosting_websites_list-setups` with the domain reports `status: completed` | up to a few minutes |
|
|
32
32
|
| `hosting_deploy-js-application` | `hosting_list-js-deployments` shows the build finished | minutes |
|
|
33
33
|
| `hosting_nodejs_start-build` | `hosting_nodejs_build` state is `completed` or `failed` | minutes |
|
|
34
34
|
| `wordpress_installations_install`, plugin/theme/core jobs | `wordpress_installations_list` lists the install | 1–2 minutes |
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Match the deploy method to what the project actually is — this is the single most common failure point.
|
|
4
4
|
|
|
5
|
+
The deploy operations below read the archive from this machine, so only the local `hostinger-api-mcp` server has them. On the hosted server (`mcp.hostinger.com`) `search` does not find them: 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
|
+
|
|
5
7
|
## Static site → `hosting_deploy-static-website`
|
|
6
8
|
|
|
7
9
|
For pre-built files only: plain HTML/CSS/JS, or the **build output** of a framework (run the build locally first).
|
|
@@ -8,7 +8,8 @@ A website can only be created on an active hosting plan.
|
|
|
8
8
|
|
|
9
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
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.
|
|
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.
|
|
12
13
|
|
|
13
14
|
Never purchase a plan, domain, or any paid item without the user explicitly approving that specific purchase.
|
|
14
15
|
|
|
@@ -23,7 +24,7 @@ Never purchase a plan, domain, or any paid item without the user explicitly appr
|
|
|
23
24
|
Generating a subdomain does **not** create a website — deploying straight to it fails with `No website found for domain`. The working sequence:
|
|
24
25
|
|
|
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`).
|
|
26
|
-
2. **Poll** `hosting_websites_list` filtered by the domain until
|
|
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.
|
|
27
28
|
3. Note the site's `username` — deployment and database operations are keyed on it.
|
|
28
29
|
|
|
29
30
|
If the domain already has a website (an `iterate` run, or the user pointed at an existing site), skip creation entirely.
|
|
@@ -41,9 +41,11 @@ Create the Hostinger website on the domain being migrated, not on a free subdoma
|
|
|
41
41
|
|
|
42
42
|
## 3. Import
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
`hosting_import-wordpress-website`, `hosting_deploy-static-website` and `agency-hosting_deploy-php-application` read files from this machine and exist only in the local `hostinger-api-mcp` server. On the hosted server (`mcp.hostinger.com`), upload the files first as described in the `deploy-to-hosting` skill ("Without the local deploy operations") and use the operation named in brackets below.
|
|
45
45
|
|
|
46
|
-
**
|
|
46
|
+
**WordPress, Shared and Cloud:** `hosting_import-wordpress-website` with `domain`, `archivePath` and `databaseDump` uploads both, extracts the files and imports the database; large sites take several minutes. [Upload `site.zip` and `dump.sql`, then `wordpress_installations_import-website` with `archive_path` and `sql_path`.] Then `wordpress_installations_detect` with `username` and poll `wordpress_installations_list` with `domain` until the install appears with `is_valid: true`.
|
|
47
|
+
|
|
48
|
+
**Static, or PHP without a database:** `hosting_deploy-static-website` [upload, then `hosting_websites_deploy-static-site-archive`]; Agency: `agency-hosting_deploy-php-application` [upload to `.h5g/`, then `agency-hosting_files_import-website-from-archive`].
|
|
47
49
|
|
|
48
50
|
**PHP with a database, Shared and Cloud:**
|
|
49
51
|
|
|
@@ -53,7 +55,7 @@ Create the Hostinger website on the domain being migrated, not on a free subdoma
|
|
|
53
55
|
|
|
54
56
|
**Node.js:** deploy with the `deploy-to-hosting` skill. When a dump must be imported, create the database with `hosting_databases_create` rather than `hosting_databases_setup-website` — the latter never reveals the password needed for the import — and pass the credentials through environment variables.
|
|
55
57
|
|
|
56
|
-
**Agency:** files with `agency-hosting_deploy-php-application
|
|
58
|
+
**Agency:** files with `agency-hosting_deploy-php-application` [or upload plus `agency-hosting_files_import-website-from-archive`]; the database with `agency-hosting_databases_create-website`, imported through phpMyAdmin in hPanel (no import operation exists). For WordPress, set the new credentials in `wp-config.php` before archiving.
|
|
57
59
|
|
|
58
60
|
## 4. Test before DNS moves
|
|
59
61
|
|
package/src/core/instructions.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Auto-generated server instructions
|
|
2
|
-
export default "Hostinger API notes for agents. Find operations with search; the inputSchema it returns is authoritative for request shapes. Run one with execute, or chain several with multi-execute.\n\nDatabases (web hosting, hosting_* operations)\n- MySQL runs on the same server as the website. From the deployed app connect to host 127.0.0.1, port 3306. PHP may also use localhost (Unix socket). Node.js should use 127.0.0.1: localhost can resolve to IPv6 (::1) and not every database user has that grant.\n- The `host` from hosting_databases_list (srvNNNN.hstgr.io) is only for connections from outside Hostinger, after hosting_databases_create-remote-connection. Never use it from the app.\n- Agency Plan (agency-hosting_* operations) database users are created for localhost; the PHP app connects there.\n\nAsynchronous operations\n- A success response often means \"queued\", not \"done\". Poll the matching read operation with backoff (seconds, then minutes). Never re-send the write.\n- hosting_websites_create -> poll hosting_websites_list
|
|
2
|
+
export default "Hostinger API notes for agents. Find operations with search; the inputSchema it returns is authoritative for request shapes. Run one with execute, or chain several with multi-execute.\n\nDatabases (web hosting, hosting_* operations)\n- MySQL runs on the same server as the website. From the deployed app connect to host 127.0.0.1, port 3306. PHP may also use localhost (Unix socket). Node.js should use 127.0.0.1: localhost can resolve to IPv6 (::1) and not every database user has that grant.\n- The `host` from hosting_databases_list (srvNNNN.hstgr.io) is only for connections from outside Hostinger, after hosting_databases_create-remote-connection. Never use it from the app.\n- Agency Plan (agency-hosting_* operations) database users are created for localhost; the PHP app connects there.\n\nAsynchronous operations\n- A success response often means \"queued\", not \"done\". Poll the matching read operation with backoff (seconds, then minutes). Never re-send the write.\n- hosting_websites_create -> poll hosting_websites_list-setups with the domain until status is completed (a few minutes); file, deploy and database calls return 404/409 before that.\n- hosting_nodejs_start-build -> hosting_nodejs_build; logs via hosting_nodejs_build-logs; on failure hosting_nodejs_analyse-failed-build.\n- wordpress_installations_install and WordPress plugin/theme/core jobs -> poll wordpress_installations_list.\n- agency-hosting_website-setups_create -> poll agency-hosting_website-setups_status with setup_uuid; other Agency Plan jobs -> agency-hosting_websites_list-processes.\n- Website deletion, database repair and domain contact changes finish in the background.\n\nCredentials\n- Never write database passwords or API tokens into source code, client-side JavaScript or committed .env files.\n- Node.js apps read them from environment variables: set the full set with hosting_nodejs_replace-environment-variables (full replace; values are masked on read). Build-time variables (Next.js) need a new build afterwards.\n- PHP apps read them from a config file on the server, outside the repository.\n- Generate strong passwords and do not echo them back once stored.\n\nFor end-to-end site builds install the headless skill: npx skills add hostinger/api-mcp-server";
|
package/src/core/instructions.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// Auto-generated server instructions
|
|
2
|
-
const instructions: string = "Hostinger API notes for agents. Find operations with search; the inputSchema it returns is authoritative for request shapes. Run one with execute, or chain several with multi-execute.\n\nDatabases (web hosting, hosting_* operations)\n- MySQL runs on the same server as the website. From the deployed app connect to host 127.0.0.1, port 3306. PHP may also use localhost (Unix socket). Node.js should use 127.0.0.1: localhost can resolve to IPv6 (::1) and not every database user has that grant.\n- The `host` from hosting_databases_list (srvNNNN.hstgr.io) is only for connections from outside Hostinger, after hosting_databases_create-remote-connection. Never use it from the app.\n- Agency Plan (agency-hosting_* operations) database users are created for localhost; the PHP app connects there.\n\nAsynchronous operations\n- A success response often means \"queued\", not \"done\". Poll the matching read operation with backoff (seconds, then minutes). Never re-send the write.\n- hosting_websites_create -> poll hosting_websites_list
|
|
2
|
+
const instructions: string = "Hostinger API notes for agents. Find operations with search; the inputSchema it returns is authoritative for request shapes. Run one with execute, or chain several with multi-execute.\n\nDatabases (web hosting, hosting_* operations)\n- MySQL runs on the same server as the website. From the deployed app connect to host 127.0.0.1, port 3306. PHP may also use localhost (Unix socket). Node.js should use 127.0.0.1: localhost can resolve to IPv6 (::1) and not every database user has that grant.\n- The `host` from hosting_databases_list (srvNNNN.hstgr.io) is only for connections from outside Hostinger, after hosting_databases_create-remote-connection. Never use it from the app.\n- Agency Plan (agency-hosting_* operations) database users are created for localhost; the PHP app connects there.\n\nAsynchronous operations\n- A success response often means \"queued\", not \"done\". Poll the matching read operation with backoff (seconds, then minutes). Never re-send the write.\n- hosting_websites_create -> poll hosting_websites_list-setups with the domain until status is completed (a few minutes); file, deploy and database calls return 404/409 before that.\n- hosting_nodejs_start-build -> hosting_nodejs_build; logs via hosting_nodejs_build-logs; on failure hosting_nodejs_analyse-failed-build.\n- wordpress_installations_install and WordPress plugin/theme/core jobs -> poll wordpress_installations_list.\n- agency-hosting_website-setups_create -> poll agency-hosting_website-setups_status with setup_uuid; other Agency Plan jobs -> agency-hosting_websites_list-processes.\n- Website deletion, database repair and domain contact changes finish in the background.\n\nCredentials\n- Never write database passwords or API tokens into source code, client-side JavaScript or committed .env files.\n- Node.js apps read them from environment variables: set the full set with hosting_nodejs_replace-environment-variables (full replace; values are masked on read). Build-time variables (Next.js) need a new build afterwards.\n- PHP apps read them from a config file on the server, outside the repository.\n- Generate strong passwords and do not echo them back once stored.\n\nFor end-to-end site builds install the headless skill: npx skills add hostinger/api-mcp-server";
|
|
3
3
|
export default instructions;
|
package/src/core/runtime.js
CHANGED
|
@@ -64,7 +64,7 @@ const GetSkillRequestSchema = z.object({
|
|
|
64
64
|
|
|
65
65
|
/**
|
|
66
66
|
* MCP Server for Hostinger API
|
|
67
|
-
* Generated from OpenAPI spec version 1.
|
|
67
|
+
* Generated from OpenAPI spec version 1.57.0
|
|
68
68
|
*/
|
|
69
69
|
class MCPServer {
|
|
70
70
|
constructor({ name, version, tools, instructions, skills = [] }) {
|
package/src/core/runtime.ts
CHANGED
|
@@ -94,7 +94,7 @@ interface Skill { uri: string; frontmatter: Record<string, unknown>; resources:
|
|
|
94
94
|
|
|
95
95
|
/**
|
|
96
96
|
* MCP Server for Hostinger API
|
|
97
|
-
* Generated from OpenAPI spec version 1.
|
|
97
|
+
* Generated from OpenAPI spec version 1.57.0
|
|
98
98
|
*/
|
|
99
99
|
class MCPServer {
|
|
100
100
|
private readonly name: string;
|
package/src/core/skills.js
CHANGED
|
@@ -41,10 +41,10 @@ export default [
|
|
|
41
41
|
"resources": [
|
|
42
42
|
{
|
|
43
43
|
"uri": "skill://deploy-to-hosting/SKILL.md",
|
|
44
|
-
"digest": "sha256:
|
|
45
|
-
"size":
|
|
44
|
+
"digest": "sha256:961503b81556b6fde88183e9a0b26704f461a880e2085e739512415f1a3e6df9",
|
|
45
|
+
"size": 11009,
|
|
46
46
|
"mimeType": "text/markdown",
|
|
47
|
-
"text": "---\nname: deploy-to-hosting\ndescription: \"Deploy an existing project to a website on Hostinger web hosting (Shared, Cloud or Agency plans) and keep it deployed: picks the right deploy for static sites, Node.js apps (Next.js, Nuxt, Express, Vite and similar), PHP apps and WordPress plugins or themes, sets up auto-deploy from GitHub or GitLab, manages Node.js environment variables and MySQL databases, and verifies the live site. Triggers: deploy this project, deploy to Hostinger, push my app live, redeploy, set up auto-deploy, connect my GitHub repo, add environment variables, my app needs a database, deploy my WordPress plugin or theme.\"\n---\n\n# Deploy to hosting\n\nShip a project that already exists — on disk or in a Git repository — to a Hostinger website. Building a new site from a prompt (design, store, blog) is the `hostinger-headless` skill; this one takes code as it is.\n\n## Calling the operations\n\n- Read the `inputSchema` that `search` returns before the first call of each operation. If a name below is rejected as unknown, `search` for what the step does (e.g. \"deploy static\").\n- Batch reads with `multi-execute`; values pass between steps as `$steps.<i>.<path>`. Batches chain operations from one server only — the Hostinger Connector runs `hosting`, `wordpress` and `agency-hosting` as separate servers.\n- Every deploy overwrites the website's current contents. Confirm the target domain with the user before the first deploy to a site that already has content.\n\n## 1. Pick the target website\n\n- `.hostinger/site.json` in the project: reuse its `domain` and `username` (or `website_uid`).\n- Otherwise look the domain up with `hosting_websites_list` (Shared and Cloud; substring match — take the exact entry) and `agency-hosting_websites_list-plan` (Agency; keep `details.uid`).\n- No website yet:\n - Shared and Cloud: take a domain (the user's own, or `hosting_domains_generate-free-subdomain`) and an `order_id` from `hosting_orders_list`, then `hosting_websites_create`. `datacenter_code` is needed only for the first website on a new plan (first entry of `hosting_datacenters_list`). Poll `hosting_websites_list-setups` with `domain` every 10–15 s until `status: completed` — uploads and deploys return 404 or 409 before that.\n - Agency: `agency-hosting_website-setups_create` with `flavor: \"php-fpm\"` (plus `type: \"node-static\"` for built frontends), `settings.php.version` from `agency-hosting_php_list-versions-for-order` and `datacenter_code` from `agency-hosting_datacenters_list`. Poll `agency-hosting_website-setups_status` until `completed`; it returns the `website_uid`.\n- Node.js apps run on Business and Cloud plans (`hostinger_business_*`, `cloud_*` in `hosting_orders_list`). On other plans, build locally and deploy the output as a static site.\n\n## 2. Choose the deploy\n\nWrong method is the most common failure. Decide from the project on disk:\n\n| Project | Shared / Cloud |\n| --- | --- |\n| Plain HTML/CSS/JS, or a framework's static build output | `hosting_deploy-static-website` |\n| `package.json` with a build or a server (Next.js, Nuxt, Express, Vite…) | `hosting_deploy-js-application` |\n| PHP code, no build step | `hosting_deploy-static-website` (extracts the archive as-is) |\n| WordPress plugin or theme folder | `hosting_deploy-wordpress-plugin` / `hosting_deploy-wordpress-theme` (`activate` optional) |\n| A whole WordPress site from elsewhere | the `migrate-to-hosting` skill |\n\nOn Agency the website's type decides (`agency-hosting_websites_get`): sites created as `node-static` take `agency-hosting_deploy-node-static-website`, which runs the build when the project has one; every other site takes `agency-hosting_deploy-php-application`, which extracts the archive as-is. WordPress plugins and themes on Agency sites are installed from wp-admin.\n\nArchive rules (name archives `name_YYYYMMDD_HHMMSS.zip`):\n\n- **Static:** build locally first. `index.html` must be at the archive root, not inside a folder: `cd dist && zip -r ../site_20260101_120000.zip .`\n- **Node.js source:** no `node_modules/`, no build output (`dist/`, `.next/`, `build/`), no `.env*`, nothing matched by `.gitignore`; 50 MB at most. `git archive --format=zip -o app_20260101_120000.zip HEAD` produces exactly the committed files — mention that uncommitted changes are left out.\n- Agency deploys are synchronous: the site is live when the call returns.\n\n## 3. Node.js builds\n\n`hosting_deploy-js-application` uploads the archive to the document root, detects settings from `package.json` and starts a build. Track it with `hosting_nodejs_list-builds` and `hosting_nodejs_build` (by `uuid`), polling every 10–20 s — builds take minutes.\n\n- Failed build: `hosting_nodejs_analyse-failed-build` once per build (5 calls a minute), then `hosting_nodejs_build-logs` if the analysis is empty.\n- Wrong detection (framework, `output_directory`, or a missing `entry_file` for express, fastify, nest, nuxt and hono): run `hosting_nodejs_start-build` with explicit values, `source_type: \"archive\"` and `source_options.archive_path` set to the archive's file name in the document root (check it is there with `hosting_files_list-website-and-directories`). Store the same values with `hosting_nodejs_update-build-settings`.\n- To review detected settings before any build: upload the archive with `hosting_files_generate-upload-url` (the TUS steps are in its description), then `hosting_nodejs_build-settings-from-archive`.\n\n## 4. Auto-deploy from Git\n\n1. `hosting_git_list-installations`. With no `active` installation (check `status: \"pending\"` and `\"suspended\"` too), the user connects GitHub or GitLab once in hPanel under Websites → Manage → Advanced → Git; there is no API for that step.\n2. `hosting_git_list-installation-repositories` with the installation `uuid` gives `owner`, `name` and `default_branch` (10 calls a minute).\n3. `hosting_git_update-auto-deployment-settings` with `installation_uuid`, `owner`, `repository`, `branch` and optional `directory`.\n - PHP and static sites deploy the branch immediately and again on every push.\n - Node.js sites clone nothing on save: start the first build with `hosting_nodejs_start-build`, `source_type: \"git\"` and the same `source_options`. Later pushes build with the stored settings, so keep `hosting_nodejs_update-build-settings` correct.\n4. Confirm with `hosting_git_auto-deployment-settings`.\n\nAgency Plan sites have no Git operations; deploy archives.\n\n## 5. Environment variables (Node.js)\n\n`hosting_nodejs_replace-environment-variables` replaces the whole set — anything not sent is deleted.\n\n1. `hosting_nodejs_list-environment-variables` for the current keys. Values come back as `********`; never send those back.\n2. Build the full set: every current key plus the new ones, with real values from the project's `.env` or the user. When the real value of an existing key is unknown, ask — do not drop it.\n3. Send it once; the app restarts. Values baked in at build time (Next.js `NEXT_PUBLIC_*`, Vite `VITE_*`) need a new `hosting_nodejs_start-build`.\n\nKeys use uppercase letters, digits and underscores. Never commit `.env` files or repeat secret values back to the user.\n\n## 6. Database\n\n- **Node.js:** `hosting_databases_setup-website` creates a MySQL database and writes `DB_HOST`, `DB_PORT`, `DB_NAME`, `DB_USER`, `DB_PASSWORD` and `DATABASE_URL` into the environment, then restarts the app. The password is generated and never returned. It fails with 422 when any of those keys exists — remove them first with the step 5 replace.\n- **PHP:** `hosting_databases_create` with `name`, `user`, a strong generated `password` and `website_domain`; read the prefixed full name back from `hosting_databases_list`. The app reads credentials from a config file on the server that stays out of Git, and connects to `localhost` or `127.0.0.1`.\n- **Agency:** `agency-hosting_databases_create-website`; the app connects to `localhost`.\n- The `srvNNNN.hstgr.io` host from `hosting_databases_list` is only for connections from outside Hostinger — never put it in the deployed app.\n\n## 7. Verify and record\n\n```bash\ncurl -s -o /dev/null -w \"%{http_code}\\n\" https://DOMAIN/\ncurl -s https://DOMAIN/ | grep -o \"TEXT THE PROJECT RENDERS\"\n```\n\nA `200` alone can be a placeholder page; match real copy. A new site may serve a default page briefly — clear it with `hosting_cache_clear-website` and retry before calling the deploy failed.\n\nWrite `.hostinger/site.json` in the project so later runs reuse the target: `{ \"domain\", \"username\" or \"website_uid\", \"type\": \"static\" | \"nodejs\" | \"php\" }`, keeping any fields already there.\n"
|
|
47
|
+
"text": "---\nname: deploy-to-hosting\ndescription: \"Deploy an existing project to a website on Hostinger web hosting (Shared, Cloud or Agency plans) and keep it deployed: picks the right deploy for static sites, Node.js apps (Next.js, Nuxt, Express, Vite and similar), PHP apps and WordPress plugins or themes, sets up auto-deploy from GitHub or GitLab, manages Node.js environment variables and MySQL databases, and verifies the live site. Triggers: deploy this project, deploy to Hostinger, push my app live, redeploy, set up auto-deploy, connect my GitHub repo, add environment variables, my app needs a database, deploy my WordPress plugin or theme.\"\n---\n\n# Deploy to hosting\n\nShip a project that already exists — on disk or in a Git repository — to a Hostinger website. Building a new site from a prompt (design, store, blog) is the `hostinger-headless` skill; this one takes code as it is.\n\n## Calling the operations\n\n- Read the `inputSchema` that `search` returns before the first call of each operation. If a name below is rejected as unknown, `search` for what the step does (e.g. \"deploy static\").\n- Batch reads with `multi-execute`; values pass between steps as `$steps.<i>.<path>`. Batches chain operations from one server only — the Hostinger Connector runs `hosting`, `wordpress` and `agency-hosting` as separate servers.\n- Every deploy overwrites the website's current contents. Confirm the target domain with the user before the first deploy to a site that already has content.\n\n## 1. Pick the target website\n\n- `.hostinger/site.json` in the project: reuse its `domain` and `username` (or `website_uid`).\n- Otherwise look the domain up with `hosting_websites_list` (Shared and Cloud; substring match — take the exact entry) and `agency-hosting_websites_list-plan` (Agency; keep `details.uid`).\n- No website yet:\n - Shared and Cloud: take a domain (the user's own, or `hosting_domains_generate-free-subdomain`) and an `order_id` from `hosting_orders_list`, then `hosting_websites_create`. `datacenter_code` is needed only for the first website on a new plan (first entry of `hosting_datacenters_list`). Poll `hosting_websites_list-setups` with `domain` every 10–15 s until `status: completed` — uploads and deploys return 404 or 409 before that.\n - Agency: `agency-hosting_website-setups_create` with `flavor: \"php-fpm\"` (plus `type: \"node-static\"` for built frontends), `settings.php.version` from `agency-hosting_php_list-versions-for-order` and `datacenter_code` from `agency-hosting_datacenters_list`. Poll `agency-hosting_website-setups_status` until `completed`; it returns the `website_uid`.\n- Node.js apps run on Business and Cloud plans (`hostinger_business_*`, `cloud_*` in `hosting_orders_list`). On other plans, build locally and deploy the output as a static site.\n\n## 2. Choose the deploy\n\nWrong method is the most common failure. Decide from the project on disk:\n\n| Project | Shared / Cloud |\n| --- | --- |\n| Plain HTML/CSS/JS, or a framework's static build output | `hosting_deploy-static-website` |\n| `package.json` with a build or a server (Next.js, Nuxt, Express, Vite…) | `hosting_deploy-js-application` |\n| PHP code, no build step | `hosting_deploy-static-website` (extracts the archive as-is) |\n| WordPress plugin or theme folder | `hosting_deploy-wordpress-plugin` / `hosting_deploy-wordpress-theme` (`activate` optional) |\n| A whole WordPress site from elsewhere | the `migrate-to-hosting` skill |\n\nOn Agency the website's type decides (`agency-hosting_websites_get`): sites created as `node-static` take `agency-hosting_deploy-node-static-website`, which runs the build when the project has one; every other site takes `agency-hosting_deploy-php-application`, which extracts the archive as-is. WordPress plugins and themes on Agency sites are installed from wp-admin.\n\nArchive rules (name archives `name_YYYYMMDD_HHMMSS.zip`):\n\n- **Static:** build locally first. `index.html` must be at the archive root, not inside a folder: `cd dist && zip -r ../site_20260101_120000.zip .`\n- **Node.js source:** no `node_modules/`, no build output (`dist/`, `.next/`, `build/`), no `.env*`, nothing matched by `.gitignore`; 50 MB at most. `git archive --format=zip -o app_20260101_120000.zip HEAD` produces exactly the committed files — mention that uncommitted changes are left out.\n- Agency deploys are synchronous: the site is live when the call returns.\n\nThe operations in the table read the archive from this machine, so only the local `hostinger-api-mcp` server has them. On the hosted server (`mcp.hostinger.com`) `search` does not find them — upload the files yourself as below.\n\n### Without the local deploy operations\n\n1. Get upload credentials: `hosting_files_generate-upload-url` (`username`, `domain`); Agency: `agency-hosting_files_generate-upload-url` (`website_uid`). Both return `url`, `auth_key` and `rest_auth_key`, which authenticate the upload instead of the API token.\n2. Upload each file with TUS, where `DEST` is its path in the website's storage:\n\n```bash\nSIZE=$(wc -c < \"$FILE\" | tr -d ' ')\ncurl -sS -X POST \"$URL/$DEST?override=true\" -H \"X-Auth: $AUTH_KEY\" -H \"X-Auth-Rest: $REST_AUTH_KEY\" -H \"Tus-Resumable: 1.0.0\" -H \"Upload-Length: $SIZE\" -H \"Upload-Offset: 0\"\ncurl -sS -X PATCH \"$URL/$DEST?override=true\" -H \"X-Auth: $AUTH_KEY\" -H \"X-Auth-Rest: $REST_AUTH_KEY\" -H \"Tus-Resumable: 1.0.0\" -H \"Content-Type: application/offset+octet-stream\" -H \"Upload-Offset: 0\" --data-binary \"@$FILE\"\n```\n\n The first call returns `201`, the second `204` with an `Upload-Offset` header equal to the file size. `override=true` makes a retry safe.\n3. Deploy from the uploaded files (`RANDOM8` is any fresh 8-character string, e.g. `$(LC_ALL=C tr -dc 'a-z0-9' < /dev/urandom | head -c 8)`):\n\n| Project | `DEST` | Then |\n| --- | --- | --- |\n| Static or PHP | `site.zip` | `hosting_websites_deploy-static-site-archive` with `archive_path: \"site.zip\"` |\n| Node.js | `app.zip` | `hosting_nodejs_build-settings-from-archive` with `archive_path: \"app.zip\"`, then `hosting_nodejs_start-build` with those settings, `source_type: \"archive\"` and `source_options.archive_path: \"app.zip\"` |\n| WordPress plugin | every file, as `wp-content/plugins/SLUG-RANDOM8/<path in the plugin>` | `wordpress_plugins_deploy` with `slug` and `plugin_path: \"SLUG-RANDOM8\"` |\n| WordPress theme | every file, as `wp-content/themes/SLUG-RANDOM8/<path in the theme>` | `wordpress_themes_deploy` with `slug`, `theme_path: \"SLUG-RANDOM8\"` and optional `is_activated` |\n| Agency, extracted as-is | `.h5g/site.zip` | `agency-hosting_files_import-website-from-archive` with `archive_name: \"site.zip\"` |\n| Agency `node-static` | `.h5g/RANDOM8/app.zip` | `agency-hosting_websites_build-nodejs-assets` with `archive_path: \".h5g/RANDOM8\"` — the directory, not the file |\n\n## 3. Node.js builds\n\n`hosting_deploy-js-application` uploads the archive to the document root, detects settings from `package.json` and starts a build. Track it with `hosting_nodejs_list-builds` and `hosting_nodejs_build` (by `uuid`), polling every 10–20 s — builds take minutes.\n\n- Failed build: `hosting_nodejs_analyse-failed-build` once per build (5 calls a minute), then `hosting_nodejs_build-logs` if the analysis is empty.\n- Wrong detection (framework, `output_directory`, or a missing `entry_file` for express, fastify, nest, nuxt and hono): run `hosting_nodejs_start-build` with explicit values, `source_type: \"archive\"` and `source_options.archive_path` set to the archive's file name in the document root (check it is there with `hosting_files_list-website-and-directories`). Store the same values with `hosting_nodejs_update-build-settings`.\n- To review detected settings before any build: upload the archive with `hosting_files_generate-upload-url` (the TUS steps are in its description), then `hosting_nodejs_build-settings-from-archive`.\n\n## 4. Auto-deploy from Git\n\n1. `hosting_git_list-installations`. With no `active` installation (check `status: \"pending\"` and `\"suspended\"` too), the user connects GitHub or GitLab once in hPanel under Websites → Manage → Advanced → Git; there is no API for that step.\n2. `hosting_git_list-installation-repositories` with the installation `uuid` gives `owner`, `name` and `default_branch` (10 calls a minute).\n3. `hosting_git_update-auto-deployment-settings` with `installation_uuid`, `owner`, `repository`, `branch` and optional `directory`.\n - PHP and static sites deploy the branch immediately and again on every push.\n - Node.js sites clone nothing on save: start the first build with `hosting_nodejs_start-build`, `source_type: \"git\"` and the same `source_options`. Later pushes build with the stored settings, so keep `hosting_nodejs_update-build-settings` correct.\n4. Confirm with `hosting_git_auto-deployment-settings`.\n\nAgency Plan sites have no Git operations; deploy archives.\n\n## 5. Environment variables (Node.js)\n\n`hosting_nodejs_replace-environment-variables` replaces the whole set — anything not sent is deleted.\n\n1. `hosting_nodejs_list-environment-variables` for the current keys. Values come back as `********`; never send those back.\n2. Build the full set: every current key plus the new ones, with real values from the project's `.env` or the user. When the real value of an existing key is unknown, ask — do not drop it.\n3. Send it once; the app restarts. Values baked in at build time (Next.js `NEXT_PUBLIC_*`, Vite `VITE_*`) need a new `hosting_nodejs_start-build`.\n\nKeys use uppercase letters, digits and underscores. Never commit `.env` files or repeat secret values back to the user.\n\n## 6. Database\n\n- **Node.js:** `hosting_databases_setup-website` creates a MySQL database and writes `DB_HOST`, `DB_PORT`, `DB_NAME`, `DB_USER`, `DB_PASSWORD` and `DATABASE_URL` into the environment, then restarts the app. The password is generated and never returned. It fails with 422 when any of those keys exists — remove them first with the step 5 replace.\n- **PHP:** `hosting_databases_create` with `name`, `user`, a strong generated `password` and `website_domain`; read the prefixed full name back from `hosting_databases_list`. The app reads credentials from a config file on the server that stays out of Git, and connects to `localhost` or `127.0.0.1`.\n- **Agency:** `agency-hosting_databases_create-website`; the app connects to `localhost`.\n- The `srvNNNN.hstgr.io` host from `hosting_databases_list` is only for connections from outside Hostinger — never put it in the deployed app.\n\n## 7. Verify and record\n\n```bash\ncurl -s -o /dev/null -w \"%{http_code}\\n\" https://DOMAIN/\ncurl -s https://DOMAIN/ | grep -o \"TEXT THE PROJECT RENDERS\"\n```\n\nA `200` alone can be a placeholder page; match real copy. A new site may serve a default page briefly — clear it with `hosting_cache_clear-website` and retry before calling the deploy failed.\n\nWrite `.hostinger/site.json` in the project so later runs reuse the target: `{ \"domain\", \"username\" or \"website_uid\", \"type\": \"static\" | \"nodejs\" | \"php\" }`, keeping any fields already there.\n"
|
|
48
48
|
}
|
|
49
49
|
]
|
|
50
50
|
},
|
|
@@ -64,24 +64,24 @@ export default [
|
|
|
64
64
|
},
|
|
65
65
|
{
|
|
66
66
|
"uri": "skill://hostinger-headless/references/DATABASE.md",
|
|
67
|
-
"digest": "sha256:
|
|
68
|
-
"size":
|
|
67
|
+
"digest": "sha256:c81159d8d4d9c36604425dd8afee5a22a4cd2286b23ad167ade9db8c478efc7f",
|
|
68
|
+
"size": 4333,
|
|
69
69
|
"mimeType": "text/markdown",
|
|
70
|
-
"text": "# Database and runtime — MySQL hosts, env vars, and what to poll\n\nUse 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.\n\n## 1. Create the database\n\n1. `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.\n2. Read the full, prefixed `name` and `user` back from `hosting_databases_list`; every other database operation wants the full name.\n3. Do not print the password to the user once it is stored, and never commit it.\n\n## 2. Which host the app connects to\n\n| Where the code runs | Host | Port | Why |\n| --- | --- | --- | --- |\n| PHP on the website | `localhost` or `127.0.0.1` | 3306 | `localhost` uses the MySQL socket; both are granted |\n| Node.js on the website | `127.0.0.1` | 3306 | `localhost` may resolve to IPv6 `::1`, and not every database user has that grant |\n| 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 |\n\nDo not put the remote `host` into the deployed app — it has no grant for connections that come from the server itself.\n\n## 3. Hand credentials to the app\n\n- **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.\n- **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.\n- **Never** in client-side JavaScript, in a committed `.env`, or in chat replies.\n\n## 4. What is asynchronous, and what to poll\n\n| You called | Poll this until | Typical wait |\n| --- | --- | --- |\n| `hosting_websites_create` | `hosting_websites_list`
|
|
70
|
+
"text": "# Database and runtime — MySQL hosts, env vars, and what to poll\n\nUse 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.\n\n## 1. Create the database\n\n1. `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.\n2. Read the full, prefixed `name` and `user` back from `hosting_databases_list`; every other database operation wants the full name.\n3. Do not print the password to the user once it is stored, and never commit it.\n\n## 2. Which host the app connects to\n\n| Where the code runs | Host | Port | Why |\n| --- | --- | --- | --- |\n| PHP on the website | `localhost` or `127.0.0.1` | 3306 | `localhost` uses the MySQL socket; both are granted |\n| Node.js on the website | `127.0.0.1` | 3306 | `localhost` may resolve to IPv6 `::1`, and not every database user has that grant |\n| 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 |\n\nDo not put the remote `host` into the deployed app — it has no grant for connections that come from the server itself.\n\n## 3. Hand credentials to the app\n\n- **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.\n- **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.\n- **Never** in client-side JavaScript, in a committed `.env`, or in chat replies.\n\n## 4. What is asynchronous, and what to poll\n\n| You called | Poll this until | Typical wait |\n| --- | --- | --- |\n| `hosting_websites_create` | `hosting_websites_list-setups` with the domain reports `status: completed` | up to a few minutes |\n| `hosting_deploy-js-application` | `hosting_list-js-deployments` shows the build finished | minutes |\n| `hosting_nodejs_start-build` | `hosting_nodejs_build` state is `completed` or `failed` | minutes |\n| `wordpress_installations_install`, plugin/theme/core jobs | `wordpress_installations_list` lists the install | 1–2 minutes |\n| `hosting_databases_repair`, `hosting_websites_delete` | nothing to poll — runs in the background | minutes |\n| `agency-hosting_website-setups_create` | `agency-hosting_website-setups_status` with `setup_uuid` is `completed` | minutes |\n\nPoll 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.\n\n## 5. When the app is up but broken\n\n- Build failed: `hosting_nodejs_build-logs` for the raw log, `hosting_nodejs_analyse-failed-build` for a diagnosis.\n- Build passed, app errors: `hosting_nodejs_runtime-logs` with a `period` such as `1h`; entries before `last_deployed_at` belong to the previous deploy.\n- `Access denied for user 'x'@'::1'`: the app used `localhost` from Node.js — set `DB_HOST` to `127.0.0.1`.\n- PHP limits (memory, upload size): `hosting_php_get`, then `hosting_php_update-options`.\n\n## Agency Plan websites (`agency-hosting_*`)\n\n`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`.\n"
|
|
71
71
|
},
|
|
72
72
|
{
|
|
73
73
|
"uri": "skill://hostinger-headless/references/DEPLOYMENT.md",
|
|
74
|
-
"digest": "sha256:
|
|
75
|
-
"size":
|
|
74
|
+
"digest": "sha256:a82e1b7dc8d6155419c8d72cc0f060f6592ea176b506a175760f4ac2a2ecccf4",
|
|
75
|
+
"size": 2570,
|
|
76
76
|
"mimeType": "text/markdown",
|
|
77
|
-
"text": "# Deployment — getting the build live\n\nMatch the deploy method to what the project actually is — this is the single most common failure point.\n\n## Static site → `hosting_deploy-static-website`\n\nFor pre-built files only: plain HTML/CSS/JS, or the **build output** of a framework (run the build locally first).\n\n- The archive (zip/tar) must have `index.html` at its **root** — not nested inside a folder.\n- Name it `name_YYYYMMDD_HHMMSS.zip`; pass `removeArchive: true` to clean up after upload.\n- Deployment is effectively immediate — verify right after.\n\n## Node.js app → `hosting_deploy-js-application`\n\nFor anything that needs a server or a server-side build (Express, Next.js, NestJS, SSR frameworks).\n\n- Archive the **source**, not the output: exclude `node_modules/`, `dist/`, `.next/`, `build/`, and everything matched by `.gitignore`. The install and build run on Hostinger.\n- Hard cap: **50 MB** archive.\n- The upload starts a build. Track it with `hosting_list-js-deployments`; on failure pull `hosting_show-js-deployment-logs`, fix, and redeploy. Poll with backoff — builds take minutes, not seconds.\n\n## WordPress → `hosting_import-wordpress-website` / plugin & theme operations\n\nOnly when the user explicitly wants a WordPress *site* migrated or themed. Site imports take an archive plus a `.sql` dump and can run for several minutes. (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.)\n\n## Verify (every deploy)\n\n```bash\ncurl -s -o /dev/null -w \"%{http_code}\\n\" https://YOURDOMAIN/\ncurl -s https://YOURDOMAIN/ | grep -o \"SOME_REAL_HEADLINE_TEXT\"\n```\n\nReplace 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`.\n\nWhen the site is live, report the URL and remind the user the site is managed from hPanel (https://hpanel.hostinger.com).\n"
|
|
77
|
+
"text": "# Deployment — getting the build live\n\nMatch the deploy method to what the project actually is — this is the single most common failure point.\n\nThe deploy operations below read the archive from this machine, so only the local `hostinger-api-mcp` server has them. On the hosted server (`mcp.hostinger.com`) `search` does not find them: 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.\n\n## Static site → `hosting_deploy-static-website`\n\nFor pre-built files only: plain HTML/CSS/JS, or the **build output** of a framework (run the build locally first).\n\n- The archive (zip/tar) must have `index.html` at its **root** — not nested inside a folder.\n- Name it `name_YYYYMMDD_HHMMSS.zip`; pass `removeArchive: true` to clean up after upload.\n- Deployment is effectively immediate — verify right after.\n\n## Node.js app → `hosting_deploy-js-application`\n\nFor anything that needs a server or a server-side build (Express, Next.js, NestJS, SSR frameworks).\n\n- Archive the **source**, not the output: exclude `node_modules/`, `dist/`, `.next/`, `build/`, and everything matched by `.gitignore`. The install and build run on Hostinger.\n- Hard cap: **50 MB** archive.\n- The upload starts a build. Track it with `hosting_list-js-deployments`; on failure pull `hosting_show-js-deployment-logs`, fix, and redeploy. Poll with backoff — builds take minutes, not seconds.\n\n## WordPress → `hosting_import-wordpress-website` / plugin & theme operations\n\nOnly when the user explicitly wants a WordPress *site* migrated or themed. Site imports take an archive plus a `.sql` dump and can run for several minutes. (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.)\n\n## Verify (every deploy)\n\n```bash\ncurl -s -o /dev/null -w \"%{http_code}\\n\" https://YOURDOMAIN/\ncurl -s https://YOURDOMAIN/ | grep -o \"SOME_REAL_HEADLINE_TEXT\"\n```\n\nReplace 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`.\n\nWhen the site is live, report the URL and remind the user the site is managed from hPanel (https://hpanel.hostinger.com).\n"
|
|
78
78
|
},
|
|
79
79
|
{
|
|
80
80
|
"uri": "skill://hostinger-headless/references/SETUP.md",
|
|
81
|
-
"digest": "sha256:
|
|
82
|
-
"size":
|
|
81
|
+
"digest": "sha256:88c14310222972f5568381ffdb31c36bb5291ce97718162fffe6d38b296e03e4",
|
|
82
|
+
"size": 3375,
|
|
83
83
|
"mimeType": "text/markdown",
|
|
84
|
-
"text": "# Setup — plan check and website provisioning\n\nEverything 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).\n\n## 1. Plan check (gate — run this first)\n\nA website can only be created on an active hosting plan.\n\n1. `hosting_websites_list` — if it returns websites, the account has a working plan; note any existing `order_id` and `username` for step 2.\n2. 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`.\n3. 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.\n\nNever purchase a plan, domain, or any paid item without the user explicitly approving that specific purchase.\n\n## 2. Choose the domain\n\n- **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.\n- **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.\n- **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).\n\n## 3. Create the website and wait for it\n\nGenerating a subdomain does **not** create a website — deploying straight to it fails with `No website found for domain`. The working sequence:\n\n1. `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`).\n2. **Poll** `hosting_websites_list` filtered by the domain until
|
|
84
|
+
"text": "# Setup — plan check and website provisioning\n\nEverything 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).\n\n## 1. Plan check (gate — run this first)\n\nA website can only be created on an active hosting plan.\n\n1. `hosting_websites_list` — if it returns websites, the account has a working plan; note any existing `order_id` and `username` for step 2.\n2. 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`.\n3. 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.\n4. 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.\n\nNever purchase a plan, domain, or any paid item without the user explicitly approving that specific purchase.\n\n## 2. Choose the domain\n\n- **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.\n- **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.\n- **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).\n\n## 3. Create the website and wait for it\n\nGenerating a subdomain does **not** create a website — deploying straight to it fails with `No website found for domain`. The working sequence:\n\n1. `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`).\n2. **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.\n3. Note the site's `username` — deployment and database operations are keyed on it.\n\nIf the domain already has a website (an `iterate` run, or the user pointed at an existing site), skip creation entirely.\n\n## 4. Optional extras (only when the run needs them)\n\n- **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.\n- **DNS records:** the DNS operations (`dns_records_update` etc.) for custom-domain records; take a snapshot (`dns_snapshots_list` context) before destructive changes.\n"
|
|
85
85
|
},
|
|
86
86
|
{
|
|
87
87
|
"uri": "skill://hostinger-headless/references/STORE.md",
|
|
@@ -124,10 +124,10 @@ export default [
|
|
|
124
124
|
"resources": [
|
|
125
125
|
{
|
|
126
126
|
"uri": "skill://migrate-to-hosting/SKILL.md",
|
|
127
|
-
"digest": "sha256:
|
|
128
|
-
"size":
|
|
127
|
+
"digest": "sha256:db36bfe5730786470806cc0b772d90bfdf457ce7ba46b41c78ea0ecab0dc6e3d",
|
|
128
|
+
"size": 7239,
|
|
129
129
|
"mimeType": "text/markdown",
|
|
130
|
-
"text": "---\nname: migrate-to-hosting\ndescription: \"Move an existing website from another host to Hostinger web hosting (Shared, Cloud or Agency plans) without downtime: WordPress sites from a files archive and SQL dump, static and PHP sites from an archive, Node.js apps from source. Creates the website on the real domain, imports files and database, tests the copy before any DNS change, then switches the domain and SSL. Triggers: migrate my site to Hostinger, move my website from another host, transfer my WordPress site, import my website, switch hosting to Hostinger.\"\n---\n\n# Migrate to hosting\n\nThe old host keeps serving the site until the copy on Hostinger is proven to work. DNS moves last.\n\n## Calling the operations\n\n- Read the `inputSchema` that `search` returns before the first call of each operation. If a name below is rejected as unknown, `search` for what the step does (e.g. \"import wordpress\").\n- Batch reads with `multi-execute`. Batches chain operations from one server only — the Hostinger Connector runs `hosting`, `wordpress`, `agency-hosting`, `domains` and `dns` as separate servers.\n- Imports and deploys overwrite the target website's contents; confirm the target before each one.\n\n## 1. What is being moved\n\nEstablish, asking only for what cannot be inferred:\n\n- **Site type:** WordPress, static, PHP (with or without MySQL), or Node.js.\n- **The export:**\n - WordPress — an archive of the whole WordPress root (including `wp-content` and `wp-config.php`) and a `.sql` dump.\n - PHP — a files archive, plus a `.sql` dump when the app has a database.\n - Static — the files. Node.js — the source or its Git repository.\n - Without one, the user exports it from the old host's panel, or over SSH: `tar -czf site.tar.gz -C /path/to/site .` and `mysqldump --single-transaction -u USER -p DBNAME > db.sql`.\n- **The exact home URL** (`https`, with or without `www`) — WordPress keeps it in the database, so the new site must answer on the same one.\n- **Current DNS**, to preserve what already works:\n\n```bash\ndig +short NS DOMAIN; dig +short A DOMAIN; dig +short MX DOMAIN; dig +short TXT DOMAIN\n```\n\n- **Cron jobs** on the old host — they do not move with the files.\n\n## 2. Create the website on the real domain\n\nCreate the Hostinger website on the domain being migrated, not on a free subdomain: step 4 tests it by pointing only this machine at Hostinger, so nothing changes for visitors yet.\n\n- Shared and Cloud: `hosting_domains_verify-ownership` first. When `is_accessible` is false, the user adds the returned `TXT` record at their current DNS provider, next to the existing ones, and verification is repeated. Then `hosting_websites_create` with `domain` and `order_id` (from `hosting_orders_list`), and poll `hosting_websites_list-setups` with `domain` every 10–15 s until `status: completed`.\n- Agency: `agency-hosting_website-setups_create` with the `domain`, `flavor: \"php-fpm\"`, a `settings.php.version` matching the old host (options in `agency-hosting_php_list-versions-for-order`) and `datacenter_code` from `agency-hosting_datacenters_list`. Poll `agency-hosting_website-setups_status` until `completed` for the `website_uid`.\n\n## 3. Import\n\n**WordPress, Shared and Cloud:** `hosting_import-wordpress-website` with `domain`, `archivePath` and `databaseDump` uploads both, extracts the files and imports the database; large sites take several minutes. Then `wordpress_installations_detect` with `username` and poll `wordpress_installations_list` with `domain` until the install appears with `is_valid: true`.\n\n**Static, or PHP without a database:** `hosting_deploy-static-website`
|
|
130
|
+
"text": "---\nname: migrate-to-hosting\ndescription: \"Move an existing website from another host to Hostinger web hosting (Shared, Cloud or Agency plans) without downtime: WordPress sites from a files archive and SQL dump, static and PHP sites from an archive, Node.js apps from source. Creates the website on the real domain, imports files and database, tests the copy before any DNS change, then switches the domain and SSL. Triggers: migrate my site to Hostinger, move my website from another host, transfer my WordPress site, import my website, switch hosting to Hostinger.\"\n---\n\n# Migrate to hosting\n\nThe old host keeps serving the site until the copy on Hostinger is proven to work. DNS moves last.\n\n## Calling the operations\n\n- Read the `inputSchema` that `search` returns before the first call of each operation. If a name below is rejected as unknown, `search` for what the step does (e.g. \"import wordpress\").\n- Batch reads with `multi-execute`. Batches chain operations from one server only — the Hostinger Connector runs `hosting`, `wordpress`, `agency-hosting`, `domains` and `dns` as separate servers.\n- Imports and deploys overwrite the target website's contents; confirm the target before each one.\n\n## 1. What is being moved\n\nEstablish, asking only for what cannot be inferred:\n\n- **Site type:** WordPress, static, PHP (with or without MySQL), or Node.js.\n- **The export:**\n - WordPress — an archive of the whole WordPress root (including `wp-content` and `wp-config.php`) and a `.sql` dump.\n - PHP — a files archive, plus a `.sql` dump when the app has a database.\n - Static — the files. Node.js — the source or its Git repository.\n - Without one, the user exports it from the old host's panel, or over SSH: `tar -czf site.tar.gz -C /path/to/site .` and `mysqldump --single-transaction -u USER -p DBNAME > db.sql`.\n- **The exact home URL** (`https`, with or without `www`) — WordPress keeps it in the database, so the new site must answer on the same one.\n- **Current DNS**, to preserve what already works:\n\n```bash\ndig +short NS DOMAIN; dig +short A DOMAIN; dig +short MX DOMAIN; dig +short TXT DOMAIN\n```\n\n- **Cron jobs** on the old host — they do not move with the files.\n\n## 2. Create the website on the real domain\n\nCreate the Hostinger website on the domain being migrated, not on a free subdomain: step 4 tests it by pointing only this machine at Hostinger, so nothing changes for visitors yet.\n\n- Shared and Cloud: `hosting_domains_verify-ownership` first. When `is_accessible` is false, the user adds the returned `TXT` record at their current DNS provider, next to the existing ones, and verification is repeated. Then `hosting_websites_create` with `domain` and `order_id` (from `hosting_orders_list`), and poll `hosting_websites_list-setups` with `domain` every 10–15 s until `status: completed`.\n- Agency: `agency-hosting_website-setups_create` with the `domain`, `flavor: \"php-fpm\"`, a `settings.php.version` matching the old host (options in `agency-hosting_php_list-versions-for-order`) and `datacenter_code` from `agency-hosting_datacenters_list`. Poll `agency-hosting_website-setups_status` until `completed` for the `website_uid`.\n\n## 3. Import\n\n`hosting_import-wordpress-website`, `hosting_deploy-static-website` and `agency-hosting_deploy-php-application` read files from this machine and exist only in the local `hostinger-api-mcp` server. On the hosted server (`mcp.hostinger.com`), upload the files first as described in the `deploy-to-hosting` skill (\"Without the local deploy operations\") and use the operation named in brackets below.\n\n**WordPress, Shared and Cloud:** `hosting_import-wordpress-website` with `domain`, `archivePath` and `databaseDump` uploads both, extracts the files and imports the database; large sites take several minutes. [Upload `site.zip` and `dump.sql`, then `wordpress_installations_import-website` with `archive_path` and `sql_path`.] Then `wordpress_installations_detect` with `username` and poll `wordpress_installations_list` with `domain` until the install appears with `is_valid: true`.\n\n**Static, or PHP without a database:** `hosting_deploy-static-website` [upload, then `hosting_websites_deploy-static-site-archive`]; Agency: `agency-hosting_deploy-php-application` [upload to `.h5g/`, then `agency-hosting_files_import-website-from-archive`].\n\n**PHP with a database, Shared and Cloud:**\n\n1. `hosting_databases_create` with a strong generated password; read the full name, user and `host` back from `hosting_databases_list`.\n2. Import the dump from this machine: allow only its public IP (`curl -s https://api.ipify.org`) with `hosting_databases_create-remote-connection`, run `mysql -h HOST -u USER -p NAME < db.sql`, then remove the rule with `hosting_databases_delete-remote-connection`. Without a MySQL client, use `hosting_databases_phpmyadmin-link` and import there.\n3. Put the new name, user and password into the app's config file, with host `localhost`, before archiving; then deploy as above. Never ship the `srvNNNN.hstgr.io` host inside the app.\n\n**Node.js:** deploy with the `deploy-to-hosting` skill. When a dump must be imported, create the database with `hosting_databases_create` rather than `hosting_databases_setup-website` — the latter never reveals the password needed for the import — and pass the credentials through environment variables.\n\n**Agency:** files with `agency-hosting_deploy-php-application` [or upload plus `agency-hosting_files_import-website-from-archive`]; the database with `agency-hosting_databases_create-website`, imported through phpMyAdmin in hPanel (no import operation exists). For WordPress, set the new credentials in `wp-config.php` before archiving.\n\n## 4. Test before DNS moves\n\nFind the server address: `details.ipv4` for Agency; for Shared and Cloud, the `A` record for `@` in the Hostinger zone (`dns_records_list` on the domain) or the IP hPanel shows for the website. Then point only this machine at it:\n\n```bash\ncurl -sSk --resolve DOMAIN:443:IP -o /dev/null -w \"%{http_code}\\n\" https://DOMAIN/\ncurl -sSk --resolve DOMAIN:443:IP https://DOMAIN/ | grep -o \"TEXT FROM THE LIVE SITE\"\ncurl -sSk --resolve DOMAIN:443:IP -o /dev/null -w \"%{http_code}\\n\" https://DOMAIN/wp-login.php\n```\n\n`-k` is expected here: the certificate for the domain can only be issued after DNS moves. Check the home page, an inner page and, for WordPress, the login page. For a look in the browser, the user adds `IP DOMAIN www.DOMAIN` to their hosts file and removes it afterwards. Fix anything broken now, while visitors still see the old site.\n\n## 5. Switch DNS and SSL\n\nFollow the `connect-domain` skill from its DNS step: keep every `MX` and `TXT` record from step 1, then install SSL once the domain resolves to Hostinger. When the user controls the old DNS, lowering the TTL of the `A` records to 300 a day ahead shortens the switch.\n\n## 6. After the switch\n\n- Verify without `--resolve`: `curl -sSI https://DOMAIN/` shows `platform: hostinger`.\n- Recreate the old host's cron jobs with `hosting_cron-jobs_create` (Agency: `agency-hosting_cron-jobs_create-website`).\n- Keep the old hosting running for a few days — some resolvers still cache the old address, and email hosted there must be moved separately.\n"
|
|
131
131
|
}
|
|
132
132
|
]
|
|
133
133
|
},
|
package/src/core/skills.ts
CHANGED
|
@@ -55,10 +55,10 @@ const skills: Skill[] = [
|
|
|
55
55
|
"resources": [
|
|
56
56
|
{
|
|
57
57
|
"uri": "skill://deploy-to-hosting/SKILL.md",
|
|
58
|
-
"digest": "sha256:
|
|
59
|
-
"size":
|
|
58
|
+
"digest": "sha256:961503b81556b6fde88183e9a0b26704f461a880e2085e739512415f1a3e6df9",
|
|
59
|
+
"size": 11009,
|
|
60
60
|
"mimeType": "text/markdown",
|
|
61
|
-
"text": "---\nname: deploy-to-hosting\ndescription: \"Deploy an existing project to a website on Hostinger web hosting (Shared, Cloud or Agency plans) and keep it deployed: picks the right deploy for static sites, Node.js apps (Next.js, Nuxt, Express, Vite and similar), PHP apps and WordPress plugins or themes, sets up auto-deploy from GitHub or GitLab, manages Node.js environment variables and MySQL databases, and verifies the live site. Triggers: deploy this project, deploy to Hostinger, push my app live, redeploy, set up auto-deploy, connect my GitHub repo, add environment variables, my app needs a database, deploy my WordPress plugin or theme.\"\n---\n\n# Deploy to hosting\n\nShip a project that already exists — on disk or in a Git repository — to a Hostinger website. Building a new site from a prompt (design, store, blog) is the `hostinger-headless` skill; this one takes code as it is.\n\n## Calling the operations\n\n- Read the `inputSchema` that `search` returns before the first call of each operation. If a name below is rejected as unknown, `search` for what the step does (e.g. \"deploy static\").\n- Batch reads with `multi-execute`; values pass between steps as `$steps.<i>.<path>`. Batches chain operations from one server only — the Hostinger Connector runs `hosting`, `wordpress` and `agency-hosting` as separate servers.\n- Every deploy overwrites the website's current contents. Confirm the target domain with the user before the first deploy to a site that already has content.\n\n## 1. Pick the target website\n\n- `.hostinger/site.json` in the project: reuse its `domain` and `username` (or `website_uid`).\n- Otherwise look the domain up with `hosting_websites_list` (Shared and Cloud; substring match — take the exact entry) and `agency-hosting_websites_list-plan` (Agency; keep `details.uid`).\n- No website yet:\n - Shared and Cloud: take a domain (the user's own, or `hosting_domains_generate-free-subdomain`) and an `order_id` from `hosting_orders_list`, then `hosting_websites_create`. `datacenter_code` is needed only for the first website on a new plan (first entry of `hosting_datacenters_list`). Poll `hosting_websites_list-setups` with `domain` every 10–15 s until `status: completed` — uploads and deploys return 404 or 409 before that.\n - Agency: `agency-hosting_website-setups_create` with `flavor: \"php-fpm\"` (plus `type: \"node-static\"` for built frontends), `settings.php.version` from `agency-hosting_php_list-versions-for-order` and `datacenter_code` from `agency-hosting_datacenters_list`. Poll `agency-hosting_website-setups_status` until `completed`; it returns the `website_uid`.\n- Node.js apps run on Business and Cloud plans (`hostinger_business_*`, `cloud_*` in `hosting_orders_list`). On other plans, build locally and deploy the output as a static site.\n\n## 2. Choose the deploy\n\nWrong method is the most common failure. Decide from the project on disk:\n\n| Project | Shared / Cloud |\n| --- | --- |\n| Plain HTML/CSS/JS, or a framework's static build output | `hosting_deploy-static-website` |\n| `package.json` with a build or a server (Next.js, Nuxt, Express, Vite…) | `hosting_deploy-js-application` |\n| PHP code, no build step | `hosting_deploy-static-website` (extracts the archive as-is) |\n| WordPress plugin or theme folder | `hosting_deploy-wordpress-plugin` / `hosting_deploy-wordpress-theme` (`activate` optional) |\n| A whole WordPress site from elsewhere | the `migrate-to-hosting` skill |\n\nOn Agency the website's type decides (`agency-hosting_websites_get`): sites created as `node-static` take `agency-hosting_deploy-node-static-website`, which runs the build when the project has one; every other site takes `agency-hosting_deploy-php-application`, which extracts the archive as-is. WordPress plugins and themes on Agency sites are installed from wp-admin.\n\nArchive rules (name archives `name_YYYYMMDD_HHMMSS.zip`):\n\n- **Static:** build locally first. `index.html` must be at the archive root, not inside a folder: `cd dist && zip -r ../site_20260101_120000.zip .`\n- **Node.js source:** no `node_modules/`, no build output (`dist/`, `.next/`, `build/`), no `.env*`, nothing matched by `.gitignore`; 50 MB at most. `git archive --format=zip -o app_20260101_120000.zip HEAD` produces exactly the committed files — mention that uncommitted changes are left out.\n- Agency deploys are synchronous: the site is live when the call returns.\n\n## 3. Node.js builds\n\n`hosting_deploy-js-application` uploads the archive to the document root, detects settings from `package.json` and starts a build. Track it with `hosting_nodejs_list-builds` and `hosting_nodejs_build` (by `uuid`), polling every 10–20 s — builds take minutes.\n\n- Failed build: `hosting_nodejs_analyse-failed-build` once per build (5 calls a minute), then `hosting_nodejs_build-logs` if the analysis is empty.\n- Wrong detection (framework, `output_directory`, or a missing `entry_file` for express, fastify, nest, nuxt and hono): run `hosting_nodejs_start-build` with explicit values, `source_type: \"archive\"` and `source_options.archive_path` set to the archive's file name in the document root (check it is there with `hosting_files_list-website-and-directories`). Store the same values with `hosting_nodejs_update-build-settings`.\n- To review detected settings before any build: upload the archive with `hosting_files_generate-upload-url` (the TUS steps are in its description), then `hosting_nodejs_build-settings-from-archive`.\n\n## 4. Auto-deploy from Git\n\n1. `hosting_git_list-installations`. With no `active` installation (check `status: \"pending\"` and `\"suspended\"` too), the user connects GitHub or GitLab once in hPanel under Websites → Manage → Advanced → Git; there is no API for that step.\n2. `hosting_git_list-installation-repositories` with the installation `uuid` gives `owner`, `name` and `default_branch` (10 calls a minute).\n3. `hosting_git_update-auto-deployment-settings` with `installation_uuid`, `owner`, `repository`, `branch` and optional `directory`.\n - PHP and static sites deploy the branch immediately and again on every push.\n - Node.js sites clone nothing on save: start the first build with `hosting_nodejs_start-build`, `source_type: \"git\"` and the same `source_options`. Later pushes build with the stored settings, so keep `hosting_nodejs_update-build-settings` correct.\n4. Confirm with `hosting_git_auto-deployment-settings`.\n\nAgency Plan sites have no Git operations; deploy archives.\n\n## 5. Environment variables (Node.js)\n\n`hosting_nodejs_replace-environment-variables` replaces the whole set — anything not sent is deleted.\n\n1. `hosting_nodejs_list-environment-variables` for the current keys. Values come back as `********`; never send those back.\n2. Build the full set: every current key plus the new ones, with real values from the project's `.env` or the user. When the real value of an existing key is unknown, ask — do not drop it.\n3. Send it once; the app restarts. Values baked in at build time (Next.js `NEXT_PUBLIC_*`, Vite `VITE_*`) need a new `hosting_nodejs_start-build`.\n\nKeys use uppercase letters, digits and underscores. Never commit `.env` files or repeat secret values back to the user.\n\n## 6. Database\n\n- **Node.js:** `hosting_databases_setup-website` creates a MySQL database and writes `DB_HOST`, `DB_PORT`, `DB_NAME`, `DB_USER`, `DB_PASSWORD` and `DATABASE_URL` into the environment, then restarts the app. The password is generated and never returned. It fails with 422 when any of those keys exists — remove them first with the step 5 replace.\n- **PHP:** `hosting_databases_create` with `name`, `user`, a strong generated `password` and `website_domain`; read the prefixed full name back from `hosting_databases_list`. The app reads credentials from a config file on the server that stays out of Git, and connects to `localhost` or `127.0.0.1`.\n- **Agency:** `agency-hosting_databases_create-website`; the app connects to `localhost`.\n- The `srvNNNN.hstgr.io` host from `hosting_databases_list` is only for connections from outside Hostinger — never put it in the deployed app.\n\n## 7. Verify and record\n\n```bash\ncurl -s -o /dev/null -w \"%{http_code}\\n\" https://DOMAIN/\ncurl -s https://DOMAIN/ | grep -o \"TEXT THE PROJECT RENDERS\"\n```\n\nA `200` alone can be a placeholder page; match real copy. A new site may serve a default page briefly — clear it with `hosting_cache_clear-website` and retry before calling the deploy failed.\n\nWrite `.hostinger/site.json` in the project so later runs reuse the target: `{ \"domain\", \"username\" or \"website_uid\", \"type\": \"static\" | \"nodejs\" | \"php\" }`, keeping any fields already there.\n"
|
|
61
|
+
"text": "---\nname: deploy-to-hosting\ndescription: \"Deploy an existing project to a website on Hostinger web hosting (Shared, Cloud or Agency plans) and keep it deployed: picks the right deploy for static sites, Node.js apps (Next.js, Nuxt, Express, Vite and similar), PHP apps and WordPress plugins or themes, sets up auto-deploy from GitHub or GitLab, manages Node.js environment variables and MySQL databases, and verifies the live site. Triggers: deploy this project, deploy to Hostinger, push my app live, redeploy, set up auto-deploy, connect my GitHub repo, add environment variables, my app needs a database, deploy my WordPress plugin or theme.\"\n---\n\n# Deploy to hosting\n\nShip a project that already exists — on disk or in a Git repository — to a Hostinger website. Building a new site from a prompt (design, store, blog) is the `hostinger-headless` skill; this one takes code as it is.\n\n## Calling the operations\n\n- Read the `inputSchema` that `search` returns before the first call of each operation. If a name below is rejected as unknown, `search` for what the step does (e.g. \"deploy static\").\n- Batch reads with `multi-execute`; values pass between steps as `$steps.<i>.<path>`. Batches chain operations from one server only — the Hostinger Connector runs `hosting`, `wordpress` and `agency-hosting` as separate servers.\n- Every deploy overwrites the website's current contents. Confirm the target domain with the user before the first deploy to a site that already has content.\n\n## 1. Pick the target website\n\n- `.hostinger/site.json` in the project: reuse its `domain` and `username` (or `website_uid`).\n- Otherwise look the domain up with `hosting_websites_list` (Shared and Cloud; substring match — take the exact entry) and `agency-hosting_websites_list-plan` (Agency; keep `details.uid`).\n- No website yet:\n - Shared and Cloud: take a domain (the user's own, or `hosting_domains_generate-free-subdomain`) and an `order_id` from `hosting_orders_list`, then `hosting_websites_create`. `datacenter_code` is needed only for the first website on a new plan (first entry of `hosting_datacenters_list`). Poll `hosting_websites_list-setups` with `domain` every 10–15 s until `status: completed` — uploads and deploys return 404 or 409 before that.\n - Agency: `agency-hosting_website-setups_create` with `flavor: \"php-fpm\"` (plus `type: \"node-static\"` for built frontends), `settings.php.version` from `agency-hosting_php_list-versions-for-order` and `datacenter_code` from `agency-hosting_datacenters_list`. Poll `agency-hosting_website-setups_status` until `completed`; it returns the `website_uid`.\n- Node.js apps run on Business and Cloud plans (`hostinger_business_*`, `cloud_*` in `hosting_orders_list`). On other plans, build locally and deploy the output as a static site.\n\n## 2. Choose the deploy\n\nWrong method is the most common failure. Decide from the project on disk:\n\n| Project | Shared / Cloud |\n| --- | --- |\n| Plain HTML/CSS/JS, or a framework's static build output | `hosting_deploy-static-website` |\n| `package.json` with a build or a server (Next.js, Nuxt, Express, Vite…) | `hosting_deploy-js-application` |\n| PHP code, no build step | `hosting_deploy-static-website` (extracts the archive as-is) |\n| WordPress plugin or theme folder | `hosting_deploy-wordpress-plugin` / `hosting_deploy-wordpress-theme` (`activate` optional) |\n| A whole WordPress site from elsewhere | the `migrate-to-hosting` skill |\n\nOn Agency the website's type decides (`agency-hosting_websites_get`): sites created as `node-static` take `agency-hosting_deploy-node-static-website`, which runs the build when the project has one; every other site takes `agency-hosting_deploy-php-application`, which extracts the archive as-is. WordPress plugins and themes on Agency sites are installed from wp-admin.\n\nArchive rules (name archives `name_YYYYMMDD_HHMMSS.zip`):\n\n- **Static:** build locally first. `index.html` must be at the archive root, not inside a folder: `cd dist && zip -r ../site_20260101_120000.zip .`\n- **Node.js source:** no `node_modules/`, no build output (`dist/`, `.next/`, `build/`), no `.env*`, nothing matched by `.gitignore`; 50 MB at most. `git archive --format=zip -o app_20260101_120000.zip HEAD` produces exactly the committed files — mention that uncommitted changes are left out.\n- Agency deploys are synchronous: the site is live when the call returns.\n\nThe operations in the table read the archive from this machine, so only the local `hostinger-api-mcp` server has them. On the hosted server (`mcp.hostinger.com`) `search` does not find them — upload the files yourself as below.\n\n### Without the local deploy operations\n\n1. Get upload credentials: `hosting_files_generate-upload-url` (`username`, `domain`); Agency: `agency-hosting_files_generate-upload-url` (`website_uid`). Both return `url`, `auth_key` and `rest_auth_key`, which authenticate the upload instead of the API token.\n2. Upload each file with TUS, where `DEST` is its path in the website's storage:\n\n```bash\nSIZE=$(wc -c < \"$FILE\" | tr -d ' ')\ncurl -sS -X POST \"$URL/$DEST?override=true\" -H \"X-Auth: $AUTH_KEY\" -H \"X-Auth-Rest: $REST_AUTH_KEY\" -H \"Tus-Resumable: 1.0.0\" -H \"Upload-Length: $SIZE\" -H \"Upload-Offset: 0\"\ncurl -sS -X PATCH \"$URL/$DEST?override=true\" -H \"X-Auth: $AUTH_KEY\" -H \"X-Auth-Rest: $REST_AUTH_KEY\" -H \"Tus-Resumable: 1.0.0\" -H \"Content-Type: application/offset+octet-stream\" -H \"Upload-Offset: 0\" --data-binary \"@$FILE\"\n```\n\n The first call returns `201`, the second `204` with an `Upload-Offset` header equal to the file size. `override=true` makes a retry safe.\n3. Deploy from the uploaded files (`RANDOM8` is any fresh 8-character string, e.g. `$(LC_ALL=C tr -dc 'a-z0-9' < /dev/urandom | head -c 8)`):\n\n| Project | `DEST` | Then |\n| --- | --- | --- |\n| Static or PHP | `site.zip` | `hosting_websites_deploy-static-site-archive` with `archive_path: \"site.zip\"` |\n| Node.js | `app.zip` | `hosting_nodejs_build-settings-from-archive` with `archive_path: \"app.zip\"`, then `hosting_nodejs_start-build` with those settings, `source_type: \"archive\"` and `source_options.archive_path: \"app.zip\"` |\n| WordPress plugin | every file, as `wp-content/plugins/SLUG-RANDOM8/<path in the plugin>` | `wordpress_plugins_deploy` with `slug` and `plugin_path: \"SLUG-RANDOM8\"` |\n| WordPress theme | every file, as `wp-content/themes/SLUG-RANDOM8/<path in the theme>` | `wordpress_themes_deploy` with `slug`, `theme_path: \"SLUG-RANDOM8\"` and optional `is_activated` |\n| Agency, extracted as-is | `.h5g/site.zip` | `agency-hosting_files_import-website-from-archive` with `archive_name: \"site.zip\"` |\n| Agency `node-static` | `.h5g/RANDOM8/app.zip` | `agency-hosting_websites_build-nodejs-assets` with `archive_path: \".h5g/RANDOM8\"` — the directory, not the file |\n\n## 3. Node.js builds\n\n`hosting_deploy-js-application` uploads the archive to the document root, detects settings from `package.json` and starts a build. Track it with `hosting_nodejs_list-builds` and `hosting_nodejs_build` (by `uuid`), polling every 10–20 s — builds take minutes.\n\n- Failed build: `hosting_nodejs_analyse-failed-build` once per build (5 calls a minute), then `hosting_nodejs_build-logs` if the analysis is empty.\n- Wrong detection (framework, `output_directory`, or a missing `entry_file` for express, fastify, nest, nuxt and hono): run `hosting_nodejs_start-build` with explicit values, `source_type: \"archive\"` and `source_options.archive_path` set to the archive's file name in the document root (check it is there with `hosting_files_list-website-and-directories`). Store the same values with `hosting_nodejs_update-build-settings`.\n- To review detected settings before any build: upload the archive with `hosting_files_generate-upload-url` (the TUS steps are in its description), then `hosting_nodejs_build-settings-from-archive`.\n\n## 4. Auto-deploy from Git\n\n1. `hosting_git_list-installations`. With no `active` installation (check `status: \"pending\"` and `\"suspended\"` too), the user connects GitHub or GitLab once in hPanel under Websites → Manage → Advanced → Git; there is no API for that step.\n2. `hosting_git_list-installation-repositories` with the installation `uuid` gives `owner`, `name` and `default_branch` (10 calls a minute).\n3. `hosting_git_update-auto-deployment-settings` with `installation_uuid`, `owner`, `repository`, `branch` and optional `directory`.\n - PHP and static sites deploy the branch immediately and again on every push.\n - Node.js sites clone nothing on save: start the first build with `hosting_nodejs_start-build`, `source_type: \"git\"` and the same `source_options`. Later pushes build with the stored settings, so keep `hosting_nodejs_update-build-settings` correct.\n4. Confirm with `hosting_git_auto-deployment-settings`.\n\nAgency Plan sites have no Git operations; deploy archives.\n\n## 5. Environment variables (Node.js)\n\n`hosting_nodejs_replace-environment-variables` replaces the whole set — anything not sent is deleted.\n\n1. `hosting_nodejs_list-environment-variables` for the current keys. Values come back as `********`; never send those back.\n2. Build the full set: every current key plus the new ones, with real values from the project's `.env` or the user. When the real value of an existing key is unknown, ask — do not drop it.\n3. Send it once; the app restarts. Values baked in at build time (Next.js `NEXT_PUBLIC_*`, Vite `VITE_*`) need a new `hosting_nodejs_start-build`.\n\nKeys use uppercase letters, digits and underscores. Never commit `.env` files or repeat secret values back to the user.\n\n## 6. Database\n\n- **Node.js:** `hosting_databases_setup-website` creates a MySQL database and writes `DB_HOST`, `DB_PORT`, `DB_NAME`, `DB_USER`, `DB_PASSWORD` and `DATABASE_URL` into the environment, then restarts the app. The password is generated and never returned. It fails with 422 when any of those keys exists — remove them first with the step 5 replace.\n- **PHP:** `hosting_databases_create` with `name`, `user`, a strong generated `password` and `website_domain`; read the prefixed full name back from `hosting_databases_list`. The app reads credentials from a config file on the server that stays out of Git, and connects to `localhost` or `127.0.0.1`.\n- **Agency:** `agency-hosting_databases_create-website`; the app connects to `localhost`.\n- The `srvNNNN.hstgr.io` host from `hosting_databases_list` is only for connections from outside Hostinger — never put it in the deployed app.\n\n## 7. Verify and record\n\n```bash\ncurl -s -o /dev/null -w \"%{http_code}\\n\" https://DOMAIN/\ncurl -s https://DOMAIN/ | grep -o \"TEXT THE PROJECT RENDERS\"\n```\n\nA `200` alone can be a placeholder page; match real copy. A new site may serve a default page briefly — clear it with `hosting_cache_clear-website` and retry before calling the deploy failed.\n\nWrite `.hostinger/site.json` in the project so later runs reuse the target: `{ \"domain\", \"username\" or \"website_uid\", \"type\": \"static\" | \"nodejs\" | \"php\" }`, keeping any fields already there.\n"
|
|
62
62
|
}
|
|
63
63
|
]
|
|
64
64
|
},
|
|
@@ -78,24 +78,24 @@ const skills: Skill[] = [
|
|
|
78
78
|
},
|
|
79
79
|
{
|
|
80
80
|
"uri": "skill://hostinger-headless/references/DATABASE.md",
|
|
81
|
-
"digest": "sha256:
|
|
82
|
-
"size":
|
|
81
|
+
"digest": "sha256:c81159d8d4d9c36604425dd8afee5a22a4cd2286b23ad167ade9db8c478efc7f",
|
|
82
|
+
"size": 4333,
|
|
83
83
|
"mimeType": "text/markdown",
|
|
84
|
-
"text": "# Database and runtime — MySQL hosts, env vars, and what to poll\n\nUse 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.\n\n## 1. Create the database\n\n1. `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.\n2. Read the full, prefixed `name` and `user` back from `hosting_databases_list`; every other database operation wants the full name.\n3. Do not print the password to the user once it is stored, and never commit it.\n\n## 2. Which host the app connects to\n\n| Where the code runs | Host | Port | Why |\n| --- | --- | --- | --- |\n| PHP on the website | `localhost` or `127.0.0.1` | 3306 | `localhost` uses the MySQL socket; both are granted |\n| Node.js on the website | `127.0.0.1` | 3306 | `localhost` may resolve to IPv6 `::1`, and not every database user has that grant |\n| 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 |\n\nDo not put the remote `host` into the deployed app — it has no grant for connections that come from the server itself.\n\n## 3. Hand credentials to the app\n\n- **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.\n- **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.\n- **Never** in client-side JavaScript, in a committed `.env`, or in chat replies.\n\n## 4. What is asynchronous, and what to poll\n\n| You called | Poll this until | Typical wait |\n| --- | --- | --- |\n| `hosting_websites_create` | `hosting_websites_list`
|
|
84
|
+
"text": "# Database and runtime — MySQL hosts, env vars, and what to poll\n\nUse 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.\n\n## 1. Create the database\n\n1. `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.\n2. Read the full, prefixed `name` and `user` back from `hosting_databases_list`; every other database operation wants the full name.\n3. Do not print the password to the user once it is stored, and never commit it.\n\n## 2. Which host the app connects to\n\n| Where the code runs | Host | Port | Why |\n| --- | --- | --- | --- |\n| PHP on the website | `localhost` or `127.0.0.1` | 3306 | `localhost` uses the MySQL socket; both are granted |\n| Node.js on the website | `127.0.0.1` | 3306 | `localhost` may resolve to IPv6 `::1`, and not every database user has that grant |\n| 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 |\n\nDo not put the remote `host` into the deployed app — it has no grant for connections that come from the server itself.\n\n## 3. Hand credentials to the app\n\n- **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.\n- **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.\n- **Never** in client-side JavaScript, in a committed `.env`, or in chat replies.\n\n## 4. What is asynchronous, and what to poll\n\n| You called | Poll this until | Typical wait |\n| --- | --- | --- |\n| `hosting_websites_create` | `hosting_websites_list-setups` with the domain reports `status: completed` | up to a few minutes |\n| `hosting_deploy-js-application` | `hosting_list-js-deployments` shows the build finished | minutes |\n| `hosting_nodejs_start-build` | `hosting_nodejs_build` state is `completed` or `failed` | minutes |\n| `wordpress_installations_install`, plugin/theme/core jobs | `wordpress_installations_list` lists the install | 1–2 minutes |\n| `hosting_databases_repair`, `hosting_websites_delete` | nothing to poll — runs in the background | minutes |\n| `agency-hosting_website-setups_create` | `agency-hosting_website-setups_status` with `setup_uuid` is `completed` | minutes |\n\nPoll 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.\n\n## 5. When the app is up but broken\n\n- Build failed: `hosting_nodejs_build-logs` for the raw log, `hosting_nodejs_analyse-failed-build` for a diagnosis.\n- Build passed, app errors: `hosting_nodejs_runtime-logs` with a `period` such as `1h`; entries before `last_deployed_at` belong to the previous deploy.\n- `Access denied for user 'x'@'::1'`: the app used `localhost` from Node.js — set `DB_HOST` to `127.0.0.1`.\n- PHP limits (memory, upload size): `hosting_php_get`, then `hosting_php_update-options`.\n\n## Agency Plan websites (`agency-hosting_*`)\n\n`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`.\n"
|
|
85
85
|
},
|
|
86
86
|
{
|
|
87
87
|
"uri": "skill://hostinger-headless/references/DEPLOYMENT.md",
|
|
88
|
-
"digest": "sha256:
|
|
89
|
-
"size":
|
|
88
|
+
"digest": "sha256:a82e1b7dc8d6155419c8d72cc0f060f6592ea176b506a175760f4ac2a2ecccf4",
|
|
89
|
+
"size": 2570,
|
|
90
90
|
"mimeType": "text/markdown",
|
|
91
|
-
"text": "# Deployment — getting the build live\n\nMatch the deploy method to what the project actually is — this is the single most common failure point.\n\n## Static site → `hosting_deploy-static-website`\n\nFor pre-built files only: plain HTML/CSS/JS, or the **build output** of a framework (run the build locally first).\n\n- The archive (zip/tar) must have `index.html` at its **root** — not nested inside a folder.\n- Name it `name_YYYYMMDD_HHMMSS.zip`; pass `removeArchive: true` to clean up after upload.\n- Deployment is effectively immediate — verify right after.\n\n## Node.js app → `hosting_deploy-js-application`\n\nFor anything that needs a server or a server-side build (Express, Next.js, NestJS, SSR frameworks).\n\n- Archive the **source**, not the output: exclude `node_modules/`, `dist/`, `.next/`, `build/`, and everything matched by `.gitignore`. The install and build run on Hostinger.\n- Hard cap: **50 MB** archive.\n- The upload starts a build. Track it with `hosting_list-js-deployments`; on failure pull `hosting_show-js-deployment-logs`, fix, and redeploy. Poll with backoff — builds take minutes, not seconds.\n\n## WordPress → `hosting_import-wordpress-website` / plugin & theme operations\n\nOnly when the user explicitly wants a WordPress *site* migrated or themed. Site imports take an archive plus a `.sql` dump and can run for several minutes. (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.)\n\n## Verify (every deploy)\n\n```bash\ncurl -s -o /dev/null -w \"%{http_code}\\n\" https://YOURDOMAIN/\ncurl -s https://YOURDOMAIN/ | grep -o \"SOME_REAL_HEADLINE_TEXT\"\n```\n\nReplace 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`.\n\nWhen the site is live, report the URL and remind the user the site is managed from hPanel (https://hpanel.hostinger.com).\n"
|
|
91
|
+
"text": "# Deployment — getting the build live\n\nMatch the deploy method to what the project actually is — this is the single most common failure point.\n\nThe deploy operations below read the archive from this machine, so only the local `hostinger-api-mcp` server has them. On the hosted server (`mcp.hostinger.com`) `search` does not find them: 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.\n\n## Static site → `hosting_deploy-static-website`\n\nFor pre-built files only: plain HTML/CSS/JS, or the **build output** of a framework (run the build locally first).\n\n- The archive (zip/tar) must have `index.html` at its **root** — not nested inside a folder.\n- Name it `name_YYYYMMDD_HHMMSS.zip`; pass `removeArchive: true` to clean up after upload.\n- Deployment is effectively immediate — verify right after.\n\n## Node.js app → `hosting_deploy-js-application`\n\nFor anything that needs a server or a server-side build (Express, Next.js, NestJS, SSR frameworks).\n\n- Archive the **source**, not the output: exclude `node_modules/`, `dist/`, `.next/`, `build/`, and everything matched by `.gitignore`. The install and build run on Hostinger.\n- Hard cap: **50 MB** archive.\n- The upload starts a build. Track it with `hosting_list-js-deployments`; on failure pull `hosting_show-js-deployment-logs`, fix, and redeploy. Poll with backoff — builds take minutes, not seconds.\n\n## WordPress → `hosting_import-wordpress-website` / plugin & theme operations\n\nOnly when the user explicitly wants a WordPress *site* migrated or themed. Site imports take an archive plus a `.sql` dump and can run for several minutes. (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.)\n\n## Verify (every deploy)\n\n```bash\ncurl -s -o /dev/null -w \"%{http_code}\\n\" https://YOURDOMAIN/\ncurl -s https://YOURDOMAIN/ | grep -o \"SOME_REAL_HEADLINE_TEXT\"\n```\n\nReplace 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`.\n\nWhen the site is live, report the URL and remind the user the site is managed from hPanel (https://hpanel.hostinger.com).\n"
|
|
92
92
|
},
|
|
93
93
|
{
|
|
94
94
|
"uri": "skill://hostinger-headless/references/SETUP.md",
|
|
95
|
-
"digest": "sha256:
|
|
96
|
-
"size":
|
|
95
|
+
"digest": "sha256:88c14310222972f5568381ffdb31c36bb5291ce97718162fffe6d38b296e03e4",
|
|
96
|
+
"size": 3375,
|
|
97
97
|
"mimeType": "text/markdown",
|
|
98
|
-
"text": "# Setup — plan check and website provisioning\n\nEverything 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).\n\n## 1. Plan check (gate — run this first)\n\nA website can only be created on an active hosting plan.\n\n1. `hosting_websites_list` — if it returns websites, the account has a working plan; note any existing `order_id` and `username` for step 2.\n2. 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`.\n3. 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.\n\nNever purchase a plan, domain, or any paid item without the user explicitly approving that specific purchase.\n\n## 2. Choose the domain\n\n- **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.\n- **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.\n- **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).\n\n## 3. Create the website and wait for it\n\nGenerating a subdomain does **not** create a website — deploying straight to it fails with `No website found for domain`. The working sequence:\n\n1. `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`).\n2. **Poll** `hosting_websites_list` filtered by the domain until
|
|
98
|
+
"text": "# Setup — plan check and website provisioning\n\nEverything 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).\n\n## 1. Plan check (gate — run this first)\n\nA website can only be created on an active hosting plan.\n\n1. `hosting_websites_list` — if it returns websites, the account has a working plan; note any existing `order_id` and `username` for step 2.\n2. 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`.\n3. 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.\n4. 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.\n\nNever purchase a plan, domain, or any paid item without the user explicitly approving that specific purchase.\n\n## 2. Choose the domain\n\n- **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.\n- **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.\n- **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).\n\n## 3. Create the website and wait for it\n\nGenerating a subdomain does **not** create a website — deploying straight to it fails with `No website found for domain`. The working sequence:\n\n1. `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`).\n2. **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.\n3. Note the site's `username` — deployment and database operations are keyed on it.\n\nIf the domain already has a website (an `iterate` run, or the user pointed at an existing site), skip creation entirely.\n\n## 4. Optional extras (only when the run needs them)\n\n- **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.\n- **DNS records:** the DNS operations (`dns_records_update` etc.) for custom-domain records; take a snapshot (`dns_snapshots_list` context) before destructive changes.\n"
|
|
99
99
|
},
|
|
100
100
|
{
|
|
101
101
|
"uri": "skill://hostinger-headless/references/STORE.md",
|
|
@@ -138,10 +138,10 @@ const skills: Skill[] = [
|
|
|
138
138
|
"resources": [
|
|
139
139
|
{
|
|
140
140
|
"uri": "skill://migrate-to-hosting/SKILL.md",
|
|
141
|
-
"digest": "sha256:
|
|
142
|
-
"size":
|
|
141
|
+
"digest": "sha256:db36bfe5730786470806cc0b772d90bfdf457ce7ba46b41c78ea0ecab0dc6e3d",
|
|
142
|
+
"size": 7239,
|
|
143
143
|
"mimeType": "text/markdown",
|
|
144
|
-
"text": "---\nname: migrate-to-hosting\ndescription: \"Move an existing website from another host to Hostinger web hosting (Shared, Cloud or Agency plans) without downtime: WordPress sites from a files archive and SQL dump, static and PHP sites from an archive, Node.js apps from source. Creates the website on the real domain, imports files and database, tests the copy before any DNS change, then switches the domain and SSL. Triggers: migrate my site to Hostinger, move my website from another host, transfer my WordPress site, import my website, switch hosting to Hostinger.\"\n---\n\n# Migrate to hosting\n\nThe old host keeps serving the site until the copy on Hostinger is proven to work. DNS moves last.\n\n## Calling the operations\n\n- Read the `inputSchema` that `search` returns before the first call of each operation. If a name below is rejected as unknown, `search` for what the step does (e.g. \"import wordpress\").\n- Batch reads with `multi-execute`. Batches chain operations from one server only — the Hostinger Connector runs `hosting`, `wordpress`, `agency-hosting`, `domains` and `dns` as separate servers.\n- Imports and deploys overwrite the target website's contents; confirm the target before each one.\n\n## 1. What is being moved\n\nEstablish, asking only for what cannot be inferred:\n\n- **Site type:** WordPress, static, PHP (with or without MySQL), or Node.js.\n- **The export:**\n - WordPress — an archive of the whole WordPress root (including `wp-content` and `wp-config.php`) and a `.sql` dump.\n - PHP — a files archive, plus a `.sql` dump when the app has a database.\n - Static — the files. Node.js — the source or its Git repository.\n - Without one, the user exports it from the old host's panel, or over SSH: `tar -czf site.tar.gz -C /path/to/site .` and `mysqldump --single-transaction -u USER -p DBNAME > db.sql`.\n- **The exact home URL** (`https`, with or without `www`) — WordPress keeps it in the database, so the new site must answer on the same one.\n- **Current DNS**, to preserve what already works:\n\n```bash\ndig +short NS DOMAIN; dig +short A DOMAIN; dig +short MX DOMAIN; dig +short TXT DOMAIN\n```\n\n- **Cron jobs** on the old host — they do not move with the files.\n\n## 2. Create the website on the real domain\n\nCreate the Hostinger website on the domain being migrated, not on a free subdomain: step 4 tests it by pointing only this machine at Hostinger, so nothing changes for visitors yet.\n\n- Shared and Cloud: `hosting_domains_verify-ownership` first. When `is_accessible` is false, the user adds the returned `TXT` record at their current DNS provider, next to the existing ones, and verification is repeated. Then `hosting_websites_create` with `domain` and `order_id` (from `hosting_orders_list`), and poll `hosting_websites_list-setups` with `domain` every 10–15 s until `status: completed`.\n- Agency: `agency-hosting_website-setups_create` with the `domain`, `flavor: \"php-fpm\"`, a `settings.php.version` matching the old host (options in `agency-hosting_php_list-versions-for-order`) and `datacenter_code` from `agency-hosting_datacenters_list`. Poll `agency-hosting_website-setups_status` until `completed` for the `website_uid`.\n\n## 3. Import\n\n**WordPress, Shared and Cloud:** `hosting_import-wordpress-website` with `domain`, `archivePath` and `databaseDump` uploads both, extracts the files and imports the database; large sites take several minutes. Then `wordpress_installations_detect` with `username` and poll `wordpress_installations_list` with `domain` until the install appears with `is_valid: true`.\n\n**Static, or PHP without a database:** `hosting_deploy-static-website`
|
|
144
|
+
"text": "---\nname: migrate-to-hosting\ndescription: \"Move an existing website from another host to Hostinger web hosting (Shared, Cloud or Agency plans) without downtime: WordPress sites from a files archive and SQL dump, static and PHP sites from an archive, Node.js apps from source. Creates the website on the real domain, imports files and database, tests the copy before any DNS change, then switches the domain and SSL. Triggers: migrate my site to Hostinger, move my website from another host, transfer my WordPress site, import my website, switch hosting to Hostinger.\"\n---\n\n# Migrate to hosting\n\nThe old host keeps serving the site until the copy on Hostinger is proven to work. DNS moves last.\n\n## Calling the operations\n\n- Read the `inputSchema` that `search` returns before the first call of each operation. If a name below is rejected as unknown, `search` for what the step does (e.g. \"import wordpress\").\n- Batch reads with `multi-execute`. Batches chain operations from one server only — the Hostinger Connector runs `hosting`, `wordpress`, `agency-hosting`, `domains` and `dns` as separate servers.\n- Imports and deploys overwrite the target website's contents; confirm the target before each one.\n\n## 1. What is being moved\n\nEstablish, asking only for what cannot be inferred:\n\n- **Site type:** WordPress, static, PHP (with or without MySQL), or Node.js.\n- **The export:**\n - WordPress — an archive of the whole WordPress root (including `wp-content` and `wp-config.php`) and a `.sql` dump.\n - PHP — a files archive, plus a `.sql` dump when the app has a database.\n - Static — the files. Node.js — the source or its Git repository.\n - Without one, the user exports it from the old host's panel, or over SSH: `tar -czf site.tar.gz -C /path/to/site .` and `mysqldump --single-transaction -u USER -p DBNAME > db.sql`.\n- **The exact home URL** (`https`, with or without `www`) — WordPress keeps it in the database, so the new site must answer on the same one.\n- **Current DNS**, to preserve what already works:\n\n```bash\ndig +short NS DOMAIN; dig +short A DOMAIN; dig +short MX DOMAIN; dig +short TXT DOMAIN\n```\n\n- **Cron jobs** on the old host — they do not move with the files.\n\n## 2. Create the website on the real domain\n\nCreate the Hostinger website on the domain being migrated, not on a free subdomain: step 4 tests it by pointing only this machine at Hostinger, so nothing changes for visitors yet.\n\n- Shared and Cloud: `hosting_domains_verify-ownership` first. When `is_accessible` is false, the user adds the returned `TXT` record at their current DNS provider, next to the existing ones, and verification is repeated. Then `hosting_websites_create` with `domain` and `order_id` (from `hosting_orders_list`), and poll `hosting_websites_list-setups` with `domain` every 10–15 s until `status: completed`.\n- Agency: `agency-hosting_website-setups_create` with the `domain`, `flavor: \"php-fpm\"`, a `settings.php.version` matching the old host (options in `agency-hosting_php_list-versions-for-order`) and `datacenter_code` from `agency-hosting_datacenters_list`. Poll `agency-hosting_website-setups_status` until `completed` for the `website_uid`.\n\n## 3. Import\n\n`hosting_import-wordpress-website`, `hosting_deploy-static-website` and `agency-hosting_deploy-php-application` read files from this machine and exist only in the local `hostinger-api-mcp` server. On the hosted server (`mcp.hostinger.com`), upload the files first as described in the `deploy-to-hosting` skill (\"Without the local deploy operations\") and use the operation named in brackets below.\n\n**WordPress, Shared and Cloud:** `hosting_import-wordpress-website` with `domain`, `archivePath` and `databaseDump` uploads both, extracts the files and imports the database; large sites take several minutes. [Upload `site.zip` and `dump.sql`, then `wordpress_installations_import-website` with `archive_path` and `sql_path`.] Then `wordpress_installations_detect` with `username` and poll `wordpress_installations_list` with `domain` until the install appears with `is_valid: true`.\n\n**Static, or PHP without a database:** `hosting_deploy-static-website` [upload, then `hosting_websites_deploy-static-site-archive`]; Agency: `agency-hosting_deploy-php-application` [upload to `.h5g/`, then `agency-hosting_files_import-website-from-archive`].\n\n**PHP with a database, Shared and Cloud:**\n\n1. `hosting_databases_create` with a strong generated password; read the full name, user and `host` back from `hosting_databases_list`.\n2. Import the dump from this machine: allow only its public IP (`curl -s https://api.ipify.org`) with `hosting_databases_create-remote-connection`, run `mysql -h HOST -u USER -p NAME < db.sql`, then remove the rule with `hosting_databases_delete-remote-connection`. Without a MySQL client, use `hosting_databases_phpmyadmin-link` and import there.\n3. Put the new name, user and password into the app's config file, with host `localhost`, before archiving; then deploy as above. Never ship the `srvNNNN.hstgr.io` host inside the app.\n\n**Node.js:** deploy with the `deploy-to-hosting` skill. When a dump must be imported, create the database with `hosting_databases_create` rather than `hosting_databases_setup-website` — the latter never reveals the password needed for the import — and pass the credentials through environment variables.\n\n**Agency:** files with `agency-hosting_deploy-php-application` [or upload plus `agency-hosting_files_import-website-from-archive`]; the database with `agency-hosting_databases_create-website`, imported through phpMyAdmin in hPanel (no import operation exists). For WordPress, set the new credentials in `wp-config.php` before archiving.\n\n## 4. Test before DNS moves\n\nFind the server address: `details.ipv4` for Agency; for Shared and Cloud, the `A` record for `@` in the Hostinger zone (`dns_records_list` on the domain) or the IP hPanel shows for the website. Then point only this machine at it:\n\n```bash\ncurl -sSk --resolve DOMAIN:443:IP -o /dev/null -w \"%{http_code}\\n\" https://DOMAIN/\ncurl -sSk --resolve DOMAIN:443:IP https://DOMAIN/ | grep -o \"TEXT FROM THE LIVE SITE\"\ncurl -sSk --resolve DOMAIN:443:IP -o /dev/null -w \"%{http_code}\\n\" https://DOMAIN/wp-login.php\n```\n\n`-k` is expected here: the certificate for the domain can only be issued after DNS moves. Check the home page, an inner page and, for WordPress, the login page. For a look in the browser, the user adds `IP DOMAIN www.DOMAIN` to their hosts file and removes it afterwards. Fix anything broken now, while visitors still see the old site.\n\n## 5. Switch DNS and SSL\n\nFollow the `connect-domain` skill from its DNS step: keep every `MX` and `TXT` record from step 1, then install SSL once the domain resolves to Hostinger. When the user controls the old DNS, lowering the TTL of the `A` records to 300 a day ahead shortens the switch.\n\n## 6. After the switch\n\n- Verify without `--resolve`: `curl -sSI https://DOMAIN/` shows `platform: hostinger`.\n- Recreate the old host's cron jobs with `hosting_cron-jobs_create` (Agency: `agency-hosting_cron-jobs_create-website`).\n- Keep the old hosting running for a few days — some resolvers still cache the old address, and email hosted there must be moved separately.\n"
|
|
145
145
|
}
|
|
146
146
|
]
|
|
147
147
|
},
|
package/src/core/tools/all.js
CHANGED
package/src/core/tools/all.ts
CHANGED
|
@@ -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.js';
|
|
6
6
|
|
|
7
|
-
startServer({ name: 'hostinger-agency-hosting-mcp', version: '2.
|
|
7
|
+
startServer({ name: 'hostinger-agency-hosting-mcp', version: '2.6.0', 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.js';
|
|
6
6
|
|
|
7
|
-
startServer({ name: 'hostinger-agency-hosting-mcp', version: '2.
|
|
7
|
+
startServer({ name: 'hostinger-agency-hosting-mcp', version: '2.6.0', tools, instructions });
|
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: '2.
|
|
8
|
+
startServer({ name: 'hostinger-api-mcp', version: '2.6.0', 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: '2.
|
|
8
|
+
startServer({ name: 'hostinger-api-mcp', version: '2.6.0', 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: '2.
|
|
7
|
+
startServer({ name: 'hostinger-hosting-mcp', version: '2.6.0', 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: '2.
|
|
7
|
+
startServer({ name: 'hostinger-hosting-mcp', version: '2.6.0', 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