@awesomate/hosting-mcp 0.23.0 → 0.25.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/dist/index.js +52 -9
- package/package.json +1 -1
- package/skill/awesomate-support/SKILL.md +41 -16
package/dist/index.js
CHANGED
|
@@ -40885,6 +40885,7 @@ var TITLES = {
|
|
|
40885
40885
|
awesomate_skill_update: "Update Awesomate skills",
|
|
40886
40886
|
awesomate_site_create: "Create WordPress site",
|
|
40887
40887
|
awesomate_site_audit: "Audit site for SEO and AEO",
|
|
40888
|
+
awesomate_php_extensions: "Check or fix PHP extensions",
|
|
40888
40889
|
awesomate_uninstall_site: "Delete WordPress site",
|
|
40889
40890
|
awesomate_snapshot_site: "Snapshot site",
|
|
40890
40891
|
awesomate_list_snapshots: "List site snapshots",
|
|
@@ -41251,17 +41252,32 @@ server.registerTool(
|
|
|
41251
41252
|
"awesomate_support",
|
|
41252
41253
|
{
|
|
41253
41254
|
annotations: annotate("awesomate_support", MUTATING),
|
|
41254
|
-
description: "Help the user with the service itself \u2014 questions, being stuck, or reaching a human. action 'faq' {q} searches the published help library (answer FROM the results; never invent policy or pricing). action 'help_docs' {q} searches the full Help Centre articles live \u2014 use when the FAQ has no good answer, and cite the returned article URLs. action 'create_ticket' {subject, message} opens a support ticket \u2014 draft it in the user's words, SHOW it, and get an explicit yes before sending; it emails the Awesomate team and returns a portal URL. action 'list_tickets' shows their tickets and status. Use the awesomate-support skill for the full flow. Not for building \u2014 route n8n work to awesomate-n8n and hosting to awesomate-hosting.",
|
|
41255
|
+
description: "Help the user with the service itself \u2014 questions, being stuck, or reaching a human. **action 'ask' {q} is the FIRST thing to try for any question about Awesomate** \u2014 it answers from Awesomate's own Knowledge Base with numbered citations, works on every plan, and composes across articles rather than matching titles; relay its answer and cite the source URLs. If it returns no_answer:true the grounding gate declined, so offer a ticket instead of guessing; if degraded:true the Knowledge Base was unavailable and you are looking at keyword matches, so do not present them as a verified answer. action 'faq' {q} searches the published help library (answer FROM the results; never invent policy or pricing). action 'help_docs' {q} searches the full Help Centre articles live \u2014 use when the FAQ has no good answer, and cite the returned article URLs. action 'create_ticket' {subject, message, category} opens a support ticket \u2014 draft it in the user's words, SHOW it, and get an explicit yes before sending; it emails the Awesomate team and returns a portal URL. **`category` is REQUIRED and must name what the ticket is actually about \u2014 'Other' is refused.** Ticket access splits by SUBJECT, not by plan: reporting a problem with AWESOMATE ITSELF ('Infrastructure fault' \u2014 site down, instance unreachable, provisioning or SSL failure; 'Claude/MCP connectivity' \u2014 pairing fails, token rejected, tools erroring) and 'Account/billing' work on EVERY plan. Asking for help USING the products ('Workflow not running', 'Workflow error', 'New automation request', 'How-to question') needs Support Plus or above and returns 403 upgrade_required below it \u2014 when that happens, answer from 'faq'/'help_docs' instead and relay the upgrade honestly; do NOT relabel the ticket as a fault to get through. action 'list_tickets' shows their tickets and status. Use the awesomate-support skill for the full flow. Not for building \u2014 route n8n work to awesomate-n8n and hosting to awesomate-hosting.",
|
|
41255
41256
|
inputSchema: {
|
|
41256
|
-
action: external_exports.enum(["faq", "help_docs", "create_ticket", "list_tickets"]),
|
|
41257
|
-
q: external_exports.string().optional().describe("faq and help_docs: the question or topic"),
|
|
41257
|
+
action: external_exports.enum(["ask", "faq", "help_docs", "create_ticket", "list_tickets"]),
|
|
41258
|
+
q: external_exports.string().optional().describe("ask, faq and help_docs: the question or topic"),
|
|
41258
41259
|
subject: external_exports.string().optional().describe("create_ticket only"),
|
|
41259
|
-
message: external_exports.string().optional().describe("create_ticket only: the body, in the user's words")
|
|
41260
|
+
message: external_exports.string().optional().describe("create_ticket only: the body, in the user's words"),
|
|
41261
|
+
category: external_exports.enum([
|
|
41262
|
+
"Infrastructure fault",
|
|
41263
|
+
"Claude/MCP connectivity",
|
|
41264
|
+
"Workflow not running",
|
|
41265
|
+
"Workflow error",
|
|
41266
|
+
"New automation request",
|
|
41267
|
+
"Account/billing",
|
|
41268
|
+
"How-to question"
|
|
41269
|
+
]).optional().describe(
|
|
41270
|
+
"create_ticket: REQUIRED. What the ticket is about. The first two and Account/billing work on every plan; the rest need Support Plus or above."
|
|
41271
|
+
)
|
|
41260
41272
|
}
|
|
41261
41273
|
},
|
|
41262
|
-
async ({ action, q, subject, message }) => {
|
|
41274
|
+
async ({ action, q, subject, message, category }) => {
|
|
41263
41275
|
try {
|
|
41264
41276
|
const cfg = requireConfig();
|
|
41277
|
+
if (action === "ask") {
|
|
41278
|
+
if (!q) return errorResult(new Error("ask needs q"));
|
|
41279
|
+
return textResult(await hubGet(cfg, `/api/help/ask?q=${encodeURIComponent(q)}`));
|
|
41280
|
+
}
|
|
41265
41281
|
if (action === "faq") {
|
|
41266
41282
|
return textResult(await hubGet(cfg, `/api/help/faq${q ? `?q=${encodeURIComponent(q)}` : ""}`));
|
|
41267
41283
|
}
|
|
@@ -41273,7 +41289,14 @@ server.registerTool(
|
|
|
41273
41289
|
return textResult(await hubGet(cfg, "/api/support/tickets"));
|
|
41274
41290
|
}
|
|
41275
41291
|
if (!subject || !message) return errorResult(new Error("create_ticket needs subject and message"));
|
|
41276
|
-
|
|
41292
|
+
if (!category) {
|
|
41293
|
+
return errorResult(
|
|
41294
|
+
new Error(
|
|
41295
|
+
'create_ticket needs a category naming what the ticket is about. Use "Infrastructure fault" or "Claude/MCP connectivity" when the problem is with Awesomate itself, "Account/billing" for money, and the workflow/how-to categories (Support Plus and above) for help using the products.'
|
|
41296
|
+
)
|
|
41297
|
+
);
|
|
41298
|
+
}
|
|
41299
|
+
return textResult(await hubPost(cfg, "/api/support/tickets", { subject, body_text: message, category }));
|
|
41277
41300
|
} catch (err) {
|
|
41278
41301
|
return errorResult(err);
|
|
41279
41302
|
}
|
|
@@ -41303,7 +41326,7 @@ server.registerTool(
|
|
|
41303
41326
|
"awesomate_site_create",
|
|
41304
41327
|
{
|
|
41305
41328
|
annotations: annotate("awesomate_site_create", MUTATING),
|
|
41306
|
-
description: "Create a WordPress site on the user's hosting. Plan limits are enforced
|
|
41329
|
+
description: "Create a WordPress site on the user's hosting. **Needs Support Plus or above from Claude** \u2014 on Essentials this returns 403 `upgrade_required` ALWAYS, not only at a cap, because building hosting from a machine token is a Support Plus capability; the Essentials site itself is real and is created by the user in the hub at hub.awesomate.ai/sites, so offer that path first rather than leading with the upgrade. Plan COUNT limits are enforced separately (403 with an upgrade hint at the cap; 409 means WordPress already exists at that domain). Ask 'live or dev?' first per the awesomate-hosting skill. Omit `domain` and the next free siteN.{primary} subdomain is chosen for you. ASYNC and returns only {success:true} \u2014 no domain, no admin details: poll awesomate_list_sites to learn the name, and expect HTTPS to refuse connections for a minute or two while AutoSSL issues even though the site is already serving over http. See 'After creating a site' in the skill.",
|
|
41307
41330
|
inputSchema: {
|
|
41308
41331
|
domain: external_exports.string().optional().describe("Custom domain if they have one; omit for a default *.awesomate.site subdomain"),
|
|
41309
41332
|
siteTitle: external_exports.string().optional(),
|
|
@@ -41322,7 +41345,7 @@ server.registerTool(
|
|
|
41322
41345
|
"awesomate_domain_add",
|
|
41323
41346
|
{
|
|
41324
41347
|
annotations: annotate("awesomate_domain_add", MUTATING),
|
|
41325
|
-
description: "Add a custom domain to the user's hosting account. Returns the DNS steps they need to complete at their registrar.
|
|
41348
|
+
description: "Add a custom domain to the user's hosting account. Returns the DNS steps they need to complete at their registrar. **Needs Support Plus or above from Claude** \u2014 Essentials gets 403 `upgrade_required` even though its plan DOES include one custom domain, because adding it from a machine token is Support Plus; tell them it takes two clicks at hub.awesomate.ai/sites/domains instead. Plan COUNT limits are enforced separately on top.",
|
|
41326
41349
|
inputSchema: { domain: external_exports.string().describe("The domain to add, e.g. example.com") }
|
|
41327
41350
|
},
|
|
41328
41351
|
async ({ domain }) => {
|
|
@@ -41337,7 +41360,7 @@ server.registerTool(
|
|
|
41337
41360
|
"awesomate_run_wp_cli",
|
|
41338
41361
|
{
|
|
41339
41362
|
annotations: annotate("awesomate_run_wp_cli", DESTRUCTIVE),
|
|
41340
|
-
description: "Run an allowlisted WP-CLI command on one of the user's WordPress sites (plugin/theme list+activate+update, cache flush, option get/update, post/media/menu/comment/user list). ARGUMENTS CANNOT CONTAIN SPACES (letters, digits and -_./=:@+, only) \u2014 so a site title, tagline or any multi-word value is impossible here: use awesomate_wp_settings for those, and awesomate_wp_post for post/page content. Installs accept wp.org SLUGS only \u2014 never URLs. args is the command as an array, e.g. ['plugin','list'] or ['plugin','install','wordpress-seo','--activate']. A 400 wp_cli_not_allowed means that command isn't permitted; a 502 wp_cli_unavailable is a temporary server-side issue, not your command.",
|
|
41363
|
+
description: "Run an allowlisted WP-CLI command on one of the user's WordPress sites (plugin/theme list+activate+update, cache flush, option get/update, post/media/menu/comment/user list). **Needs Support Plus or above** \u2014 the whole route is behind the write gate, so even the READS (option get, plugin list) return 403 `upgrade_required` on Essentials. ARGUMENTS CANNOT CONTAIN SPACES (letters, digits and -_./=:@+, only) \u2014 so a site title, tagline or any multi-word value is impossible here: use awesomate_wp_settings for those, and awesomate_wp_post for post/page content. Installs accept wp.org SLUGS only \u2014 never URLs. args is the command as an array, e.g. ['plugin','list'] or ['plugin','install','wordpress-seo','--activate']. A 400 wp_cli_not_allowed means that command isn't permitted; a 502 wp_cli_unavailable is a temporary server-side issue, not your command.",
|
|
41341
41364
|
inputSchema: {
|
|
41342
41365
|
domain: external_exports.string().describe("The site domain"),
|
|
41343
41366
|
args: external_exports.array(external_exports.string()).describe("WP-CLI args, e.g. ['plugin','list']")
|
|
@@ -41394,6 +41417,26 @@ readTool(
|
|
|
41394
41417
|
"cPanel account details: package, server, provisioned-at, masked username.",
|
|
41395
41418
|
"/api/client-hosting/account"
|
|
41396
41419
|
);
|
|
41420
|
+
server.registerTool(
|
|
41421
|
+
"awesomate_php_extensions",
|
|
41422
|
+
{
|
|
41423
|
+
description: "Check (and optionally fix) the PHP extensions enabled for the hosting account's PHP runtime. Use this when WordPress fails on a SPECIFIC operation while the rest of the site works: `wp media import` or image uploads dying with \"critical error\" (missing dom), sudden white screens on text handling (missing mbstring), importers or sitemap generation failing (missing xmlreader/xmlwriter), or a plugin that installs fine but cannot connect (missing soap). The CloudLinux alt-php82 default set is much leaner than 7.4's, so accounts on PHP 8.2 often come up without these even though the modules are installed on the server. The account holder CANNOT fix this from a shell \u2014 CageFS blocks selectorctl for jailed accounts \u2014 so do it here rather than talking them through cPanel. Pass fix:true to enable the missing ones. Enabling is additive (nothing already on is removed), needs no PHP restart and causes no downtime.",
|
|
41424
|
+
inputSchema: {
|
|
41425
|
+
fix: external_exports.boolean().optional().describe("Enable the missing extensions. Omit or false to only report what is missing.")
|
|
41426
|
+
},
|
|
41427
|
+
annotations: annotate("awesomate_php_extensions", MUTATING)
|
|
41428
|
+
},
|
|
41429
|
+
async ({ fix }) => {
|
|
41430
|
+
try {
|
|
41431
|
+
const config3 = requireConfig();
|
|
41432
|
+
return textResult(
|
|
41433
|
+
fix ? await hubPost(config3, "/api/client-hosting/php-extensions", {}) : await hubGet(config3, "/api/client-hosting/php-extensions")
|
|
41434
|
+
);
|
|
41435
|
+
} catch (err) {
|
|
41436
|
+
return errorResult(err);
|
|
41437
|
+
}
|
|
41438
|
+
}
|
|
41439
|
+
);
|
|
41397
41440
|
readTool(
|
|
41398
41441
|
"awesomate_list_sites",
|
|
41399
41442
|
"All WordPress sites on the hosting account: canonical domain, URL, title, WP version, SSL state, install date.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@awesomate/hosting-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "Awesomate MCP server — lets Claude manage your Awesomate WordPress hosting, plan, limits, n8n automations, and build Node/static apps + databases",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -28,36 +28,61 @@ what's actually spendable once credits promised to builds in flight are
|
|
|
28
28
|
set aside — rather than the raw balance.) Never quote a plan, price, or
|
|
29
29
|
balance from memory.
|
|
30
30
|
|
|
31
|
-
## 1.
|
|
31
|
+
## 1. Ask the Knowledge Base first
|
|
32
32
|
|
|
33
33
|
For any "how do I", "why does", "what is" question about the service:
|
|
34
34
|
|
|
35
|
-
1. Call `awesomate_support {action:'
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
35
|
+
1. Call `awesomate_support {action:'ask', q:'<their question>'}`. This is
|
|
36
|
+
Awesomate's own Knowledge Base answering from Awesomate's own content,
|
|
37
|
+
with numbered citations. It works on every plan.
|
|
38
|
+
2. Read the response's `source` and `degraded` fields before you answer —
|
|
39
|
+
they are the difference between three very different situations:
|
|
40
|
+
|
|
41
|
+
- `source:'knowledge_base'`, `no_answer:false` → a grounded answer.
|
|
42
|
+
Relay it in your own plain words and give the citation URLs.
|
|
43
|
+
- `source:'knowledge_base'`, `no_answer:true` → the grounding gate
|
|
44
|
+
declined, because the answer is not in our content. **Do not fill the
|
|
45
|
+
gap yourself.** Offer a ticket (§2).
|
|
46
|
+
- `degraded:true` → the Knowledge Base was unavailable or is not
|
|
47
|
+
switched on, and you are looking at keyword matches from `faq` and
|
|
48
|
+
`docs` instead. Useful, but **never present them as a verified
|
|
49
|
+
answer**, and say the search was limited if it matters.
|
|
50
|
+
|
|
51
|
+
3. Only if `ask` came back thin do you need `faq` or `help_docs` directly.
|
|
52
|
+
Both remain available and behave as before, and `help_centre_url` in
|
|
53
|
+
any response is always safe to offer for browsing.
|
|
54
|
+
4. Cite nothing the tools didn't say. No invented policy, no guessed
|
|
55
|
+
pricing, no remembered plan limits.
|
|
47
56
|
|
|
48
57
|
## 2. Ticket flow — talking to a human
|
|
49
58
|
|
|
50
59
|
When the user wants a human, or §1 came up empty:
|
|
51
60
|
|
|
61
|
+
**First, what is this ticket about?** Access splits by SUBJECT, not by
|
|
62
|
+
plan, and you must pass a `category` naming it. `Other` is refused.
|
|
63
|
+
|
|
64
|
+
| The problem is | category | Who can raise it |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| Our platform is broken: site down, n8n unreachable, provisioning or SSL failed, the hub is erroring | `Infrastructure fault` | **every plan** |
|
|
67
|
+
| They cannot connect or use Claude: pairing fails, the token is rejected, tools error | `Claude/MCP connectivity` | **every plan** |
|
|
68
|
+
| Money: invoices, plans, credits, refunds | `Account/billing` | **every plan** |
|
|
69
|
+
| Help USING n8n, their website, or the Knowledge Base | `Workflow not running`, `Workflow error`, `New automation request`, `How-to question` | **Support Plus and above** |
|
|
70
|
+
|
|
71
|
+
Choose the category that is actually true. If a product-help ticket comes
|
|
72
|
+
back `403 upgrade_required`, answer from §1 instead and relay the upgrade
|
|
73
|
+
honestly — **never relabel a workflow question as an outage to get it
|
|
74
|
+
through.** That is lying to your own support team about the state of the
|
|
75
|
+
platform, and it puts a false fault report in front of an engineer.
|
|
76
|
+
|
|
52
77
|
1. Draft the ticket in the USER'S words — their description of the problem,
|
|
53
78
|
what they were trying to do, what happened. Add context you observed
|
|
54
79
|
(which site/app, what you already tried) in one short paragraph. No
|
|
55
80
|
stack traces, no jargon dumps.
|
|
56
81
|
2. Show the full draft (subject + message) and ask plainly: "Send this to
|
|
57
82
|
the Awesomate team?" NEVER call `create_ticket` without an explicit yes.
|
|
58
|
-
3. On yes: `awesomate_support {action:'create_ticket', subject, message
|
|
59
|
-
Confirm: "Sent. The team replies by email, usually within a
|
|
60
|
-
day."
|
|
83
|
+
3. On yes: `awesomate_support {action:'create_ticket', subject, message,
|
|
84
|
+
category}`. Confirm: "Sent. The team replies by email, usually within a
|
|
85
|
+
business day."
|
|
61
86
|
4. Later, "any update on my ticket?" →
|
|
62
87
|
`awesomate_support {action:'list_tickets'}` and report each ticket's
|
|
63
88
|
status in one line.
|