@elitedcs/ghl-mcp 3.34.8 → 3.34.9
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 +41 -0
- package/dist/index.js +69 -35
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.34.9 — Calendar availability: create_calendar / update_calendar now set `openHours`
|
|
4
|
+
|
|
5
|
+
Closes the on-camera "assign availability hours" gap. `create_calendar` and
|
|
6
|
+
`update_calendar` previously exposed no availability parameter, so every calendar
|
|
7
|
+
was created with `openHours: {}` and a caller could not set business hours through
|
|
8
|
+
the MCP — the calendar only offered GHL's default window.
|
|
9
|
+
|
|
10
|
+
- **New `openHours` (and `availabilityType`) params on `create_calendar` and
|
|
11
|
+
`update_calendar`.** `openHours` is an array of `{daysOfTheWeek:[0-6], hours:
|
|
12
|
+
[{openHour,openMinute,closeHour,closeMinute}]}` (0=Sun … 6=Sat, 24-hour clock).
|
|
13
|
+
When `openHours` is supplied the builder also sends `availabilityType: 0`
|
|
14
|
+
(standard weekly hours) — the exact payload GHL honors — unless the caller
|
|
15
|
+
overrides it.
|
|
16
|
+
- **Multi-day blocks are auto-expanded to one block per day.** GHL's CREATE
|
|
17
|
+
endpoint 422s (`openHours.0.must be a valid day of week`) on a block listing more
|
|
18
|
+
than one weekday. Single-day-per-block is GHL's own canonical form (what it reads
|
|
19
|
+
back) and is accepted by both create and update. The builder accepts the natural
|
|
20
|
+
compact form (`daysOfTheWeek:[1,2,3,4,5]`) and expands it to per-day blocks. Logic
|
|
21
|
+
extracted to `buildCreateCalendarBody` / `buildUpdateCalendarBody` /
|
|
22
|
+
`expandOpenHours`, with tests.
|
|
23
|
+
|
|
24
|
+
**Corrects the 3.34.8 note.** The earlier guess — that round-robin availability
|
|
25
|
+
comes only from the user's working hours and not a calendar `openHours` field — was
|
|
26
|
+
wrong. Pinned live on a real sub-account, the full model is:
|
|
27
|
+
|
|
28
|
+
- `openHours` **does** drive availability. Setting it changes `/free-slots`
|
|
29
|
+
immediately (a Wed-only 13:00–15:00 window collapsed slots to Wednesdays
|
|
30
|
+
13:00–14:30; a Mon–Fri 9–6 window produced exactly 09:00–17:30 each weekday).
|
|
31
|
+
- On **event / simple** calendars `openHours` is the sole source — every configured
|
|
32
|
+
day/time becomes bookable (a Sat 10–1 window booked Saturdays).
|
|
33
|
+
- On **round_robin** "OptimizeForAvailability" calendars the bookable slots are the
|
|
34
|
+
**intersection** of `openHours` and each assigned user's working hours, so a day
|
|
35
|
+
only opens if a team member is also available then (the same Sat 10–1 window
|
|
36
|
+
produced zero slots when the lone user had no Saturday availability). To open a day
|
|
37
|
+
on round_robin, set the user's availability too (UI-gated), or use an event-type
|
|
38
|
+
calendar where `openHours` alone controls. The tool descriptions state this.
|
|
39
|
+
|
|
40
|
+
Write-verified live: created calendars with hours through the builders, read the
|
|
41
|
+
hours back, and confirmed `/free-slots` returned exactly the configured days/times;
|
|
42
|
+
all throwaways deleted. Suite 289 pass / 1 skip.
|
|
43
|
+
|
|
3
44
|
## 3.34.8 — create_opportunity + get_funnel_pages no longer 422 on omitted required params
|
|
4
45
|
|
|
5
46
|
Two real defects found during a full end-to-end build test on a live sub-account
|
package/dist/index.js
CHANGED
|
@@ -31,7 +31,7 @@ var require_package = __commonJS({
|
|
|
31
31
|
"package.json"(exports2, module2) {
|
|
32
32
|
module2.exports = {
|
|
33
33
|
name: "@elitedcs/ghl-mcp",
|
|
34
|
-
version: "3.34.
|
|
34
|
+
version: "3.34.9",
|
|
35
35
|
mcpName: "io.github.drjerryrelth/ghl-command",
|
|
36
36
|
description: "GoHighLevel MCP Server for Claude. 218 tools \u2014 full CRM, automation, marketing control, account-wide workflow audit, and the only programmatic GHL workflow builder, now multi-tenant across client accounts.",
|
|
37
37
|
main: "dist/index.js",
|
|
@@ -2727,6 +2727,58 @@ var CalendarTeamMemberSchema = import_zod9.z.object({
|
|
|
2727
2727
|
selected: import_zod9.z.boolean().describe("Whether this user is currently active on the calendar (true to enable)."),
|
|
2728
2728
|
locationConfigurations: import_zod9.z.array(TeamMemberLocationConfigSchema).min(1).describe("At least one meeting-location config. Typical shape: [{kind:'custom', position:0, location:''}].")
|
|
2729
2729
|
}).strict();
|
|
2730
|
+
var OpenHoursWindowSchema = import_zod9.z.object({
|
|
2731
|
+
openHour: import_zod9.z.number().int().min(0).max(23).describe("Opening hour on a 24-hour clock (0-23)."),
|
|
2732
|
+
openMinute: import_zod9.z.number().int().min(0).max(59).describe("Opening minute (0-59)."),
|
|
2733
|
+
closeHour: import_zod9.z.number().int().min(0).max(23).describe("Closing hour on a 24-hour clock (0-23)."),
|
|
2734
|
+
closeMinute: import_zod9.z.number().int().min(0).max(59).describe("Closing minute (0-59).")
|
|
2735
|
+
}).strict();
|
|
2736
|
+
var OpenHoursBlockSchema = import_zod9.z.object({
|
|
2737
|
+
daysOfTheWeek: import_zod9.z.array(import_zod9.z.number().int().min(0).max(6)).min(1).describe("Weekdays this block applies to. 0=Sunday, 1=Monday, \u2026 6=Saturday."),
|
|
2738
|
+
hours: import_zod9.z.array(OpenHoursWindowSchema).min(1).describe("One or more open time windows that apply to these days.")
|
|
2739
|
+
}).strict();
|
|
2740
|
+
function expandOpenHours(blocks) {
|
|
2741
|
+
const out = [];
|
|
2742
|
+
for (const block of blocks) {
|
|
2743
|
+
for (const day of block.daysOfTheWeek) {
|
|
2744
|
+
out.push({ daysOfTheWeek: [day], hours: block.hours });
|
|
2745
|
+
}
|
|
2746
|
+
}
|
|
2747
|
+
return out;
|
|
2748
|
+
}
|
|
2749
|
+
function applyCalendarFields(body, args) {
|
|
2750
|
+
if (args.description !== void 0) body.description = args.description;
|
|
2751
|
+
if (args.slug !== void 0) body.slug = args.slug;
|
|
2752
|
+
if (args.widgetSlug !== void 0) body.widgetSlug = args.widgetSlug;
|
|
2753
|
+
if (args.calendarType !== void 0) body.calendarType = args.calendarType;
|
|
2754
|
+
if (args.teamMembers !== void 0) body.teamMembers = args.teamMembers;
|
|
2755
|
+
if (args.eventTitle !== void 0) body.eventTitle = args.eventTitle;
|
|
2756
|
+
if (args.eventColor !== void 0) body.eventColor = args.eventColor;
|
|
2757
|
+
if (args.slotDuration !== void 0) body.slotDuration = args.slotDuration;
|
|
2758
|
+
if (args.slotBuffer !== void 0) body.slotBuffer = args.slotBuffer;
|
|
2759
|
+
if (args.slotInterval !== void 0) body.slotInterval = args.slotInterval;
|
|
2760
|
+
if (args.appointmentPerSlot !== void 0) body.appointmentPerSlot = args.appointmentPerSlot;
|
|
2761
|
+
if (args.openHours !== void 0) {
|
|
2762
|
+
body.openHours = expandOpenHours(args.openHours);
|
|
2763
|
+
body.availabilityType = args.availabilityType ?? 0;
|
|
2764
|
+
} else if (args.availabilityType !== void 0) {
|
|
2765
|
+
body.availabilityType = args.availabilityType;
|
|
2766
|
+
}
|
|
2767
|
+
}
|
|
2768
|
+
function buildCreateCalendarBody(args, resolvedLocationId) {
|
|
2769
|
+
const body = {
|
|
2770
|
+
locationId: resolvedLocationId,
|
|
2771
|
+
name: args.name
|
|
2772
|
+
};
|
|
2773
|
+
applyCalendarFields(body, args);
|
|
2774
|
+
return body;
|
|
2775
|
+
}
|
|
2776
|
+
function buildUpdateCalendarBody(args) {
|
|
2777
|
+
const body = {};
|
|
2778
|
+
if (args.name !== void 0) body.name = args.name;
|
|
2779
|
+
applyCalendarFields(body, args);
|
|
2780
|
+
return body;
|
|
2781
|
+
}
|
|
2730
2782
|
function registerCalendarTools(server2, client) {
|
|
2731
2783
|
safeTool(
|
|
2732
2784
|
server2,
|
|
@@ -2771,25 +2823,15 @@ function registerCalendarTools(server2, client) {
|
|
|
2771
2823
|
slotDuration: import_zod9.z.number().optional().describe("Slot duration in minutes"),
|
|
2772
2824
|
slotBuffer: import_zod9.z.number().optional().describe("Buffer time between slots in minutes"),
|
|
2773
2825
|
slotInterval: import_zod9.z.number().optional().describe("Slot interval in minutes"),
|
|
2774
|
-
appointmentPerSlot: import_zod9.z.number().optional().describe("Max appointments per slot")
|
|
2826
|
+
appointmentPerSlot: import_zod9.z.number().optional().describe("Max appointments per slot"),
|
|
2827
|
+
openHours: import_zod9.z.array(OpenHoursBlockSchema).optional().describe(
|
|
2828
|
+
"Weekly business hours that make slots bookable (the 'assign availability hours' step). Each entry maps weekdays (0=Sun \u2026 6=Sat) to one or more open windows on a 24-hour clock; multi-day entries are auto-expanded to GHL's required one-block-per-day form. Example Mon-Fri 9-6 + Sat 10-1: [{daysOfTheWeek:[1,2,3,4,5],hours:[{openHour:9,openMinute:0,closeHour:18,closeMinute:0}]},{daysOfTheWeek:[6],hours:[{openHour:10,openMinute:0,closeHour:13,closeMinute:0}]}]. Behavior (verified live): on event/simple calendars these hours are the sole source of availability. On round_robin calendars the bookable slots are the INTERSECTION of these hours and each assigned user's working hours, so a day only opens if a team member is also available then (e.g. a Saturday window needs a user with Saturday availability). Omit to use GHL's defaults."
|
|
2829
|
+
),
|
|
2830
|
+
availabilityType: import_zod9.z.number().int().optional().describe("Availability mode. 0 = standard weekly hours (from openHours); auto-set when you pass openHours. Leave unset otherwise.")
|
|
2775
2831
|
},
|
|
2776
|
-
async (
|
|
2777
|
-
const resolvedLocationId = client.resolveLocationId(
|
|
2778
|
-
const body =
|
|
2779
|
-
locationId: resolvedLocationId,
|
|
2780
|
-
name
|
|
2781
|
-
};
|
|
2782
|
-
if (description !== void 0) body.description = description;
|
|
2783
|
-
if (slug !== void 0) body.slug = slug;
|
|
2784
|
-
if (widgetSlug !== void 0) body.widgetSlug = widgetSlug;
|
|
2785
|
-
if (calendarType !== void 0) body.calendarType = calendarType;
|
|
2786
|
-
if (teamMembers !== void 0) body.teamMembers = teamMembers;
|
|
2787
|
-
if (eventTitle !== void 0) body.eventTitle = eventTitle;
|
|
2788
|
-
if (eventColor !== void 0) body.eventColor = eventColor;
|
|
2789
|
-
if (slotDuration !== void 0) body.slotDuration = slotDuration;
|
|
2790
|
-
if (slotBuffer !== void 0) body.slotBuffer = slotBuffer;
|
|
2791
|
-
if (slotInterval !== void 0) body.slotInterval = slotInterval;
|
|
2792
|
-
if (appointmentPerSlot !== void 0) body.appointmentPerSlot = appointmentPerSlot;
|
|
2832
|
+
async (args) => {
|
|
2833
|
+
const resolvedLocationId = client.resolveLocationId(args.locationId);
|
|
2834
|
+
const body = buildCreateCalendarBody(args, resolvedLocationId);
|
|
2793
2835
|
return await client.post("/calendars/", { body });
|
|
2794
2836
|
}
|
|
2795
2837
|
);
|
|
@@ -2810,23 +2852,15 @@ function registerCalendarTools(server2, client) {
|
|
|
2810
2852
|
slotDuration: import_zod9.z.number().optional().describe("Slot duration in minutes"),
|
|
2811
2853
|
slotBuffer: import_zod9.z.number().optional().describe("Buffer time between slots in minutes"),
|
|
2812
2854
|
slotInterval: import_zod9.z.number().optional().describe("Slot interval in minutes"),
|
|
2813
|
-
appointmentPerSlot: import_zod9.z.number().optional().describe("Max appointments per slot")
|
|
2855
|
+
appointmentPerSlot: import_zod9.z.number().optional().describe("Max appointments per slot"),
|
|
2856
|
+
openHours: import_zod9.z.array(OpenHoursBlockSchema).optional().describe(
|
|
2857
|
+
"Weekly business hours that make slots bookable. Each entry maps weekdays (0=Sun \u2026 6=Sat) to one or more open windows on a 24-hour clock; multi-day entries are auto-expanded to GHL's required one-block-per-day form (e.g. [{daysOfTheWeek:[1,2,3,4,5],hours:[{openHour:9,openMinute:0,closeHour:18,closeMinute:0}]}] = Mon-Fri 9am-6pm). Replaces the calendar's existing hours. Behavior (verified live): event/simple calendars use these hours directly; round_robin calendars intersect them with each assigned user's working hours (a day only opens if a team member is available then)."
|
|
2858
|
+
),
|
|
2859
|
+
availabilityType: import_zod9.z.number().int().optional().describe("Availability mode. 0 = standard weekly hours (from openHours); auto-set when you pass openHours. Leave unset otherwise.")
|
|
2814
2860
|
},
|
|
2815
|
-
async (
|
|
2816
|
-
const body =
|
|
2817
|
-
|
|
2818
|
-
if (description !== void 0) body.description = description;
|
|
2819
|
-
if (slug !== void 0) body.slug = slug;
|
|
2820
|
-
if (widgetSlug !== void 0) body.widgetSlug = widgetSlug;
|
|
2821
|
-
if (calendarType !== void 0) body.calendarType = calendarType;
|
|
2822
|
-
if (teamMembers !== void 0) body.teamMembers = teamMembers;
|
|
2823
|
-
if (eventTitle !== void 0) body.eventTitle = eventTitle;
|
|
2824
|
-
if (eventColor !== void 0) body.eventColor = eventColor;
|
|
2825
|
-
if (slotDuration !== void 0) body.slotDuration = slotDuration;
|
|
2826
|
-
if (slotBuffer !== void 0) body.slotBuffer = slotBuffer;
|
|
2827
|
-
if (slotInterval !== void 0) body.slotInterval = slotInterval;
|
|
2828
|
-
if (appointmentPerSlot !== void 0) body.appointmentPerSlot = appointmentPerSlot;
|
|
2829
|
-
return await client.put(`/calendars/${calendarId}`, { body });
|
|
2861
|
+
async (args) => {
|
|
2862
|
+
const body = buildUpdateCalendarBody(args);
|
|
2863
|
+
return await client.put(`/calendars/${args.calendarId}`, { body });
|
|
2830
2864
|
}
|
|
2831
2865
|
);
|
|
2832
2866
|
safeTool(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elitedcs/ghl-mcp",
|
|
3
|
-
"version": "3.34.
|
|
3
|
+
"version": "3.34.9",
|
|
4
4
|
"mcpName": "io.github.drjerryrelth/ghl-command",
|
|
5
5
|
"description": "GoHighLevel MCP Server for Claude. 218 tools — full CRM, automation, marketing control, account-wide workflow audit, and the only programmatic GHL workflow builder, now multi-tenant across client accounts.",
|
|
6
6
|
"main": "dist/index.js",
|