Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "hostinger-connector",
"displayName": "Hostinger Connector",
"version": "0.3.1",
"version": "0.3.2",
"description": "MCP plugin to deploy and manage Hostinger websites, WordPress, domains, DNS, VPS, and subscriptions from inside Cursor.",
"author": "Hostinger",
"license": "MIT",
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## [0.3.2] - 2026-10-05

### Changed

- Synced with `@hostinger/mcp` 2.5.0: deploy-to-hosting, hostinger-headless, migrate-to-hosting

## [0.3.1] - 2026-10-02

### Changed
Expand Down
18 changes: 9 additions & 9 deletions mcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,47 @@
"hostinger-hosting": {
"command": "npx",
"args": ["--yes", "--package=@hostinger/mcp@latest", "hostinger-hosting-mcp"],
"env": { "USER_AGENT": "plugin;cursor;0.3.1" }
"env": { "USER_AGENT": "plugin;cursor;0.3.2" }
},
"hostinger-wordpress": {
"command": "npx",
"args": ["--yes", "--package=@hostinger/mcp@latest", "hostinger-wordpress-mcp"],
"env": { "USER_AGENT": "plugin;cursor;0.3.1" }
"env": { "USER_AGENT": "plugin;cursor;0.3.2" }
},
"hostinger-agency-hosting": {
"command": "npx",
"args": ["--yes", "--package=@hostinger/mcp@latest", "hostinger-agency-hosting-mcp"],
"env": { "USER_AGENT": "plugin;cursor;0.3.1" }
"env": { "USER_AGENT": "plugin;cursor;0.3.2" }
},
"hostinger-domains": {
"command": "npx",
"args": ["--yes", "--package=@hostinger/mcp@latest", "hostinger-domains-mcp"],
"env": { "USER_AGENT": "plugin;cursor;0.3.1" }
"env": { "USER_AGENT": "plugin;cursor;0.3.2" }
},
"hostinger-dns": {
"command": "npx",
"args": ["--yes", "--package=@hostinger/mcp@latest", "hostinger-dns-mcp"],
"env": { "USER_AGENT": "plugin;cursor;0.3.1" }
"env": { "USER_AGENT": "plugin;cursor;0.3.2" }
},
"hostinger-billing": {
"command": "npx",
"args": ["--yes", "--package=@hostinger/mcp@latest", "hostinger-billing-mcp"],
"env": { "USER_AGENT": "plugin;cursor;0.3.1" }
"env": { "USER_AGENT": "plugin;cursor;0.3.2" }
},
"hostinger-reach": {
"command": "npx",
"args": ["--yes", "--package=@hostinger/mcp@latest", "hostinger-reach-mcp"],
"env": { "USER_AGENT": "plugin;cursor;0.3.1" }
"env": { "USER_AGENT": "plugin;cursor;0.3.2" }
},
"hostinger-ecommerce": {
"command": "npx",
"args": ["--yes", "--package=@hostinger/mcp@latest", "hostinger-ecommerce-mcp"],
"env": { "USER_AGENT": "plugin;cursor;0.3.1" }
"env": { "USER_AGENT": "plugin;cursor;0.3.2" }
},
"hostinger-vps": {
"command": "npx",
"args": ["--yes", "--package=@hostinger/mcp@latest", "hostinger-vps-mcp"],
"env": { "USER_AGENT": "plugin;cursor;0.3.1" }
"env": { "USER_AGENT": "plugin;cursor;0.3.2" }
}
}
}
25 changes: 0 additions & 25 deletions skills/deploy-to-hosting/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,31 +42,6 @@ Archive rules (name archives `name_YYYYMMDD_HHMMSS.zip`):
- **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.
- Agency deploys are synchronous: the site is live when the call returns.

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.

### Without the local deploy operations

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.
2. Upload each file with TUS, where `DEST` is its path in the website's storage:

```bash
SIZE=$(wc -c < "$FILE" | tr -d ' ')
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"
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"
```

The first call returns `201`, the second `204` with an `Upload-Offset` header equal to the file size. `override=true` makes a retry safe.
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)`):

| Project | `DEST` | Then |
| --- | --- | --- |
| Static or PHP | `site.zip` | `hosting_websites_deploy-static-site-archive` with `archive_path: "site.zip"` |
| 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"` |
| WordPress plugin | every file, as `wp-content/plugins/SLUG-RANDOM8/<path in the plugin>` | `wordpress_plugins_deploy` with `slug` and `plugin_path: "SLUG-RANDOM8"` |
| 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` |
| Agency, extracted as-is | `.h5g/site.zip` | `agency-hosting_files_import-website-from-archive` with `archive_name: "site.zip"` |
| Agency `node-static` | `.h5g/RANDOM8/app.zip` | `agency-hosting_websites_build-nodejs-assets` with `archive_path: ".h5g/RANDOM8"` — the directory, not the file |

## 3. Node.js builds

`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.
Expand Down
2 changes: 1 addition & 1 deletion skills/hostinger-headless/references/DATABASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Do not put the remote `host` into the deployed app — it has no grant for conne

| You called | Poll this until | Typical wait |
| --- | --- | --- |
| `hosting_websites_create` | `hosting_websites_list-setups` with the domain reports `status: completed` | up to a few minutes |
| `hosting_websites_create` | `hosting_websites_list` lists the domain | up to a few minutes |
| `hosting_deploy-js-application` | `hosting_list-js-deployments` shows the build finished | minutes |
| `hosting_nodejs_start-build` | `hosting_nodejs_build` state is `completed` or `failed` | minutes |
| `wordpress_installations_install`, plugin/theme/core jobs | `wordpress_installations_list` lists the install | 1–2 minutes |
Expand Down
2 changes: 0 additions & 2 deletions skills/hostinger-headless/references/DEPLOYMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

Match the deploy method to what the project actually is — this is the single most common failure point.

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.

## Static site → `hosting_deploy-static-website`

For pre-built files only: plain HTML/CSS/JS, or the **build output** of a framework (run the build locally first).
Expand Down
5 changes: 2 additions & 3 deletions skills/hostinger-headless/references/SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ A website can only be created on an active hosting plan.

1. `hosting_websites_list` — if it returns websites, the account has a working plan; note any existing `order_id` and `username` for step 2.
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`.
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.
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.
3. 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.

Never purchase a plan, domain, or any paid item without the user explicitly approving that specific purchase.

Expand All @@ -24,7 +23,7 @@ Never purchase a plan, domain, or any paid item without the user explicitly appr
Generating a subdomain does **not** create a website — deploying straight to it fails with `No website found for domain`. The working sequence:

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`).
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.
2. **Poll** `hosting_websites_list` filtered by the domain until the site appears. Creation takes up to a few minutes — poll with backoff, don't fail fast.
3. Note the site's `username` — deployment and database operations are keyed on it.

If the domain already has a website (an `iterate` run, or the user pointed at an existing site), skip creation entirely.
Expand Down
8 changes: 3 additions & 5 deletions skills/migrate-to-hosting/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,9 @@ Create the Hostinger website on the domain being migrated, not on a free subdoma

## 3. Import

`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.
**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`.

**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`.

**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`].
**Static, or PHP without a database:** `hosting_deploy-static-website` (Agency: `agency-hosting_deploy-php-application`).

**PHP with a database, Shared and Cloud:**

Expand All @@ -55,7 +53,7 @@ Create the Hostinger website on the domain being migrated, not on a free subdoma

**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.

**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.
**Agency:** files with `agency-hosting_deploy-php-application`; 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.

## 4. Test before DNS moves

Expand Down
Loading