Skip to content
Merged
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
9 changes: 5 additions & 4 deletions .cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"name": "hostinger-connector",
"displayName": "Hostinger Connector",
"version": "0.1.0",
"description": "MCP plugin to deploy and manage Hostinger hosting, Node.js apps, deployments, and DNS from inside Cursor.",
"version": "0.2.0",
"description": "MCP plugin to deploy and manage Hostinger websites, WordPress, domains, DNS, VPS, and subscriptions from inside Cursor.",
"author": "Hostinger",
"license": "MIT",
"homepage": "https://hostinger.com/",
"repository": {
"type": "git",
"url": "https://github.com/hostinger/api-mcp-server"
"url": "https://github.com/hostinger/hostinger-cursor-plugin"
},
"keywords": [
"hosting",
Expand All @@ -17,7 +17,8 @@
"mcp",
"hostinger",
"dns",
"wordpress"
"wordpress",
"vps"
],
"logo": "assets/logo.svg"
}
63 changes: 63 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: CI

on:
pull_request:
push:
branches: [main, master]

jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Comment on lines +3 to +12

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Restrict token access in this workflow.

This workflow executes repository code from pull requests but relies on repository-default GITHUB_TOKEN permissions. Both checkout steps also persist credentials. Limit the token to read-only contents access and disable credential persistence.

Proposed workflow hardening
 on:
   pull_request:
   push:
     branches: [main, master]

+permissions:
+  contents: read
+
 jobs:
   validate:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v4
+        with:
+          persist-credentials: false
...
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v4
+        with:
+          persist-credentials: false

Also applies to: 46-46

🧰 Tools
🪛 zizmor (1.29.0)

[warning] 12-12: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 3 - 12, Harden the CI workflow by
declaring read-only contents permissions for the workflow and setting
persist-credentials to false on both checkout steps using actions/checkout@v4.
Apply the same checkout configuration in the duplicated checkout location.

Source: Linters/SAST tools


- uses: actions/setup-node@v4
with:
node-version: 22

- name: Validate plugin manifest and component frontmatter
run: node scripts/validate-template.mjs

- name: Check every referenced MCP tool exists
run: node scripts/check-tool-names.mjs

- name: Check JSON files parse
run: |
for f in mcp.json hooks/hooks.json .cursor-plugin/plugin.json scripts/mcp-tools.json; do
node --input-type=module -e "
import { readFileSync } from 'node:fs';
JSON.parse(readFileSync('$f', 'utf8'));
console.log('ok $f');
"
done

- name: Lint hook script
run: shellcheck scripts/check-no-token-leak.sh

- name: Check hook script is executable
run: test -x scripts/check-no-token-leak.sh

# The MCP server ships new tools regularly. This is advisory: it tells us the
# checked-in catalog has fallen behind, without failing PRs that didn't cause it.
catalog-drift:
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: 22

- name: Regenerate the catalog from the latest published server
run: node scripts/sync-mcp-tools.mjs

- name: Report drift
run: |
if git diff --quiet -- scripts/mcp-tools.json; then
echo "Catalog is up to date with hostinger-api-mcp@latest."
else
echo "::warning::scripts/mcp-tools.json is behind hostinger-api-mcp@latest."
echo "Run 'node scripts/sync-mcp-tools.mjs' and commit the result."
git --no-pager diff --stat -- scripts/mcp-tools.json
fi
35 changes: 35 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Changelog

## [0.2.0] - 2026-08-06

Brings the plugin back in line with `hostinger-api-mcp` (now 1.29.0) and with the product surface of the Hostinger VS Code extension (1.3.2). The plugin was last touched on 2026-05-27, two days before OAuth shipped.

### Fixed

- **Every Hostinger tool name in the rules, skills, agent, and command was invented.** The plugin instructed the agent to call `list_hosting_plans`, `create_nodejs_deployment`, `list_dns_records`, `create_dns_snapshot`, `query_logs`, `restore_backup`, and others — none of which the MCP server has ever exposed. All 104 tool references now use the real OpenAPI operation IDs (`hosting_listWebsitesV1`, `DNS_getDNSRecordsV1`, `billing_getSubscriptionListV1`, …) and are verified in CI.
- **The token-leak hook never ran.** `hooks/hooks.json` used a `pre-commit` trigger, which is not a Cursor hook event, along with an array shape and a `script` key that Cursor's v1 schema doesn't read. It is now a `beforeShellExecution` hook matching `git commit`, and the script speaks the hook JSON protocol on stdin/stdout. It fails open, so a guard that can't read the staged diff won't block every commit.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail
rg -n -C 5 'beforeShellExecution|git commit|fail|exit|staged|diff' \
  hooks/hooks.json scripts/check-no-token-leak.sh

Repository: hostinger/hostinger-cursor-plugin

Length of output: 3953


Fail closed when the staged diff cannot be read.

scripts/check-no-token-leak.sh lets commits pass on git unavailable, non-work-tree state, unreadable git diff --cached, or malformed JSON/stdin. Since the hook fails open, these cases bypass token scanning. Use fail-close behavior for input failures, or narrow/suppress fail-open cases and add tests for them.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CHANGELOG.md` at line 10, Update scripts/check-no-token-leak.sh to fail
closed whenever it cannot obtain or parse the staged diff, including unavailable
git, non-work-tree state, unreadable git diff --cached output, or malformed hook
JSON/stdin; return the blocking result through the existing hook protocol while
preserving normal token-scan behavior.

- **The deployment guidance described an API that doesn't exist.** There is no framework "preset" parameter. `rules/framework-presets.mdc` invented seven preset names; the real `app_type` override accepts only `create-react-app`, `vite`, `angular`, `react`, `vue`, `parcel`, `express`, `fastify`, and `nest`, with everything else auto-detected from `package.json`. Replaced by `rules/nodejs-deployments.mdc`, documenting the real tools and the accepted `node_version`, `package_manager`, `root_directory`, `output_directory`, `build_script`, and `entry_file` overrides.
- **DNS guidance assumed per-record operations.** Hostinger's DNS API is zone-oriented: `DNS_updateDNSRecordsV1` takes a whole zone array plus an `overwrite` flag, and there is no tool to create a snapshot on demand. The skill now explains the `overwrite` semantics, uses `DNS_validateDNSRecordsV1` as a dry run, and cites an existing snapshot ID for rollback instead of promising a fresh backup.
- **`query-hosting-logs` promised access and error logs the API does not expose.** Renamed to `query-deployment-logs` and scoped to what exists: JS deployment logs, Node.js build logs, and cron output. The plugin now states plainly that HTTP access logs, PHP error logs, Node.js environment variables, and shared-hosting backups are hPanel-only.
- `repository.url` in `plugin.json` pointed at `hostinger/api-mcp-server` instead of this repository.
- Added the `LICENSE` file that `plugin.json` has always declared.

### Changed

- **One MCP server per product area instead of a single monolith.** `mcp.json` previously started `hostinger-api-mcp`, loading all 289 tools into context at once. It now registers eight servers — hosting, wordpress, domains, dns, billing, reach, ecommerce, vps — mirroring the VS Code extension's groups, so users can disable areas they don't use from Cursor's MCP settings.
- **OAuth is the default auth path.** The README claimed OAuth was "not currently supported by the Hostinger backend"; it shipped in the MCP server and in extension 1.1.0 on 2026-05-29. The server now signs in through the browser on the first authenticated tool call, and `mcp.json` no longer hardcodes `HOSTINGER_API_TOKEN` — the fragile `${HOSTINGER_API_TOKEN}` interpolation would have shadowed the OAuth fallback. An exported token still takes precedence.
- **Product naming matches the extension.** "Web Hosting" → Websites, "Reach" → Email Marketing, "Billing" → Subscriptions & Payments, and DNS is documented alongside Domains.
- The README now documents the overlap with the VS Code extension, which writes these same servers into `~/.cursor/mcp.json` — running both in Cursor duplicates every server.

### Added

- `USER_AGENT` on every MCP server (`plugin;cursor;<version>`), matching the extension's attribution so plugin traffic is no longer invisible to Hostinger.
- `scripts/check-tool-names.mjs` — asserts every tool-shaped identifier in the docs resolves to a real tool. It default-denies unknown snake_case identifiers rather than checking known prefixes, because the original fabricated names had no prefix at all and a prefix check would have missed them entirely.
- `scripts/sync-mcp-tools.mjs` and `scripts/mcp-tools.json` — a checked-in snapshot of the published tool catalog (289 tools, 11 groups) so the check runs offline.
- `.github/workflows/ci.yml` — runs both validators, parses every JSON file, shellchecks the hook, and confirms it's executable. A second advisory job flags when the catalog snapshot falls behind `hostinger-api-mcp@latest`.

## [0.1.0] - 2026-05-27

### Initial release

- Hostinger MCP server wiring, five skills, three rules, one agent, one command.
10 changes: 10 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
The MIT License (MIT) Copyright (c) 2026 Hostinger International Ltd.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

By using this plugin you agree to Hostinger's Terms of Service:
https://www.hostinger.com/legal/universal-terms-of-service-agreement
Comment on lines +9 to +10

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== LICENSE =="
if [ -f LICENSE ]; then
  cat -n LICENSE
else
  echo "LICENSE not found"
fi

echo
echo "== candidate license/toc files =="
git ls-files | rg -i '(^|/)(LICENSE|license|README\.md|readme\.md|terms|terms-of-service|hostinger)' | head -100

echo
echo "== references to Hostinger Terms of Service / license type =="
rg -n -i "hostinger.*terms|terms of service|mit license|license" -S -g '!**/node_modules/**' -g '!**/dist/**' -g '!**/build/**' | head -200

Repository: hostinger/hostinger-cursor-plugin

Length of output: 1667


🌐 Web query:

MIT license canonical SPDX license text additional restrictions

💡 Result:

The canonical SPDX short identifier for the MIT License is MIT [1][2][3]. The authoritative text for this license is maintained by the Open Source Initiative (OSI) and indexed by the Software Package Data Exchange (SPDX) [1][4][3]. Regarding additional restrictions, the MIT License explicitly grants permission to deal in the software without restriction, provided that the original copyright notice and permission notice are included in all copies or substantial portions of the software [5][4][6]. Because the license requires the inclusion of these specific notices, any attempt to remove or modify them violates the license terms [7]. While the MIT License is permissive and allows for sublicensing—meaning you can incorporate MIT-licensed code into larger works that may be distributed under different or proprietary terms—you cannot remove the original license or copyright notice from the MIT-licensed components themselves [7][8]. Any redistribution of the MIT-licensed code must retain the original notice [4][7]. If you distribute a modified version of the license or add extra conditions that contradict the original permissions, it is no longer the standard MIT License, but rather a custom or modified license [9]. Adding restrictive conditions to the original MIT text or demanding they apply to the original code effectively nullifies the standard MIT grant for that software [10].

Citations:


🌐 Web query:

Hostinger universal terms of service agreement website services plugin terms

💡 Result:

Hostinger's primary legal framework is centered on its Universal Terms of Service Agreement (UTOS) [1][2]. This document establishes the general terms and conditions for using the Hostinger website and all products or services accessed through it [1][2]. Key aspects of Hostinger's legal agreements include: Universal Terms of Service Agreement (UTOS): The UTOS acts as the overarching contract between you and the relevant Hostinger group entity [1][2]. It is incorporated by reference into all other specific product agreements, such as the Hosting Agreement and the Domain Name Registration Agreement [3][4]. If a conflict arises between the UTOS and a specific product agreement, the terms of the specific product agreement typically control [3][5]. Product-Specific Terms: Hostinger utilizes various agreements to govern specific services [2]. For example: - The Hosting Agreement covers the terms for hosting services and explicitly incorporates the UTOS [3][5]. - The Domain Name Registration Agreement governs domain services and incorporates both the UTOS and relevant Registry Policies [4]. - These agreements, along with others like the Refund Policy and Privacy Policy, are part of the broader legal framework that binds users [6][2][7]. Plugin and Third-Party Terms: Hostinger's UTOS contains a specific section regarding Product Specific Terms and Third-Party Products (Section 17) [2]. Because Hostinger often provides access to third-party software (such as plugins or applications via platforms like WordPress), users are typically required to adhere to the terms set forth by those third-party providers in addition to Hostinger's own terms. Compliance and Policy: Users are expected to comply with applicable laws and Hostinger's policies [8]. The use of prohibited items, such as nulled or cracked scripts (often associated with plugins or themes), is strictly forbidden and can result in service suspension under the terms outlined in the UTOS [8]. You can review the official Universal Terms of Service Agreement and related legal documents directly on the Hostinger legal portal [2].

Citations:


Remove the Hostinger ToS clause from LICENSE.

LICENSE should remain the canonical MIT text. The TOU adds an acceptance clause that is not part of MIT and can be read as an additional condition on use of the plugin. Keep Terms of Service language out of the license file and reference it separately only where appropriate.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@LICENSE` around lines 9 - 10, Remove the Hostinger Terms of Service
acceptance clause and its URL from LICENSE, leaving only the canonical MIT
license text. Do not add replacement licensing language; keep any ToS reference
outside the license file.

Loading
Loading