fix: sync plugin with the real MCP server and extension parity - #2
Conversation
The plugin was last touched on 2026-05-27 and had drifted from both
hostinger-api-mcp (now 1.29.0) and the VS Code extension (1.3.2). Several
parts were not merely stale but non-functional.
Every Hostinger tool name in the rules, skills, agent, and command was
invented. The plugin told the agent to call list_hosting_plans,
create_nodejs_deployment, list_dns_records, create_dns_snapshot,
query_logs and others, none of which the MCP server has ever exposed. All
104 references now use the real OpenAPI operation IDs.
The token-leak hook never fired: hooks.json used a "pre-commit" trigger,
which is not a Cursor hook event, plus an array shape and a "script" key
the v1 schema does not read. It is now a beforeShellExecution hook that
matches git commit and speaks the hook JSON protocol, failing open so a
guard that cannot read the staged diff does not block every commit.
Deployment guidance described an API that does not exist. There is no
framework preset parameter; the real app_type override accepts only
create-react-app, vite, angular, react, vue, parcel, express, fastify and
nest, with everything else auto-detected. DNS guidance assumed per-record
tools, but the API is zone-oriented with an overwrite flag and no
on-demand snapshot creation. query-hosting-logs promised access and error
logs the API does not expose, so it is now query-deployment-logs, scoped
to build, deployment and cron logs.
mcp.json now registers eight per-product servers mirroring the extension's
groups instead of one monolith loading all 289 tools, drops the fragile
${HOSTINGER_API_TOKEN} interpolation that shadowed the OAuth fallback, and
sets USER_AGENT so plugin traffic is attributable.
To stop the tool-name class of bug recurring, check-tool-names.mjs
validates every tool-shaped identifier in the docs against a checked-in
catalog. It default-denies unknown snake_case names rather than checking
known prefixes, because the fabricated names had no prefix at all. CI runs
it alongside the manifest validator, JSON parsing and shellcheck.
📝 WalkthroughWalkthroughThe plugin release updates Hostinger service coverage, MCP server configuration, authentication, safety rules, operational workflows, validation tooling, CI, documentation, and licensing. ChangesHostinger plugin platform
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant hostinger-status
participant HostingMCP
participant DomainsMCP
participant VPSMCP
participant BillingMCP
User->>hostinger-status: Request read-only account status
par Query enabled services
hostinger-status->>HostingMCP: Query websites and deployments
hostinger-status->>DomainsMCP: Query domains
hostinger-status->>VPSMCP: Query VPS state
hostinger-status->>BillingMCP: Query subscriptions
end
HostingMCP-->>hostinger-status: Return hosting data
DomainsMCP-->>hostinger-status: Return domain data
VPSMCP-->>hostinger-status: Return VPS data
BillingMCP-->>hostinger-status: Return subscription data
hostinger-status-->>User: Render compact sections and attention markers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 18
🤖 Prompt for all review comments with 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.
Inline comments:
In @.github/workflows/ci.yml:
- Around line 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.
In `@CHANGELOG.md`:
- 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.
In `@commands/hostinger-status.md`:
- Line 21: Update the hostinger status snapshot handling so only the specific
case where a configured server is disabled is marked unavailable and skipped.
Preserve and surface authentication, permission, timeout, and API errors in
their affected sections instead of treating all MCP request failures as
unavailable or aborting the entire snapshot.
In `@LICENSE`:
- Around line 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.
In `@mcp.json`:
- Line 5: Update every hostinger-api-mcp entry in the mcp.json command
arguments, including the shown hostinger-hosting-mcp entry, replacing the
`@latest` package tag with `@1.29.0` so all eight commands match the catalog
version.
In `@README.md`:
- Around line 31-33: Add language identifiers to the affected Markdown fences:
use text or console for the /add-plugin fence in README.md (31-33), text for the
checklist fence in agents/hostinger-deployment-reviewer.md (32-40), and text for
the output fence in commands/hostinger-status.md (25-45).
- Around line 76-93: The runtime package version and tool catalog version are
inconsistent. Update the MCP configuration and validation flow so Cursor
launches and CI validates the same exact hostinger-api-mcp version recorded in
scripts/mcp-tools.json (currently 1.29.0), replacing the floating latest
reference or resolving it from that shared version.
In `@rules/confirm-destructive-actions.mdc`:
- Around line 71-73: Replace the name-prefix exemption in the “Read-only is
safe” section with an explicit catalog of approved read-only tools or required
read-only catalog metadata, so arbitrary tools named list*, get*, show*, check*,
or validate* cannot bypass confirmation. Retain DNS_validateDNSRecordsV1 as an
approved entry and document that it has no side effects and serves as the dry
run for DNS_updateDNSRecordsV1.
In `@rules/nodejs-deployments.mdc`:
- Around line 32-34: Replace the archive command with a tested file-list
generation step that honors .gitignore, then apply explicit exclusions for all
documented build-output directories and secret files, including .env.local. Keep
the resulting archive example consistent with the exclusions described in Lines
26-29 and prevent ignored credentials or generated files from being included.
In `@rules/prefer-mcp-tools.mdc`:
- Around line 22-37: Update the “Which server to use” guidance to route requests
by the operation ID and server mapping, explicitly treating the shared hosting_
prefix as ambiguous. Clarify that WordPress operation IDs must use
hostinger-wordpress, while non-WordPress hosting operations use
hostinger-hosting, preventing agents from selecting the wrong server.
In `@scripts/check-no-token-leak.sh`:
- Around line 37-38: Update the staged-file handling in the token-leak hook so
filenames are JSON-encoded before interpolation into the agent_message response,
preserving valid JSON for quotes and control characters. Alternatively, remove
the dynamic files list from the response; keep the existing token-blocking
behavior unchanged.
In `@scripts/check-tool-names.mjs`:
- Around line 21-24: Align the MCP server runtime package version with the
catalog’s validated hostinger-api-mcp@1.29.0 by updating every configured server
entry to use that exact version instead of latest. Ensure all entries checked by
the catalog validation flow, including the additional server configuration,
remain pinned consistently.
In `@skills/deploy-nodejs-app/SKILL.md`:
- Line 26: Update step 2 in the deployment instructions so build-output
directories are excluded only for server-built Node.js deployments. For the
hosting_deployStaticWebsite path, retain the finished files from dist, build, or
out in the archive while continuing to exclude node_modules, .git, and .env and
enforce the 50 MB limit.
In `@skills/manage-dns-records/SKILL.md`:
- Around line 52-60: Update the Deleting and Rolling back guidance for
DNS_deleteDNSRecordsV1 and DNS_restoreDNSSnapshotV1 to require explicit
confirmation immediately before each call. Instruct the assistant to show the
exact deletion filters or snapshot target before requesting confirmation; keep
DNS_getDNSSnapshotV1 inspection separate from approval and retain the existing
DNS_updateDNSRecordsV1 confirmation guidance.
In `@skills/query-deployment-logs/SKILL.md`:
- Around line 34-35: Update the reporting guidance in the “Summarize rather than
dumping” section so the final 20 log lines are redacted for credentials and
sensitive environment values before being quoted verbatim. Preserve the existing
requirement to report those lines for failures.
In `@skills/troubleshoot-wordpress/SKILL.md`:
- Around line 57-63: Update the “Confirm before” list to include
hosting_updatePHPExtensionsV1, hosting_updatePHPOptionsV1, and
hosting_updateHostingerWordPressPluginV1 alongside the existing high-impact
update operations, preserving the explicit confirmation requirement for each.
- Line 55: Update the plugin isolation procedure to reactivate a plugin with
hosting_activateWordPressPluginV1 only if the symptom persists while it is
disabled. Keep the plugin deactivated when its removal resolves the symptom,
identify it as the confirmed suspect, and preserve the requirement to announce
the plugin and affected feature before deactivation.
- Around line 45-47: Update the troubleshooting steps for cacheless mode,
Memcached object cache, and maintenance mode to inspect each setting’s current
state before invoking its toggle tool. Call hosting_toggleCachelessModeV1,
hosting_toggleMemcachedObjectCacheV1, and hosting_toggleMaintenanceModeV1 only
when the observed state differs from the intended troubleshooting state;
otherwise leave the setting unchanged.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 34491975-2ba2-465a-9646-4612f1ffa0b9
📒 Files selected for processing (23)
.cursor-plugin/plugin.json.github/workflows/ci.ymlCHANGELOG.mdLICENSEREADME.mdagents/hostinger-deployment-reviewer.mdcommands/hostinger-status.mdhooks/hooks.jsonmcp.jsonrules/confirm-destructive-actions.mdcrules/framework-presets.mdcrules/nodejs-deployments.mdcrules/prefer-mcp-tools.mdcscripts/check-no-token-leak.shscripts/check-tool-names.mjsscripts/mcp-tools.jsonscripts/sync-mcp-tools.mjsskills/deploy-nodejs-app/SKILL.mdskills/diagnose-build-failure/SKILL.mdskills/manage-dns-records/SKILL.mdskills/query-deployment-logs/SKILL.mdskills/query-hosting-logs/SKILL.mdskills/troubleshoot-wordpress/SKILL.md
💤 Files with no reviewable changes (2)
- rules/framework-presets.mdc
- skills/query-hosting-logs/SKILL.md
| on: | ||
| pull_request: | ||
| push: | ||
| branches: [main, master] | ||
|
|
||
| jobs: | ||
| validate: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 |
There was a problem hiding this comment.
🔒 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: falseAlso 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
| ### 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. |
There was a problem hiding this comment.
🔒 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.shRepository: 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.
| 2. Render as compact sections — do not paginate. | ||
| 3. Flag anything that needs attention with `[!]`: a failed deployment, a disabled website, a stopped VPS, or a subscription renewing within 30 days without auto-renewal. | ||
|
|
||
| If a server isn't enabled in the user's Cursor MCP settings, its section will error. Note the section as unavailable and carry on — don't abort the whole snapshot. |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Files matching hostinger-status:"
fd -i 'hostinger-status' . || true
echo
echo "Search relevant symbols:"
rg -n "hostinger-status|Hostinger|server isn't enabled|unavailable|Cursor MCP settings|timeout|authentication|permission|API" . -S || trueRepository: hostinger/hostinger-cursor-plugin
Length of output: 19918
🌐 Web query:
hostinger-api-mcp disabled server timeout authentication error handling
💡 Result:
If you are experiencing authentication errors, connection timeouts, or service issues with the Hostinger API Model Context Protocol (MCP) server, please follow the troubleshooting steps outlined below. Authentication Errors - Unauthorized (401) or Authentication Errors: These typically indicate that your session has expired, the token was revoked, or the credentials are invalid [1][2]. - Troubleshooting Steps: Run the Hostinger: Disconnect command in your IDE to clear all stored credentials [1][3]. Re-authenticate using the recommended OAuth flow, or if you are using an API token, generate a fresh one via hPanel (Account → API) and ensure it is set correctly in your environment variables without leading or trailing spaces [1][4][2]. - Environment Variables: When using an API token, ensure it is set via the HOSTINGER_API_TOKEN environment variable (note that API_TOKEN is a deprecated alias) [5][6]. Connection Timeouts and Setup Issues - Connection Timeouts: Often caused by environmental or network issues. Verify that you have a stable internet connection and that your system meets requirements, such as running a modern version of Node.js (v20+) [1][2]. - OAuth Sign-in Timeouts: The browser-based OAuth flow must be completed within 3 minutes [1]. If the browser fails to open, manually copy the sign-in link printed in your terminal [1]. Ensure that you do not close any terminal windows explicitly opened for the "Hostinger OAuth" process on Windows, as this will cancel the flow [1]. - Transport Modes: The Hostinger MCP server supports both stdio (default) and HTTP transport modes [5][7]. Note that OAuth sign-in is not supported in --http mode; if you use the --http flag, you must provide a valid HOSTINGER_API_TOKEN [5][6]. General Troubleshooting - Debugging: You can enable verbose logging by setting the DEBUG environment variable to true to help identify specific failure points [5][7]. - Rate Limits: If you receive a 429 Too Many Requests response, you have exceeded API rate limits [8][9]. Reduce your request frequency, as repeated violations may lead to temporary IP blocks [8]. - Verification: Ensure the MCP server is correctly installed globally (e.g., npm install -g hostinger-api-mcp) and that your AI client (Claude Desktop, Cursor, etc.) has been restarted after any configuration changes [2]. If issues persist, consult the official Hostinger Connector troubleshooting documentation or contact Hostinger support for further assistance [1][4].
Citations:
- 1: https://docs.hostinger.com/hostinger-connector/troubleshooting
- 2: https://techdg.in/hostinger-api-mcp-connect-ides-claude-cursor-jetbrains-windsurf/
- 3: https://docs.hostinger.com/hostinger-connector/overview
- 4: https://www.hostinger.com/support/11079316-hostinger-api-mcp-server/
- 5: https://github.com/hostinger/api-mcp-server
- 6: https://github.com/hostinger/api-mcp-server/blob/4d2b3665/README.md
- 7: https://playbooks.com/mcp/hostinger-api
- 8: https://developers.hostinger.com/
- 9: https://www.postman.com/hostinger-api/hostinger/documentation/1jnj25h/hostinger-api
🌐 Web query:
github hostinger/api-mcp-server error handling unavailable section disabled server
💡 Result:
There is no specific issue or official documentation within the hostinger/api-mcp-server project that refers to an "error handling unavailable section disabled server" error. The phrasing you mentioned likely conflates general MCP error handling patterns or issues from other MCP server implementations [1][2][3] with the Hostinger MCP server's actual operations. Here is a clarification of how error handling and server availability function within the hostinger/api-mcp-server ecosystem: 1. Standard Hostinger API Errors: The Hostinger API returns standard HTTP status codes (e.g., 403 for permission issues, 404 for missing resources, 422 for invalid requests) with a JSON response containing an error field and a correlation_id for support tracking [4]. The hostinger/api-mcp-server passes these underlying API errors back to the MCP client [5][6]. 2. Tool Availability and Server State: While the hostinger/api-mcp-server documentation does not have a specific "disabled" mode for its internal tools, the Model Context Protocol (MCP) specification and related community discussions (such as SEP-2140) emphasize that servers should report "Tool not callable" errors when a tool is unavailable, disabled, or policy-restricted [3]. This is a protocol-level recommendation, not a bug specific to Hostinger. 3. Common Configuration Errors: Users of the hostinger/api-mcp-server often encounter issues related to: - Authentication: Ensure HOSTINGER_API_TOKEN (or the deprecated APITOKEN) is correctly set in your environment [5][7][8]. OAuth is not supported in --http mode [5][7]. - Resource Pathing: Certain tools (like hosting_deployStaticWebsite) require specific path formats, such as prefixing archive paths with public_html/ [9]. - Feature Availability: Some features, such as "Patch Node.js Vulnerabilities," are only available on specific hosting plans (Business/Cloud) and require a connected GitHub repository [5][10]. If you are experiencing an error where a server section appears "unavailable" or "disabled," it is likely a client-side display issue (e.g., in Claude Desktop or an n8n workflow) where the server has failed to authenticate or initialize correctly, rather than a built-in "disabled server" state within the code [11][12]. Check your logs by enabling the DEBUG=true environment variable to see the exact API response being returned by the Hostinger service [5][7].
Citations:
- 1: listStacks fails with 503 error when Edge functionality is disabled portainer/portainer-mcp#28
- 2: Return a friendly error message when Pulse or VDS is disabled tableau/tableau-mcp#111
- 3: SEP-2140: Standardize
tools/callFailure Reporting (Tool Resolution + Output Validation) modelcontextprotocol/modelcontextprotocol#2140 - 4: https://developers.hostinger.com/
- 5: https://github.com/hostinger/api-mcp-server
- 6: https://deepwiki.com/hostinger/api-mcp-server
- 7: https://github.com/hostinger/api-mcp-server/blob/4d2b3665/README.md
- 8: https://github.com/hostinger/api-mcp-server/blob/main/.env.example
- 9: hosting_deployStaticWebsite fails with 500 'Archive not found' — archive_path needs public_html/ prefix api-mcp-server#34
- 10: https://github.com/hostinger/api-mcp-server/blob/main/types.d.ts
- 11: https://www.hostinger.com/ca/tutorials/how-to-build-n8n-personal-assistant-with-mcp/
- 12: https://www.hostinger.com/tutorials/how-to-run-hostinger-api-mcp-server/
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "README section around hostinger-status command:"
fd -i '^README\.md$' . -x sed -n '120,145p' {} \;
echo
echo "Exact command file:"
cat -n commands/hostinger-status.md | sed -n '1,80p'
echo
echo "Search for hostinger-status command implementation or references outside docs:"
rg -n '"hostinger-status"|hostinger-status|/hostinger-status' . -SRepository: hostinger/hostinger-cursor-plugin
Length of output: 3812
Surface failed MCP requests instead of marking every missing section unavailable.
Only suppress the enabled-but-disabled-server case. Render authentication, permission, timeout, and API failures in the affected section so users can fix the broken account connection.
🤖 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 `@commands/hostinger-status.md` at line 21, Update the hostinger status
snapshot handling so only the specific case where a configured server is
disabled is marked unavailable and skipped. Preserve and surface authentication,
permission, timeout, and API errors in their affected sections instead of
treating all MCP request failures as unavailable or aborting the entire
snapshot.
| By using this plugin you agree to Hostinger's Terms of Service: | ||
| https://www.hostinger.com/legal/universal-terms-of-service-agreement |
There was a problem hiding this comment.
🔒 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 -200Repository: 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:
- 1: https://spdx.org/licenses/index.html
- 2: https://spdx.org/licenses
- 3: https://spdx.org/licenses/MIT
- 4: https://opensource.org/license/mit
- 5: https://spdx.org/licenses/MIT.html
- 6: https://www.debian.org/legal/licenses/mit
- 7: https://opensource.stackexchange.com/questions/2644/does-the-mit-licenses-right-to-sublicense-allow-me-to-change-the-license-of-s
- 8: https://opensource.stackexchange.com/questions/8120/proprietary-licensing-combinations-of-non-copyleft-software
- 9: https://opensource.stackexchange.com/questions/8485/mit-license-with-extra-conditions
- 10: https://community.blackduck.com/s/article/Why-does-Black-Duck-say-that-MIT-license-forbids-to-place-additional-restrictions
🌐 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:
- 1: https://www.hostinger.com/ca/legal/universal-terms-of-service-agreement
- 2: https://www.hostinger.com/legal/universal-terms-of-service-agreement
- 3: https://www.hostinger.com/legal/hosting-agreement
- 4: https://www.hostinger.com/legal/domain-name-registration-agreement
- 5: https://www.hostinger.com/ca/legal/hosting-agreement
- 6: https://www.hostinger.com/pk/legal/universal-terms-of-service-agreement
- 7: https://www.hostinger.com/legal/refund-policy
- 8: https://www.hostinger.com/support/which-types-of-content-and-websites-are-allowed-at-hostinger/
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.
| "env": { | ||
| "HOSTINGER_API_TOKEN": "${HOSTINGER_API_TOKEN}" | ||
| } | ||
| "args": ["--yes", "--package=hostinger-api-mcp@latest", "hostinger-hosting-mcp"], |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
jq -r '
.mcpServers
| to_entries[]
| "\(.key): \(.value.args[] | select(startswith("--package=hostinger-api-mcp@")))"
' mcp.json
rg -n -C2 'hostinger-api-mcp@|1\.29\.0' \
mcp.json scripts/sync-mcp-tools.mjs scripts/mcp-tools.json README.mdRepository: hostinger/hostinger-cursor-plugin
Length of output: 4153
Pin every hostinger-api-mcp entry in mcp.json to 1.29.0.
The catalog is checked in as scripts/mcp-tools.json with version: "1.29.0", but the MCP server commands still use --package=hostinger-api-mcp@latest. Pin all eight entries to --package=hostinger-api-mcp@1.29.0 so the plugin runs against the same package/version as the checked-in tool catalog.
Proposed fix
- "--package=hostinger-api-mcp@latest"
+ "--package=hostinger-api-mcp@1.29.0"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "args": ["--yes", "--package=hostinger-api-mcp@latest", "hostinger-hosting-mcp"], | |
| "args": ["--yes", "--package=hostinger-api-mcp@1.29.0", "hostinger-hosting-mcp"], |
🤖 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 `@mcp.json` at line 5, Update every hostinger-api-mcp entry in the mcp.json
command arguments, including the shown hostinger-hosting-mcp entry, replacing
the `@latest` package tag with `@1.29.0` so all eight commands match the catalog
version.
| ## Deleting | ||
|
|
||
| ## Validation | ||
| `DNS_deleteDNSRecordsV1` filters by name and type, and removes *all* records matching each filter. To drop only some of several records sharing a name and type, use `DNS_updateDNSRecordsV1` with `overwrite: true` and the records you want to keep. | ||
|
|
||
| - Reject syntactically invalid records before calling the API: | ||
| - A → IPv4 only. | ||
| - AAAA → IPv6 only. | ||
| - CNAME → cannot coexist with other records on the same name. | ||
| - MX → must reference a hostname, not an IP. | ||
| - TXT → quote-escape inner double quotes. | ||
| - Warn if TTL is below 300s (propagation thrash) or above 86400s (slow recovery). | ||
| `DNS_resetDNSRecordsV1` returns the entire zone to Hostinger defaults. It is not a targeted delete — treat it as a last resort and confirm explicitly. | ||
|
|
||
| ## Confirm before | ||
| ## Rolling back | ||
|
|
||
| - Deleting any record (always). | ||
| - Replacing all MX records (mail delivery risk). | ||
| - Changing NS records (delegation change — can break the domain). | ||
| - Changing the A/AAAA record of the apex (`@`) — site downtime risk. | ||
| `DNS_restoreDNSSnapshotV1` with the domain and a snapshot ID from `DNS_getDNSSnapshotListV1`. Inspect a snapshot's contents first with `DNS_getDNSSnapshotV1` so the user knows what state they're reverting to. |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Gate DNS deletion and snapshot restoration with explicit confirmation.
DNS_deleteDNSRecordsV1 and DNS_restoreDNSSnapshotV1 can remove or replace zone state. Require the assistant to show the exact filters or snapshot target and wait for explicit confirmation immediately before each call. The current confirmation step is scoped to DNS_updateDNSRecordsV1, and snapshot inspection alone is not approval.
🤖 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 `@skills/manage-dns-records/SKILL.md` around lines 52 - 60, Update the Deleting
and Rolling back guidance for DNS_deleteDNSRecordsV1 and
DNS_restoreDNSSnapshotV1 to require explicit confirmation immediately before
each call. Instruct the assistant to show the exact deletion filters or snapshot
target before requesting confirmation; keep DNS_getDNSSnapshotV1 inspection
separate from approval and retain the existing DNS_updateDNSRecordsV1
confirmation guidance.
| 5. Summarize rather than dumping. Report: | ||
| - The final state and, for a failure, the first error and the last 20 lines verbatim. |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Require redaction before reporting the final log lines.
The report format says to provide the last 20 lines verbatim. The privacy section requires credential redaction before quoting logs. A build log can contain a token or an environment value.
State that the final 20 lines must be redacted before they are quoted.
Proposed fix
- - The final state and, for a failure, the first error and the last 20 lines verbatim.
+ - The final state and, for a failure, the first error and the last 20 lines after credential redaction.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 5. Summarize rather than dumping. Report: | |
| - The final state and, for a failure, the first error and the last 20 lines verbatim. | |
| 5. Summarize rather than dumping. Report: | |
| - The final state and, for a failure, the first error and the last 20 lines after credential redaction. |
🤖 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 `@skills/query-deployment-logs/SKILL.md` around lines 34 - 35, Update the
reporting guidance in the “Summarize rather than dumping” section so the final
20 log lines are redacted for credentials and sensitive environment values
before being quoted verbatim. Preserve the existing requirement to report those
lines for failures.
| | Changes not appearing | LiteSpeed or website cache serving stale content | `hosting_showLiteSpeedCacheStatusV1`, then `hosting_purgeLiteSpeedCacheV1`; also `hosting_clearWebsiteCacheV1`, and `hosting_toggleCachelessModeV1` while actively debugging | | ||
| | Object cache errors after a plugin change | Memcached object cache out of sync | `hosting_showMemcachedObjectCacheStatusV1`, then `hosting_toggleMemcachedObjectCacheV1` | | ||
| | Site stuck showing "briefly unavailable" | Maintenance mode left on | `hosting_showMaintenanceStatusV1`, then `hosting_toggleMaintenanceModeV1` | |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Make toggle operations conditional on the observed state.
hosting_toggleCachelessModeV1, hosting_toggleMemcachedObjectCacheV1, and hosting_toggleMaintenanceModeV1 invert state. Call each tool only when the current state differs from the intended state. Otherwise, the troubleshooting step can disable a correct setting or enable a setting that is causing the issue.
🤖 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 `@skills/troubleshoot-wordpress/SKILL.md` around lines 45 - 47, Update the
troubleshooting steps for cacheless mode, Memcached object cache, and
maintenance mode to inspect each setting’s current state before invoking its
toggle tool. Call hosting_toggleCachelessModeV1,
hosting_toggleMemcachedObjectCacheV1, and hosting_toggleMaintenanceModeV1 only
when the observed state differs from the intended troubleshooting state;
otherwise leave the setting unchanged.
|
|
||
| ## Isolating a plugin conflict | ||
|
|
||
| Deactivate one plugin at a time with `hosting_deactivateWordPressPluginV1`, re-test, and reactivate with `hosting_activateWordPressPluginV1` before moving to the next. Say which plugin you're about to disable and what user-facing feature might break. Do not bulk-deactivate a production site without explicit approval. |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Do not always reactivate the plugin before continuing isolation.
If deactivation removes the symptom, reactivating the plugin immediately restores the failure and can hide a plugin conflict. Reactivate it only when the symptom persists after deactivation. Keep a plugin disabled when it is the confirmed suspect.
🤖 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 `@skills/troubleshoot-wordpress/SKILL.md` at line 55, Update the plugin
isolation procedure to reactivate a plugin with
hosting_activateWordPressPluginV1 only if the symptom persists while it is
disabled. Keep the plugin deactivated when its removal resolves the symptom,
identify it as the confirmed suspect, and preserve the requirement to announce
the plugin and affected feature before deactivation.
| ## Confirm before | ||
|
|
||
| - `restore_backup` (overwrites current site). | ||
| - `disable_wordpress_plugin` on production (could break a customer-facing feature). | ||
| - `update_php_version` (can break themes/plugins that don't support the new version). | ||
| - `hosting_deleteWordPressInstallationV1` — destroys the site. | ||
| - `hosting_uninstallWordPressPluginsV1`, `hosting_uninstallWordPressThemesV1` — may drop plugin data. | ||
| - `hosting_updateWordPressCoreV1`, `hosting_updateWordPressPluginsV1`, `hosting_updateWordPressThemesV1` — can introduce new breakage. | ||
| - `hosting_updatePHPVersionV1` — can break themes and plugins that don't support the new version. | ||
| - `hosting_toggleMaintenanceModeV1` on production — takes the site offline for visitors. |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Include all high-impact update operations in the confirmation list.
Add hosting_updatePHPExtensionsV1, hosting_updatePHPOptionsV1, and hosting_updateHostingerWordPressPluginV1. These operations can change runtime behavior or introduce site breakage, but the current list names only hosting_updatePHPVersionV1 and the standard WordPress update tools. The generic instruction at Line 35 helps, but the explicit safety contract is incomplete.
🧰 Tools
🪛 LanguageTool
[grammar] ~61-~61: Ensure spelling is correct
Context: ...eWordPressThemesV1— can introduce new breakage. -hosting_updatePHPVersionV1` — can b...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
🤖 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 `@skills/troubleshoot-wordpress/SKILL.md` around lines 57 - 63, Update the
“Confirm before” list to include hosting_updatePHPExtensionsV1,
hosting_updatePHPOptionsV1, and hosting_updateHostingerWordPressPluginV1
alongside the existing high-impact update operations, preserving the explicit
confirmation requirement for each.
Why
The plugin was last touched on 2026-05-27. Since then
hostinger-api-mcpmoved to 1.29.0 (289 tools, 12 binaries) and the VS Code extension moved to 1.3.2. Some of the drift is cosmetic, but several parts of the plugin are non-functional as shipped — not merely dated.The two repos are different kinds of artifact (a TypeScript extension with a sidebar and auth flow vs. a declarative plugin), so this doesn't chase feature parity. It fixes what's broken and aligns the three things that genuinely overlap: MCP wiring, the auth story, and tool names.
The three real defects
1. Every 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,get_php_error_logand others. None of these have ever existed on the MCP server — searchingapi-mcp-serverfor them returns zero matches. Real names are OpenAPI operation IDs:hosting_listWebsitesV1,DNS_getDNSRecordsV1,billing_getSubscriptionListV1.All 104 tool references are now real and verified in CI.
2. The token-leak hook never fired
hooks/hooks.jsondidn't match Cursor's hook schema on any axis: it was missingversion, used an array where an object keyed by event name is expected, usedscriptinstead ofcommand, and set"trigger": "pre-commit"— which isn't a Cursor hook event at all, since git commits aren't an agent lifecycle event. Meanwhile the README promised users it blocked leaks.Now a
beforeShellExecutionhook matchinggit commit, with the script speaking the hook JSON protocol on stdin/stdout. Tested against five cases: clean repo, staged token, token in a.md, placeholder value, and outside a git repo.It fails open by design. A path-resolution problem in a plugin distributed to many users would otherwise block every
git committhey make; failing open degrades to today's behaviour (no protection) rather than something worse.3. Guidance described APIs that don't exist
rules/framework-presets.mdcinvented seven preset names. The realapp_typeoverride accepts onlycreate-react-app,vite,angular,react,vue,parcel,express,fastify,nest— everything else is auto-detected frompackage.json. Replaced byrules/nodejs-deployments.mdcwith the real overrides (node_version18/20/22/24,package_manager,root_directory,output_directory,build_script,entry_file) and the 50 MB archive limit.DNS_updateDNSRecordsV1takes a whole zone array plus anoverwriteflag, and there is no tool to create a snapshot on demand — so the old "snapshot before changing" step was impossible. The skill now explainsoverwritesemantics (the difference between silently duplicating and silently deleting records), usesDNS_validateDNSRecordsV1as a dry run, and cites an existing snapshot ID for rollback.query-hosting-logspromised 4xx/5xx breakdowns and PHP fatals; the API exposes neither. Renamedquery-deployment-logs, scoped to JS deployment logs, Node.js build logs, and cron output. The plugin now states plainly what's hPanel-only.Alignment with the extension
mcp.jsonstarted a singlehostinger-api-mcp, loading all 289 tools into context at once — the exact problem the extension's split solves. It now registers eight per-product servers mirroring the extension's groups, using the same server keys, so users can disable areas from Cursor's MCP settings.Two more fixes there:
${HOSTINGER_API_TOKEN}interpolation. OAuth shipped in extension 1.1.0 on 2026-05-29 — two days after this repo's last commit — and the README still claimed it was "not supported by the Hostinger backend". The MCP server signs in via browser automatically on the first authenticated tool call when the variable is absent, so hardcoding it risked shadowing that fallback with a literal unexpanded string. An exported token still takes precedence.USER_AGENT(plugin;cursor;<version>), matching the extension's attribution. Plugin traffic was previously invisible to Hostinger.Preventing recurrence
scripts/check-tool-names.mjsvalidates every tool-shaped identifier in the docs againstscripts/mcp-tools.json, a checked-in catalog so the check runs offline.The design choice worth reviewing: it default-denies unknown snake_case identifiers rather than validating known prefixes. A prefix check would have missed this entire bug, because the fabricated names had no prefix at all. Non-tool identifiers (
app_type,node_modules,public_html, …) live in an explicit allowlist. Verified by reintroducinglist_hosting_plans,create_dns_snapshot, andquery_logs— all three are caught.It also asserts each
mcp.jsonbinary maps to a real tool group, and thatUSER_AGENTtracks the version inplugin.json..github/workflows/ci.ymlruns both validators, parses every JSON file, shellchecks the hook, and checks it's executable. A second advisory job (continue-on-error) flags when the catalog snapshot falls behindhostinger-api-mcp@latestwithout failing unrelated PRs.Also
repository.urlinplugin.jsonpointed athostinger/api-mcp-server.~/.cursor/mcp.jsontoo.LICENSEfile thatplugin.jsonhas always declared MIT.Verification
All green locally:
Open question for reviewers
hostinger-api-mcpalso publisheshostinger-mail-mcp(38 tools) andhostinger-agency-hosting-mcp(27), which neither this plugin nor the extension wires up.hostinger-horizons-mcpwas added to the extension in hostinger/hostinger-vscode#32 and removed again in hostinger/hostinger-vscode#37. I left all three out to keep this PR at parity rather than ahead of the extension — worth deciding separately whether they should be exposed in both.