@elitedcs/ghl-mcp 3.62.0 → 3.63.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/CHANGELOG.md +38 -0
- package/dist/index.js +32 -17
- package/guide/guide.html +908 -26
- package/package.json +1 -1
- package/templates/action-schemas.json +72 -47
- package/templates/trigger-schemas.json +59 -23
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.63.0 — the guide library grows from 3 guides to 20
|
|
4
|
+
|
|
5
|
+
- **`get_user_guide` now opens a 20-guide library.** Seventeen guides were
|
|
6
|
+
written and proven live but had never shipped, so anyone running
|
|
7
|
+
`get user guide` was still getting the three-guide edition. The bundled
|
|
8
|
+
offline guide goes from 43KB to 111KB: 20 open guides, 10 still marked
|
|
9
|
+
"Available in the app" until their prompts are proven. Every prompt marked
|
|
10
|
+
"Proven live" was run against a real GoHighLevel account before it shipped.
|
|
11
|
+
- Same library renders to ghlcommand.com/skills, so the in-product guide and
|
|
12
|
+
the website always match.
|
|
13
|
+
- **Fix: reading appointments returned nothing.** `get_calendar_events` sent
|
|
14
|
+
ISO timestamps, but GHL's `/calendars/events` needs epoch milliseconds and
|
|
15
|
+
answers a wrong-format request with `200` and an empty array instead of an
|
|
16
|
+
error — so a calendar holding real confirmed bookings read back as "nothing
|
|
17
|
+
booked". Now converts via the timezone-aware helper free-slots already used,
|
|
18
|
+
plus an optional `timezone` parameter so a bare `YYYY-MM-DD` window resolves
|
|
19
|
+
in the sub-account's timezone (end date inclusive). Live-proven both
|
|
20
|
+
directions.
|
|
21
|
+
|
|
22
|
+
## 3.62.1 — update_pipeline works again (Bug 8)
|
|
23
|
+
|
|
24
|
+
- **Fix: `update_pipeline` no longer 422s.** GHL's pipeline PUT rejects unknown
|
|
25
|
+
body properties, and the request body was seeded with `locationId` — so every
|
|
26
|
+
update died with "property locationId should not exist" before the stages were
|
|
27
|
+
read. locationId now rides as a query parameter (the same pattern
|
|
28
|
+
`delete_pipeline` already used). Live-proven on the sandbox with the case that
|
|
29
|
+
matters: existing stage IDs survive the update (rename + reorder + append in
|
|
30
|
+
one call), so open opportunities are never orphaned. New regression proof:
|
|
31
|
+
`scripts/pipeline-update-proof.mjs`.
|
|
32
|
+
- Trigger reference: `custom_date_reminder` real UI-generated shape captured
|
|
33
|
+
(conditions + custom_date_reminder_config; before-days variant — after-days
|
|
34
|
+
still unverified).
|
|
35
|
+
- Action reference: the workflow Email action has NO "to" field — it always
|
|
36
|
+
mails the enrolled contact; third parties are copied via `cc` (merge fields
|
|
37
|
+
supported). Documented so nobody builds a "send to a third party" node that
|
|
38
|
+
silently mails the contact.
|
|
39
|
+
|
|
40
|
+
|
|
3
41
|
## 3.62.0 — The user guide ships inside the product
|
|
4
42
|
|
|
5
43
|
- **New tool `get_user_guide`** (free tier included): opens the full GHL Command
|
package/dist/index.js
CHANGED
|
@@ -2854,7 +2854,7 @@ var require_package = __commonJS({
|
|
|
2854
2854
|
"package.json"(exports2, module2) {
|
|
2855
2855
|
module2.exports = {
|
|
2856
2856
|
name: "@elitedcs/ghl-mcp",
|
|
2857
|
-
version: "3.
|
|
2857
|
+
version: "3.63.0",
|
|
2858
2858
|
mcpName: "io.github.drjerryrelth/ghl-command",
|
|
2859
2859
|
description: "GoHighLevel MCP Server for Claude. 235 tools \u2014 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.",
|
|
2860
2860
|
main: "dist/index.js",
|
|
@@ -7643,7 +7643,7 @@ function toEpochMillis(value, opts = {}) {
|
|
|
7643
7643
|
const trimmed = value.trim();
|
|
7644
7644
|
if (/^\d+$/.test(trimmed)) {
|
|
7645
7645
|
if (trimmed.length === 13) return trimmed;
|
|
7646
|
-
throw new Error(`Ambiguous numeric date "${value}"
|
|
7646
|
+
throw new Error(`Ambiguous numeric date "${value}" \u2014 pass epoch MILLISECONDS (13 digits), a YYYY-MM-DD date, or a full ISO datetime.`);
|
|
7647
7647
|
}
|
|
7648
7648
|
const dateOnly = /^(\d{4})-(\d{2})-(\d{2})$/.exec(trimmed);
|
|
7649
7649
|
if (dateOnly) {
|
|
@@ -7658,7 +7658,7 @@ function toEpochMillis(value, opts = {}) {
|
|
|
7658
7658
|
}
|
|
7659
7659
|
const parsed = Date.parse(trimmed);
|
|
7660
7660
|
if (!Number.isNaN(parsed)) return String(parsed);
|
|
7661
|
-
throw new Error(`Invalid date "${value}"
|
|
7661
|
+
throw new Error(`Invalid date "${value}" \u2014 use YYYY-MM-DD, a full ISO datetime, or epoch milliseconds.`);
|
|
7662
7662
|
}
|
|
7663
7663
|
function buildFreeSlotsParams(args) {
|
|
7664
7664
|
const params = {
|
|
@@ -7669,6 +7669,16 @@ function buildFreeSlotsParams(args) {
|
|
|
7669
7669
|
if (args.userId !== void 0) params.userId = args.userId;
|
|
7670
7670
|
return params;
|
|
7671
7671
|
}
|
|
7672
|
+
function buildCalendarEventsParams(args) {
|
|
7673
|
+
const params = {
|
|
7674
|
+
locationId: args.locationId,
|
|
7675
|
+
startTime: toEpochMillis(args.startTime, { timeZone: args.timezone }),
|
|
7676
|
+
endTime: toEpochMillis(args.endTime, { endOfDay: true, timeZone: args.timezone })
|
|
7677
|
+
};
|
|
7678
|
+
if (args.calendarId !== void 0) params.calendarId = args.calendarId;
|
|
7679
|
+
if (args.userId !== void 0) params.userId = args.userId;
|
|
7680
|
+
return params;
|
|
7681
|
+
}
|
|
7672
7682
|
function registerCalendarTools(server2, client) {
|
|
7673
7683
|
safeTool(
|
|
7674
7684
|
server2,
|
|
@@ -7789,20 +7799,25 @@ function registerCalendarTools(server2, client) {
|
|
|
7789
7799
|
"List calendar events for a location within a time range",
|
|
7790
7800
|
{
|
|
7791
7801
|
locationId: import_zod12.z.string().optional().describe("Location ID (falls back to GHL_LOCATION_ID env var)"),
|
|
7792
|
-
startTime: import_zod12.z.string().describe(
|
|
7793
|
-
|
|
7802
|
+
startTime: import_zod12.z.string().describe(
|
|
7803
|
+
"Start of the window. Accepts a date (YYYY-MM-DD), a full ISO datetime, or epoch milliseconds. A bare date is taken as start-of-day in `timezone` (UTC if unset). GHL needs epoch ms here; the tool converts for you."
|
|
7804
|
+
),
|
|
7805
|
+
endTime: import_zod12.z.string().describe(
|
|
7806
|
+
"End of the window. Accepts a date (YYYY-MM-DD), a full ISO datetime, or epoch milliseconds. A bare date is taken as END of that day, inclusive, in `timezone`."
|
|
7807
|
+
),
|
|
7808
|
+
timezone: import_zod12.z.string().optional().describe("IANA timezone (e.g. America/Phoenix) used to resolve bare YYYY-MM-DD dates. Defaults to UTC."),
|
|
7794
7809
|
calendarId: import_zod12.z.string().optional().describe("Filter by calendar ID"),
|
|
7795
7810
|
userId: import_zod12.z.string().optional().describe("Filter by user ID")
|
|
7796
7811
|
},
|
|
7797
|
-
async ({ locationId: locationId2, startTime, endTime, calendarId, userId }) => {
|
|
7798
|
-
const
|
|
7799
|
-
|
|
7800
|
-
locationId: resolvedLocationId,
|
|
7812
|
+
async ({ locationId: locationId2, startTime, endTime, timezone, calendarId, userId }) => {
|
|
7813
|
+
const params = buildCalendarEventsParams({
|
|
7814
|
+
locationId: client.resolveLocationId(locationId2),
|
|
7801
7815
|
startTime,
|
|
7802
|
-
endTime
|
|
7803
|
-
|
|
7804
|
-
|
|
7805
|
-
|
|
7816
|
+
endTime,
|
|
7817
|
+
timezone,
|
|
7818
|
+
calendarId,
|
|
7819
|
+
userId
|
|
7820
|
+
});
|
|
7806
7821
|
return await client.get("/calendars/events", { params });
|
|
7807
7822
|
}
|
|
7808
7823
|
);
|
|
@@ -12486,7 +12501,7 @@ ${text2}`);
|
|
|
12486
12501
|
},
|
|
12487
12502
|
async ({ pipelineId }) => {
|
|
12488
12503
|
try {
|
|
12489
|
-
const result = await pipelineRequest("GET", `/${pipelineId}?locationId=${client.locationId}`);
|
|
12504
|
+
const result = await pipelineRequest("GET", `/${encodeURIComponent(pipelineId)}?locationId=${client.locationId}`);
|
|
12490
12505
|
return {
|
|
12491
12506
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
12492
12507
|
};
|
|
@@ -12556,12 +12571,12 @@ ${text2}`);
|
|
|
12556
12571
|
},
|
|
12557
12572
|
async ({ pipelineId, name, stages, showInFunnel, showInPieChart }) => {
|
|
12558
12573
|
try {
|
|
12559
|
-
const body = {
|
|
12574
|
+
const body = {};
|
|
12560
12575
|
if (name !== void 0) body.name = name;
|
|
12561
12576
|
if (stages !== void 0) body.stages = stages;
|
|
12562
12577
|
if (showInFunnel !== void 0) body.showInFunnel = showInFunnel;
|
|
12563
12578
|
if (showInPieChart !== void 0) body.showInPieChart = showInPieChart;
|
|
12564
|
-
const result = await pipelineRequest("PUT", `/${pipelineId}`, body);
|
|
12579
|
+
const result = await pipelineRequest("PUT", `/${encodeURIComponent(pipelineId)}?locationId=${client.locationId}`, body);
|
|
12565
12580
|
return {
|
|
12566
12581
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
12567
12582
|
};
|
|
@@ -12580,7 +12595,7 @@ ${text2}`);
|
|
|
12580
12595
|
},
|
|
12581
12596
|
async ({ pipelineId }) => {
|
|
12582
12597
|
try {
|
|
12583
|
-
const result = await pipelineRequest("DELETE", `/${pipelineId}?locationId=${client.locationId}`);
|
|
12598
|
+
const result = await pipelineRequest("DELETE", `/${encodeURIComponent(pipelineId)}?locationId=${client.locationId}`);
|
|
12584
12599
|
return {
|
|
12585
12600
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
12586
12601
|
};
|