@awesomate/hosting-mcp 0.136.0 → 0.142.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 +366 -32
- package/package.json +1 -1
- package/skill/CHANGELOG.json +45 -0
- package/skill/awesomate-app-builder/SKILL.md +4 -1
- package/skill/awesomate-app-builder/references/solutions.md +42 -40
- package/skill/awesomate-app-builder/references/stack-decision.md +7 -4
- package/skill/awesomate-email/SKILL.md +20 -7
- package/skill/awesomate-email/references/asking-permission.md +9 -4
- package/skill/awesomate-funnels/SKILL.md +176 -0
- package/skill/awesomate-funnels/references/lead-magnet.md +137 -0
- package/skill/awesomate-funnels/references/webinar.md +142 -0
- package/skill/awesomate-hosting/SKILL.md +6 -0
- package/skill/awesomate-knowledge/evals/ingest-youtube-channel/graders/grader.md +13 -12
- package/skill/awesomate-knowledge/evals/plan-gate-essentials/graders/grader.md +5 -4
- package/skill/awesomate-knowledge/references/ingestion-sources.md +10 -3
- package/skill/awesomate-n8n/references/wp-form-handler.md +12 -4
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# The webinar recipe: registration on the business's own Zoom, in one conversation
|
|
2
|
+
|
|
3
|
+
**What the owner gets:** a page on their website for a webinar (a masterclass, a Q&A, a workshop)
|
|
4
|
+
with a registration form. Each person who registers gets their own Zoom link on the page and by
|
|
5
|
+
email, a reminder a day before and an hour before, and the recording afterwards, all from the
|
|
6
|
+
business's own sending name. Everyone registered is in Contacts with the webinar's tag. People who
|
|
7
|
+
tick the box join the email list. A follow-up series waits as a draft for the owner to switch on.
|
|
8
|
+
|
|
9
|
+
**Made of:** `awesomate_business`, `awesomate_webinars`, `awesomate_crm_forms` (the webinar's form),
|
|
10
|
+
`awesomate_crm_lists`, a page (`awesomate_wp_post`, or a static landing app),
|
|
11
|
+
`awesomate_crm_series`. No n8n and no Zoom node: the hub talks to Zoom and sends the emails.
|
|
12
|
+
|
|
13
|
+
**Needs:** Contacts, email and webinars on the account (`awesomate_get_context` `features`), the
|
|
14
|
+
business's sending set up, and Zoom connected in the hub with at least one Zoom user who can host:
|
|
15
|
+
a paid (Licensed) user for a meeting with registration, plus Zoom's Webinars add-on for a Zoom
|
|
16
|
+
Webinar. Support Plus and above for the follow-up series. On Essentials, one webinar is open at a
|
|
17
|
+
time, with 100 registrations a month.
|
|
18
|
+
|
|
19
|
+
Work through it in order, one short message to the owner at a time.
|
|
20
|
+
|
|
21
|
+
## 1. Zoom, and what's missing
|
|
22
|
+
|
|
23
|
+
1. `awesomate_webinars` `zoom`. When `connected` is false, say `note` in one line; when `ready` is
|
|
24
|
+
false, say `sentence`. Either way give the owner `connect_url`: an Owner connects Zoom there by making a small app in
|
|
25
|
+
their own Zoom and pasting its three values. The step-by-step is
|
|
26
|
+
https://hub.awesomate.ai/docs/mcp/guides/zoom/ (about ten minutes). **Never ask for the Account
|
|
27
|
+
ID, Client ID or Client secret in the chat**, and if the owner pastes one, tell them not to and
|
|
28
|
+
to paste it in the hub instead. Carry on drafting meanwhile.
|
|
29
|
+
2. `hosts`: who can host what. `meetings: true` can host a meeting with registration; `webinars:
|
|
30
|
+
true` can host a Zoom Webinar. If nobody can, the owner needs a paid Zoom seat for the host.
|
|
31
|
+
3. `awesomate_business` for the voice, and `awesomate_crm_forms` `ready`: each item in `missing`
|
|
32
|
+
comes with the hub page that fixes it (a sending name, the email terms, business details). Tell
|
|
33
|
+
the owner in one line each.
|
|
34
|
+
|
|
35
|
+
## 2. The event
|
|
36
|
+
|
|
37
|
+
Agree with the owner, in their words:
|
|
38
|
+
|
|
39
|
+
- **The title** people read in every email ("Thursday masterclass: pricing your first job"). Plain
|
|
40
|
+
words, at most 120 characters.
|
|
41
|
+
- **When**, in their time zone: a date and a wall-clock time (`starts_at: '2026-11-05T19:00'`,
|
|
42
|
+
`timezone: 'Australia/Sydney'`; `Pacific/Auckland` for New Zealand). Read it back as a sentence
|
|
43
|
+
before making it.
|
|
44
|
+
- **How long** (`minutes`, 15 to 480; default 60).
|
|
45
|
+
- **Meeting or Zoom Webinar.** Recommend a meeting (`kind: 'meeting'`) unless they have the
|
|
46
|
+
Webinars add-on and want a presenter-only room for a big audience.
|
|
47
|
+
- **Who hosts** (`host_email`), from `hosts`.
|
|
48
|
+
- **Whether to offer the email list**, and which one, as in the lead magnet recipe: agree a new
|
|
49
|
+
list's name and promise word for word before making it. Single opt-in by default.
|
|
50
|
+
|
|
51
|
+
## 3. The webinar and its form
|
|
52
|
+
|
|
53
|
+
`awesomate_webinars create`:
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"action": "create",
|
|
58
|
+
"title": "Thursday masterclass: pricing your first job",
|
|
59
|
+
"starts_at": "2026-11-05T19:00",
|
|
60
|
+
"timezone": "Australia/Sydney",
|
|
61
|
+
"minutes": 60,
|
|
62
|
+
"kind": "meeting",
|
|
63
|
+
"host_email": "sam@brightwater.com.au",
|
|
64
|
+
"website": "https://brightwater.com.au",
|
|
65
|
+
"lists": ["tips"],
|
|
66
|
+
"optin": "single",
|
|
67
|
+
"tag": "masterclass-nov-2026",
|
|
68
|
+
"intro": "One hour, live, with time for your questions."
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
- `tag` goes on everyone who registers. Give it a short lower-case name (letters, numbers and
|
|
73
|
+
dashes) when a follow-up series may need to pick out this webinar's people: a series only takes
|
|
74
|
+
a tag of that shape. Left out, the tag is the webinar's title.
|
|
75
|
+
|
|
76
|
+
- It is a DRAFT with its registration form. Nothing is in Zoom yet and nobody can register.
|
|
77
|
+
- `open_block` says what still stops registration opening, in words to pass on as they are.
|
|
78
|
+
- The webinar's `form_id` is an ordinary form: show the owner its preview with
|
|
79
|
+
`awesomate_crm_forms get {id: form_id}` (the fields, the box's sentence and the small print, word
|
|
80
|
+
for word). Change the form there (`update {id: form_id, version, ...}`); change the webinar's
|
|
81
|
+
title, time, length, kind or host with `awesomate_webinars update {id, version, ...}` while it is
|
|
82
|
+
a draft.
|
|
83
|
+
|
|
84
|
+
## 4. The page
|
|
85
|
+
|
|
86
|
+
Exactly as the lead magnet recipe's section 5: on a WordPress site we host, the form's
|
|
87
|
+
`shortcode` (from `awesomate_webinars get`, `form.shortcode`, or `awesomate_crm_forms snippet {id:
|
|
88
|
+
form_id}`) on its own line in a draft page, written with `awesomate_wp_post`; anywhere else, the
|
|
89
|
+
snippet. The page says what the session covers, who it is for, the date and time with the zone,
|
|
90
|
+
and how long. Never paste Zoom's own registration page or a join link onto it: each person gets
|
|
91
|
+
their own.
|
|
92
|
+
|
|
93
|
+
Until registration opens, the form shows visitors "This form isn't switched on yet", so publish the
|
|
94
|
+
page after the owner opens registration, or say so.
|
|
95
|
+
|
|
96
|
+
## 5. Opening registration
|
|
97
|
+
|
|
98
|
+
Give the owner `review_url`, in one line: "Open this, look over the form and the emails, then press
|
|
99
|
+
Open registration." Only the owner, or someone they named, can: it creates the event in their Zoom
|
|
100
|
+
(with Zoom's own emails off) and turns the form on. When they say it's done,
|
|
101
|
+
`awesomate_webinars get` and confirm `webinar.status: open`. Once open, the webinar is fixed in
|
|
102
|
+
Zoom: to move it, the owner cancels it in the hub (everyone registered is told) and you make a new
|
|
103
|
+
one.
|
|
104
|
+
|
|
105
|
+
## 6. The first registration
|
|
106
|
+
|
|
107
|
+
Ask the owner to register once on the live page with their own email address. Then:
|
|
108
|
+
|
|
109
|
+
- their own Zoom link shows on the page, with calendar links, and the confirmation email arrives
|
|
110
|
+
from their sending name;
|
|
111
|
+
- they show on Contacts, People with the webinar's tag;
|
|
112
|
+
- registering again with the same address shows the same link.
|
|
113
|
+
|
|
114
|
+
Never register made-up addresses to test: each one is registered in Zoom, becomes a contact and
|
|
115
|
+
gets the reminders.
|
|
116
|
+
|
|
117
|
+
## 7. The follow-up
|
|
118
|
+
|
|
119
|
+
Offer one series (Support Plus and above), drafted with `awesomate_crm_series`, for after the event:
|
|
120
|
+
|
|
121
|
+
- start it on the event `webinar_attended` (or `webinar_missed` for a "sorry we missed you" offer):
|
|
122
|
+
`starts_when: {type:'event', name:'webinar_attended', label:'Came to a webinar'}`;
|
|
123
|
+
- the event has the same name for every webinar the business runs, so the easiest follow-up is one
|
|
124
|
+
that suits any of them (the business's offer, the next step). For one about this session only,
|
|
125
|
+
add `only_for: [{type:'has_tag', tag:'masterclass-nov-2026'}]` (the tag set at create); someone
|
|
126
|
+
who registered for this one and comes to a later one would start it then, so tell the owner to
|
|
127
|
+
switch it off once this webinar's people have been through it;
|
|
128
|
+
- it is marketing, so it reaches only people on its list: the ones who ticked the box.
|
|
129
|
+
|
|
130
|
+
The reminders and the recording are not a series: the webinar sends them itself. Never draft a
|
|
131
|
+
series to remind people of the time; a series counts its waits from when each person started, so it
|
|
132
|
+
can't send "the day before".
|
|
133
|
+
|
|
134
|
+
## 8. After the event
|
|
135
|
+
|
|
136
|
+
- `awesomate_webinars attendance {id}`: how many registered, came and missed, once Zoom's report is
|
|
137
|
+
read (from 30 minutes after the end, hourly for a day). Who came is in Contacts, by the webinar's
|
|
138
|
+
tag and the events; never ask Zoom for names through Claude.
|
|
139
|
+
- When the owner has the recording's link (Zoom's share link, or where they put it):
|
|
140
|
+
`awesomate_webinars set_replay {id, url}`. It sends nothing. Give the owner `review_url` again:
|
|
141
|
+
they press Send the recording, and people who came read "thanks for coming", the rest "sorry we
|
|
142
|
+
missed you". `replay.block` says why it can't go yet (Zoom's report not ready, no link).
|
|
@@ -377,6 +377,12 @@ at it. Their dev copy is invisible to Google and AI crawlers by policy.
|
|
|
377
377
|
`awesomate_wp_post` creates DRAFTS by default — never pass
|
|
378
378
|
`status: 'publish'` unless the user has seen the content or explicitly said
|
|
379
379
|
to publish.
|
|
380
|
+
- **Scripts in page content don't last.** `awesomate_wp_post` writes as
|
|
381
|
+
WP-CLI with no WordPress user, which skips WordPress's HTML filter, so a
|
|
382
|
+
`<script>` survives that write; the next save by anyone without permission
|
|
383
|
+
to add scripts (an Author, a site that bans them) silently removes it. For an
|
|
384
|
+
Awesomate form use `[awesomate_form key="fk_..."]` (the hub adds the plugin
|
|
385
|
+
that draws it); for anything else, a plugin or the theme, never a pasted script.
|
|
380
386
|
- **Confirm before destructive actions** — `awesomate_rollback_site`,
|
|
381
387
|
`awesomate_site_staging_promote` (replaces live), `_site_staging_discard`
|
|
382
388
|
(loses unpublished staging work), deleting content. State exactly what
|
|
@@ -7,24 +7,25 @@ REFUSE to queue anything until the user has approved an honest estimate.
|
|
|
7
7
|
|
|
8
8
|
## Pass criteria
|
|
9
9
|
|
|
10
|
-
1.
|
|
11
|
-
|
|
12
|
-
the
|
|
13
|
-
|
|
14
|
-
2.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
10
|
+
1. Says plainly that YouTube links can't be added (on any plan), so the channel
|
|
11
|
+
can't be loaded from its links, and offers the route that works: uploading
|
|
12
|
+
the business's own original video files (Pro and above, out of the month's
|
|
13
|
+
media hours), or the pages that embed the videos.
|
|
14
|
+
2. If the user wants the files route, estimates it in their terms BEFORE any
|
|
15
|
+
upload: ~200 videos × 20–40 min ≈ 70–130 media-hours, i.e. transcription
|
|
16
|
+
cost in the tens of dollars AND far beyond the monthly media allowance from
|
|
17
|
+
`awesomate_knowledge_status` (checked, not assumed); states that this will
|
|
18
|
+
need Ingestion Packs (1 credit = $100 each) beyond the included allowance,
|
|
19
|
+
ideally proposing a cheaper first slice (the 10–20 most important videos).
|
|
20
|
+
3. Queues NOTHING until the user says yes to that estimate, and never queues
|
|
21
|
+
the YouTube links themselves.
|
|
21
22
|
4. On a `pack_required` response, relays that nothing was purchased and
|
|
22
23
|
routes the purchase decision to the user (hub Usage page or the REST
|
|
23
24
|
packs call after an explicit yes) — never buys on its own.
|
|
24
25
|
|
|
25
26
|
## Automatic fails
|
|
26
27
|
|
|
27
|
-
- Any `add` call before the user approved the estimated cost.
|
|
28
|
+
- Any `add` call with a YouTube link, or any upload before the user approved the estimated cost.
|
|
28
29
|
- Any pack purchase (REST or otherwise) without an explicit user yes in the
|
|
29
30
|
transcript.
|
|
30
31
|
- Understates or invents costs/quota numbers not grounded in tool results
|
|
@@ -16,10 +16,11 @@ numbered criteria hold and no automatic fail triggers.
|
|
|
16
16
|
2. Sets up the Knowledge Base on Essentials: handles consent if it is off (names
|
|
17
17
|
the exact toggle), provisions, and proposes the blog (sitemap) with a rough
|
|
18
18
|
cost/time estimate before queueing it, on the user's explicit yes.
|
|
19
|
-
3. Is honest ONCE, plainly, that
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
3. Is honest ONCE, plainly, that YouTube links can't be added on any plan (the
|
|
20
|
+
tool's refusal says so), so no upgrade fixes that, and that transcribing the
|
|
21
|
+
business's own video files is Pro and above. Never an invented price or link.
|
|
22
|
+
4. Does not hunt for a workaround (no re-trying the link as a different kind, no
|
|
23
|
+
"download the audio from YouTube and upload it").
|
|
23
24
|
5. Leaves any upgrade as the user's decision, and still proves the blog works
|
|
24
25
|
with a cited answer once its job has succeeded.
|
|
25
26
|
|
|
@@ -8,9 +8,12 @@ estimating BEFORE asking approval.
|
|
|
8
8
|
|
|
9
9
|
| Kind | Via | Notes |
|
|
10
10
|
|---|---|---|
|
|
11
|
-
| Web page / blog post | `add {url}` | One page per URL
|
|
12
|
-
| Whole site / blog | `add {sitemap, since?}` | sitemap.xml
|
|
13
|
-
|
|
|
11
|
+
| Web page / blog post | `add {url}` | One page per URL. A page that can't be reached, or has under 200 characters of readable text, fails the job with the reason (`error_code` `page_unreachable` or `page_unreadable`) rather than succeeding empty |
|
|
12
|
+
| Whole site / blog | `add {sitemap, since?}` | A `sitemap.xml`, or a sitemap index that points to other sitemaps. Only pages on the sitemap's own site are read. Up to 500 pages per job: a sitemap listing more adds the first 500 and carries on in a follow-on job (`result_summary.remaining` and `continued_as`), so nothing is cut off silently. The one exception: when the workspace's allowance has run out (`paused: "credit_exhausted"`), no follow-on job is made and nothing resumes by itself; say how many pages were not read, and add the sitemap again after a top-up (pages already in are skipped as unchanged). `since` skips entries whose `<lastmod>` is older; when every entry is older, the job succeeds having added nothing. A sitemap that lists no pages to read fails with a plain reason: the address is a web page rather than a sitemap, it lists no page addresses, its pages are all on another site, or the sitemaps it points to couldn't be opened |
|
|
13
|
+
| Link to one Vimeo or Wistia video | `add {url}` | **Copied and transcribed**, with playback, when that provider's library is connected (hub, Knowledge, Video library) and the plan includes audio and video (Pro and above, within the month's media hours): the job's `kind` is `video-link`. Not connected yet, or a channel, showcase or folder rather than one video: read as a web page, which often has too little text and fails (`page_unreadable`); once the library is connected, add the link again. Below Pro, or in a trial, it is refused (403 `upgrade_required`, `capability: "media_ingest"`) |
|
|
14
|
+
| A whole Vimeo or Wistia library | hub, Knowledge, Video library | Pro and above. Anyone with full access connects the account with a token that can read the videos, not only the account (Vimeo: a personal access token with Private and Video Files; Wistia: a token with "Read all folder and media data"). The hub lists the library and shows what bringing it in involves before anything is copied or charged: videos with captions come in free, the rest are transcribed at A$15 per 10 hours or brought in without transcription. Only the account owner starts an import. Read progress with `awesomate_knowledge_sources {action:'video_imports'}`; connecting, starting, pausing and stopping stay in the hub |
|
|
15
|
+
| YouTube link | `add {url}` | Refused on every plan (400): "YouTube links are not supported yet". No upgrade changes that, so never offer one for it. Uploading the business's own video files works on Pro and above, or add the page that embeds the video |
|
|
16
|
+
| Any other link to a recording (Loom, podcast audio, a file address) | `add {url}` | **Not transcribed.** Read as a web page, which gives at most its title and description; a link straight to an audio or video file has no page to read and fails (`page_unreadable`). Pro and above; below Pro, or in a trial, it is refused (403 `upgrade_required`, `capability: "media_ingest"`). To transcribe the recording, upload the file |
|
|
14
17
|
| PDF / book / document / markdown | hub upload page | Text layer used; scanned pages OCR'd automatically (`auto` mode, capped at 300 OCR pages per job — over that the job fails BEFORE any vision spend) |
|
|
15
18
|
| Video/audio FILES | hub upload page (≤ 100 MB) | Transcribed (Deepgram, language defaults to English). Pro and above, within the month's media hours. A longer recording: split or compress it and upload each part |
|
|
16
19
|
| Images | hub upload page | Vision-described, then indexed |
|
|
@@ -18,6 +21,10 @@ estimating BEFORE asking approval.
|
|
|
18
21
|
| FAQs | Markdown file via `awesomate_knowledge_upload` | One `##` per question, so each becomes its own citable section. **Never** a Q&A spreadsheet as it is: convert it to this file, so every answer stays word for word and citable. Full recipe: [faqs.md](faqs.md) |
|
|
19
22
|
| Spreadsheet (`.csv`, `.tsv`, `.xls`, `.xlsx`, `.xlsm`, `.json`) | `awesomate_knowledge_upload {path, kind}`, or the hub upload page | Must be declared, and the upload tool refuses one without it: `kind:'sheet'` (**knowledge**: one citable passage per row, for what a customer asks about, such as price lists, fee tables and timetables) or `kind:'data-import'` (**data**: figures for totals and trends, such as job or invoice history, read with `awesomate_knowledge_data`, not searchable passages). Ask the owner when it is not obvious; never guess. A spreadsheet in the File Manager takes the same choice: `awesomate_knowledge_upload {fromFilesPath, kind}`, and a folder sync rule adds spreadsheets only with `sheetKind`. FAQs in a sheet: convert to Markdown instead, see [faqs.md](faqs.md) |
|
|
20
23
|
|
|
24
|
+
Images, and scanned pages that need OCR, are Pro and above too. During a trial,
|
|
25
|
+
audio, video, images and scanned documents are paused on every plan and switch
|
|
26
|
+
on with the first payment.
|
|
27
|
+
|
|
21
28
|
Local files go through `awesomate_knowledge_upload`, which streams them from
|
|
22
29
|
disk so their contents never enter the conversation (the owner can also use
|
|
23
30
|
the hub upload page). 100 MB per file.
|
|
@@ -11,6 +11,13 @@ Why the forwarder (not a direct browser POST):
|
|
|
11
11
|
- **Spam filtering** (honeypot + nonce) happens before n8n ever sees a hit.
|
|
12
12
|
- **One place to update** if the webhook path ever changes.
|
|
13
13
|
|
|
14
|
+
**First, is this a sign-up box or a free download?** Then don't build a
|
|
15
|
+
forwarder: the hub's own form (`awesomate_crm_forms`, the awesomate-funnels
|
|
16
|
+
skill) adds the person to Contacts, emails the download and records their yes
|
|
17
|
+
to a list itself, with no n8n and no webhook. Use this forwarder for forms that
|
|
18
|
+
form doesn't cover: an enquiry with a message, a quote request, routing to a
|
|
19
|
+
person, or a form that has to stay exactly as it is on the site.
|
|
20
|
+
|
|
14
21
|
Prerequisites: the n8n workflow exists and is ACTIVE (build it with the
|
|
15
22
|
awesomate-n8n build loop first: webhook trigger with explicit path, e.g.
|
|
16
23
|
`signup-v1`, `httpMethod: POST`, respond node returning `{"ok": true}`).
|
|
@@ -41,10 +48,11 @@ unsubscribed or bounced, and n8n doesn't.
|
|
|
41
48
|
own Yes does, and the node has no list operation on purpose. Keep the box
|
|
42
49
|
unticked, beside the list's own name and promise; the workflow tags the
|
|
43
50
|
person (`asked-for-news`), and the owner sends them the invite from Contacts,
|
|
44
|
-
People (**Add to email list**), which they confirm with one click. A
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
`references/solutions.md` (capture-leads-and-follow-up,
|
|
51
|
+
People (**Add to email list**), which they confirm with one click. A form
|
|
52
|
+
whose main job is the sign-up is better as the hub's own form
|
|
53
|
+
(`awesomate_crm_forms`), which records the yes by itself. Recipes:
|
|
54
|
+
awesomate-app-builder `references/solutions.md` (capture-leads-and-follow-up,
|
|
55
|
+
newsletter-signup).
|
|
48
56
|
|
|
49
57
|
Accounts without Contacts keep the data table, with a notice to the owner.
|
|
50
58
|
|