@awesomate/hosting-mcp 0.43.0 → 0.44.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 CHANGED
@@ -41187,7 +41187,8 @@ var TITLES = {
41187
41187
  awesomate_crm_rows: "Look up people in the contact list",
41188
41188
  awesomate_crm_types: "Generate TypeScript types for contact data",
41189
41189
  awesomate_crm_kinds: "Define app data kinds",
41190
- awesomate_crm_write: "Write app data records"
41190
+ awesomate_crm_write: "Write app data records",
41191
+ awesomate_crm_email: "Draft an email to a contact list"
41191
41192
  };
41192
41193
  function annotate(name, kind) {
41193
41194
  const title = TITLES[name];
@@ -42845,6 +42846,38 @@ server.registerTool(
42845
42846
  }
42846
42847
  }
42847
42848
  );
42849
+ server.registerTool(
42850
+ "awesomate_crm_email",
42851
+ {
42852
+ annotations: annotate("awesomate_crm_email", MUTATING),
42853
+ description: "Write an email DRAFT to one of the client's contact lists, for the owner to review and approve in the hub. Claude never sends: a draft reaches nobody until a person opens reviewUrl, sends themselves a test and approves the exact version they saw. Always give the user reviewUrl. action 'lists': the lists an email can go to, with how many people each would reach right now and why others are left out (counts only). action 'draft' {topic, doc}: a new draft to list `topic` (a key from 'lists'). action 'update' {id, topic, doc}: replace a draft (refused once someone approved it; they change it in the hub). action 'get' {id}: its status, the checks, the audience, what happened after sending. action 'list': recent emails. doc is a block document, never HTML: {kind: 'marketing'|'transactional' (marketing if ANY part promotes), voice: 'brand'|'personal' (whose name is on the From line), subject (max 150), preheader (the inbox preview line, max 200), reason (marketing: one line finishing \"You're getting this because...\"), blocks: [...]}. Blocks: {type:'eyebrow', text, tone?:'info'|'action'} \xB7 {type:'heading', text, level?:1|2} \xB7 {type:'paragraph', text} \xB7 {type:'list', items:[...], ordered?} \xB7 {type:'panel', tone?:'info'|'neutral'|'success'|'warm'|'alert', label?, text} \xB7 {type:'button', label (max 40), url} \xB7 {type:'image', src, alt, href?, width?} \xB7 {type:'divider'} \xB7 {type:'signoff', lines:[...]}. Inside text: **bold**, [label](https://url), and {{first_name|there}}, {{last_name}}, {{email}} (the part after | is the fallback when the field is empty). The footer, unsubscribe link, business details and dark mode are added by the hub: do not write them. The response's checks.blockers must be empty before the owner can approve; fix them and update. Warnings are for the owner to weigh. Write in plain Australian English, short paragraphs, one clear button.",
42854
+ inputSchema: {
42855
+ action: external_exports.enum(["lists", "draft", "update", "get", "list"]),
42856
+ id: external_exports.string().max(64).optional().describe("update/get: the email id from a draft or list"),
42857
+ topic: external_exports.string().max(63).optional().describe("draft/update: the list's key, from action 'lists'"),
42858
+ doc: external_exports.record(external_exports.unknown()).optional().describe("draft/update: the email document (see the description)")
42859
+ }
42860
+ },
42861
+ async ({ action, id, topic, doc }) => {
42862
+ try {
42863
+ const cfg = requireConfig();
42864
+ if (action === "lists") return textResult(await hubGet(cfg, "/api/my-crm/v1/emails/lists"));
42865
+ if (action === "list") return textResult(await hubGet(cfg, "/api/my-crm/v1/emails"));
42866
+ if (action === "get") {
42867
+ if (!id) return errorResult(new Error("get needs the email's id."));
42868
+ return textResult(await hubGet(cfg, `/api/my-crm/v1/emails/${encodeURIComponent(id)}`));
42869
+ }
42870
+ if (!topic || !doc) return errorResult(new Error(`${action} needs topic (a list key from action 'lists') and doc.`));
42871
+ if (action === "update") {
42872
+ if (!id) return errorResult(new Error("update needs the id of the draft to replace."));
42873
+ return textResult(await hubPatch(cfg, `/api/my-crm/v1/emails/${encodeURIComponent(id)}`, { topic, doc }));
42874
+ }
42875
+ return textResult(await hubPost(cfg, "/api/my-crm/v1/emails", { topic, doc }));
42876
+ } catch (err) {
42877
+ return errorResult(err);
42878
+ }
42879
+ }
42880
+ );
42848
42881
  server.registerTool(
42849
42882
  "awesomate_n8n_kpis",
42850
42883
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awesomate/hosting-mcp",
3
- "version": "0.43.0",
3
+ "version": "0.44.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",
@@ -1,5 +1,13 @@
1
1
  {
2
2
  "versions": [
3
+ {
4
+ "version": "0.44.0",
5
+ "highlights": [
6
+ "Claude can now write an email to one of your contact lists (awesomate_crm_email). It shows you which lists you have and how many people each would reach",
7
+ "It only ever writes a draft. You open the link it gives you, see the email on desktop, phone and dark mode, send yourself a test, and approve it in the hub. Nothing is sent until you do",
8
+ "Once you approve an email, Claude can't change it. Any edit after that is yours, in the hub"
9
+ ]
10
+ },
3
11
  {
4
12
  "version": "0.43.0",
5
13
  "highlights": [