conduyt-mcp 4.69.0 → 4.70.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.
@@ -24,9 +24,51 @@ const pageFields = {
24
24
  leadSource: z.string().max(100).nullable().optional().describe("lead source stamped on contacts the page creates"),
25
25
  brandName: z.string().max(100).nullable().optional().describe("white-label name shown on the page and in Zoom meeting names"),
26
26
  embedAllowedOrigins: z.array(z.string().url()).nullable().optional().describe("origins allowed to embed/call the page; null or empty = any"),
27
+ documentsEnabled: z.boolean().optional().describe("the documents step: the public upload-url and documents routes answer for this page's bookings (bank statements and funding agreements attached to the lead)"),
28
+ documentsPageUrl: z.string().url().nullable().optional().describe("the site page the confirmation email links the visitor back to for the upload (https; the page reads ?appointment=<id>); null = no link"),
27
29
  availabilityRules: z.array(availabilityWindow).nullable().optional().describe("availability override; null = the host's own rules"),
28
30
  isActive: z.boolean().optional(),
29
31
  };
32
+ /** (Codex rb-r9 m3) every other field PATCH /booking-pages/{id} accepts (the OpenAPI BookingPagePatch schema): with pageFields
33
+ * the update tool covers the route's whole body, typed as the route normalises it */
34
+ const updateOnlyFields = {
35
+ durationOptions: z.array(z.object({ label: z.string().min(1), minutes: z.number().int().min(5).max(480) })).nullable().optional().describe("selectable durations; empty or null clears"),
36
+ bufferBefore: z.number().int().min(0).nullable().optional().describe("minutes blocked before each booking"),
37
+ bufferAfter: z.number().int().min(0).nullable().optional().describe("minutes blocked after each booking"),
38
+ maxBookingsPerDay: z.number().int().min(1).nullable().optional(),
39
+ color: z.string().regex(/^#[0-9a-fA-F]{3,8}$/).nullable().optional().describe("hex colour"),
40
+ thankYouMessage: z.string().max(2000).nullable().optional(),
41
+ redirectUrl: z.string().url().nullable().optional().describe("where the visitor goes after booking"),
42
+ requirePhone: z.boolean().optional(),
43
+ embedEnabled: z.boolean().optional(),
44
+ // (Codex rb-r10 m3) the shapes the route's sanitizers keep (an entry outside them is dropped; a list with none clears)
45
+ customQuestions: z.array(z.object({ id: z.string().max(57).optional(), label: z.string().min(1).max(500), type: z.enum(["short_text", "long_text", "email", "phone", "select", "checkbox", "date", "number", "hidden"]), required: z.boolean().optional(), options: z.array(z.string().max(500)).max(50).optional(), defaultValue: z.string().max(500).optional() })).max(50).optional(),
46
+ formFields: z.array(z.object({ id: z.string().min(1).max(64), label: z.string().min(1).max(120), type: z.enum(["text", "email", "tel", "textarea"]), show: z.boolean(), required: z.boolean(), locked: z.boolean().optional() })).max(20).nullable().optional(),
47
+ fieldMappings: z.array(z.object({ formFieldId: z.string().min(1).max(64), contactField: z.string().regex(/^(firstName|lastName|email|phone|company|jobTitle|address|city|state|zip|country|source|notes|website|customFields\.[a-zA-Z_][a-zA-Z0-9_]*)$/) })).max(20).nullable().optional(),
48
+ reminders: z.array(z.object({ type: z.enum(["email", "sms"]), minutesBefore: z.number().int().min(1).max(10080) })).max(10).optional(),
49
+ logoUrl: z.string().url().nullable().optional(),
50
+ hideBranding: z.boolean().optional(),
51
+ template: z.enum(["bda"]).nullable().optional().describe("null = the default page, 'bda' = the BDA template"),
52
+ reviews: z.object({ badges: z.array(z.record(z.string(), z.unknown())).optional(), testimonials: z.array(z.record(z.string(), z.unknown())).optional() }).nullable().optional(),
53
+ campaign: z.string().nullable().optional(),
54
+ hyrosTag: z.string().nullable().optional(),
55
+ eventType: z.enum(["one_on_one", "round_robin", "collective", "group"]).optional(),
56
+ maxAttendees: z.number().int().min(1).nullable().optional(),
57
+ hostUserIds: z.array(z.string().uuid()).optional().describe("users on this account who can host"),
58
+ hostGroupId: z.string().uuid().nullable().optional(),
59
+ hostPriorities: z.record(z.string(), z.enum(["highest", "high", "low", "lowest"])).nullable().optional().describe("host user id to priority"),
60
+ distributionMethod: z.enum(["maximize", "equal"]).optional(),
61
+ paymentEnabled: z.boolean().optional().describe("accepted, but checkout is not implemented yet: the page stays unpaid and the answer carries a warning"),
62
+ paymentAmount: z.number().int().min(1).nullable().optional().describe("cents"),
63
+ paymentCurrency: z.enum(["usd", "eur", "gbp", "cad", "aud", "mxn"]).nullable().optional(),
64
+ stripeProductId: z.string().nullable().optional(),
65
+ stripePriceId: z.string().nullable().optional(),
66
+ gdprEnabled: z.boolean().optional(),
67
+ gdprText: z.string().max(2000).nullable().optional(),
68
+ gdprLinkUrl: z.string().url().nullable().optional(),
69
+ waitlistEnabled: z.boolean().optional(),
70
+ enableIcalFeed: z.boolean().optional().describe("true issues a new iCal feed token, false revokes it"),
71
+ };
30
72
  export function registerBookingPageTools(server, client) {
31
73
  server.tool("conduyt_list_booking_pages", "List the account's booking pages (GET /api/v1/booking-pages): slug, title, host, duration, active, video option. Requires calendar:view.", { activeOnly: z.boolean().optional().describe("only pages accepting bookings") }, async ({ activeOnly }) => {
32
74
  const result = await client.get(`/api/v1/booking-pages?${activeOnly ? "is_active=true" : ""}`);
@@ -40,7 +82,7 @@ export function registerBookingPageTools(server, client) {
40
82
  const result = await client.post("/api/v1/booking-pages", params);
41
83
  return formatResult(result);
42
84
  });
43
- server.tool("conduyt_update_booking_page", "Update a booking page (PATCH /api/v1/booking-pages/{id}): only the fields given change. videoProvider 'zoom' turns on one Zoom meeting per booking (null turns it off and clears the host); videoHostEmail must be a user of the connected Zoom account (null = the app's own user). Requires calendar:edit (admin/owner).", { id: z.string().uuid().describe("booking page UUID"), ...pageFields }, async ({ id, ...updates }) => {
85
+ server.tool("conduyt_update_booking_page", "Update a booking page (PATCH /api/v1/booking-pages/{id}): only the fields given change. videoProvider 'zoom' turns on one Zoom meeting per booking (null turns it off and clears the host); videoHostEmail must be a user of the connected Zoom account (null = the app's own user). Requires calendar:edit (admin/owner).", { id: z.string().uuid().describe("booking page UUID"), ...pageFields, ...updateOnlyFields }, async ({ id, ...updates }) => {
44
86
  const result = await client.patch(`/api/v1/booking-pages/${id}`, updates);
45
87
  return formatResult(result);
46
88
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "conduyt-mcp",
3
- "version": "4.69.0",
3
+ "version": "4.70.0",
4
4
  "description": "MCP server for Conduyt CRM — expose CRM operations as AI-accessible tools",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,10 +1,10 @@
1
1
  {
2
- "generatedAt": "2026-09-27T00:07:38.757Z",
2
+ "generatedAt": "2026-09-27T22:23:01.252Z",
3
3
  "toolCount": 290,
4
- "totalEndpoints": 1011,
4
+ "totalEndpoints": 1015,
5
5
  "counts": {
6
6
  "covered": 266,
7
- "excluded": 295,
7
+ "excluded": 299,
8
8
  "planned": 450,
9
9
  "uncategorized": 0
10
10
  },
@@ -3239,6 +3239,14 @@
3239
3239
  "status": "excluded",
3240
3240
  "reason": "public unauthenticated surfaces — no key semantics"
3241
3241
  },
3242
+ "POST /api/v1/public/booking/:slug/documents": {
3243
+ "status": "excluded",
3244
+ "reason": "public unauthenticated surfaces — no key semantics"
3245
+ },
3246
+ "OPTIONS /api/v1/public/booking/:slug/documents": {
3247
+ "status": "excluded",
3248
+ "reason": "public unauthenticated surfaces — no key semantics"
3249
+ },
3242
3250
  "GET /api/v1/public/booking/:slug/embed": {
3243
3251
  "status": "excluded",
3244
3252
  "reason": "public unauthenticated surfaces — no key semantics"
@@ -3267,6 +3275,14 @@
3267
3275
  "status": "excluded",
3268
3276
  "reason": "public unauthenticated surfaces — no key semantics"
3269
3277
  },
3278
+ "POST /api/v1/public/booking/:slug/upload-url": {
3279
+ "status": "excluded",
3280
+ "reason": "public unauthenticated surfaces — no key semantics"
3281
+ },
3282
+ "OPTIONS /api/v1/public/booking/:slug/upload-url": {
3283
+ "status": "excluded",
3284
+ "reason": "public unauthenticated surfaces — no key semantics"
3285
+ },
3270
3286
  "POST /api/v1/public/booking/:slug/waitlist": {
3271
3287
  "status": "excluded",
3272
3288
  "reason": "public unauthenticated surfaces — no key semantics"