@elitedcs/ghl-mcp 3.72.1 → 3.72.3
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/CHANGELOG.md +51 -0
- package/dist/index.js +11140 -8686
- package/guide/guide.html +1 -1
- package/package.json +3 -1
- package/templates/action-schemas.json +3 -3
- package/templates/clinic-medspa.json +1 -1
- package/templates/external-funnel/README.md +5 -2
- package/templates/external-funnel/wrangler.toml.example +40 -0
package/guide/guide.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
6
|
<title>GHL Command — User Guide</title>
|
|
7
|
-
<!-- guides-hash:
|
|
7
|
+
<!-- guides-hash: a47eca1c8dbf1dd3 -->
|
|
8
8
|
<style>
|
|
9
9
|
/* Deliberately light in every environment, including a dark-mode OS. This is a
|
|
10
10
|
reference document people read at length, print, and save to PDF, and a page
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elitedcs/ghl-mcp",
|
|
3
|
-
"version": "3.72.
|
|
3
|
+
"version": "3.72.3",
|
|
4
4
|
"mcpName": "io.github.drjerryrelth/ghl-command",
|
|
5
5
|
"description": "GoHighLevel MCP Server for Claude. 247 tools — full CRM, automation, marketing control, account-wide workflow audit, live funnel-capture verification, and the only programmatic GHL workflow builder, now multi-tenant across client accounts.",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"templates/trigger-schemas.json",
|
|
16
16
|
"templates/external-funnel/cloudflare-worker.js",
|
|
17
17
|
"templates/external-funnel/README.md",
|
|
18
|
+
"templates/external-funnel/wrangler.toml.example",
|
|
18
19
|
"README.md",
|
|
19
20
|
"CHANGELOG.md",
|
|
20
21
|
"guide",
|
|
@@ -25,6 +26,7 @@
|
|
|
25
26
|
"scripts": {
|
|
26
27
|
"build": "esbuild src/index.ts --bundle --platform=node --target=node20 --format=cjs --outfile=dist/index.js --packages=external && esbuild src/capture-helper.ts --bundle --platform=node --target=node20 --format=cjs --outfile=dist/capture-helper.js --packages=external",
|
|
27
28
|
"setup": "node setup-wizard.mjs",
|
|
29
|
+
"catalogue": "node scripts/export-command-os-catalogue.mjs",
|
|
28
30
|
"start": "node dist/index.js",
|
|
29
31
|
"dev": "tsc --watch",
|
|
30
32
|
"test": "vitest run",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"example_3days": {
|
|
83
83
|
"type": "time",
|
|
84
84
|
"startAfter": {
|
|
85
|
-
"type": "
|
|
85
|
+
"type": "days",
|
|
86
86
|
"value": 3,
|
|
87
87
|
"when": "after"
|
|
88
88
|
},
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"convertToMultipath": false,
|
|
93
93
|
"transitions": []
|
|
94
94
|
},
|
|
95
|
-
"notes": "startAfter.type: 'minutes', 'hour', or 'day'. ALL 5 fields required (type, startAfter, isHybridAction, hybridActionType, transitions). Derived from working GHL UI-built workflows."
|
|
95
|
+
"notes": "startAfter.type: 'minutes', 'hour', or 'days' — NOT consistently singular, and 'day' is rejected with 400 INVALID_FIELD_VALUE on a workflow that has a real action before the wait (live-verified 2026-08-29). ALL 5 fields required (type, startAfter, isHybridAction, hybridActionType, transitions). Derived from working GHL UI-built workflows."
|
|
96
96
|
},
|
|
97
97
|
"internal_notification": {
|
|
98
98
|
"example": {
|
|
@@ -165,7 +165,7 @@
|
|
|
165
165
|
"traffic_index": [{ "id": "USER_ID", "indexes": [1] }],
|
|
166
166
|
"total_index": 1
|
|
167
167
|
},
|
|
168
|
-
"notes": "[
|
|
168
|
+
"notes": "[PROVEN LIVE 2026-08-27 on the MCP Testing sandbox: a scratch workflow carrying both a single-user and a two-user round-robin assign_user node saved, read back with every attribute intact (user_list, only_unassigned_contact, traffic_split, traffic_weightage, traffic_index, total_index) and both real user ids present, and PUBLISHED — GHL's own builder validator accepted it, which is the check that requires a non-empty user_list and verifies each id against the location's users. Scratch workflow deleted; the account was left byte-identical.] 'Assign to user' — the listed users become the contact owner. Linear actions-category node like add_contact_tag. user_list is REQUIRED and non-empty (GHL's builder validator: 'user_list_required'; every id is checked against the location's users — a dead id silently never assigns). Multiple users = round-robin; the equal-split bookkeeping the builder saves is weightage {id:1 each}, traffic_index [{id, indexes:[1..weight]}] with globally sequential indexes, total_index = sum of weights — single user: weightage {id:1}, index [{id, indexes:[1]}], total 1. only_unassigned_contact false always (re)assigns; true skips contacts that already have an owner. traffic_split 'unevenly' + custom weights and customUserList (custom-value mode) exist in the builder but are NOT built by us. LIVE TEST TO CLOSE: build one workflow with this node on a sandbox (MCP Testing), publish, run a test contact through, read back with get_workflow_full + get_contact — confirm the node persists byte-for-byte and the contact's assignedTo/owner becomes USER_ID; then remove this UNVERIFIED label."
|
|
169
169
|
},
|
|
170
170
|
"remove_from_workflow": {
|
|
171
171
|
"example": {
|
|
@@ -243,7 +243,7 @@
|
|
|
243
243
|
"actions": [
|
|
244
244
|
{ "name": "Add Reactivation Tag", "type": "add_contact_tag", "attributes": { "tags": ["reactivation-candidate"] } },
|
|
245
245
|
{ "name": "Send Reactivation SMS", "type": "sms", "attributes": { "body": "Hi {{contact.first_name}}, it's been a while since your last visit to {{business_name}}. We miss you! Book your next session and get 10% off.", "attachments": [] } },
|
|
246
|
-
{ "name": "Wait 3 Days", "type": "wait", "attributes": { "type": "time", "startAfter": { "type": "
|
|
246
|
+
{ "name": "Wait 3 Days", "type": "wait", "attributes": { "type": "time", "startAfter": { "type": "days", "value": 3, "when": "after" }, "name": "Wait", "isHybridAction": true, "hybridActionType": "wait", "convertToMultipath": false, "transitions": [] } },
|
|
247
247
|
{ "name": "Send Reactivation Email", "type": "email", "attributes": { "subject": "We miss you, {{contact.first_name}}!", "html": "<p style=\"margin:0px;\">Hi {{contact.first_name}},</p><p style=\"margin:0px;\"><br></p><p style=\"margin:0px;\">It's been over 90 days since your last visit to {{business_name}}, and we wanted to check in.</p><p style=\"margin:0px;\"><br></p><p style=\"margin:0px;\">As a valued patient, we'd like to offer you 10% off your next treatment. Just mention this email when you book.</p><p style=\"margin:0px;\"><br></p><p style=\"margin:0px;\">See you soon!</p><p style=\"margin:0px;\">{{owner_name}}</p>", "trackingOptions": { "hasTrackingLinks": false, "hasUtmTracking": false, "hasTags": false } } }
|
|
248
248
|
]
|
|
249
249
|
}
|
|
@@ -36,8 +36,11 @@ The executor returns what you plug into the Worker config + form:
|
|
|
36
36
|
## Deploy (Cloudflare)
|
|
37
37
|
1. `npm i -g wrangler && wrangler login`
|
|
38
38
|
2. `wrangler secret put GHL_PIT` ← paste your token (secret; never in code/repo)
|
|
39
|
-
3.
|
|
40
|
-
`ALLOWED_ORIGIN` (your funnel
|
|
39
|
+
3. `cp wrangler.toml.example wrangler.toml`, then fill in the four values it
|
|
40
|
+
asks for: `GHL_LOCATION_ID`, `TRIGGER_TAG`, `ALLOWED_ORIGIN` (your funnel
|
|
41
|
+
domain — locks CORS), and optional `RE_ENROLL`. The example file ships beside
|
|
42
|
+
this README with each value explained and the right/wrong forms of
|
|
43
|
+
`ALLOWED_ORIGIN` spelled out.
|
|
41
44
|
4. (Optional) Turnstile: add the widget to your form, `wrangler secret put
|
|
42
45
|
TURNSTILE_SECRET`.
|
|
43
46
|
5. `wrangler deploy` → point your form at the Worker URL.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# External-Funnel Lead Bridge — Worker config.
|
|
2
|
+
#
|
|
3
|
+
# Copy this file to `wrangler.toml` (same directory as cloudflare-worker.js),
|
|
4
|
+
# fill in the four values below, then `wrangler deploy`.
|
|
5
|
+
#
|
|
6
|
+
# cp wrangler.toml.example wrangler.toml
|
|
7
|
+
#
|
|
8
|
+
# The GHL token is NOT in here on purpose. It is a secret:
|
|
9
|
+
# wrangler secret put GHL_PIT
|
|
10
|
+
# Never put a token in this file — wrangler.toml is committed by most people,
|
|
11
|
+
# and a Private Integration token can write to your whole sub-account.
|
|
12
|
+
|
|
13
|
+
name = "ghl-lead-bridge" # your Worker's name; becomes <name>.<subdomain>.workers.dev
|
|
14
|
+
main = "cloudflare-worker.js"
|
|
15
|
+
compatibility_date = "2026-01-01"
|
|
16
|
+
|
|
17
|
+
[vars]
|
|
18
|
+
# The GHL sub-account this bridge writes into. `apply_build_plan` returns it.
|
|
19
|
+
GHL_LOCATION_ID = "PUT_YOUR_LOCATION_ID_HERE"
|
|
20
|
+
|
|
21
|
+
# The tag that starts your speed-to-lead workflow. `apply_build_plan` returns it.
|
|
22
|
+
TRIGGER_TAG = "PUT_YOUR_TRIGGER_TAG_HERE"
|
|
23
|
+
|
|
24
|
+
# Your funnel's exact origin — scheme + host, no trailing slash, no path.
|
|
25
|
+
# This locks CORS. The Worker refuses to start without it and never falls back
|
|
26
|
+
# to "*", so a stranger's page cannot post leads into your account.
|
|
27
|
+
# right: "https://clinic.example.com"
|
|
28
|
+
# wrong: "https://clinic.example.com/" | "clinic.example.com" | "*"
|
|
29
|
+
ALLOWED_ORIGIN = "https://PUT_YOUR_FUNNEL_DOMAIN_HERE"
|
|
30
|
+
|
|
31
|
+
# Optional. "true" removes and re-adds the trigger tag so a returning lead
|
|
32
|
+
# re-enters the workflow. Leave "false" if a second submission should not
|
|
33
|
+
# restart the sequence.
|
|
34
|
+
RE_ENROLL = "false"
|
|
35
|
+
|
|
36
|
+
# ── Optional: Turnstile (bot protection on your form) ─────────────────
|
|
37
|
+
# The Worker checks Turnstile ONLY when TURNSTILE_SECRET is set, so this is
|
|
38
|
+
# entirely opt-in. Add the widget to your form, then:
|
|
39
|
+
# wrangler secret put TURNSTILE_SECRET
|
|
40
|
+
# Nothing to add here — it is a secret, not a var.
|