@awesomate/hosting-mcp 0.56.0 → 0.58.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 +42 -5
- package/package.json +1 -1
- package/skill/CHANGELOG.json +14 -0
- package/skill/awesomate-portals/SKILL.md +9 -0
package/dist/index.js
CHANGED
|
@@ -41219,6 +41219,7 @@ var TITLES = {
|
|
|
41219
41219
|
awesomate_crm_apps: "Set up sign-in for your own apps",
|
|
41220
41220
|
awesomate_crm_app_users: "Manage the people who sign in to your apps",
|
|
41221
41221
|
awesomate_crm_assistant: "Set up the AI in your app's conversations",
|
|
41222
|
+
awesomate_crm_notifications: "Email people when someone replies in your app",
|
|
41222
41223
|
awesomate_crm_hooks: "Send record changes to your n8n",
|
|
41223
41224
|
awesomate_crm_email: "Draft an email to a contact list"
|
|
41224
41225
|
};
|
|
@@ -42415,7 +42416,7 @@ server.registerTool(
|
|
|
42415
42416
|
removeCollectionIds: external_exports.array(external_exports.string().max(64)).max(16).optional().describe("move: remove from these collections"),
|
|
42416
42417
|
sourceIds: external_exports.array(external_exports.string().max(300)).max(200).optional().describe("set_visibility/move: several sources at once"),
|
|
42417
42418
|
confirm: external_exports.string().max(64).optional().describe("set_visibility to 'public' only: the account slug, after the user agreed in so many words"),
|
|
42418
|
-
url: external_exports.string().url().optional().describe("add: one public page
|
|
42419
|
+
url: external_exports.string().url().optional().describe("add: one public page or blog post. A YouTube or other video link is not transcribed: on Pro it is read as a page (title and description), below Pro it is refused. To transcribe a recording, upload the file"),
|
|
42419
42420
|
sitemap: external_exports.string().url().optional().describe("add: sitemap.xml URL \u2014 ingests every listed page"),
|
|
42420
42421
|
since: external_exports.string().optional().describe("add+sitemap only: skip entries with lastmod older than this ISO date"),
|
|
42421
42422
|
sourceId: external_exports.string().optional().describe("remove only"),
|
|
@@ -43042,6 +43043,37 @@ server.registerTool(
|
|
|
43042
43043
|
}
|
|
43043
43044
|
}
|
|
43044
43045
|
);
|
|
43046
|
+
server.registerTool(
|
|
43047
|
+
"awesomate_crm_notifications",
|
|
43048
|
+
{
|
|
43049
|
+
annotations: annotate("awesomate_crm_notifications", MUTATING),
|
|
43050
|
+
description: "Reply emails for an app's conversations (a portal's messages on a job): when someone writes, the people on the other side who are not in the app at that moment get one email, at most once an hour per conversation. A customer writing emails the team (app people in staff_roles); the team, the assistant, the account or an n8n workflow writing emails that conversation's customer. Never the author, never someone switched off. Sent from the app's name, with the message quoted and a link to the app's first https address. They are system emails, like a ticket reply or a receipt, so they carry no unsubscribe link: the owner switches them on or off per app. Off until switched on; switching on starts from now, so nothing said earlier is emailed. Email only for now. Pro and above to change; reading is every plan. action 'get' {app_id}: the setting, how many have been sent, and the last error. action 'set' {app_id, notifications}: notifications is {enabled, thread_link (the message kind's link to the conversation, e.g. 'job'), message_kind? ('message'), body_attribute? ('body'), title_attribute? ('title', on the conversation record, used in the subject), customer_link? ('customer', the conversation record's link to the customer contact), staff_roles? (['owner', 'staff'])}. Turning it on is refused with every problem listed while the kinds don't fit. Confirm with the owner before switching it on: it emails their customers.",
|
|
43051
|
+
inputSchema: {
|
|
43052
|
+
action: external_exports.enum(["get", "set"]),
|
|
43053
|
+
app_id: external_exports.string().max(48).describe("the app, from awesomate_crm_apps list"),
|
|
43054
|
+
notifications: external_exports.object({
|
|
43055
|
+
enabled: external_exports.boolean(),
|
|
43056
|
+
thread_link: external_exports.string().max(41),
|
|
43057
|
+
message_kind: external_exports.string().max(41).optional(),
|
|
43058
|
+
body_attribute: external_exports.string().max(41).optional(),
|
|
43059
|
+
title_attribute: external_exports.string().max(41).optional(),
|
|
43060
|
+
customer_link: external_exports.string().max(41).optional(),
|
|
43061
|
+
staff_roles: external_exports.array(external_exports.string().max(31)).max(10).optional()
|
|
43062
|
+
}).optional().describe("set: the whole setting; fields left out take their defaults")
|
|
43063
|
+
}
|
|
43064
|
+
},
|
|
43065
|
+
async ({ action, app_id, notifications }) => {
|
|
43066
|
+
try {
|
|
43067
|
+
const cfg = requireConfig();
|
|
43068
|
+
const path = `/api/my-crm/v1/apps/${encodeURIComponent(app_id)}/notifications`;
|
|
43069
|
+
if (action === "get") return textResult(await hubGet(cfg, path));
|
|
43070
|
+
if (!notifications) return errorResult(new Error("set needs notifications: {enabled, thread_link, ...}."));
|
|
43071
|
+
return textResult(await hubPut(cfg, path, { notifications }));
|
|
43072
|
+
} catch (err) {
|
|
43073
|
+
return errorResult(err);
|
|
43074
|
+
}
|
|
43075
|
+
}
|
|
43076
|
+
);
|
|
43045
43077
|
var crmParam = external_exports.object({
|
|
43046
43078
|
name: external_exports.string().max(41).describe("lower_case"),
|
|
43047
43079
|
type: external_exports.enum(["text", "number", "date", "datetime", "boolean", "uuid", "text_list", "number_list"]).optional().describe("default text"),
|
|
@@ -43091,21 +43123,26 @@ server.registerTool(
|
|
|
43091
43123
|
"awesomate_crm_recipes",
|
|
43092
43124
|
{
|
|
43093
43125
|
annotations: annotate("awesomate_crm_recipes", MUTATING),
|
|
43094
|
-
description: `Write recipes: an app's own named writes over its kinds, a few steps that always happen together (log a job and its first memo; close a job and archive its booking). Run one with awesomate_crm_write action 'call'. action 'list': the recipes with their params. action 'save' {key, label, description?, params?, steps}: Support Plus and above; saving a key again replaces it. steps (1 to 10) are {op: 'write_record', kind, data?, links?, id?, as?} or {op: 'archive_record', kind, id}, run in order inside one transaction. {"$param": "<name>"} takes a caller's value; {"$step": "<as>"} takes the id an earlier step wrote, so a memo can link to the job made one step before. An id (an update or an archive) must come from a required uuid param or an earlier step, never a literal. Every kind, attribute, link and reference is checked when it is saved and again when it runs. Contacts are not written by recipes. A recipe is data the hub interprets, never code: there is no SQL and no condition logic. Confirm the steps with the user before saving.`,
|
|
43126
|
+
description: `Write recipes: an app's own named writes over its kinds, a few steps that always happen together (log a job and its first memo; close a job and archive its booking). Run one with awesomate_crm_write action 'call'. action 'list': the recipes with their params. action 'save' {key, label, description?, params?, steps}: Support Plus and above; saving a key again replaces it. steps (1 to 10) are {op: 'write_record', kind, data?, links?, id?, as?} or {op: 'archive_record', kind, id}, run in order inside one transaction. {"$param": "<name>"} takes a caller's value; {"$step": "<as>"} takes the id an earlier step wrote, so a memo can link to the job made one step before. An id (an update or an archive) must come from a required uuid param or an earlier step, never a literal. Every kind, attribute, link and reference is checked when it is saved and again when it runs. Contacts are not written by recipes. A recipe is data the hub interprets, never code: there is no SQL and no condition logic. Confirm the steps with the user before saving. action 'run_by' {key, roles}: Pro and above. Lets the people who sign in to the account's apps, in those roles, run this recipe themselves with @awesomate/sdk app.call(key, args): something their write rule would not let them do by hand, such as accept their own quote ({op: 'write_record', kind: 'job', id: {$param: 'job'}, data: {status: 'accepted'}}). The database lets them do exactly the recipe's steps: only $param and $step positions take their values, every other value is fixed, and an existing record must be one they can already read. roles [] closes it again; archiving a recipe closes it too. Editing a recipe that customers can run changes what they can do: say so and confirm with the user before saving it.`,
|
|
43095
43127
|
inputSchema: {
|
|
43096
|
-
action: external_exports.enum(["list", "save", "archive"]),
|
|
43097
|
-
key: external_exports.string().max(61).optional().describe("save/archive: lower_case name, not write_record or archive_record"),
|
|
43128
|
+
action: external_exports.enum(["list", "save", "archive", "run_by"]),
|
|
43129
|
+
key: external_exports.string().max(61).optional().describe("save/archive/run_by: lower_case name, not write_record or archive_record"),
|
|
43130
|
+
roles: external_exports.array(external_exports.string().max(31)).max(10).optional().describe("run_by: the app roles (from awesomate_crm_app_users) that may run it; [] for the account only"),
|
|
43098
43131
|
label: external_exports.string().max(120).optional(),
|
|
43099
43132
|
description: external_exports.string().max(1e3).optional(),
|
|
43100
43133
|
params: external_exports.array(crmParam).max(20).optional(),
|
|
43101
43134
|
steps: external_exports.array(external_exports.record(external_exports.unknown())).min(1).max(10).optional()
|
|
43102
43135
|
}
|
|
43103
43136
|
},
|
|
43104
|
-
async ({ action, key, label, description, params, steps }) => {
|
|
43137
|
+
async ({ action, key, label, description, params, steps, roles }) => {
|
|
43105
43138
|
try {
|
|
43106
43139
|
const cfg = requireConfig();
|
|
43107
43140
|
if (action === "list") return textResult(await hubGet(cfg, "/api/my-crm/v1/recipes"));
|
|
43108
43141
|
if (!key) return errorResult(new Error(`${action} needs the key.`));
|
|
43142
|
+
if (action === "run_by") {
|
|
43143
|
+
if (!roles) return errorResult(new Error("run_by needs roles: a list of app roles, or [] to close it."));
|
|
43144
|
+
return textResult(await hubPut(cfg, `/api/my-crm/v1/recipes/${encodeURIComponent(key)}/run-by`, { roles }));
|
|
43145
|
+
}
|
|
43109
43146
|
if (action === "save") return textResult(await hubPost(cfg, "/api/my-crm/v1/recipes", { key, label, description, params: params ?? [], steps: steps ?? [] }));
|
|
43110
43147
|
return textResult(await hubDelete(cfg, `/api/my-crm/v1/recipes/${encodeURIComponent(key)}`));
|
|
43111
43148
|
} catch (err) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@awesomate/hosting-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.58.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",
|
package/skill/CHANGELOG.json
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"versions": [
|
|
3
|
+
{
|
|
4
|
+
"version": "0.58.0",
|
|
5
|
+
"highlights": [
|
|
6
|
+
"Customers can do one exact thing their access would not let them do by hand, such as accept their own quote: Claude saves it as a recipe and, on your say-so, opens it to a role (awesomate_crm_recipes action 'run_by'). Pro and above",
|
|
7
|
+
"Your app runs it with @awesomate/sdk app.call(). The database lets them change only what the recipe says, and only on records they can already see; archiving the recipe closes it again"
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"version": "0.57.0",
|
|
12
|
+
"highlights": [
|
|
13
|
+
"Reply emails for your portal's conversations (awesomate_crm_notifications): when your team or Bree replies, the customer gets an email if they aren't in the portal, and when a customer writes, your team does. At most one an hour per conversation",
|
|
14
|
+
"Off until you switch them on, per app. They're system emails, like a ticket reply or a receipt, sent from your app's name with the message quoted and a link back"
|
|
15
|
+
]
|
|
16
|
+
},
|
|
3
17
|
{
|
|
4
18
|
"version": "0.56.0",
|
|
5
19
|
"highlights": [
|
|
@@ -135,6 +135,15 @@ lists the two staff-only kinds it needs (`assistant_thread`, `assistant_draft`)
|
|
|
135
135
|
agent (awesomate-knowledge skill) so she can answer questions about the business. Confirm the
|
|
136
136
|
name and the default mode with the owner: switching it on lets an AI reply to their customers.
|
|
137
137
|
|
|
138
|
+
## 6b. Optional: reply emails
|
|
139
|
+
|
|
140
|
+
`awesomate_crm_notifications {action:'set', app_id, notifications: {enabled: true, thread_link: 'job'}}`
|
|
141
|
+
emails the other side of a conversation when someone writes there and they are not in the app:
|
|
142
|
+
the customer when the team or the assistant replies, the team when a customer writes. At most one
|
|
143
|
+
an hour per conversation, from the app's name, with the message quoted and a link back. They are
|
|
144
|
+
system emails (no unsubscribe link); the owner switches them on or off per app. Ask the owner
|
|
145
|
+
first: it emails their customers.
|
|
146
|
+
|
|
138
147
|
## 7. Optional: automation
|
|
139
148
|
|
|
140
149
|
- **Server key** (`awesomate_crm_apps {action:'create_key'}`): for the app's own server or an n8n
|