@elitedcs/ghl-mcp 3.12.0 → 3.13.1

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 CHANGED
@@ -31,8 +31,8 @@ var require_package = __commonJS({
31
31
  "package.json"(exports2, module2) {
32
32
  module2.exports = {
33
33
  name: "@elitedcs/ghl-mcp",
34
- version: "3.12.0",
35
- description: "GoHighLevel MCP Server for Claude. 198 tools \u2014 full CRM, automation, marketing control, and the only programmatic GHL workflow builder.",
34
+ version: "3.13.1",
35
+ description: "GoHighLevel MCP Server for Claude. 201 tools \u2014 full CRM, automation, marketing control, and the only programmatic GHL workflow builder.",
36
36
  main: "dist/index.js",
37
37
  bin: {
38
38
  "ghl-mcp": "dist/index.js"
@@ -262,37 +262,144 @@ ${errorBody}`
262
262
  };
263
263
 
264
264
  // src/token-registry.ts
265
+ var fs2 = __toESM(require("fs"));
266
+ var path2 = __toESM(require("path"));
267
+ var import_crypto = require("crypto");
268
+ var import_zod2 = require("zod");
269
+
270
+ // src/credentials-store.ts
265
271
  var fs = __toESM(require("fs"));
266
272
  var path = __toESM(require("path"));
267
- var import_crypto = require("crypto");
273
+ var os = __toESM(require("os"));
268
274
  var import_zod = require("zod");
269
- var LocationTokenSchema = import_zod.z.object({ name: import_zod.z.string(), apiKey: import_zod.z.string() });
270
- var TokenRegistryDataSchema = import_zod.z.object({
271
- tokens: import_zod.z.record(LocationTokenSchema),
272
- agencyKey: import_zod.z.string().optional(),
273
- firebase: import_zod.z.object({
274
- apiKey: import_zod.z.string(),
275
- refreshToken: import_zod.z.string(),
276
- userId: import_zod.z.string()
275
+ var APP_NAME = "elitedcs-ghl-mcp";
276
+ var CredentialsSchema = import_zod.z.object({
277
+ license_key: import_zod.z.string().min(1),
278
+ email: import_zod.z.string().email(),
279
+ verified_at: import_zod.z.string().min(1),
280
+ ghl_api_key: import_zod.z.string().min(1),
281
+ ghl_location_id: import_zod.z.string().min(1),
282
+ ghl_company_id: import_zod.z.string().optional(),
283
+ ghl_user_id: import_zod.z.string().optional(),
284
+ ghl_firebase_api_key: import_zod.z.string().optional(),
285
+ ghl_firebase_refresh_token: import_zod.z.string().optional()
286
+ });
287
+ function appDataDir() {
288
+ const home = os.homedir();
289
+ if (process.platform === "darwin") {
290
+ return path.join(home, "Library", "Application Support", APP_NAME);
291
+ }
292
+ if (process.platform === "win32") {
293
+ const appData = process.env.APPDATA || path.join(home, "AppData", "Roaming");
294
+ return path.join(appData, APP_NAME);
295
+ }
296
+ const xdg = process.env.XDG_CONFIG_HOME || path.join(home, ".config");
297
+ return path.join(xdg, APP_NAME);
298
+ }
299
+ function ensureAppDataDir() {
300
+ const dir = appDataDir();
301
+ fs.mkdirSync(dir, { recursive: true });
302
+ if (process.platform !== "win32") {
303
+ try {
304
+ fs.chmodSync(dir, 448);
305
+ } catch {
306
+ }
307
+ }
308
+ return dir;
309
+ }
310
+ function credentialsPath() {
311
+ return path.join(appDataDir(), "credentials.json");
312
+ }
313
+ function tokenRegistryPath() {
314
+ return path.join(appDataDir(), ".ghl-tokens.json");
315
+ }
316
+ function readCredentials() {
317
+ const file = credentialsPath();
318
+ if (!fs.existsSync(file)) return null;
319
+ try {
320
+ const raw = fs.readFileSync(file, "utf-8");
321
+ const parsed = JSON.parse(raw);
322
+ return CredentialsSchema.parse(parsed);
323
+ } catch {
324
+ return null;
325
+ }
326
+ }
327
+ function writeCredentials(creds) {
328
+ ensureAppDataDir();
329
+ const file = credentialsPath();
330
+ fs.writeFileSync(file, JSON.stringify(creds, null, 2) + "\n", "utf-8");
331
+ if (process.platform !== "win32") {
332
+ try {
333
+ fs.chmodSync(file, 384);
334
+ } catch {
335
+ }
336
+ }
337
+ }
338
+
339
+ // src/token-registry.ts
340
+ var LocationTokenSchema = import_zod2.z.object({ name: import_zod2.z.string(), apiKey: import_zod2.z.string() });
341
+ var TokenRegistryDataSchema = import_zod2.z.object({
342
+ tokens: import_zod2.z.record(LocationTokenSchema),
343
+ agencyKey: import_zod2.z.string().optional(),
344
+ firebase: import_zod2.z.object({
345
+ apiKey: import_zod2.z.string(),
346
+ refreshToken: import_zod2.z.string(),
347
+ userId: import_zod2.z.string()
277
348
  }).optional()
278
349
  });
279
350
  var TokenRegistry = class {
280
351
  data;
281
352
  filePath;
282
353
  constructor(filePath) {
283
- this.filePath = filePath || path.resolve(__dirname, "..", ".ghl-tokens.json");
354
+ if (filePath) {
355
+ this.filePath = filePath;
356
+ } else {
357
+ this.filePath = tokenRegistryPath();
358
+ this.migrateLegacyRegistry();
359
+ }
284
360
  this.data = this.load();
285
361
  }
362
+ /**
363
+ * One-time move of a pre-existing registry from the legacy package-root
364
+ * location to the app-data dir. Runs only when the new file is absent and a
365
+ * legacy file exists (local checkout / wrapper-script installs, where the
366
+ * package root is stable). Best-effort: any failure leaves the legacy file
367
+ * in place and is logged, never thrown.
368
+ */
369
+ migrateLegacyRegistry() {
370
+ try {
371
+ if (fs2.existsSync(this.filePath)) return;
372
+ const legacyPath = path2.resolve(__dirname, "..", ".ghl-tokens.json");
373
+ if (legacyPath === this.filePath || !fs2.existsSync(legacyPath)) return;
374
+ ensureAppDataDir();
375
+ fs2.copyFileSync(legacyPath, this.filePath);
376
+ if (process.platform !== "win32") {
377
+ try {
378
+ fs2.chmodSync(this.filePath, 384);
379
+ } catch {
380
+ }
381
+ }
382
+ try {
383
+ fs2.unlinkSync(legacyPath);
384
+ } catch {
385
+ }
386
+ process.stderr.write(`[ghl-mcp] Migrated token registry to ${this.filePath}
387
+ `);
388
+ } catch (error) {
389
+ process.stderr.write(`[ghl-mcp] Warning: token registry migration failed: ${error}
390
+ `);
391
+ }
392
+ }
286
393
  load() {
287
394
  try {
288
- if (fs.existsSync(this.filePath)) {
289
- const raw = fs.readFileSync(this.filePath, "utf-8");
395
+ if (fs2.existsSync(this.filePath)) {
396
+ const raw = fs2.readFileSync(this.filePath, "utf-8");
290
397
  return TokenRegistryDataSchema.parse(JSON.parse(raw));
291
398
  }
292
399
  } catch (error) {
293
400
  try {
294
401
  const backupPath = this.filePath + ".corrupted." + Date.now();
295
- fs.copyFileSync(this.filePath, backupPath);
402
+ fs2.copyFileSync(this.filePath, backupPath);
296
403
  process.stderr.write(`[ghl-mcp] ERROR: Token registry corrupted. Backed up to ${backupPath}
297
404
  `);
298
405
  } catch {
@@ -305,15 +412,22 @@ var TokenRegistry = class {
305
412
  save() {
306
413
  const tmpPath = `${this.filePath}.tmp.${process.pid}.${(0, import_crypto.randomBytes)(8).toString("hex")}`;
307
414
  try {
308
- fs.writeFileSync(tmpPath, JSON.stringify(this.data, null, 2), { mode: 384 });
309
- fs.renameSync(tmpPath, this.filePath);
415
+ fs2.mkdirSync(path2.dirname(this.filePath), { recursive: true });
416
+ if (process.platform !== "win32") {
417
+ try {
418
+ fs2.chmodSync(path2.dirname(this.filePath), 448);
419
+ } catch {
420
+ }
421
+ }
422
+ fs2.writeFileSync(tmpPath, JSON.stringify(this.data, null, 2), { mode: 384 });
423
+ fs2.renameSync(tmpPath, this.filePath);
310
424
  try {
311
- fs.chmodSync(this.filePath, 384);
425
+ fs2.chmodSync(this.filePath, 384);
312
426
  } catch {
313
427
  }
314
428
  } catch (error) {
315
429
  try {
316
- fs.unlinkSync(tmpPath);
430
+ fs2.unlinkSync(tmpPath);
317
431
  } catch {
318
432
  }
319
433
  process.stderr.write(`[ghl-mcp] Warning: Could not save token registry: ${error}
@@ -383,31 +497,31 @@ var TokenRegistry = class {
383
497
  };
384
498
 
385
499
  // src/workflow-builder-client.ts
386
- var fs2 = __toESM(require("fs"));
387
- var path2 = __toESM(require("path"));
500
+ var fs3 = __toESM(require("fs"));
501
+ var path3 = __toESM(require("path"));
388
502
  var dotenv = __toESM(require("dotenv"));
389
- var import_zod3 = require("zod");
503
+ var import_zod4 = require("zod");
390
504
 
391
505
  // src/trigger-schemas.ts
392
- var import_zod2 = require("zod");
393
- var TriggerActionSchema = import_zod2.z.object({
394
- workflow_id: import_zod2.z.string(),
395
- type: import_zod2.z.literal("add_to_workflow")
506
+ var import_zod3 = require("zod");
507
+ var TriggerActionSchema = import_zod3.z.object({
508
+ workflow_id: import_zod3.z.string(),
509
+ type: import_zod3.z.literal("add_to_workflow")
396
510
  }).passthrough();
397
- var TriggerCommonSchema = import_zod2.z.object({
398
- id: import_zod2.z.string().optional(),
399
- date_added: import_zod2.z.string().optional(),
400
- deleted: import_zod2.z.boolean().optional(),
401
- belongs_to: import_zod2.z.literal("workflow").optional(),
402
- location_id: import_zod2.z.string().optional(),
403
- origin_id: import_zod2.z.string().optional(),
404
- active: import_zod2.z.boolean().optional(),
405
- workflow_id: import_zod2.z.string().optional(),
406
- masterType: import_zod2.z.literal("highlevel").optional(),
407
- name: import_zod2.z.string().optional(),
408
- actions: import_zod2.z.array(TriggerActionSchema).optional(),
409
- schedule_config: import_zod2.z.record(import_zod2.z.unknown()).optional(),
410
- date_updated: import_zod2.z.string().optional()
511
+ var TriggerCommonSchema = import_zod3.z.object({
512
+ id: import_zod3.z.string().optional(),
513
+ date_added: import_zod3.z.string().optional(),
514
+ deleted: import_zod3.z.boolean().optional(),
515
+ belongs_to: import_zod3.z.literal("workflow").optional(),
516
+ location_id: import_zod3.z.string().optional(),
517
+ origin_id: import_zod3.z.string().optional(),
518
+ active: import_zod3.z.boolean().optional(),
519
+ workflow_id: import_zod3.z.string().optional(),
520
+ masterType: import_zod3.z.literal("highlevel").optional(),
521
+ name: import_zod3.z.string().optional(),
522
+ actions: import_zod3.z.array(TriggerActionSchema).optional(),
523
+ schedule_config: import_zod3.z.record(import_zod3.z.unknown()).optional(),
524
+ date_updated: import_zod3.z.string().optional()
411
525
  }).passthrough();
412
526
  function describe(status, knownFields) {
413
527
  switch (status) {
@@ -424,26 +538,26 @@ function describe(status, knownFields) {
424
538
  function typedTrigger(typeLiteral, knownFields, status = "documented") {
425
539
  const fieldDesc = describe(status, knownFields);
426
540
  return TriggerCommonSchema.extend({
427
- type: import_zod2.z.literal(typeLiteral),
428
- conditions: import_zod2.z.array(import_zod2.z.object({
429
- operator: import_zod2.z.string().describe("Comparison operator (equals, greater_than, less_than, contains, index-of-true, is-any-of, etc.)."),
430
- field: import_zod2.z.string().describe(fieldDesc),
431
- value: import_zod2.z.unknown().optional(),
432
- title: import_zod2.z.string().optional(),
433
- type: import_zod2.z.string().optional(),
434
- id: import_zod2.z.string().optional()
541
+ type: import_zod3.z.literal(typeLiteral),
542
+ conditions: import_zod3.z.array(import_zod3.z.object({
543
+ operator: import_zod3.z.string().describe("Comparison operator (equals, greater_than, less_than, contains, index-of-true, is-any-of, etc.)."),
544
+ field: import_zod3.z.string().describe(fieldDesc),
545
+ value: import_zod3.z.unknown().optional(),
546
+ title: import_zod3.z.string().optional(),
547
+ type: import_zod3.z.string().optional(),
548
+ id: import_zod3.z.string().optional()
435
549
  }).passthrough()).optional()
436
550
  });
437
551
  }
438
552
  var ContactTagTriggerSchema = TriggerCommonSchema.extend({
439
- type: import_zod2.z.literal("contact_tag"),
440
- conditions: import_zod2.z.array(import_zod2.z.object({
441
- operator: import_zod2.z.string(),
442
- field: import_zod2.z.enum(["tagsAdded", "tagsRemoved"]),
443
- value: import_zod2.z.string(),
444
- title: import_zod2.z.string().optional(),
445
- type: import_zod2.z.string().optional(),
446
- id: import_zod2.z.string().optional()
553
+ type: import_zod3.z.literal("contact_tag"),
554
+ conditions: import_zod3.z.array(import_zod3.z.object({
555
+ operator: import_zod3.z.string(),
556
+ field: import_zod3.z.enum(["tagsAdded", "tagsRemoved"]),
557
+ value: import_zod3.z.string(),
558
+ title: import_zod3.z.string().optional(),
559
+ type: import_zod3.z.string().optional(),
560
+ id: import_zod3.z.string().optional()
447
561
  }).passthrough())
448
562
  });
449
563
  var AppointmentTriggerSchema = typedTrigger("appointment", [
@@ -685,34 +799,34 @@ var FacebookLeadGenTriggerSchema = typedTrigger("facebook_lead_gen", [
685
799
  "contact.tags"
686
800
  ]);
687
801
  var CustomObjectCreatedTriggerSchema = TriggerCommonSchema.extend({
688
- type: import_zod2.z.literal("custom_object_created"),
689
- conditions: import_zod2.z.array(import_zod2.z.object({
690
- operator: import_zod2.z.string(),
691
- field: import_zod2.z.string().describe("Custom-object field paths use the `customObject.<your_field_name>` prefix. Field names are user-defined per custom object \u2014 query the location's custom objects to discover valid field paths."),
692
- value: import_zod2.z.unknown().optional(),
693
- title: import_zod2.z.string().optional(),
694
- type: import_zod2.z.string().optional(),
695
- id: import_zod2.z.string().optional()
802
+ type: import_zod3.z.literal("custom_object_created"),
803
+ conditions: import_zod3.z.array(import_zod3.z.object({
804
+ operator: import_zod3.z.string(),
805
+ field: import_zod3.z.string().describe("Custom-object field paths use the `customObject.<your_field_name>` prefix. Field names are user-defined per custom object \u2014 query the location's custom objects to discover valid field paths."),
806
+ value: import_zod3.z.unknown().optional(),
807
+ title: import_zod3.z.string().optional(),
808
+ type: import_zod3.z.string().optional(),
809
+ id: import_zod3.z.string().optional()
696
810
  }).passthrough()).optional()
697
811
  });
698
812
  var CustomObjectChangedTriggerSchema = TriggerCommonSchema.extend({
699
- type: import_zod2.z.literal("custom_object_changed"),
700
- conditions: import_zod2.z.array(import_zod2.z.object({
701
- operator: import_zod2.z.string(),
702
- field: import_zod2.z.string().describe("Custom-object field paths use the `customObject.<your_field_name>` prefix. Field names are user-defined per custom object \u2014 query the location's custom objects to discover valid field paths."),
703
- value: import_zod2.z.unknown().optional(),
704
- title: import_zod2.z.string().optional(),
705
- type: import_zod2.z.string().optional(),
706
- id: import_zod2.z.string().optional()
813
+ type: import_zod3.z.literal("custom_object_changed"),
814
+ conditions: import_zod3.z.array(import_zod3.z.object({
815
+ operator: import_zod3.z.string(),
816
+ field: import_zod3.z.string().describe("Custom-object field paths use the `customObject.<your_field_name>` prefix. Field names are user-defined per custom object \u2014 query the location's custom objects to discover valid field paths."),
817
+ value: import_zod3.z.unknown().optional(),
818
+ title: import_zod3.z.string().optional(),
819
+ type: import_zod3.z.string().optional(),
820
+ id: import_zod3.z.string().optional()
707
821
  }).passthrough()).optional()
708
822
  });
709
823
  var ConvAiTriggerTriggerSchema = typedTrigger("conv_ai_trigger", [], "fieldless");
710
824
  var ConvAiAutonomousTriggerTriggerSchema = typedTrigger("conv_ai_autonomous_trigger", [], "fieldless");
711
825
  var UnknownTriggerSchema = TriggerCommonSchema.extend({
712
- type: import_zod2.z.string(),
713
- conditions: import_zod2.z.array(import_zod2.z.record(import_zod2.z.unknown())).optional()
826
+ type: import_zod3.z.string(),
827
+ conditions: import_zod3.z.array(import_zod3.z.record(import_zod3.z.unknown())).optional()
714
828
  });
715
- var WorkflowTriggerSchema = import_zod2.z.union([
829
+ var WorkflowTriggerSchema = import_zod3.z.union([
716
830
  ContactTagTriggerSchema,
717
831
  AppointmentTriggerSchema,
718
832
  BirthdayReminderTriggerSchema,
@@ -778,36 +892,36 @@ var BACKEND_BASE = "https://backend.leadconnectorhq.com/workflow";
778
892
  var FIREBASE_TOKEN_URL = "https://securetoken.googleapis.com/v1/token";
779
893
  var MAX_RETRIES2 = 3;
780
894
  var BASE_DELAY_MS2 = 500;
781
- var FirebaseTokenSchema = import_zod3.z.object({
782
- id_token: import_zod3.z.string(),
783
- refresh_token: import_zod3.z.string(),
784
- expires_in: import_zod3.z.string()
895
+ var FirebaseTokenSchema = import_zod4.z.object({
896
+ id_token: import_zod4.z.string(),
897
+ refresh_token: import_zod4.z.string(),
898
+ expires_in: import_zod4.z.string()
785
899
  });
786
- var WorkflowActionSchema = import_zod3.z.custom(
900
+ var WorkflowActionSchema = import_zod4.z.custom(
787
901
  (value) => typeof value === "object" && value !== null && "type" in value
788
902
  );
789
- var WorkflowFullSchema = import_zod3.z.object({
790
- _id: import_zod3.z.string(),
791
- name: import_zod3.z.string(),
792
- status: import_zod3.z.string(),
793
- version: import_zod3.z.number(),
794
- dataVersion: import_zod3.z.number().optional(),
795
- timezone: import_zod3.z.string().optional(),
796
- workflowData: import_zod3.z.object({ templates: import_zod3.z.array(WorkflowActionSchema).optional() }).optional(),
797
- triggers: import_zod3.z.array(WorkflowTriggerSchema).optional(),
798
- createdAt: import_zod3.z.string().optional(),
799
- updatedAt: import_zod3.z.string().optional(),
800
- locationId: import_zod3.z.string().optional(),
801
- stopOnResponse: import_zod3.z.boolean().optional(),
802
- allowMultiple: import_zod3.z.boolean().optional(),
803
- allowMultipleOpportunity: import_zod3.z.boolean().optional(),
804
- autoMarkAsRead: import_zod3.z.boolean().optional(),
805
- removeContactFromLastStep: import_zod3.z.boolean().optional()
903
+ var WorkflowFullSchema = import_zod4.z.object({
904
+ _id: import_zod4.z.string(),
905
+ name: import_zod4.z.string(),
906
+ status: import_zod4.z.string(),
907
+ version: import_zod4.z.number(),
908
+ dataVersion: import_zod4.z.number().optional(),
909
+ timezone: import_zod4.z.string().optional(),
910
+ workflowData: import_zod4.z.object({ templates: import_zod4.z.array(WorkflowActionSchema).optional() }).optional(),
911
+ triggers: import_zod4.z.array(WorkflowTriggerSchema).optional(),
912
+ createdAt: import_zod4.z.string().optional(),
913
+ updatedAt: import_zod4.z.string().optional(),
914
+ locationId: import_zod4.z.string().optional(),
915
+ stopOnResponse: import_zod4.z.boolean().optional(),
916
+ allowMultiple: import_zod4.z.boolean().optional(),
917
+ allowMultipleOpportunity: import_zod4.z.boolean().optional(),
918
+ autoMarkAsRead: import_zod4.z.boolean().optional(),
919
+ removeContactFromLastStep: import_zod4.z.boolean().optional()
806
920
  }).passthrough();
807
- var CreateWorkflowResponseSchema = import_zod3.z.union([
921
+ var CreateWorkflowResponseSchema = import_zod4.z.union([
808
922
  WorkflowFullSchema,
809
- import_zod3.z.object({ _id: import_zod3.z.string() }).passthrough(),
810
- import_zod3.z.object({ id: import_zod3.z.string() }).passthrough()
923
+ import_zod4.z.object({ _id: import_zod4.z.string() }).passthrough(),
924
+ import_zod4.z.object({ id: import_zod4.z.string() }).passthrough()
811
925
  ]).transform((data) => {
812
926
  const id = "_id" in data && typeof data._id === "string" ? data._id : data.id;
813
927
  return WorkflowFullSchema.parse({
@@ -1023,23 +1137,39 @@ var WorkflowBuilderClient = class _WorkflowBuilderClient {
1023
1137
  return data.id_token;
1024
1138
  }
1025
1139
  /**
1026
- * Persist rotated refresh token back to .env or wrapper script
1140
+ * Persist a rotated refresh token to every store that backs it.
1141
+ *
1142
+ * The npm-install path (npx @elitedcs/ghl-mcp) is authoritative via
1143
+ * credentials.json — there is no .env in cwd, so the legacy .env write below
1144
+ * is a silent no-op for buyers. Don Harris flagged 2026-05-24 that the
1145
+ * rotated token was being dropped: the old code only wrote cwd/.env, which
1146
+ * doesn't exist under npx, so the next restart reloaded the stale token from
1147
+ * credentials.json. Both writes are independent and non-fatal — the token
1148
+ * still works for the current session even if persistence fails.
1027
1149
  */
1028
1150
  persistRefreshToken(newToken) {
1029
1151
  try {
1030
- const envPath = path2.resolve(process.cwd(), ".env");
1031
- if (fs2.existsSync(envPath)) {
1032
- let content = fs2.readFileSync(envPath, "utf-8");
1152
+ const creds = readCredentials();
1153
+ if (creds) {
1154
+ writeCredentials({ ...creds, ghl_firebase_refresh_token: newToken });
1155
+ }
1156
+ } catch {
1157
+ process.stderr.write("[ghl-mcp] Warning: Could not persist rotated refresh token to credentials file\n");
1158
+ }
1159
+ try {
1160
+ const envPath = path3.resolve(process.cwd(), ".env");
1161
+ if (fs3.existsSync(envPath)) {
1162
+ let content = fs3.readFileSync(envPath, "utf-8");
1033
1163
  content = content.replace(
1034
1164
  /^GHL_FIREBASE_REFRESH_TOKEN=.*/m,
1035
1165
  `GHL_FIREBASE_REFRESH_TOKEN=${newToken}`
1036
1166
  );
1037
1167
  const tmpPath = envPath + ".tmp";
1038
- fs2.writeFileSync(tmpPath, content);
1039
- fs2.renameSync(tmpPath, envPath);
1168
+ fs3.writeFileSync(tmpPath, content);
1169
+ fs3.renameSync(tmpPath, envPath);
1040
1170
  }
1041
1171
  } catch {
1042
- process.stderr.write("[ghl-mcp] Warning: Could not persist rotated refresh token\n");
1172
+ process.stderr.write("[ghl-mcp] Warning: Could not persist rotated refresh token to .env\n");
1043
1173
  }
1044
1174
  }
1045
1175
  /**
@@ -1330,7 +1460,7 @@ ${errorBody}`
1330
1460
  };
1331
1461
 
1332
1462
  // src/tools/contacts.ts
1333
- var import_zod5 = require("zod");
1463
+ var import_zod6 = require("zod");
1334
1464
 
1335
1465
  // src/tool-helpers.ts
1336
1466
  function errorResponse(error) {
@@ -1367,55 +1497,55 @@ function safeTool(server2, name, description, schema, handler) {
1367
1497
  }
1368
1498
 
1369
1499
  // src/api-schemas.ts
1370
- var import_zod4 = require("zod");
1371
- var ContactSchema = import_zod4.z.object({
1372
- id: import_zod4.z.string(),
1373
- locationId: import_zod4.z.string().nullable().optional(),
1374
- firstName: import_zod4.z.string().nullable().optional(),
1375
- lastName: import_zod4.z.string().nullable().optional(),
1376
- name: import_zod4.z.string().nullable().optional(),
1377
- email: import_zod4.z.string().nullable().optional(),
1378
- phone: import_zod4.z.string().nullable().optional(),
1379
- tags: import_zod4.z.array(import_zod4.z.string()).nullable().optional(),
1380
- source: import_zod4.z.string().nullable().optional(),
1381
- dateAdded: import_zod4.z.string().nullable().optional()
1500
+ var import_zod5 = require("zod");
1501
+ var ContactSchema = import_zod5.z.object({
1502
+ id: import_zod5.z.string(),
1503
+ locationId: import_zod5.z.string().nullable().optional(),
1504
+ firstName: import_zod5.z.string().nullable().optional(),
1505
+ lastName: import_zod5.z.string().nullable().optional(),
1506
+ name: import_zod5.z.string().nullable().optional(),
1507
+ email: import_zod5.z.string().nullable().optional(),
1508
+ phone: import_zod5.z.string().nullable().optional(),
1509
+ tags: import_zod5.z.array(import_zod5.z.string()).nullable().optional(),
1510
+ source: import_zod5.z.string().nullable().optional(),
1511
+ dateAdded: import_zod5.z.string().nullable().optional()
1382
1512
  }).passthrough();
1383
- var ContactSearchResponseSchema = import_zod4.z.object({
1384
- contacts: import_zod4.z.array(ContactSchema),
1385
- meta: import_zod4.z.object({
1386
- total: import_zod4.z.number().nullable().optional(),
1387
- count: import_zod4.z.number().nullable().optional(),
1388
- currentPage: import_zod4.z.number().nullable().optional(),
1389
- nextPage: import_zod4.z.union([import_zod4.z.number(), import_zod4.z.string()]).nullable().optional(),
1390
- prevPage: import_zod4.z.union([import_zod4.z.number(), import_zod4.z.string()]).nullable().optional(),
1391
- startAfterId: import_zod4.z.string().nullable().optional(),
1392
- startAfter: import_zod4.z.number().nullable().optional()
1513
+ var ContactSearchResponseSchema = import_zod5.z.object({
1514
+ contacts: import_zod5.z.array(ContactSchema),
1515
+ meta: import_zod5.z.object({
1516
+ total: import_zod5.z.number().nullable().optional(),
1517
+ count: import_zod5.z.number().nullable().optional(),
1518
+ currentPage: import_zod5.z.number().nullable().optional(),
1519
+ nextPage: import_zod5.z.union([import_zod5.z.number(), import_zod5.z.string()]).nullable().optional(),
1520
+ prevPage: import_zod5.z.union([import_zod5.z.number(), import_zod5.z.string()]).nullable().optional(),
1521
+ startAfterId: import_zod5.z.string().nullable().optional(),
1522
+ startAfter: import_zod5.z.number().nullable().optional()
1393
1523
  }).passthrough().optional()
1394
1524
  }).passthrough();
1395
- var ContactResponseSchema = import_zod4.z.object({
1525
+ var ContactResponseSchema = import_zod5.z.object({
1396
1526
  contact: ContactSchema
1397
1527
  }).passthrough();
1398
- var PipelineStageSchema = import_zod4.z.object({
1399
- id: import_zod4.z.string(),
1400
- name: import_zod4.z.string(),
1401
- position: import_zod4.z.number().optional()
1528
+ var PipelineStageSchema = import_zod5.z.object({
1529
+ id: import_zod5.z.string(),
1530
+ name: import_zod5.z.string(),
1531
+ position: import_zod5.z.number().optional()
1402
1532
  }).passthrough();
1403
- var PipelineSchema = import_zod4.z.object({
1404
- id: import_zod4.z.string(),
1405
- name: import_zod4.z.string(),
1406
- stages: import_zod4.z.array(PipelineStageSchema),
1407
- locationId: import_zod4.z.string().optional()
1533
+ var PipelineSchema = import_zod5.z.object({
1534
+ id: import_zod5.z.string(),
1535
+ name: import_zod5.z.string(),
1536
+ stages: import_zod5.z.array(PipelineStageSchema),
1537
+ locationId: import_zod5.z.string().optional()
1408
1538
  }).passthrough();
1409
- var PipelinesResponseSchema = import_zod4.z.object({
1410
- pipelines: import_zod4.z.array(PipelineSchema)
1539
+ var PipelinesResponseSchema = import_zod5.z.object({
1540
+ pipelines: import_zod5.z.array(PipelineSchema)
1411
1541
  }).passthrough();
1412
- var CalendarSchema = import_zod4.z.object({
1413
- id: import_zod4.z.string(),
1414
- name: import_zod4.z.string(),
1415
- locationId: import_zod4.z.string().optional()
1542
+ var CalendarSchema = import_zod5.z.object({
1543
+ id: import_zod5.z.string(),
1544
+ name: import_zod5.z.string(),
1545
+ locationId: import_zod5.z.string().optional()
1416
1546
  }).passthrough();
1417
- var CalendarsResponseSchema = import_zod4.z.object({
1418
- calendars: import_zod4.z.array(CalendarSchema)
1547
+ var CalendarsResponseSchema = import_zod5.z.object({
1548
+ calendars: import_zod5.z.array(CalendarSchema)
1419
1549
  }).passthrough();
1420
1550
 
1421
1551
  // src/tools/contacts.ts
@@ -1425,12 +1555,12 @@ function registerContactTools(server2, client) {
1425
1555
  "search_contacts",
1426
1556
  "Search and list contacts in a GHL location. Supports filtering by query string, pagination, and sorting.",
1427
1557
  {
1428
- locationId: import_zod5.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
1429
- query: import_zod5.z.string().optional().describe("Search query to filter contacts (searches name, email, phone, etc.)."),
1430
- limit: import_zod5.z.number().optional().describe("Maximum number of contacts to return. Defaults to 20."),
1431
- startAfterId: import_zod5.z.string().optional().describe("Contact ID to start after, for cursor-based pagination."),
1432
- sortBy: import_zod5.z.string().optional().describe("Field to sort results by (e.g. 'dateAdded', 'name')."),
1433
- sortOrder: import_zod5.z.string().optional().describe("Sort direction: 'asc' or 'desc'.")
1558
+ locationId: import_zod6.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
1559
+ query: import_zod6.z.string().optional().describe("Search query to filter contacts (searches name, email, phone, etc.)."),
1560
+ limit: import_zod6.z.number().optional().describe("Maximum number of contacts to return. Defaults to 20."),
1561
+ startAfterId: import_zod6.z.string().optional().describe("Contact ID to start after, for cursor-based pagination."),
1562
+ sortBy: import_zod6.z.string().optional().describe("Field to sort results by (e.g. 'dateAdded', 'name')."),
1563
+ sortOrder: import_zod6.z.string().optional().describe("Sort direction: 'asc' or 'desc'.")
1434
1564
  },
1435
1565
  async ({ locationId: locationId2, query, limit, startAfterId, sortBy, sortOrder }) => {
1436
1566
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -1452,7 +1582,7 @@ function registerContactTools(server2, client) {
1452
1582
  "get_contact",
1453
1583
  "Retrieve a single contact by their ID, including all profile fields, tags, and custom fields.",
1454
1584
  {
1455
- contactId: import_zod5.z.string().describe("The ID of the contact to retrieve.")
1585
+ contactId: import_zod6.z.string().describe("The ID of the contact to retrieve.")
1456
1586
  },
1457
1587
  async ({ contactId }) => {
1458
1588
  const raw = await client.get(`/contacts/${contactId}`);
@@ -1464,25 +1594,25 @@ function registerContactTools(server2, client) {
1464
1594
  "create_contact",
1465
1595
  "Create a new contact in a GHL location. At minimum, provide a locationId and at least one identifying field (name, email, or phone).",
1466
1596
  {
1467
- locationId: import_zod5.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
1468
- firstName: import_zod5.z.string().optional().describe("Contact's first name."),
1469
- lastName: import_zod5.z.string().optional().describe("Contact's last name."),
1470
- name: import_zod5.z.string().optional().describe("Contact's full name."),
1471
- email: import_zod5.z.string().optional().describe("Contact's email address."),
1472
- phone: import_zod5.z.string().optional().describe("Contact's phone number."),
1473
- tags: import_zod5.z.array(import_zod5.z.string()).optional().describe("Array of tags to assign to the contact."),
1474
- source: import_zod5.z.string().optional().describe("Lead source for the contact."),
1475
- companyName: import_zod5.z.string().optional().describe("Contact's company name."),
1476
- address1: import_zod5.z.string().optional().describe("Street address."),
1477
- city: import_zod5.z.string().optional().describe("City."),
1478
- state: import_zod5.z.string().optional().describe("State or province."),
1479
- postalCode: import_zod5.z.string().optional().describe("Postal / ZIP code."),
1480
- website: import_zod5.z.string().optional().describe("Contact's website URL."),
1481
- timezone: import_zod5.z.string().optional().describe("Contact's timezone (e.g. 'America/New_York')."),
1482
- customFields: import_zod5.z.array(
1483
- import_zod5.z.object({
1484
- id: import_zod5.z.string().describe("Custom field ID."),
1485
- value: import_zod5.z.union([import_zod5.z.string(), import_zod5.z.number(), import_zod5.z.boolean()]).describe("Custom field value.")
1597
+ locationId: import_zod6.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
1598
+ firstName: import_zod6.z.string().optional().describe("Contact's first name."),
1599
+ lastName: import_zod6.z.string().optional().describe("Contact's last name."),
1600
+ name: import_zod6.z.string().optional().describe("Contact's full name."),
1601
+ email: import_zod6.z.string().optional().describe("Contact's email address."),
1602
+ phone: import_zod6.z.string().optional().describe("Contact's phone number."),
1603
+ tags: import_zod6.z.array(import_zod6.z.string()).optional().describe("Array of tags to assign to the contact."),
1604
+ source: import_zod6.z.string().optional().describe("Lead source for the contact."),
1605
+ companyName: import_zod6.z.string().optional().describe("Contact's company name."),
1606
+ address1: import_zod6.z.string().optional().describe("Street address."),
1607
+ city: import_zod6.z.string().optional().describe("City."),
1608
+ state: import_zod6.z.string().optional().describe("State or province."),
1609
+ postalCode: import_zod6.z.string().optional().describe("Postal / ZIP code."),
1610
+ website: import_zod6.z.string().optional().describe("Contact's website URL."),
1611
+ timezone: import_zod6.z.string().optional().describe("Contact's timezone (e.g. 'America/New_York')."),
1612
+ customFields: import_zod6.z.array(
1613
+ import_zod6.z.object({
1614
+ id: import_zod6.z.string().describe("Custom field ID."),
1615
+ value: import_zod6.z.union([import_zod6.z.string(), import_zod6.z.number(), import_zod6.z.boolean()]).describe("Custom field value.")
1486
1616
  })
1487
1617
  ).optional().describe("Array of custom field objects with id and value.")
1488
1618
  },
@@ -1503,25 +1633,25 @@ function registerContactTools(server2, client) {
1503
1633
  "update_contact",
1504
1634
  "Update an existing contact's fields. Only provided fields will be changed; omitted fields remain unchanged.",
1505
1635
  {
1506
- contactId: import_zod5.z.string().describe("The ID of the contact to update."),
1507
- firstName: import_zod5.z.string().optional().describe("Contact's first name."),
1508
- lastName: import_zod5.z.string().optional().describe("Contact's last name."),
1509
- name: import_zod5.z.string().optional().describe("Contact's full name."),
1510
- email: import_zod5.z.string().optional().describe("Contact's email address."),
1511
- phone: import_zod5.z.string().optional().describe("Contact's phone number."),
1512
- tags: import_zod5.z.array(import_zod5.z.string()).optional().describe("Array of tags to set on the contact (replaces existing tags)."),
1513
- source: import_zod5.z.string().optional().describe("Lead source for the contact."),
1514
- companyName: import_zod5.z.string().optional().describe("Contact's company name."),
1515
- address1: import_zod5.z.string().optional().describe("Street address."),
1516
- city: import_zod5.z.string().optional().describe("City."),
1517
- state: import_zod5.z.string().optional().describe("State or province."),
1518
- postalCode: import_zod5.z.string().optional().describe("Postal / ZIP code."),
1519
- website: import_zod5.z.string().optional().describe("Contact's website URL."),
1520
- timezone: import_zod5.z.string().optional().describe("Contact's timezone (e.g. 'America/New_York')."),
1521
- customFields: import_zod5.z.array(
1522
- import_zod5.z.object({
1523
- id: import_zod5.z.string().describe("Custom field ID."),
1524
- value: import_zod5.z.union([import_zod5.z.string(), import_zod5.z.number(), import_zod5.z.boolean()]).describe("Custom field value.")
1636
+ contactId: import_zod6.z.string().describe("The ID of the contact to update."),
1637
+ firstName: import_zod6.z.string().optional().describe("Contact's first name."),
1638
+ lastName: import_zod6.z.string().optional().describe("Contact's last name."),
1639
+ name: import_zod6.z.string().optional().describe("Contact's full name."),
1640
+ email: import_zod6.z.string().optional().describe("Contact's email address."),
1641
+ phone: import_zod6.z.string().optional().describe("Contact's phone number."),
1642
+ tags: import_zod6.z.array(import_zod6.z.string()).optional().describe("Array of tags to set on the contact (replaces existing tags)."),
1643
+ source: import_zod6.z.string().optional().describe("Lead source for the contact."),
1644
+ companyName: import_zod6.z.string().optional().describe("Contact's company name."),
1645
+ address1: import_zod6.z.string().optional().describe("Street address."),
1646
+ city: import_zod6.z.string().optional().describe("City."),
1647
+ state: import_zod6.z.string().optional().describe("State or province."),
1648
+ postalCode: import_zod6.z.string().optional().describe("Postal / ZIP code."),
1649
+ website: import_zod6.z.string().optional().describe("Contact's website URL."),
1650
+ timezone: import_zod6.z.string().optional().describe("Contact's timezone (e.g. 'America/New_York')."),
1651
+ customFields: import_zod6.z.array(
1652
+ import_zod6.z.object({
1653
+ id: import_zod6.z.string().describe("Custom field ID."),
1654
+ value: import_zod6.z.union([import_zod6.z.string(), import_zod6.z.number(), import_zod6.z.boolean()]).describe("Custom field value.")
1525
1655
  })
1526
1656
  ).optional().describe("Array of custom field objects with id and value.")
1527
1657
  },
@@ -1540,8 +1670,8 @@ function registerContactTools(server2, client) {
1540
1670
  "delete_contact",
1541
1671
  "Permanently delete a contact. IRREVERSIBLE.",
1542
1672
  {
1543
- contactId: import_zod5.z.string().describe("The ID of the contact to delete."),
1544
- confirm: import_zod5.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
1673
+ contactId: import_zod6.z.string().describe("The ID of the contact to delete."),
1674
+ confirm: import_zod6.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
1545
1675
  },
1546
1676
  async ({ contactId }) => {
1547
1677
  return client.delete(`/contacts/${contactId}`);
@@ -1552,25 +1682,25 @@ function registerContactTools(server2, client) {
1552
1682
  "upsert_contact",
1553
1683
  "Create or update a contact. Matches on email or phone; creates a new contact if no match is found, otherwise updates the existing one.",
1554
1684
  {
1555
- locationId: import_zod5.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
1556
- firstName: import_zod5.z.string().optional().describe("Contact's first name."),
1557
- lastName: import_zod5.z.string().optional().describe("Contact's last name."),
1558
- name: import_zod5.z.string().optional().describe("Contact's full name."),
1559
- email: import_zod5.z.string().optional().describe("Contact's email address (used for matching)."),
1560
- phone: import_zod5.z.string().optional().describe("Contact's phone number (used for matching)."),
1561
- tags: import_zod5.z.array(import_zod5.z.string()).optional().describe("Array of tags to assign to the contact."),
1562
- source: import_zod5.z.string().optional().describe("Lead source for the contact."),
1563
- companyName: import_zod5.z.string().optional().describe("Contact's company name."),
1564
- address1: import_zod5.z.string().optional().describe("Street address."),
1565
- city: import_zod5.z.string().optional().describe("City."),
1566
- state: import_zod5.z.string().optional().describe("State or province."),
1567
- postalCode: import_zod5.z.string().optional().describe("Postal / ZIP code."),
1568
- website: import_zod5.z.string().optional().describe("Contact's website URL."),
1569
- timezone: import_zod5.z.string().optional().describe("Contact's timezone (e.g. 'America/New_York')."),
1570
- customFields: import_zod5.z.array(
1571
- import_zod5.z.object({
1572
- id: import_zod5.z.string().describe("Custom field ID."),
1573
- value: import_zod5.z.union([import_zod5.z.string(), import_zod5.z.number(), import_zod5.z.boolean()]).describe("Custom field value.")
1685
+ locationId: import_zod6.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
1686
+ firstName: import_zod6.z.string().optional().describe("Contact's first name."),
1687
+ lastName: import_zod6.z.string().optional().describe("Contact's last name."),
1688
+ name: import_zod6.z.string().optional().describe("Contact's full name."),
1689
+ email: import_zod6.z.string().optional().describe("Contact's email address (used for matching)."),
1690
+ phone: import_zod6.z.string().optional().describe("Contact's phone number (used for matching)."),
1691
+ tags: import_zod6.z.array(import_zod6.z.string()).optional().describe("Array of tags to assign to the contact."),
1692
+ source: import_zod6.z.string().optional().describe("Lead source for the contact."),
1693
+ companyName: import_zod6.z.string().optional().describe("Contact's company name."),
1694
+ address1: import_zod6.z.string().optional().describe("Street address."),
1695
+ city: import_zod6.z.string().optional().describe("City."),
1696
+ state: import_zod6.z.string().optional().describe("State or province."),
1697
+ postalCode: import_zod6.z.string().optional().describe("Postal / ZIP code."),
1698
+ website: import_zod6.z.string().optional().describe("Contact's website URL."),
1699
+ timezone: import_zod6.z.string().optional().describe("Contact's timezone (e.g. 'America/New_York')."),
1700
+ customFields: import_zod6.z.array(
1701
+ import_zod6.z.object({
1702
+ id: import_zod6.z.string().describe("Custom field ID."),
1703
+ value: import_zod6.z.union([import_zod6.z.string(), import_zod6.z.number(), import_zod6.z.boolean()]).describe("Custom field value.")
1574
1704
  })
1575
1705
  ).optional().describe("Array of custom field objects with id and value.")
1576
1706
  },
@@ -1591,8 +1721,8 @@ function registerContactTools(server2, client) {
1591
1721
  "add_contact_tags",
1592
1722
  "Add one or more tags to an existing contact. Does not remove existing tags.",
1593
1723
  {
1594
- contactId: import_zod5.z.string().describe("The ID of the contact to add tags to."),
1595
- tags: import_zod5.z.array(import_zod5.z.string()).describe("Array of tag names to add to the contact.")
1724
+ contactId: import_zod6.z.string().describe("The ID of the contact to add tags to."),
1725
+ tags: import_zod6.z.array(import_zod6.z.string()).describe("Array of tag names to add to the contact.")
1596
1726
  },
1597
1727
  async ({ contactId, tags }) => {
1598
1728
  return client.post(`/contacts/${contactId}/tags`, {
@@ -1605,8 +1735,8 @@ function registerContactTools(server2, client) {
1605
1735
  "remove_contact_tags",
1606
1736
  "Remove one or more tags from an existing contact.",
1607
1737
  {
1608
- contactId: import_zod5.z.string().describe("The ID of the contact to remove tags from."),
1609
- tags: import_zod5.z.array(import_zod5.z.string()).describe("Array of tag names to remove from the contact.")
1738
+ contactId: import_zod6.z.string().describe("The ID of the contact to remove tags from."),
1739
+ tags: import_zod6.z.array(import_zod6.z.string()).describe("Array of tag names to remove from the contact.")
1610
1740
  },
1611
1741
  async ({ contactId, tags }) => {
1612
1742
  return client.delete(`/contacts/${contactId}/tags`, {
@@ -1619,7 +1749,7 @@ function registerContactTools(server2, client) {
1619
1749
  "get_contact_tasks",
1620
1750
  "Retrieve all tasks associated with a specific contact.",
1621
1751
  {
1622
- contactId: import_zod5.z.string().describe("The ID of the contact whose tasks to retrieve.")
1752
+ contactId: import_zod6.z.string().describe("The ID of the contact whose tasks to retrieve.")
1623
1753
  },
1624
1754
  async ({ contactId }) => {
1625
1755
  return client.get(`/contacts/${contactId}/tasks`);
@@ -1630,12 +1760,12 @@ function registerContactTools(server2, client) {
1630
1760
  "create_contact_task",
1631
1761
  "Create a new task associated with a contact (e.g. follow-up call, send proposal).",
1632
1762
  {
1633
- contactId: import_zod5.z.string().describe("The ID of the contact to create the task for."),
1634
- title: import_zod5.z.string().describe("Title / summary of the task."),
1635
- body: import_zod5.z.string().optional().describe("Detailed description of the task."),
1636
- dueDate: import_zod5.z.string().optional().describe("Due date for the task in ISO 8601 format."),
1637
- completed: import_zod5.z.boolean().optional().describe("Whether the task is already completed."),
1638
- assignedTo: import_zod5.z.string().optional().describe("User ID to assign the task to.")
1763
+ contactId: import_zod6.z.string().describe("The ID of the contact to create the task for."),
1764
+ title: import_zod6.z.string().describe("Title / summary of the task."),
1765
+ body: import_zod6.z.string().optional().describe("Detailed description of the task."),
1766
+ dueDate: import_zod6.z.string().optional().describe("Due date for the task in ISO 8601 format."),
1767
+ completed: import_zod6.z.boolean().optional().describe("Whether the task is already completed."),
1768
+ assignedTo: import_zod6.z.string().optional().describe("User ID to assign the task to.")
1639
1769
  },
1640
1770
  async ({ contactId, title, body: taskBody, dueDate, completed, assignedTo }) => {
1641
1771
  const reqBody = { title };
@@ -1653,7 +1783,7 @@ function registerContactTools(server2, client) {
1653
1783
  "get_contact_notes",
1654
1784
  "Retrieve all notes associated with a specific contact.",
1655
1785
  {
1656
- contactId: import_zod5.z.string().describe("The ID of the contact whose notes to retrieve.")
1786
+ contactId: import_zod6.z.string().describe("The ID of the contact whose notes to retrieve.")
1657
1787
  },
1658
1788
  async ({ contactId }) => {
1659
1789
  return client.get(`/contacts/${contactId}/notes`);
@@ -1664,9 +1794,9 @@ function registerContactTools(server2, client) {
1664
1794
  "create_contact_note",
1665
1795
  "Add a note to a contact's record. Useful for logging interactions, observations, or internal memos.",
1666
1796
  {
1667
- contactId: import_zod5.z.string().describe("The ID of the contact to add the note to."),
1668
- body: import_zod5.z.string().describe("The text content of the note."),
1669
- userId: import_zod5.z.string().optional().describe("ID of the user creating the note.")
1797
+ contactId: import_zod6.z.string().describe("The ID of the contact to add the note to."),
1798
+ body: import_zod6.z.string().describe("The text content of the note."),
1799
+ userId: import_zod6.z.string().optional().describe("ID of the user creating the note.")
1670
1800
  },
1671
1801
  async ({ contactId, body: noteBody, userId }) => {
1672
1802
  const reqBody = { body: noteBody };
@@ -1681,7 +1811,7 @@ function registerContactTools(server2, client) {
1681
1811
  "get_contact_appointments",
1682
1812
  "Retrieve all appointments / calendar events associated with a specific contact.",
1683
1813
  {
1684
- contactId: import_zod5.z.string().describe("The ID of the contact whose appointments to retrieve.")
1814
+ contactId: import_zod6.z.string().describe("The ID of the contact whose appointments to retrieve.")
1685
1815
  },
1686
1816
  async ({ contactId }) => {
1687
1817
  return client.get(`/contacts/${contactId}/appointments`);
@@ -1692,8 +1822,8 @@ function registerContactTools(server2, client) {
1692
1822
  "add_contact_to_workflow",
1693
1823
  "Enroll a contact into an automation workflow. The contact will begin receiving the workflow's actions.",
1694
1824
  {
1695
- contactId: import_zod5.z.string().describe("The ID of the contact to add to the workflow."),
1696
- workflowId: import_zod5.z.string().describe("The ID of the workflow to enroll the contact in.")
1825
+ contactId: import_zod6.z.string().describe("The ID of the contact to add to the workflow."),
1826
+ workflowId: import_zod6.z.string().describe("The ID of the workflow to enroll the contact in.")
1697
1827
  },
1698
1828
  async ({ contactId, workflowId }) => {
1699
1829
  return client.post(
@@ -1706,8 +1836,8 @@ function registerContactTools(server2, client) {
1706
1836
  "remove_contact_from_workflow",
1707
1837
  "Remove a contact from an automation workflow, stopping any pending workflow actions.",
1708
1838
  {
1709
- contactId: import_zod5.z.string().describe("The ID of the contact to remove from the workflow."),
1710
- workflowId: import_zod5.z.string().describe("The ID of the workflow to remove the contact from.")
1839
+ contactId: import_zod6.z.string().describe("The ID of the contact to remove from the workflow."),
1840
+ workflowId: import_zod6.z.string().describe("The ID of the workflow to remove the contact from.")
1711
1841
  },
1712
1842
  async ({ contactId, workflowId }) => {
1713
1843
  return client.delete(
@@ -1718,20 +1848,20 @@ function registerContactTools(server2, client) {
1718
1848
  }
1719
1849
 
1720
1850
  // src/tools/conversations.ts
1721
- var import_zod6 = require("zod");
1851
+ var import_zod7 = require("zod");
1722
1852
  function registerConversationTools(server2, client) {
1723
1853
  safeTool(
1724
1854
  server2,
1725
1855
  "search_conversations",
1726
1856
  "Search conversations in GoHighLevel by various filters such as contact, assignee, status, or query string.",
1727
1857
  {
1728
- locationId: import_zod6.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
1729
- contactId: import_zod6.z.string().optional().describe("Filter conversations by contact ID."),
1730
- assignedTo: import_zod6.z.string().optional().describe("Filter conversations by the assigned user ID."),
1731
- query: import_zod6.z.string().optional().describe("Free-text search query to filter conversations."),
1732
- status: import_zod6.z.enum(["all", "read", "unread", "starred", "recents"]).optional().describe("Filter by conversation status."),
1733
- limit: import_zod6.z.number().optional().describe("Maximum number of conversations to return."),
1734
- startAfterDate: import_zod6.z.string().optional().describe("Return conversations that started after this date (ISO 8601 / epoch ms).")
1858
+ locationId: import_zod7.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
1859
+ contactId: import_zod7.z.string().optional().describe("Filter conversations by contact ID."),
1860
+ assignedTo: import_zod7.z.string().optional().describe("Filter conversations by the assigned user ID."),
1861
+ query: import_zod7.z.string().optional().describe("Free-text search query to filter conversations."),
1862
+ status: import_zod7.z.enum(["all", "read", "unread", "starred", "recents"]).optional().describe("Filter by conversation status."),
1863
+ limit: import_zod7.z.number().optional().describe("Maximum number of conversations to return."),
1864
+ startAfterDate: import_zod7.z.string().optional().describe("Return conversations that started after this date (ISO 8601 / epoch ms).")
1735
1865
  },
1736
1866
  async ({ locationId: locationId2, contactId, assignedTo, query, status, limit, startAfterDate }) => {
1737
1867
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -1753,7 +1883,7 @@ function registerConversationTools(server2, client) {
1753
1883
  "get_conversation",
1754
1884
  "Retrieve a single conversation by its ID from GoHighLevel.",
1755
1885
  {
1756
- conversationId: import_zod6.z.string().describe("The ID of the conversation to retrieve.")
1886
+ conversationId: import_zod7.z.string().describe("The ID of the conversation to retrieve.")
1757
1887
  },
1758
1888
  async ({ conversationId }) => {
1759
1889
  return await client.get(`/conversations/${conversationId}`);
@@ -1764,8 +1894,8 @@ function registerConversationTools(server2, client) {
1764
1894
  "create_conversation",
1765
1895
  "Create a new conversation in GoHighLevel for a given contact.",
1766
1896
  {
1767
- locationId: import_zod6.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
1768
- contactId: import_zod6.z.string().describe("The contact ID to create the conversation for.")
1897
+ locationId: import_zod7.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
1898
+ contactId: import_zod7.z.string().describe("The contact ID to create the conversation for.")
1769
1899
  },
1770
1900
  async ({ locationId: locationId2, contactId }) => {
1771
1901
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -1779,9 +1909,9 @@ function registerConversationTools(server2, client) {
1779
1909
  "get_messages",
1780
1910
  "Retrieve messages for a specific conversation from GoHighLevel.",
1781
1911
  {
1782
- conversationId: import_zod6.z.string().describe("The ID of the conversation to retrieve messages for."),
1783
- limit: import_zod6.z.number().optional().describe("Maximum number of messages to return."),
1784
- type: import_zod6.z.string().optional().describe("Filter messages by type.")
1912
+ conversationId: import_zod7.z.string().describe("The ID of the conversation to retrieve messages for."),
1913
+ limit: import_zod7.z.number().optional().describe("Maximum number of messages to return."),
1914
+ type: import_zod7.z.string().optional().describe("Filter messages by type.")
1785
1915
  },
1786
1916
  async ({ conversationId, limit, type }) => {
1787
1917
  return await client.get(`/conversations/${conversationId}/messages`, {
@@ -1794,16 +1924,16 @@ function registerConversationTools(server2, client) {
1794
1924
  "send_message",
1795
1925
  "Send an outbound message (SMS, Email, WhatsApp, etc.) to a contact via GoHighLevel.",
1796
1926
  {
1797
- type: import_zod6.z.enum(["SMS", "Email", "WhatsApp", "GMB", "IG", "FB", "Custom", "Live_Chat"]).describe("The channel type for the outbound message."),
1798
- contactId: import_zod6.z.string().describe("The contact ID to send the message to."),
1799
- message: import_zod6.z.string().optional().describe("The message body text. Used for SMS, WhatsApp, and other chat-based channels."),
1800
- subject: import_zod6.z.string().optional().describe("Email subject line. Used when type is Email."),
1801
- html: import_zod6.z.string().optional().describe("HTML body for the email. Used when type is Email."),
1802
- emailFrom: import_zod6.z.string().optional().describe("Sender email address (for Email type)."),
1803
- emailTo: import_zod6.z.string().optional().describe("Recipient email address (for Email type)."),
1804
- emailCc: import_zod6.z.array(import_zod6.z.string()).optional().describe("CC email addresses (for Email type)."),
1805
- emailBcc: import_zod6.z.array(import_zod6.z.string()).optional().describe("BCC email addresses (for Email type)."),
1806
- attachments: import_zod6.z.array(import_zod6.z.string()).optional().describe("Array of attachment URLs to include with the message.")
1927
+ type: import_zod7.z.enum(["SMS", "Email", "WhatsApp", "GMB", "IG", "FB", "Custom", "Live_Chat"]).describe("The channel type for the outbound message."),
1928
+ contactId: import_zod7.z.string().describe("The contact ID to send the message to."),
1929
+ message: import_zod7.z.string().optional().describe("The message body text. Used for SMS, WhatsApp, and other chat-based channels."),
1930
+ subject: import_zod7.z.string().optional().describe("Email subject line. Used when type is Email."),
1931
+ html: import_zod7.z.string().optional().describe("HTML body for the email. Used when type is Email."),
1932
+ emailFrom: import_zod7.z.string().optional().describe("Sender email address (for Email type)."),
1933
+ emailTo: import_zod7.z.string().optional().describe("Recipient email address (for Email type)."),
1934
+ emailCc: import_zod7.z.array(import_zod7.z.string()).optional().describe("CC email addresses (for Email type)."),
1935
+ emailBcc: import_zod7.z.array(import_zod7.z.string()).optional().describe("BCC email addresses (for Email type)."),
1936
+ attachments: import_zod7.z.array(import_zod7.z.string()).optional().describe("Array of attachment URLs to include with the message.")
1807
1937
  },
1808
1938
  async ({ type, contactId, message, subject, html, emailFrom, emailTo, emailCc, emailBcc, attachments }) => {
1809
1939
  const body = { type, contactId };
@@ -1823,10 +1953,10 @@ function registerConversationTools(server2, client) {
1823
1953
  "add_inbound_message",
1824
1954
  "Record an inbound message in a GoHighLevel conversation (e.g., from an external channel).",
1825
1955
  {
1826
- type: import_zod6.z.string().describe("The channel type of the inbound message (e.g., SMS, Email, WhatsApp)."),
1827
- conversationId: import_zod6.z.string().describe("The conversation ID to add the message to."),
1828
- conversationProviderId: import_zod6.z.string().describe("The provider ID for the conversation channel."),
1829
- message: import_zod6.z.string().describe("The inbound message body text.")
1956
+ type: import_zod7.z.string().describe("The channel type of the inbound message (e.g., SMS, Email, WhatsApp)."),
1957
+ conversationId: import_zod7.z.string().describe("The conversation ID to add the message to."),
1958
+ conversationProviderId: import_zod7.z.string().describe("The provider ID for the conversation channel."),
1959
+ message: import_zod7.z.string().describe("The inbound message body text.")
1830
1960
  },
1831
1961
  async ({ type, conversationId, conversationProviderId, message }) => {
1832
1962
  return await client.post("/conversations/messages/inbound", {
@@ -1839,9 +1969,9 @@ function registerConversationTools(server2, client) {
1839
1969
  "update_message_status",
1840
1970
  "Update the delivery/read status of a specific message in GoHighLevel.",
1841
1971
  {
1842
- messageId: import_zod6.z.string().describe("The ID of the message to update."),
1843
- status: import_zod6.z.enum(["read", "pending", "delivered", "failed"]).describe("The new status to set for the message."),
1844
- error: import_zod6.z.string().optional().describe("Error details if the status is 'failed'.")
1972
+ messageId: import_zod7.z.string().describe("The ID of the message to update."),
1973
+ status: import_zod7.z.enum(["read", "pending", "delivered", "failed"]).describe("The new status to set for the message."),
1974
+ error: import_zod7.z.string().optional().describe("Error details if the status is 'failed'.")
1845
1975
  },
1846
1976
  async ({ messageId, status, error }) => {
1847
1977
  const body = { status };
@@ -1854,7 +1984,7 @@ function registerConversationTools(server2, client) {
1854
1984
  "get_message",
1855
1985
  "Retrieve a single message by its ID from GoHighLevel.",
1856
1986
  {
1857
- messageId: import_zod6.z.string().describe("The ID of the message to retrieve.")
1987
+ messageId: import_zod7.z.string().describe("The ID of the message to retrieve.")
1858
1988
  },
1859
1989
  async ({ messageId }) => {
1860
1990
  return await client.get(`/conversations/messages/${messageId}`);
@@ -1863,30 +1993,30 @@ function registerConversationTools(server2, client) {
1863
1993
  }
1864
1994
 
1865
1995
  // src/tools/opportunities.ts
1866
- var import_zod7 = require("zod");
1867
- var statusEnum = import_zod7.z.enum(["open", "won", "lost", "abandoned"]).describe("Opportunity status");
1868
- var statusEnumWithAll = import_zod7.z.enum(["open", "won", "lost", "abandoned", "all"]).describe("Opportunity status filter (use 'all' to include every status)");
1996
+ var import_zod8 = require("zod");
1997
+ var statusEnum = import_zod8.z.enum(["open", "won", "lost", "abandoned"]).describe("Opportunity status");
1998
+ var statusEnumWithAll = import_zod8.z.enum(["open", "won", "lost", "abandoned", "all"]).describe("Opportunity status filter (use 'all' to include every status)");
1869
1999
  function registerOpportunityTools(server2, client) {
1870
2000
  safeTool(
1871
2001
  server2,
1872
2002
  "search_opportunities",
1873
2003
  "Search opportunities in GoHighLevel with optional filters",
1874
2004
  {
1875
- locationId: import_zod7.z.string().optional().describe(
2005
+ locationId: import_zod8.z.string().optional().describe(
1876
2006
  "Location ID. Falls back to GHL_LOCATION_ID env var if omitted."
1877
2007
  ),
1878
- pipelineId: import_zod7.z.string().optional().describe("Filter by pipeline ID"),
1879
- pipelineStageId: import_zod7.z.string().optional().describe("Filter by pipeline stage ID"),
1880
- contactId: import_zod7.z.string().optional().describe("Filter by contact ID"),
2008
+ pipelineId: import_zod8.z.string().optional().describe("Filter by pipeline ID"),
2009
+ pipelineStageId: import_zod8.z.string().optional().describe("Filter by pipeline stage ID"),
2010
+ contactId: import_zod8.z.string().optional().describe("Filter by contact ID"),
1881
2011
  status: statusEnumWithAll.optional().describe("Filter by status"),
1882
- assignedTo: import_zod7.z.string().optional().describe("Filter by assigned user ID"),
1883
- query: import_zod7.z.string().optional().describe("Search query string"),
1884
- limit: import_zod7.z.number().optional().describe("Maximum number of results to return"),
1885
- startAfter: import_zod7.z.string().optional().describe("Cursor timestamp for pagination"),
1886
- startAfterId: import_zod7.z.string().optional().describe("Cursor ID for pagination"),
1887
- order: import_zod7.z.enum(["asc", "desc"]).optional().describe("Sort order"),
1888
- endDate: import_zod7.z.string().optional().describe("End date filter (ISO string)"),
1889
- startDate: import_zod7.z.string().optional().describe("Start date filter (ISO string)")
2012
+ assignedTo: import_zod8.z.string().optional().describe("Filter by assigned user ID"),
2013
+ query: import_zod8.z.string().optional().describe("Search query string"),
2014
+ limit: import_zod8.z.number().optional().describe("Maximum number of results to return"),
2015
+ startAfter: import_zod8.z.string().optional().describe("Cursor timestamp for pagination"),
2016
+ startAfterId: import_zod8.z.string().optional().describe("Cursor ID for pagination"),
2017
+ order: import_zod8.z.enum(["asc", "desc"]).optional().describe("Sort order"),
2018
+ endDate: import_zod8.z.string().optional().describe("End date filter (ISO string)"),
2019
+ startDate: import_zod8.z.string().optional().describe("Start date filter (ISO string)")
1890
2020
  },
1891
2021
  async (args) => {
1892
2022
  const locationId2 = client.resolveLocationId(args.locationId);
@@ -1914,7 +2044,7 @@ function registerOpportunityTools(server2, client) {
1914
2044
  "get_opportunity",
1915
2045
  "Get a single opportunity by ID from GoHighLevel",
1916
2046
  {
1917
- opportunityId: import_zod7.z.string().describe("The ID of the opportunity to retrieve")
2047
+ opportunityId: import_zod8.z.string().describe("The ID of the opportunity to retrieve")
1918
2048
  },
1919
2049
  async (args) => {
1920
2050
  return await client.get(`/opportunities/${args.opportunityId}`);
@@ -1925,17 +2055,17 @@ function registerOpportunityTools(server2, client) {
1925
2055
  "create_opportunity",
1926
2056
  "Create a new opportunity in GoHighLevel",
1927
2057
  {
1928
- locationId: import_zod7.z.string().optional().describe(
2058
+ locationId: import_zod8.z.string().optional().describe(
1929
2059
  "Location ID. Falls back to GHL_LOCATION_ID env var if omitted."
1930
2060
  ),
1931
- pipelineId: import_zod7.z.string().describe("Pipeline ID (required)"),
1932
- pipelineStageId: import_zod7.z.string().describe("Pipeline stage ID (required)"),
1933
- contactId: import_zod7.z.string().describe("Contact ID (required)"),
1934
- name: import_zod7.z.string().describe("Opportunity name (required)"),
2061
+ pipelineId: import_zod8.z.string().describe("Pipeline ID (required)"),
2062
+ pipelineStageId: import_zod8.z.string().describe("Pipeline stage ID (required)"),
2063
+ contactId: import_zod8.z.string().describe("Contact ID (required)"),
2064
+ name: import_zod8.z.string().describe("Opportunity name (required)"),
1935
2065
  status: statusEnum.optional().describe("Opportunity status"),
1936
- monetaryValue: import_zod7.z.number().optional().describe("Monetary value of the opportunity"),
1937
- assignedTo: import_zod7.z.string().optional().describe("User ID to assign the opportunity to"),
1938
- source: import_zod7.z.string().optional().describe("Lead source")
2066
+ monetaryValue: import_zod8.z.number().optional().describe("Monetary value of the opportunity"),
2067
+ assignedTo: import_zod8.z.string().optional().describe("User ID to assign the opportunity to"),
2068
+ source: import_zod8.z.string().optional().describe("Lead source")
1939
2069
  },
1940
2070
  async (args) => {
1941
2071
  const locationId2 = client.resolveLocationId(args.locationId);
@@ -1959,14 +2089,14 @@ function registerOpportunityTools(server2, client) {
1959
2089
  "update_opportunity",
1960
2090
  "Update an existing opportunity in GoHighLevel",
1961
2091
  {
1962
- opportunityId: import_zod7.z.string().describe("The ID of the opportunity to update"),
1963
- pipelineId: import_zod7.z.string().optional().describe("Pipeline ID"),
1964
- pipelineStageId: import_zod7.z.string().optional().describe("Pipeline stage ID"),
1965
- name: import_zod7.z.string().optional().describe("Opportunity name"),
2092
+ opportunityId: import_zod8.z.string().describe("The ID of the opportunity to update"),
2093
+ pipelineId: import_zod8.z.string().optional().describe("Pipeline ID"),
2094
+ pipelineStageId: import_zod8.z.string().optional().describe("Pipeline stage ID"),
2095
+ name: import_zod8.z.string().optional().describe("Opportunity name"),
1966
2096
  status: statusEnum.optional().describe("Opportunity status"),
1967
- monetaryValue: import_zod7.z.number().optional().describe("Monetary value of the opportunity"),
1968
- assignedTo: import_zod7.z.string().optional().describe("User ID to assign the opportunity to"),
1969
- source: import_zod7.z.string().optional().describe("Lead source")
2097
+ monetaryValue: import_zod8.z.number().optional().describe("Monetary value of the opportunity"),
2098
+ assignedTo: import_zod8.z.string().optional().describe("User ID to assign the opportunity to"),
2099
+ source: import_zod8.z.string().optional().describe("Lead source")
1970
2100
  },
1971
2101
  async (args) => {
1972
2102
  const body = {};
@@ -1989,8 +2119,8 @@ function registerOpportunityTools(server2, client) {
1989
2119
  "delete_opportunity",
1990
2120
  "Permanently delete an opportunity. IRREVERSIBLE.",
1991
2121
  {
1992
- opportunityId: import_zod7.z.string().describe("The ID of the opportunity to delete"),
1993
- confirm: import_zod7.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
2122
+ opportunityId: import_zod8.z.string().describe("The ID of the opportunity to delete"),
2123
+ confirm: import_zod8.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
1994
2124
  },
1995
2125
  async (args) => {
1996
2126
  return await client.delete(`/opportunities/${args.opportunityId}`);
@@ -2001,7 +2131,7 @@ function registerOpportunityTools(server2, client) {
2001
2131
  "update_opportunity_status",
2002
2132
  "Update only the status of an opportunity in GoHighLevel",
2003
2133
  {
2004
- opportunityId: import_zod7.z.string().describe("The ID of the opportunity to update"),
2134
+ opportunityId: import_zod8.z.string().describe("The ID of the opportunity to update"),
2005
2135
  status: statusEnum.describe("New status for the opportunity")
2006
2136
  },
2007
2137
  async (args) => {
@@ -2016,7 +2146,7 @@ function registerOpportunityTools(server2, client) {
2016
2146
  "get_pipelines",
2017
2147
  "List all pipelines for a location in GoHighLevel",
2018
2148
  {
2019
- locationId: import_zod7.z.string().optional().describe(
2149
+ locationId: import_zod8.z.string().optional().describe(
2020
2150
  "Location ID. Falls back to GHL_LOCATION_ID env var if omitted."
2021
2151
  )
2022
2152
  },
@@ -2031,14 +2161,14 @@ function registerOpportunityTools(server2, client) {
2031
2161
  }
2032
2162
 
2033
2163
  // src/tools/calendars.ts
2034
- var import_zod8 = require("zod");
2164
+ var import_zod9 = require("zod");
2035
2165
  function registerCalendarTools(server2, client) {
2036
2166
  safeTool(
2037
2167
  server2,
2038
2168
  "get_calendars",
2039
2169
  "List all calendars for a location",
2040
2170
  {
2041
- locationId: import_zod8.z.string().optional().describe("Location ID (falls back to GHL_LOCATION_ID env var)")
2171
+ locationId: import_zod9.z.string().optional().describe("Location ID (falls back to GHL_LOCATION_ID env var)")
2042
2172
  },
2043
2173
  async ({ locationId: locationId2 }) => {
2044
2174
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2053,7 +2183,7 @@ function registerCalendarTools(server2, client) {
2053
2183
  "get_calendar",
2054
2184
  "Get a single calendar by ID",
2055
2185
  {
2056
- calendarId: import_zod8.z.string().describe("The calendar ID")
2186
+ calendarId: import_zod9.z.string().describe("The calendar ID")
2057
2187
  },
2058
2188
  async ({ calendarId }) => {
2059
2189
  return await client.get(`/calendars/${calendarId}`);
@@ -2064,19 +2194,19 @@ function registerCalendarTools(server2, client) {
2064
2194
  "create_calendar",
2065
2195
  "Create a new calendar",
2066
2196
  {
2067
- locationId: import_zod8.z.string().optional().describe("Location ID (falls back to GHL_LOCATION_ID env var)"),
2068
- name: import_zod8.z.string().describe("Calendar name"),
2069
- description: import_zod8.z.string().optional().describe("Calendar description"),
2070
- slug: import_zod8.z.string().optional().describe("Calendar slug"),
2071
- widgetSlug: import_zod8.z.string().optional().describe("Widget slug for embedding"),
2072
- calendarType: import_zod8.z.string().optional().describe("Calendar type"),
2073
- teamMembers: import_zod8.z.array(import_zod8.z.record(import_zod8.z.unknown())).optional().describe("Array of team member objects"),
2074
- eventTitle: import_zod8.z.string().optional().describe("Default event title"),
2075
- eventColor: import_zod8.z.string().optional().describe("Event color hex code"),
2076
- slotDuration: import_zod8.z.number().optional().describe("Slot duration in minutes"),
2077
- slotBuffer: import_zod8.z.number().optional().describe("Buffer time between slots in minutes"),
2078
- slotInterval: import_zod8.z.number().optional().describe("Slot interval in minutes"),
2079
- appointmentPerSlot: import_zod8.z.number().optional().describe("Max appointments per slot")
2197
+ locationId: import_zod9.z.string().optional().describe("Location ID (falls back to GHL_LOCATION_ID env var)"),
2198
+ name: import_zod9.z.string().describe("Calendar name"),
2199
+ description: import_zod9.z.string().optional().describe("Calendar description"),
2200
+ slug: import_zod9.z.string().optional().describe("Calendar slug"),
2201
+ widgetSlug: import_zod9.z.string().optional().describe("Widget slug for embedding"),
2202
+ calendarType: import_zod9.z.string().optional().describe("Calendar type"),
2203
+ teamMembers: import_zod9.z.array(import_zod9.z.record(import_zod9.z.unknown())).optional().describe("Array of team member objects"),
2204
+ eventTitle: import_zod9.z.string().optional().describe("Default event title"),
2205
+ eventColor: import_zod9.z.string().optional().describe("Event color hex code"),
2206
+ slotDuration: import_zod9.z.number().optional().describe("Slot duration in minutes"),
2207
+ slotBuffer: import_zod9.z.number().optional().describe("Buffer time between slots in minutes"),
2208
+ slotInterval: import_zod9.z.number().optional().describe("Slot interval in minutes"),
2209
+ appointmentPerSlot: import_zod9.z.number().optional().describe("Max appointments per slot")
2080
2210
  },
2081
2211
  async ({ locationId: locationId2, name, description, slug, widgetSlug, calendarType, teamMembers, eventTitle, eventColor, slotDuration, slotBuffer, slotInterval, appointmentPerSlot }) => {
2082
2212
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2103,19 +2233,19 @@ function registerCalendarTools(server2, client) {
2103
2233
  "update_calendar",
2104
2234
  "Update an existing calendar",
2105
2235
  {
2106
- calendarId: import_zod8.z.string().describe("The calendar ID to update"),
2107
- name: import_zod8.z.string().optional().describe("Calendar name"),
2108
- description: import_zod8.z.string().optional().describe("Calendar description"),
2109
- slug: import_zod8.z.string().optional().describe("Calendar slug"),
2110
- widgetSlug: import_zod8.z.string().optional().describe("Widget slug for embedding"),
2111
- calendarType: import_zod8.z.string().optional().describe("Calendar type"),
2112
- teamMembers: import_zod8.z.array(import_zod8.z.record(import_zod8.z.unknown())).optional().describe("Array of team member objects"),
2113
- eventTitle: import_zod8.z.string().optional().describe("Default event title"),
2114
- eventColor: import_zod8.z.string().optional().describe("Event color hex code"),
2115
- slotDuration: import_zod8.z.number().optional().describe("Slot duration in minutes"),
2116
- slotBuffer: import_zod8.z.number().optional().describe("Buffer time between slots in minutes"),
2117
- slotInterval: import_zod8.z.number().optional().describe("Slot interval in minutes"),
2118
- appointmentPerSlot: import_zod8.z.number().optional().describe("Max appointments per slot")
2236
+ calendarId: import_zod9.z.string().describe("The calendar ID to update"),
2237
+ name: import_zod9.z.string().optional().describe("Calendar name"),
2238
+ description: import_zod9.z.string().optional().describe("Calendar description"),
2239
+ slug: import_zod9.z.string().optional().describe("Calendar slug"),
2240
+ widgetSlug: import_zod9.z.string().optional().describe("Widget slug for embedding"),
2241
+ calendarType: import_zod9.z.string().optional().describe("Calendar type"),
2242
+ teamMembers: import_zod9.z.array(import_zod9.z.record(import_zod9.z.unknown())).optional().describe("Array of team member objects"),
2243
+ eventTitle: import_zod9.z.string().optional().describe("Default event title"),
2244
+ eventColor: import_zod9.z.string().optional().describe("Event color hex code"),
2245
+ slotDuration: import_zod9.z.number().optional().describe("Slot duration in minutes"),
2246
+ slotBuffer: import_zod9.z.number().optional().describe("Buffer time between slots in minutes"),
2247
+ slotInterval: import_zod9.z.number().optional().describe("Slot interval in minutes"),
2248
+ appointmentPerSlot: import_zod9.z.number().optional().describe("Max appointments per slot")
2119
2249
  },
2120
2250
  async ({ calendarId, name, description, slug, widgetSlug, calendarType, teamMembers, eventTitle, eventColor, slotDuration, slotBuffer, slotInterval, appointmentPerSlot }) => {
2121
2251
  const body = {};
@@ -2139,8 +2269,8 @@ function registerCalendarTools(server2, client) {
2139
2269
  "delete_calendar",
2140
2270
  "Permanently delete a calendar. IRREVERSIBLE.",
2141
2271
  {
2142
- calendarId: import_zod8.z.string().describe("The calendar ID to delete"),
2143
- confirm: import_zod8.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
2272
+ calendarId: import_zod9.z.string().describe("The calendar ID to delete"),
2273
+ confirm: import_zod9.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
2144
2274
  },
2145
2275
  async ({ calendarId }) => {
2146
2276
  return await client.delete(`/calendars/${calendarId}`);
@@ -2151,11 +2281,11 @@ function registerCalendarTools(server2, client) {
2151
2281
  "get_free_slots",
2152
2282
  "Get available free slots for a calendar",
2153
2283
  {
2154
- calendarId: import_zod8.z.string().describe("The calendar ID"),
2155
- startDate: import_zod8.z.string().describe("Start date in ISO format (YYYY-MM-DD)"),
2156
- endDate: import_zod8.z.string().describe("End date in ISO format (YYYY-MM-DD)"),
2157
- timezone: import_zod8.z.string().optional().describe("Timezone (e.g. America/New_York)"),
2158
- userId: import_zod8.z.string().optional().describe("Filter by user ID")
2284
+ calendarId: import_zod9.z.string().describe("The calendar ID"),
2285
+ startDate: import_zod9.z.string().describe("Start date in ISO format (YYYY-MM-DD)"),
2286
+ endDate: import_zod9.z.string().describe("End date in ISO format (YYYY-MM-DD)"),
2287
+ timezone: import_zod9.z.string().optional().describe("Timezone (e.g. America/New_York)"),
2288
+ userId: import_zod9.z.string().optional().describe("Filter by user ID")
2159
2289
  },
2160
2290
  async ({ calendarId, startDate, endDate, timezone, userId }) => {
2161
2291
  const params = { startDate, endDate };
@@ -2171,11 +2301,11 @@ function registerCalendarTools(server2, client) {
2171
2301
  "get_calendar_events",
2172
2302
  "List calendar events for a location within a time range",
2173
2303
  {
2174
- locationId: import_zod8.z.string().optional().describe("Location ID (falls back to GHL_LOCATION_ID env var)"),
2175
- startTime: import_zod8.z.string().describe("Start time in ISO format"),
2176
- endTime: import_zod8.z.string().describe("End time in ISO format"),
2177
- calendarId: import_zod8.z.string().optional().describe("Filter by calendar ID"),
2178
- userId: import_zod8.z.string().optional().describe("Filter by user ID")
2304
+ locationId: import_zod9.z.string().optional().describe("Location ID (falls back to GHL_LOCATION_ID env var)"),
2305
+ startTime: import_zod9.z.string().describe("Start time in ISO format"),
2306
+ endTime: import_zod9.z.string().describe("End time in ISO format"),
2307
+ calendarId: import_zod9.z.string().optional().describe("Filter by calendar ID"),
2308
+ userId: import_zod9.z.string().optional().describe("Filter by user ID")
2179
2309
  },
2180
2310
  async ({ locationId: locationId2, startTime, endTime, calendarId, userId }) => {
2181
2311
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2194,7 +2324,7 @@ function registerCalendarTools(server2, client) {
2194
2324
  "get_appointment",
2195
2325
  "Get a single appointment by event ID",
2196
2326
  {
2197
- eventId: import_zod8.z.string().describe("The appointment event ID")
2327
+ eventId: import_zod9.z.string().describe("The appointment event ID")
2198
2328
  },
2199
2329
  async ({ eventId }) => {
2200
2330
  return await client.get(
@@ -2207,17 +2337,17 @@ function registerCalendarTools(server2, client) {
2207
2337
  "create_appointment",
2208
2338
  "Create a new appointment",
2209
2339
  {
2210
- calendarId: import_zod8.z.string().describe("The calendar ID to book into"),
2211
- locationId: import_zod8.z.string().optional().describe("Location ID (falls back to GHL_LOCATION_ID env var)"),
2212
- contactId: import_zod8.z.string().describe("The contact ID for the appointment"),
2213
- startTime: import_zod8.z.string().describe("Start time in ISO format"),
2214
- endTime: import_zod8.z.string().describe("End time in ISO format"),
2215
- title: import_zod8.z.string().optional().describe("Appointment title"),
2216
- appointmentStatus: import_zod8.z.enum(["confirmed", "new", "cancelled", "showed", "noshow"]).optional().describe("Appointment status"),
2217
- assignedUserId: import_zod8.z.string().optional().describe("Assigned user ID"),
2218
- address: import_zod8.z.string().optional().describe("Appointment address"),
2219
- notes: import_zod8.z.string().optional().describe("Appointment notes"),
2220
- toNotify: import_zod8.z.boolean().optional().describe("Whether to send notifications")
2340
+ calendarId: import_zod9.z.string().describe("The calendar ID to book into"),
2341
+ locationId: import_zod9.z.string().optional().describe("Location ID (falls back to GHL_LOCATION_ID env var)"),
2342
+ contactId: import_zod9.z.string().describe("The contact ID for the appointment"),
2343
+ startTime: import_zod9.z.string().describe("Start time in ISO format"),
2344
+ endTime: import_zod9.z.string().describe("End time in ISO format"),
2345
+ title: import_zod9.z.string().optional().describe("Appointment title"),
2346
+ appointmentStatus: import_zod9.z.enum(["confirmed", "new", "cancelled", "showed", "noshow"]).optional().describe("Appointment status"),
2347
+ assignedUserId: import_zod9.z.string().optional().describe("Assigned user ID"),
2348
+ address: import_zod9.z.string().optional().describe("Appointment address"),
2349
+ notes: import_zod9.z.string().optional().describe("Appointment notes"),
2350
+ toNotify: import_zod9.z.boolean().optional().describe("Whether to send notifications")
2221
2351
  },
2222
2352
  async ({ calendarId, locationId: locationId2, contactId, startTime, endTime, title, appointmentStatus, assignedUserId, address, notes, toNotify }) => {
2223
2353
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2244,16 +2374,16 @@ function registerCalendarTools(server2, client) {
2244
2374
  "update_appointment",
2245
2375
  "Update an existing appointment",
2246
2376
  {
2247
- eventId: import_zod8.z.string().describe("The appointment event ID to update"),
2248
- calendarId: import_zod8.z.string().optional().describe("Calendar ID"),
2249
- startTime: import_zod8.z.string().optional().describe("Start time in ISO format"),
2250
- endTime: import_zod8.z.string().optional().describe("End time in ISO format"),
2251
- title: import_zod8.z.string().optional().describe("Appointment title"),
2252
- appointmentStatus: import_zod8.z.enum(["confirmed", "new", "cancelled", "showed", "noshow"]).optional().describe("Appointment status"),
2253
- assignedUserId: import_zod8.z.string().optional().describe("Assigned user ID"),
2254
- address: import_zod8.z.string().optional().describe("Appointment address"),
2255
- notes: import_zod8.z.string().optional().describe("Appointment notes"),
2256
- toNotify: import_zod8.z.boolean().optional().describe("Whether to send notifications")
2377
+ eventId: import_zod9.z.string().describe("The appointment event ID to update"),
2378
+ calendarId: import_zod9.z.string().optional().describe("Calendar ID"),
2379
+ startTime: import_zod9.z.string().optional().describe("Start time in ISO format"),
2380
+ endTime: import_zod9.z.string().optional().describe("End time in ISO format"),
2381
+ title: import_zod9.z.string().optional().describe("Appointment title"),
2382
+ appointmentStatus: import_zod9.z.enum(["confirmed", "new", "cancelled", "showed", "noshow"]).optional().describe("Appointment status"),
2383
+ assignedUserId: import_zod9.z.string().optional().describe("Assigned user ID"),
2384
+ address: import_zod9.z.string().optional().describe("Appointment address"),
2385
+ notes: import_zod9.z.string().optional().describe("Appointment notes"),
2386
+ toNotify: import_zod9.z.boolean().optional().describe("Whether to send notifications")
2257
2387
  },
2258
2388
  async ({ eventId, calendarId, startTime, endTime, title, appointmentStatus, assignedUserId, address, notes, toNotify }) => {
2259
2389
  const body = {};
@@ -2277,8 +2407,8 @@ function registerCalendarTools(server2, client) {
2277
2407
  "delete_appointment",
2278
2408
  "Permanently delete an appointment. IRREVERSIBLE.",
2279
2409
  {
2280
- eventId: import_zod8.z.string().describe("The appointment event ID to delete"),
2281
- confirm: import_zod8.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
2410
+ eventId: import_zod9.z.string().describe("The appointment event ID to delete"),
2411
+ confirm: import_zod9.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
2282
2412
  },
2283
2413
  async ({ eventId }) => {
2284
2414
  return await client.delete(
@@ -2289,14 +2419,14 @@ function registerCalendarTools(server2, client) {
2289
2419
  }
2290
2420
 
2291
2421
  // src/tools/locations.ts
2292
- var import_zod9 = require("zod");
2422
+ var import_zod10 = require("zod");
2293
2423
  function registerLocationTools(server2, client) {
2294
2424
  safeTool(
2295
2425
  server2,
2296
2426
  "get_location",
2297
2427
  "Retrieve a single location (sub-account) by its ID from GoHighLevel.",
2298
2428
  {
2299
- locationId: import_zod9.z.string().describe("The ID of the location to retrieve.")
2429
+ locationId: import_zod10.z.string().describe("The ID of the location to retrieve.")
2300
2430
  },
2301
2431
  async ({ locationId: locationId2 }) => {
2302
2432
  return await client.get(`/locations/${locationId2}`);
@@ -2307,18 +2437,18 @@ function registerLocationTools(server2, client) {
2307
2437
  "update_location",
2308
2438
  "Update a location (sub-account) in GoHighLevel. Only provided fields will be updated.",
2309
2439
  {
2310
- locationId: import_zod9.z.string().describe("The ID of the location to update."),
2311
- name: import_zod9.z.string().optional().describe("Business name."),
2312
- address: import_zod9.z.string().optional().describe("Street address."),
2313
- city: import_zod9.z.string().optional().describe("City."),
2314
- state: import_zod9.z.string().optional().describe("State or province."),
2315
- postalCode: import_zod9.z.string().optional().describe("Postal / ZIP code."),
2316
- country: import_zod9.z.string().optional().describe("Country (e.g., 'US')."),
2317
- website: import_zod9.z.string().optional().describe("Website URL."),
2318
- timezone: import_zod9.z.string().optional().describe("IANA timezone (e.g., 'America/New_York')."),
2319
- phone: import_zod9.z.string().optional().describe("Phone number."),
2320
- email: import_zod9.z.string().optional().describe("Email address."),
2321
- settings: import_zod9.z.record(import_zod9.z.unknown()).optional().describe("Location settings object with key-value pairs.")
2440
+ locationId: import_zod10.z.string().describe("The ID of the location to update."),
2441
+ name: import_zod10.z.string().optional().describe("Business name."),
2442
+ address: import_zod10.z.string().optional().describe("Street address."),
2443
+ city: import_zod10.z.string().optional().describe("City."),
2444
+ state: import_zod10.z.string().optional().describe("State or province."),
2445
+ postalCode: import_zod10.z.string().optional().describe("Postal / ZIP code."),
2446
+ country: import_zod10.z.string().optional().describe("Country (e.g., 'US')."),
2447
+ website: import_zod10.z.string().optional().describe("Website URL."),
2448
+ timezone: import_zod10.z.string().optional().describe("IANA timezone (e.g., 'America/New_York')."),
2449
+ phone: import_zod10.z.string().optional().describe("Phone number."),
2450
+ email: import_zod10.z.string().optional().describe("Email address."),
2451
+ settings: import_zod10.z.record(import_zod10.z.unknown()).optional().describe("Location settings object with key-value pairs.")
2322
2452
  },
2323
2453
  async ({ locationId: locationId2, name, address, city, state, postalCode, country, website, timezone, phone, email, settings }) => {
2324
2454
  const body = {};
@@ -2341,11 +2471,11 @@ function registerLocationTools(server2, client) {
2341
2471
  "search_locations",
2342
2472
  "Search locations (sub-accounts) under an agency in GoHighLevel. Requires companyId (agency-level).",
2343
2473
  {
2344
- companyId: import_zod9.z.string().describe("The agency / company ID (required for agency-level search)."),
2345
- limit: import_zod9.z.number().optional().describe("Maximum number of locations to return."),
2346
- skip: import_zod9.z.number().optional().describe("Number of locations to skip for pagination."),
2347
- order: import_zod9.z.string().optional().describe("Sort order (e.g., 'asc' or 'desc')."),
2348
- isActive: import_zod9.z.boolean().optional().describe("Filter by active status.")
2474
+ companyId: import_zod10.z.string().describe("The agency / company ID (required for agency-level search)."),
2475
+ limit: import_zod10.z.number().optional().describe("Maximum number of locations to return."),
2476
+ skip: import_zod10.z.number().optional().describe("Number of locations to skip for pagination."),
2477
+ order: import_zod10.z.string().optional().describe("Sort order (e.g., 'asc' or 'desc')."),
2478
+ isActive: import_zod10.z.boolean().optional().describe("Filter by active status.")
2349
2479
  },
2350
2480
  async ({ companyId, limit, skip, order, isActive }) => {
2351
2481
  return await client.get("/locations/search", {
@@ -2358,9 +2488,9 @@ function registerLocationTools(server2, client) {
2358
2488
  "get_location_tags",
2359
2489
  "Retrieve tags for a location in GoHighLevel.",
2360
2490
  {
2361
- locationId: import_zod9.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
2362
- limit: import_zod9.z.number().optional().describe("Maximum number of tags to return."),
2363
- skip: import_zod9.z.number().optional().describe("Number of tags to skip for pagination.")
2491
+ locationId: import_zod10.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
2492
+ limit: import_zod10.z.number().optional().describe("Maximum number of tags to return."),
2493
+ skip: import_zod10.z.number().optional().describe("Number of tags to skip for pagination.")
2364
2494
  },
2365
2495
  async ({ locationId: locationId2, limit, skip }) => {
2366
2496
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2374,8 +2504,8 @@ function registerLocationTools(server2, client) {
2374
2504
  "create_location_tag",
2375
2505
  "Create a new tag for a location in GoHighLevel.",
2376
2506
  {
2377
- locationId: import_zod9.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
2378
- name: import_zod9.z.string().describe("The name of the tag to create.")
2507
+ locationId: import_zod10.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
2508
+ name: import_zod10.z.string().describe("The name of the tag to create.")
2379
2509
  },
2380
2510
  async ({ locationId: locationId2, name }) => {
2381
2511
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2389,9 +2519,9 @@ function registerLocationTools(server2, client) {
2389
2519
  "update_location_tag",
2390
2520
  "Update an existing tag for a location in GoHighLevel.",
2391
2521
  {
2392
- locationId: import_zod9.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
2393
- tagId: import_zod9.z.string().describe("The ID of the tag to update."),
2394
- name: import_zod9.z.string().describe("The new name for the tag.")
2522
+ locationId: import_zod10.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
2523
+ tagId: import_zod10.z.string().describe("The ID of the tag to update."),
2524
+ name: import_zod10.z.string().describe("The new name for the tag.")
2395
2525
  },
2396
2526
  async ({ locationId: locationId2, tagId, name }) => {
2397
2527
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2405,8 +2535,8 @@ function registerLocationTools(server2, client) {
2405
2535
  "delete_location_tag",
2406
2536
  "Delete a tag from a location in GoHighLevel.",
2407
2537
  {
2408
- locationId: import_zod9.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
2409
- tagId: import_zod9.z.string().describe("The ID of the tag to delete.")
2538
+ locationId: import_zod10.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
2539
+ tagId: import_zod10.z.string().describe("The ID of the tag to delete.")
2410
2540
  },
2411
2541
  async ({ locationId: locationId2, tagId }) => {
2412
2542
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2418,7 +2548,7 @@ function registerLocationTools(server2, client) {
2418
2548
  "get_custom_fields",
2419
2549
  "Retrieve custom fields for a location in GoHighLevel.",
2420
2550
  {
2421
- locationId: import_zod9.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted.")
2551
+ locationId: import_zod10.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted.")
2422
2552
  },
2423
2553
  async ({ locationId: locationId2 }) => {
2424
2554
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2430,9 +2560,9 @@ function registerLocationTools(server2, client) {
2430
2560
  "create_custom_field",
2431
2561
  "Create a new custom field for a location in GoHighLevel.",
2432
2562
  {
2433
- locationId: import_zod9.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
2434
- name: import_zod9.z.string().describe("The name of the custom field."),
2435
- dataType: import_zod9.z.enum([
2563
+ locationId: import_zod10.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
2564
+ name: import_zod10.z.string().describe("The name of the custom field."),
2565
+ dataType: import_zod10.z.enum([
2436
2566
  "TEXT",
2437
2567
  "LARGE_TEXT",
2438
2568
  "NUMERICAL",
@@ -2447,10 +2577,10 @@ function registerLocationTools(server2, client) {
2447
2577
  "FILE_UPLOAD",
2448
2578
  "SIGNATURE"
2449
2579
  ]).describe("The data type of the custom field."),
2450
- placeholder: import_zod9.z.string().optional().describe("Placeholder text for the field."),
2451
- position: import_zod9.z.number().optional().describe("Display position / sort order of the field."),
2452
- options: import_zod9.z.array(import_zod9.z.string()).optional().describe("Options for dropdown types (SINGLE_OPTIONS, MULTIPLE_OPTIONS)."),
2453
- model: import_zod9.z.enum(["contact", "opportunity"]).optional().describe("The model this custom field belongs to. Defaults to contact.")
2580
+ placeholder: import_zod10.z.string().optional().describe("Placeholder text for the field."),
2581
+ position: import_zod10.z.number().optional().describe("Display position / sort order of the field."),
2582
+ options: import_zod10.z.array(import_zod10.z.string()).optional().describe("Options for dropdown types (SINGLE_OPTIONS, MULTIPLE_OPTIONS)."),
2583
+ model: import_zod10.z.enum(["contact", "opportunity"]).optional().describe("The model this custom field belongs to. Defaults to contact.")
2454
2584
  },
2455
2585
  async ({ locationId: locationId2, name, dataType, placeholder, position, options, model }) => {
2456
2586
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2467,10 +2597,10 @@ function registerLocationTools(server2, client) {
2467
2597
  "update_custom_field",
2468
2598
  "Update an existing custom field for a location in GoHighLevel.",
2469
2599
  {
2470
- locationId: import_zod9.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
2471
- fieldId: import_zod9.z.string().describe("The ID of the custom field to update."),
2472
- name: import_zod9.z.string().optional().describe("The name of the custom field."),
2473
- dataType: import_zod9.z.enum([
2600
+ locationId: import_zod10.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
2601
+ fieldId: import_zod10.z.string().describe("The ID of the custom field to update."),
2602
+ name: import_zod10.z.string().optional().describe("The name of the custom field."),
2603
+ dataType: import_zod10.z.enum([
2474
2604
  "TEXT",
2475
2605
  "LARGE_TEXT",
2476
2606
  "NUMERICAL",
@@ -2485,10 +2615,10 @@ function registerLocationTools(server2, client) {
2485
2615
  "FILE_UPLOAD",
2486
2616
  "SIGNATURE"
2487
2617
  ]).optional().describe("The data type of the custom field."),
2488
- placeholder: import_zod9.z.string().optional().describe("Placeholder text for the field."),
2489
- position: import_zod9.z.number().optional().describe("Display position / sort order of the field."),
2490
- options: import_zod9.z.array(import_zod9.z.string()).optional().describe("Options for dropdown types (SINGLE_OPTIONS, MULTIPLE_OPTIONS)."),
2491
- model: import_zod9.z.enum(["contact", "opportunity"]).optional().describe("The model this custom field belongs to.")
2618
+ placeholder: import_zod10.z.string().optional().describe("Placeholder text for the field."),
2619
+ position: import_zod10.z.number().optional().describe("Display position / sort order of the field."),
2620
+ options: import_zod10.z.array(import_zod10.z.string()).optional().describe("Options for dropdown types (SINGLE_OPTIONS, MULTIPLE_OPTIONS)."),
2621
+ model: import_zod10.z.enum(["contact", "opportunity"]).optional().describe("The model this custom field belongs to.")
2492
2622
  },
2493
2623
  async ({ locationId: locationId2, fieldId, name, dataType, placeholder, position, options, model }) => {
2494
2624
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2507,8 +2637,8 @@ function registerLocationTools(server2, client) {
2507
2637
  "delete_custom_field",
2508
2638
  "Delete a custom field from a location in GoHighLevel.",
2509
2639
  {
2510
- locationId: import_zod9.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
2511
- fieldId: import_zod9.z.string().describe("The ID of the custom field to delete.")
2640
+ locationId: import_zod10.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
2641
+ fieldId: import_zod10.z.string().describe("The ID of the custom field to delete.")
2512
2642
  },
2513
2643
  async ({ locationId: locationId2, fieldId }) => {
2514
2644
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2520,7 +2650,7 @@ function registerLocationTools(server2, client) {
2520
2650
  "get_custom_values",
2521
2651
  "Retrieve custom values for a location in GoHighLevel.",
2522
2652
  {
2523
- locationId: import_zod9.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted.")
2653
+ locationId: import_zod10.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted.")
2524
2654
  },
2525
2655
  async ({ locationId: locationId2 }) => {
2526
2656
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2532,9 +2662,9 @@ function registerLocationTools(server2, client) {
2532
2662
  "create_custom_value",
2533
2663
  "Create a new custom value for a location in GoHighLevel.",
2534
2664
  {
2535
- locationId: import_zod9.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
2536
- name: import_zod9.z.string().describe("The name / key of the custom value."),
2537
- value: import_zod9.z.string().describe("The value to set.")
2665
+ locationId: import_zod10.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
2666
+ name: import_zod10.z.string().describe("The name / key of the custom value."),
2667
+ value: import_zod10.z.string().describe("The value to set.")
2538
2668
  },
2539
2669
  async ({ locationId: locationId2, name, value }) => {
2540
2670
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2548,10 +2678,10 @@ function registerLocationTools(server2, client) {
2548
2678
  "update_custom_value",
2549
2679
  "Update an existing custom value for a location in GoHighLevel.",
2550
2680
  {
2551
- locationId: import_zod9.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
2552
- valueId: import_zod9.z.string().describe("The ID of the custom value to update."),
2553
- name: import_zod9.z.string().optional().describe("The new name / key of the custom value."),
2554
- value: import_zod9.z.string().optional().describe("The new value to set.")
2681
+ locationId: import_zod10.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
2682
+ valueId: import_zod10.z.string().describe("The ID of the custom value to update."),
2683
+ name: import_zod10.z.string().optional().describe("The new name / key of the custom value."),
2684
+ value: import_zod10.z.string().optional().describe("The new value to set.")
2555
2685
  },
2556
2686
  async ({ locationId: locationId2, valueId, name, value }) => {
2557
2687
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2566,8 +2696,8 @@ function registerLocationTools(server2, client) {
2566
2696
  "delete_custom_value",
2567
2697
  "Delete a custom value from a location in GoHighLevel.",
2568
2698
  {
2569
- locationId: import_zod9.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
2570
- valueId: import_zod9.z.string().describe("The ID of the custom value to delete.")
2699
+ locationId: import_zod10.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted."),
2700
+ valueId: import_zod10.z.string().describe("The ID of the custom value to delete.")
2571
2701
  },
2572
2702
  async ({ locationId: locationId2, valueId }) => {
2573
2703
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2577,14 +2707,14 @@ function registerLocationTools(server2, client) {
2577
2707
  }
2578
2708
 
2579
2709
  // src/tools/workflows.ts
2580
- var import_zod10 = require("zod");
2710
+ var import_zod11 = require("zod");
2581
2711
  function registerWorkflowTools(server2, client) {
2582
2712
  safeTool(
2583
2713
  server2,
2584
2714
  "get_workflows",
2585
2715
  "Retrieve all workflows for a location in GoHighLevel. To trigger a workflow for a contact, use add_contact_to_workflow in the contacts tools.",
2586
2716
  {
2587
- locationId: import_zod10.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted.")
2717
+ locationId: import_zod11.z.string().optional().describe("Location ID. Falls back to the environment default (GHL_LOCATION_ID) if omitted.")
2588
2718
  },
2589
2719
  async ({ locationId: locationId2 }) => {
2590
2720
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2596,16 +2726,16 @@ function registerWorkflowTools(server2, client) {
2596
2726
  }
2597
2727
 
2598
2728
  // src/tools/funnels.ts
2599
- var import_zod11 = require("zod");
2729
+ var import_zod12 = require("zod");
2600
2730
  function registerFunnelTools(server2, client) {
2601
2731
  safeTool(
2602
2732
  server2,
2603
2733
  "get_funnels",
2604
2734
  "List funnels for a location. Offset-based pagination via limit/offset.",
2605
2735
  {
2606
- locationId: import_zod11.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
2607
- limit: import_zod11.z.number().optional().describe("Max number of funnels to return"),
2608
- offset: import_zod11.z.number().optional().describe("Offset for pagination")
2736
+ locationId: import_zod12.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
2737
+ limit: import_zod12.z.number().optional().describe("Max number of funnels to return"),
2738
+ offset: import_zod12.z.number().optional().describe("Offset for pagination")
2609
2739
  },
2610
2740
  async ({ locationId: locationId2, limit, offset }) => {
2611
2741
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2620,10 +2750,10 @@ function registerFunnelTools(server2, client) {
2620
2750
  "get_funnel_pages",
2621
2751
  "List pages for a specific funnel. Offset-based pagination via limit/offset.",
2622
2752
  {
2623
- locationId: import_zod11.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
2624
- funnelId: import_zod11.z.string().describe("The funnel ID"),
2625
- limit: import_zod11.z.number().optional().describe("Max number of pages to return"),
2626
- offset: import_zod11.z.number().optional().describe("Offset for pagination")
2753
+ locationId: import_zod12.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
2754
+ funnelId: import_zod12.z.string().describe("The funnel ID"),
2755
+ limit: import_zod12.z.number().optional().describe("Max number of pages to return"),
2756
+ offset: import_zod12.z.number().optional().describe("Offset for pagination")
2627
2757
  },
2628
2758
  async ({ locationId: locationId2, funnelId, limit, offset }) => {
2629
2759
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2639,17 +2769,17 @@ function registerFunnelTools(server2, client) {
2639
2769
  }
2640
2770
 
2641
2771
  // src/tools/forms.ts
2642
- var import_zod12 = require("zod");
2772
+ var import_zod13 = require("zod");
2643
2773
  function registerFormTools(server2, client) {
2644
2774
  safeTool(
2645
2775
  server2,
2646
2776
  "get_forms",
2647
2777
  "List forms for a location",
2648
2778
  {
2649
- locationId: import_zod12.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
2650
- limit: import_zod12.z.number().optional().describe("Max number of forms to return"),
2651
- skip: import_zod12.z.number().optional().describe("Number of forms to skip"),
2652
- type: import_zod12.z.string().optional().describe("Filter by form type")
2779
+ locationId: import_zod13.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
2780
+ limit: import_zod13.z.number().optional().describe("Max number of forms to return"),
2781
+ skip: import_zod13.z.number().optional().describe("Number of forms to skip"),
2782
+ type: import_zod13.z.string().optional().describe("Filter by form type")
2653
2783
  },
2654
2784
  async ({ locationId: locationId2, limit, skip, type }) => {
2655
2785
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2665,13 +2795,13 @@ function registerFormTools(server2, client) {
2665
2795
  "get_form_submissions",
2666
2796
  "List form submissions for a location. Page-based pagination via page/limit (page starts at 1).",
2667
2797
  {
2668
- locationId: import_zod12.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
2669
- page: import_zod12.z.number().optional().describe("Page number for pagination"),
2670
- limit: import_zod12.z.number().optional().describe("Max number of submissions to return"),
2671
- formId: import_zod12.z.string().optional().describe("Filter by specific form ID"),
2672
- q: import_zod12.z.string().optional().describe("Search query"),
2673
- startAt: import_zod12.z.string().optional().describe("Start date filter (ISO string)"),
2674
- endAt: import_zod12.z.string().optional().describe("End date filter (ISO string)")
2798
+ locationId: import_zod13.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
2799
+ page: import_zod13.z.number().optional().describe("Page number for pagination"),
2800
+ limit: import_zod13.z.number().optional().describe("Max number of submissions to return"),
2801
+ formId: import_zod13.z.string().optional().describe("Filter by specific form ID"),
2802
+ q: import_zod13.z.string().optional().describe("Search query"),
2803
+ startAt: import_zod13.z.string().optional().describe("Start date filter (ISO string)"),
2804
+ endAt: import_zod13.z.string().optional().describe("End date filter (ISO string)")
2675
2805
  },
2676
2806
  async ({ locationId: locationId2, page, limit, formId, q, startAt, endAt }) => {
2677
2807
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2688,16 +2818,16 @@ function registerFormTools(server2, client) {
2688
2818
  }
2689
2819
 
2690
2820
  // src/tools/surveys.ts
2691
- var import_zod13 = require("zod");
2821
+ var import_zod14 = require("zod");
2692
2822
  function registerSurveyTools(server2, client) {
2693
2823
  safeTool(
2694
2824
  server2,
2695
2825
  "get_surveys",
2696
2826
  "List surveys for a location",
2697
2827
  {
2698
- locationId: import_zod13.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
2699
- limit: import_zod13.z.number().optional().describe("Max number of surveys to return"),
2700
- skip: import_zod13.z.number().optional().describe("Number of surveys to skip")
2828
+ locationId: import_zod14.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
2829
+ limit: import_zod14.z.number().optional().describe("Max number of surveys to return"),
2830
+ skip: import_zod14.z.number().optional().describe("Number of surveys to skip")
2701
2831
  },
2702
2832
  async ({ locationId: locationId2, limit, skip }) => {
2703
2833
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2712,13 +2842,13 @@ function registerSurveyTools(server2, client) {
2712
2842
  "get_survey_submissions",
2713
2843
  "List survey submissions for a location. Page-based pagination via page/limit (page starts at 1).",
2714
2844
  {
2715
- locationId: import_zod13.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
2716
- page: import_zod13.z.number().optional().describe("Page number for pagination"),
2717
- limit: import_zod13.z.number().optional().describe("Max number of submissions to return"),
2718
- surveyId: import_zod13.z.string().optional().describe("Filter by specific survey ID"),
2719
- q: import_zod13.z.string().optional().describe("Search query"),
2720
- startAt: import_zod13.z.string().optional().describe("Start date filter (ISO string)"),
2721
- endAt: import_zod13.z.string().optional().describe("End date filter (ISO string)")
2845
+ locationId: import_zod14.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
2846
+ page: import_zod14.z.number().optional().describe("Page number for pagination"),
2847
+ limit: import_zod14.z.number().optional().describe("Max number of submissions to return"),
2848
+ surveyId: import_zod14.z.string().optional().describe("Filter by specific survey ID"),
2849
+ q: import_zod14.z.string().optional().describe("Search query"),
2850
+ startAt: import_zod14.z.string().optional().describe("Start date filter (ISO string)"),
2851
+ endAt: import_zod14.z.string().optional().describe("End date filter (ISO string)")
2722
2852
  },
2723
2853
  async ({ locationId: locationId2, page, limit, surveyId, q, startAt, endAt }) => {
2724
2854
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2735,22 +2865,22 @@ function registerSurveyTools(server2, client) {
2735
2865
  }
2736
2866
 
2737
2867
  // src/tools/payments.ts
2738
- var import_zod14 = require("zod");
2868
+ var import_zod15 = require("zod");
2739
2869
  function registerPaymentTools(server2, client) {
2740
2870
  safeTool(
2741
2871
  server2,
2742
2872
  "get_orders",
2743
2873
  "List orders for a location. Offset-based pagination via limit/offset.",
2744
2874
  {
2745
- locationId: import_zod14.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
2746
- limit: import_zod14.z.number().optional().describe("Max number of orders to return"),
2747
- offset: import_zod14.z.number().optional().describe("Offset for pagination"),
2748
- startAt: import_zod14.z.string().optional().describe("Start date filter (ISO 8601)"),
2749
- endAt: import_zod14.z.string().optional().describe("End date filter (ISO 8601)"),
2750
- search: import_zod14.z.string().optional().describe("Search term"),
2751
- contactId: import_zod14.z.string().optional().describe("Filter by contact ID"),
2752
- paymentMode: import_zod14.z.string().optional().describe("Filter by payment mode"),
2753
- status: import_zod14.z.string().optional().describe("Filter by order status")
2875
+ locationId: import_zod15.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
2876
+ limit: import_zod15.z.number().optional().describe("Max number of orders to return"),
2877
+ offset: import_zod15.z.number().optional().describe("Offset for pagination"),
2878
+ startAt: import_zod15.z.string().optional().describe("Start date filter (ISO 8601)"),
2879
+ endAt: import_zod15.z.string().optional().describe("End date filter (ISO 8601)"),
2880
+ search: import_zod15.z.string().optional().describe("Search term"),
2881
+ contactId: import_zod15.z.string().optional().describe("Filter by contact ID"),
2882
+ paymentMode: import_zod15.z.string().optional().describe("Filter by payment mode"),
2883
+ status: import_zod15.z.string().optional().describe("Filter by order status")
2754
2884
  },
2755
2885
  async ({ locationId: locationId2, limit, offset, startAt, endAt, search, contactId, paymentMode, status }) => {
2756
2886
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2775,8 +2905,8 @@ function registerPaymentTools(server2, client) {
2775
2905
  "get_order",
2776
2906
  "Get a specific order by ID",
2777
2907
  {
2778
- locationId: import_zod14.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
2779
- orderId: import_zod14.z.string().describe("The order ID")
2908
+ locationId: import_zod15.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
2909
+ orderId: import_zod15.z.string().describe("The order ID")
2780
2910
  },
2781
2911
  async ({ locationId: locationId2, orderId }) => {
2782
2912
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2792,12 +2922,12 @@ function registerPaymentTools(server2, client) {
2792
2922
  "get_subscriptions",
2793
2923
  "List subscriptions for a location. Offset-based pagination via limit/offset.",
2794
2924
  {
2795
- locationId: import_zod14.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
2796
- limit: import_zod14.z.number().optional().describe("Max number of subscriptions to return"),
2797
- offset: import_zod14.z.number().optional().describe("Offset for pagination"),
2798
- search: import_zod14.z.string().optional().describe("Search term"),
2799
- contactId: import_zod14.z.string().optional().describe("Filter by contact ID"),
2800
- entityId: import_zod14.z.string().optional().describe("Filter by entity ID")
2925
+ locationId: import_zod15.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
2926
+ limit: import_zod15.z.number().optional().describe("Max number of subscriptions to return"),
2927
+ offset: import_zod15.z.number().optional().describe("Offset for pagination"),
2928
+ search: import_zod15.z.string().optional().describe("Search term"),
2929
+ contactId: import_zod15.z.string().optional().describe("Filter by contact ID"),
2930
+ entityId: import_zod15.z.string().optional().describe("Filter by entity ID")
2801
2931
  },
2802
2932
  async ({ locationId: locationId2, limit, offset, search, contactId, entityId }) => {
2803
2933
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2818,16 +2948,16 @@ function registerPaymentTools(server2, client) {
2818
2948
  "get_transactions",
2819
2949
  "List transactions for a location. Offset-based pagination via limit/offset.",
2820
2950
  {
2821
- locationId: import_zod14.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
2822
- limit: import_zod14.z.number().optional().describe("Max number of transactions to return"),
2823
- offset: import_zod14.z.number().optional().describe("Offset for pagination"),
2824
- startAt: import_zod14.z.string().optional().describe("Start date filter (ISO 8601)"),
2825
- endAt: import_zod14.z.string().optional().describe("End date filter (ISO 8601)"),
2826
- search: import_zod14.z.string().optional().describe("Search term"),
2827
- entityId: import_zod14.z.string().optional().describe("Filter by entity ID"),
2828
- paymentMode: import_zod14.z.string().optional().describe("Filter by payment mode"),
2829
- contactId: import_zod14.z.string().optional().describe("Filter by contact ID"),
2830
- subscriptionId: import_zod14.z.string().optional().describe("Filter by subscription ID")
2951
+ locationId: import_zod15.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
2952
+ limit: import_zod15.z.number().optional().describe("Max number of transactions to return"),
2953
+ offset: import_zod15.z.number().optional().describe("Offset for pagination"),
2954
+ startAt: import_zod15.z.string().optional().describe("Start date filter (ISO 8601)"),
2955
+ endAt: import_zod15.z.string().optional().describe("End date filter (ISO 8601)"),
2956
+ search: import_zod15.z.string().optional().describe("Search term"),
2957
+ entityId: import_zod15.z.string().optional().describe("Filter by entity ID"),
2958
+ paymentMode: import_zod15.z.string().optional().describe("Filter by payment mode"),
2959
+ contactId: import_zod15.z.string().optional().describe("Filter by contact ID"),
2960
+ subscriptionId: import_zod15.z.string().optional().describe("Filter by subscription ID")
2831
2961
  },
2832
2962
  async ({ locationId: locationId2, limit, offset, startAt, endAt, search, entityId, paymentMode, contactId, subscriptionId }) => {
2833
2963
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -2850,7 +2980,7 @@ function registerPaymentTools(server2, client) {
2850
2980
  }
2851
2981
 
2852
2982
  // src/tools/products.ts
2853
- var import_zod15 = require("zod");
2983
+ var import_zod16 = require("zod");
2854
2984
  var PRODUCT_TYPES = ["DIGITAL", "PHYSICAL", "SERVICE", "PHYSICAL/DIGITAL"];
2855
2985
  function registerProductTools(server2, client) {
2856
2986
  safeTool(
@@ -2858,10 +2988,10 @@ function registerProductTools(server2, client) {
2858
2988
  "list_products",
2859
2989
  "List products in a GHL location's catalog.",
2860
2990
  {
2861
- locationId: import_zod15.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var."),
2862
- limit: import_zod15.z.number().optional().describe("Max products to return. Defaults to 100."),
2863
- offset: import_zod15.z.number().optional().describe("Skip this many records for pagination."),
2864
- search: import_zod15.z.string().optional().describe("Free-text search across product names + descriptions.")
2991
+ locationId: import_zod16.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var."),
2992
+ limit: import_zod16.z.number().optional().describe("Max products to return. Defaults to 100."),
2993
+ offset: import_zod16.z.number().optional().describe("Skip this many records for pagination."),
2994
+ search: import_zod16.z.string().optional().describe("Free-text search across product names + descriptions.")
2865
2995
  },
2866
2996
  async ({ locationId: locationId2, limit, offset, search }) => {
2867
2997
  const resolved = client.resolveLocationId(locationId2);
@@ -2877,8 +3007,8 @@ function registerProductTools(server2, client) {
2877
3007
  "get_product",
2878
3008
  "Get a single product by ID with full details (media, variants, taxes, etc.).",
2879
3009
  {
2880
- productId: import_zod15.z.string().describe("The product ID."),
2881
- locationId: import_zod15.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
3010
+ productId: import_zod16.z.string().describe("The product ID."),
3011
+ locationId: import_zod16.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
2882
3012
  },
2883
3013
  async ({ productId, locationId: locationId2 }) => {
2884
3014
  const resolved = client.resolveLocationId(locationId2);
@@ -2890,12 +3020,12 @@ function registerProductTools(server2, client) {
2890
3020
  "create_product",
2891
3021
  "Create a new product in a GHL location's catalog. Required: name, productType. Created products have no prices by default \u2014 buyers add prices via the GHL UI (sub-account scope can't write prices through the public API).",
2892
3022
  {
2893
- name: import_zod15.z.string().describe("Product display name."),
2894
- productType: import_zod15.z.enum(PRODUCT_TYPES).describe("Type of product. DIGITAL (e-courses, downloads), PHYSICAL (shipped goods), SERVICE (appointments, consultations), or PHYSICAL/DIGITAL (hybrid)."),
2895
- description: import_zod15.z.string().optional().describe("Product description / marketing copy."),
2896
- image: import_zod15.z.string().optional().describe("Primary product image URL."),
2897
- statementDescriptor: import_zod15.z.string().optional().describe("Up to 22 characters shown on the buyer's card statement."),
2898
- locationId: import_zod15.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
3023
+ name: import_zod16.z.string().describe("Product display name."),
3024
+ productType: import_zod16.z.enum(PRODUCT_TYPES).describe("Type of product. DIGITAL (e-courses, downloads), PHYSICAL (shipped goods), SERVICE (appointments, consultations), or PHYSICAL/DIGITAL (hybrid)."),
3025
+ description: import_zod16.z.string().optional().describe("Product description / marketing copy."),
3026
+ image: import_zod16.z.string().optional().describe("Primary product image URL."),
3027
+ statementDescriptor: import_zod16.z.string().optional().describe("Up to 22 characters shown on the buyer's card statement."),
3028
+ locationId: import_zod16.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
2899
3029
  },
2900
3030
  async ({ name, productType, description, image, statementDescriptor, locationId: locationId2 }) => {
2901
3031
  const resolved = client.resolveLocationId(locationId2);
@@ -2911,13 +3041,13 @@ function registerProductTools(server2, client) {
2911
3041
  "update_product",
2912
3042
  "Update an existing product. Pass only the fields you want to change \u2014 others are preserved. The product type and location can't be changed after creation.",
2913
3043
  {
2914
- productId: import_zod15.z.string().describe("The product ID to update."),
2915
- name: import_zod15.z.string().optional().describe("New product display name."),
2916
- description: import_zod15.z.string().optional().describe("New product description."),
2917
- image: import_zod15.z.string().optional().describe("New primary product image URL."),
2918
- statementDescriptor: import_zod15.z.string().optional().describe("Up to 22 characters shown on the buyer's card statement."),
2919
- productType: import_zod15.z.enum(PRODUCT_TYPES).optional().describe("Type of product (rarely changed after creation)."),
2920
- locationId: import_zod15.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
3044
+ productId: import_zod16.z.string().describe("The product ID to update."),
3045
+ name: import_zod16.z.string().optional().describe("New product display name."),
3046
+ description: import_zod16.z.string().optional().describe("New product description."),
3047
+ image: import_zod16.z.string().optional().describe("New primary product image URL."),
3048
+ statementDescriptor: import_zod16.z.string().optional().describe("Up to 22 characters shown on the buyer's card statement."),
3049
+ productType: import_zod16.z.enum(PRODUCT_TYPES).optional().describe("Type of product (rarely changed after creation)."),
3050
+ locationId: import_zod16.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
2921
3051
  },
2922
3052
  async ({ productId, name, description, image, statementDescriptor, productType, locationId: locationId2 }) => {
2923
3053
  const resolved = client.resolveLocationId(locationId2);
@@ -2936,9 +3066,9 @@ function registerProductTools(server2, client) {
2936
3066
  "delete_product",
2937
3067
  "Permanently delete a product. IRREVERSIBLE. Will also remove the product from any invoices, subscriptions, or membership offers that reference it \u2014 those will fail next time they run. Verify with `list_products` (or with an account export) before deleting.",
2938
3068
  {
2939
- productId: import_zod15.z.string().describe("The product ID to delete."),
2940
- confirm: import_zod15.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action."),
2941
- locationId: import_zod15.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
3069
+ productId: import_zod16.z.string().describe("The product ID to delete."),
3070
+ confirm: import_zod16.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action."),
3071
+ locationId: import_zod16.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
2942
3072
  },
2943
3073
  async ({ productId, locationId: locationId2 }) => {
2944
3074
  const resolved = client.resolveLocationId(locationId2);
@@ -2950,10 +3080,10 @@ function registerProductTools(server2, client) {
2950
3080
  "list_product_prices",
2951
3081
  "List all prices for a single product. Products can have multiple price points (one-time / recurring / tiered). Sub-account scope can READ prices but NOT write them \u2014 adding new prices currently requires going through the GHL UI.",
2952
3082
  {
2953
- productId: import_zod15.z.string().describe("The product ID."),
2954
- locationId: import_zod15.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var."),
2955
- limit: import_zod15.z.number().optional().describe("Max prices to return."),
2956
- offset: import_zod15.z.number().optional().describe("Skip this many for pagination.")
3083
+ productId: import_zod16.z.string().describe("The product ID."),
3084
+ locationId: import_zod16.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var."),
3085
+ limit: import_zod16.z.number().optional().describe("Max prices to return."),
3086
+ offset: import_zod16.z.number().optional().describe("Skip this many for pagination.")
2957
3087
  },
2958
3088
  async ({ productId, locationId: locationId2, limit, offset }) => {
2959
3089
  const resolved = client.resolveLocationId(locationId2);
@@ -2966,21 +3096,21 @@ function registerProductTools(server2, client) {
2966
3096
  }
2967
3097
 
2968
3098
  // src/tools/invoices.ts
2969
- var import_zod16 = require("zod");
3099
+ var import_zod17 = require("zod");
2970
3100
  function registerInvoiceTools(server2, client) {
2971
3101
  safeTool(
2972
3102
  server2,
2973
3103
  "list_invoices",
2974
3104
  "List invoices for a location. Offset-based pagination via limit/offset.",
2975
3105
  {
2976
- locationId: import_zod16.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
2977
- limit: import_zod16.z.number().optional().describe("Max number of invoices to return"),
2978
- offset: import_zod16.z.number().optional().describe("Offset for pagination"),
2979
- status: import_zod16.z.enum(["draft", "sent", "paid", "void", "partially_paid"]).optional().describe("Filter by invoice status"),
2980
- contactId: import_zod16.z.string().optional().describe("Filter by contact ID"),
2981
- startAt: import_zod16.z.string().optional().describe("Start date filter (ISO 8601)"),
2982
- endAt: import_zod16.z.string().optional().describe("End date filter (ISO 8601)"),
2983
- search: import_zod16.z.string().optional().describe("Search term")
3106
+ locationId: import_zod17.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3107
+ limit: import_zod17.z.number().optional().describe("Max number of invoices to return"),
3108
+ offset: import_zod17.z.number().optional().describe("Offset for pagination"),
3109
+ status: import_zod17.z.enum(["draft", "sent", "paid", "void", "partially_paid"]).optional().describe("Filter by invoice status"),
3110
+ contactId: import_zod17.z.string().optional().describe("Filter by contact ID"),
3111
+ startAt: import_zod17.z.string().optional().describe("Start date filter (ISO 8601)"),
3112
+ endAt: import_zod17.z.string().optional().describe("End date filter (ISO 8601)"),
3113
+ search: import_zod17.z.string().optional().describe("Search term")
2984
3114
  },
2985
3115
  async ({ locationId: locationId2, limit, offset, status, contactId, startAt, endAt, search }) => {
2986
3116
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3004,8 +3134,8 @@ function registerInvoiceTools(server2, client) {
3004
3134
  "get_invoice",
3005
3135
  "Get a specific invoice by ID",
3006
3136
  {
3007
- locationId: import_zod16.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3008
- invoiceId: import_zod16.z.string().describe("The invoice ID")
3137
+ locationId: import_zod17.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3138
+ invoiceId: import_zod17.z.string().describe("The invoice ID")
3009
3139
  },
3010
3140
  async ({ locationId: locationId2, invoiceId }) => {
3011
3141
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3021,22 +3151,22 @@ function registerInvoiceTools(server2, client) {
3021
3151
  "create_invoice",
3022
3152
  "Create a new invoice",
3023
3153
  {
3024
- locationId: import_zod16.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3025
- name: import_zod16.z.string().describe("Invoice name"),
3026
- contactId: import_zod16.z.string().describe("Contact ID for the invoice"),
3027
- items: import_zod16.z.array(import_zod16.z.object({
3028
- name: import_zod16.z.string().describe("Item name"),
3029
- description: import_zod16.z.string().describe("Item description"),
3030
- quantity: import_zod16.z.number().describe("Item quantity"),
3031
- price: import_zod16.z.number().describe("Item price"),
3032
- currency: import_zod16.z.string().describe("Currency code (e.g. USD)")
3154
+ locationId: import_zod17.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3155
+ name: import_zod17.z.string().describe("Invoice name"),
3156
+ contactId: import_zod17.z.string().describe("Contact ID for the invoice"),
3157
+ items: import_zod17.z.array(import_zod17.z.object({
3158
+ name: import_zod17.z.string().describe("Item name"),
3159
+ description: import_zod17.z.string().describe("Item description"),
3160
+ quantity: import_zod17.z.number().describe("Item quantity"),
3161
+ price: import_zod17.z.number().describe("Item price"),
3162
+ currency: import_zod17.z.string().describe("Currency code (e.g. USD)")
3033
3163
  })).describe("Invoice line items"),
3034
- discount: import_zod16.z.object({
3035
- type: import_zod16.z.string().optional(),
3036
- value: import_zod16.z.number().optional()
3164
+ discount: import_zod17.z.object({
3165
+ type: import_zod17.z.string().optional(),
3166
+ value: import_zod17.z.number().optional()
3037
3167
  }).optional().describe("Discount to apply"),
3038
- termsNotes: import_zod16.z.string().optional().describe("Terms and notes for the invoice"),
3039
- title: import_zod16.z.string().optional().describe("Invoice title")
3168
+ termsNotes: import_zod17.z.string().optional().describe("Terms and notes for the invoice"),
3169
+ title: import_zod17.z.string().optional().describe("Invoice title")
3040
3170
  },
3041
3171
  async ({ locationId: locationId2, name, contactId, items, discount, termsNotes, title }) => {
3042
3172
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3058,22 +3188,22 @@ function registerInvoiceTools(server2, client) {
3058
3188
  "update_invoice",
3059
3189
  "Update an existing invoice",
3060
3190
  {
3061
- locationId: import_zod16.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3062
- invoiceId: import_zod16.z.string().describe("The invoice ID to update"),
3063
- name: import_zod16.z.string().optional().describe("Invoice name"),
3064
- items: import_zod16.z.array(import_zod16.z.object({
3065
- name: import_zod16.z.string().describe("Item name"),
3066
- description: import_zod16.z.string().describe("Item description"),
3067
- quantity: import_zod16.z.number().describe("Item quantity"),
3068
- price: import_zod16.z.number().describe("Item price"),
3069
- currency: import_zod16.z.string().describe("Currency code (e.g. USD)")
3191
+ locationId: import_zod17.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3192
+ invoiceId: import_zod17.z.string().describe("The invoice ID to update"),
3193
+ name: import_zod17.z.string().optional().describe("Invoice name"),
3194
+ items: import_zod17.z.array(import_zod17.z.object({
3195
+ name: import_zod17.z.string().describe("Item name"),
3196
+ description: import_zod17.z.string().describe("Item description"),
3197
+ quantity: import_zod17.z.number().describe("Item quantity"),
3198
+ price: import_zod17.z.number().describe("Item price"),
3199
+ currency: import_zod17.z.string().describe("Currency code (e.g. USD)")
3070
3200
  })).optional().describe("Invoice line items"),
3071
- discount: import_zod16.z.object({
3072
- type: import_zod16.z.string().optional(),
3073
- value: import_zod16.z.number().optional()
3201
+ discount: import_zod17.z.object({
3202
+ type: import_zod17.z.string().optional(),
3203
+ value: import_zod17.z.number().optional()
3074
3204
  }).optional().describe("Discount to apply"),
3075
- termsNotes: import_zod16.z.string().optional().describe("Terms and notes for the invoice"),
3076
- title: import_zod16.z.string().optional().describe("Invoice title")
3205
+ termsNotes: import_zod17.z.string().optional().describe("Terms and notes for the invoice"),
3206
+ title: import_zod17.z.string().optional().describe("Invoice title")
3077
3207
  },
3078
3208
  async ({ locationId: locationId2, invoiceId, name, items, discount, termsNotes, title }) => {
3079
3209
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3094,8 +3224,8 @@ function registerInvoiceTools(server2, client) {
3094
3224
  "delete_invoice",
3095
3225
  "Delete an invoice",
3096
3226
  {
3097
- locationId: import_zod16.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3098
- invoiceId: import_zod16.z.string().describe("The invoice ID to delete")
3227
+ locationId: import_zod17.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3228
+ invoiceId: import_zod17.z.string().describe("The invoice ID to delete")
3099
3229
  },
3100
3230
  async ({ locationId: locationId2, invoiceId }) => {
3101
3231
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3111,8 +3241,8 @@ function registerInvoiceTools(server2, client) {
3111
3241
  "send_invoice",
3112
3242
  "Send an invoice to the contact",
3113
3243
  {
3114
- locationId: import_zod16.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3115
- invoiceId: import_zod16.z.string().describe("The invoice ID to send")
3244
+ locationId: import_zod17.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3245
+ invoiceId: import_zod17.z.string().describe("The invoice ID to send")
3116
3246
  },
3117
3247
  async ({ locationId: locationId2, invoiceId }) => {
3118
3248
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3128,8 +3258,8 @@ function registerInvoiceTools(server2, client) {
3128
3258
  "void_invoice",
3129
3259
  "Void an invoice",
3130
3260
  {
3131
- locationId: import_zod16.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3132
- invoiceId: import_zod16.z.string().describe("The invoice ID to void")
3261
+ locationId: import_zod17.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3262
+ invoiceId: import_zod17.z.string().describe("The invoice ID to void")
3133
3263
  },
3134
3264
  async ({ locationId: locationId2, invoiceId }) => {
3135
3265
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3145,11 +3275,11 @@ function registerInvoiceTools(server2, client) {
3145
3275
  "record_invoice_payment",
3146
3276
  "Record a manual payment for an invoice",
3147
3277
  {
3148
- locationId: import_zod16.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3149
- invoiceId: import_zod16.z.string().describe("The invoice ID"),
3150
- amount: import_zod16.z.number().describe("Payment amount"),
3151
- mode: import_zod16.z.enum(["cash", "cheque", "bank_transfer", "other"]).describe("Payment mode"),
3152
- notes: import_zod16.z.string().optional().describe("Payment notes")
3278
+ locationId: import_zod17.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3279
+ invoiceId: import_zod17.z.string().describe("The invoice ID"),
3280
+ amount: import_zod17.z.number().describe("Payment amount"),
3281
+ mode: import_zod17.z.enum(["cash", "cheque", "bank_transfer", "other"]).describe("Payment mode"),
3282
+ notes: import_zod17.z.string().optional().describe("Payment notes")
3153
3283
  },
3154
3284
  async ({ locationId: locationId2, invoiceId, amount, mode, notes }) => {
3155
3285
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3166,15 +3296,15 @@ function registerInvoiceTools(server2, client) {
3166
3296
  }
3167
3297
 
3168
3298
  // src/tools/campaigns.ts
3169
- var import_zod17 = require("zod");
3299
+ var import_zod18 = require("zod");
3170
3300
  function registerCampaignTools(server2, client) {
3171
3301
  safeTool(
3172
3302
  server2,
3173
3303
  "get_campaigns",
3174
3304
  "List campaigns for a location",
3175
3305
  {
3176
- locationId: import_zod17.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3177
- status: import_zod17.z.string().optional().describe("Filter by campaign status")
3306
+ locationId: import_zod18.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3307
+ status: import_zod18.z.string().optional().describe("Filter by campaign status")
3178
3308
  },
3179
3309
  async ({ locationId: locationId2, status }) => {
3180
3310
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3186,16 +3316,16 @@ function registerCampaignTools(server2, client) {
3186
3316
  }
3187
3317
 
3188
3318
  // src/tools/users.ts
3189
- var import_zod18 = require("zod");
3319
+ var import_zod19 = require("zod");
3190
3320
  function registerUserTools(server2, client) {
3191
3321
  safeTool(
3192
3322
  server2,
3193
3323
  "get_users",
3194
3324
  "List users for a location",
3195
3325
  {
3196
- locationId: import_zod18.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3197
- limit: import_zod18.z.number().optional().describe("Max number of users to return"),
3198
- skip: import_zod18.z.number().optional().describe("Number of users to skip")
3326
+ locationId: import_zod19.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3327
+ limit: import_zod19.z.number().optional().describe("Max number of users to return"),
3328
+ skip: import_zod19.z.number().optional().describe("Number of users to skip")
3199
3329
  },
3200
3330
  async ({ locationId: locationId2, limit, skip }) => {
3201
3331
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3210,7 +3340,7 @@ function registerUserTools(server2, client) {
3210
3340
  "get_user",
3211
3341
  "Get a single user by ID",
3212
3342
  {
3213
- userId: import_zod18.z.string().describe("The user ID")
3343
+ userId: import_zod19.z.string().describe("The user ID")
3214
3344
  },
3215
3345
  async ({ userId }) => {
3216
3346
  return client.get(`/users/${userId}`);
@@ -3219,19 +3349,19 @@ function registerUserTools(server2, client) {
3219
3349
  }
3220
3350
 
3221
3351
  // src/tools/media.ts
3222
- var import_zod19 = require("zod");
3352
+ var import_zod20 = require("zod");
3223
3353
  function registerMediaTools(server2, client) {
3224
3354
  safeTool(
3225
3355
  server2,
3226
3356
  "get_media_files",
3227
3357
  "List media files for a location",
3228
3358
  {
3229
- locationId: import_zod19.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3230
- sortBy: import_zod19.z.string().optional().describe("Field to sort by"),
3231
- sortOrder: import_zod19.z.enum(["asc", "desc"]).optional().describe("Sort order"),
3232
- limit: import_zod19.z.number().optional().describe("Max number of files to return"),
3233
- offset: import_zod19.z.number().optional().describe("Number of files to skip"),
3234
- query: import_zod19.z.string().optional().describe("Search query to filter files")
3359
+ locationId: import_zod20.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3360
+ sortBy: import_zod20.z.string().optional().describe("Field to sort by"),
3361
+ sortOrder: import_zod20.z.enum(["asc", "desc"]).optional().describe("Sort order"),
3362
+ limit: import_zod20.z.number().optional().describe("Max number of files to return"),
3363
+ offset: import_zod20.z.number().optional().describe("Number of files to skip"),
3364
+ query: import_zod20.z.string().optional().describe("Search query to filter files")
3235
3365
  },
3236
3366
  async ({ locationId: locationId2, sortBy, sortOrder, limit, offset, query }) => {
3237
3367
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3249,8 +3379,8 @@ function registerMediaTools(server2, client) {
3249
3379
  "delete_media_file",
3250
3380
  "Delete a media file",
3251
3381
  {
3252
- mediaId: import_zod19.z.string().describe("The media file ID to delete"),
3253
- locationId: import_zod19.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
3382
+ mediaId: import_zod20.z.string().describe("The media file ID to delete"),
3383
+ locationId: import_zod20.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
3254
3384
  },
3255
3385
  async ({ mediaId, locationId: locationId2 }) => {
3256
3386
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3262,20 +3392,20 @@ function registerMediaTools(server2, client) {
3262
3392
  }
3263
3393
 
3264
3394
  // src/tools/social-planner.ts
3265
- var import_zod20 = require("zod");
3395
+ var import_zod21 = require("zod");
3266
3396
  function registerSocialPlannerTools(server2, client) {
3267
3397
  safeTool(
3268
3398
  server2,
3269
3399
  "get_social_posts",
3270
3400
  "List social media posts for a location",
3271
3401
  {
3272
- locationId: import_zod20.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3273
- type: import_zod20.z.enum(["post", "story", "reel"]).optional().describe("Post type filter"),
3274
- accounts: import_zod20.z.string().optional().describe("Comma-separated account IDs to filter by"),
3275
- fromDate: import_zod20.z.string().optional().describe("Start date filter (ISO string)"),
3276
- toDate: import_zod20.z.string().optional().describe("End date filter (ISO string)"),
3277
- includeUsers: import_zod20.z.boolean().optional().describe("Whether to include user details"),
3278
- status: import_zod20.z.enum(["in_review", "scheduled", "published", "failed", "in_progress"]).optional().describe("Post status filter")
3402
+ locationId: import_zod21.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3403
+ type: import_zod21.z.enum(["post", "story", "reel"]).optional().describe("Post type filter"),
3404
+ accounts: import_zod21.z.string().optional().describe("Comma-separated account IDs to filter by"),
3405
+ fromDate: import_zod21.z.string().optional().describe("Start date filter (ISO string)"),
3406
+ toDate: import_zod21.z.string().optional().describe("End date filter (ISO string)"),
3407
+ includeUsers: import_zod21.z.boolean().optional().describe("Whether to include user details"),
3408
+ status: import_zod21.z.enum(["in_review", "scheduled", "published", "failed", "in_progress"]).optional().describe("Post status filter")
3279
3409
  },
3280
3410
  async ({ locationId: locationId2, type, accounts, fromDate, toDate, includeUsers, status }) => {
3281
3411
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3294,7 +3424,7 @@ function registerSocialPlannerTools(server2, client) {
3294
3424
  "get_social_post",
3295
3425
  "Get a single social media post by ID",
3296
3426
  {
3297
- postId: import_zod20.z.string().describe("The social media post ID")
3427
+ postId: import_zod21.z.string().describe("The social media post ID")
3298
3428
  },
3299
3429
  async ({ postId }) => {
3300
3430
  return client.get(`/social-media-posting/${postId}`);
@@ -3305,7 +3435,7 @@ function registerSocialPlannerTools(server2, client) {
3305
3435
  "delete_social_post",
3306
3436
  "Delete a social media post",
3307
3437
  {
3308
- postId: import_zod20.z.string().describe("The social media post ID to delete")
3438
+ postId: import_zod21.z.string().describe("The social media post ID to delete")
3309
3439
  },
3310
3440
  async ({ postId }) => {
3311
3441
  return client.delete(`/social-media-posting/${postId}`);
@@ -3315,7 +3445,7 @@ function registerSocialPlannerTools(server2, client) {
3315
3445
  "get_social_media_accounts",
3316
3446
  "Get connected social media accounts for a location",
3317
3447
  {
3318
- locationId: import_zod20.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
3448
+ locationId: import_zod21.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
3319
3449
  },
3320
3450
  async ({ locationId: locationId2 }) => {
3321
3451
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3341,17 +3471,17 @@ function registerSocialPlannerTools(server2, client) {
3341
3471
  "create_social_post",
3342
3472
  "Create a new social media post",
3343
3473
  {
3344
- locationId: import_zod20.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3345
- accountIds: import_zod20.z.array(import_zod20.z.string()).describe("Array of social account IDs to post to"),
3346
- summary: import_zod20.z.string().optional().describe("The post text/caption"),
3347
- media: import_zod20.z.array(import_zod20.z.string()).optional().describe("Array of media URLs to attach"),
3348
- status: import_zod20.z.enum(["in_review", "scheduled", "draft"]).optional().describe("Post status"),
3349
- scheduledAt: import_zod20.z.string().optional().describe("Scheduled publish time (ISO string)"),
3350
- tags: import_zod20.z.array(import_zod20.z.string()).optional().describe("Tags for the post"),
3351
- ogData: import_zod20.z.object({
3352
- title: import_zod20.z.string().optional(),
3353
- description: import_zod20.z.string().optional(),
3354
- image: import_zod20.z.string().optional()
3474
+ locationId: import_zod21.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3475
+ accountIds: import_zod21.z.array(import_zod21.z.string()).describe("Array of social account IDs to post to"),
3476
+ summary: import_zod21.z.string().optional().describe("The post text/caption"),
3477
+ media: import_zod21.z.array(import_zod21.z.string()).optional().describe("Array of media URLs to attach"),
3478
+ status: import_zod21.z.enum(["in_review", "scheduled", "draft"]).optional().describe("Post status"),
3479
+ scheduledAt: import_zod21.z.string().optional().describe("Scheduled publish time (ISO string)"),
3480
+ tags: import_zod21.z.array(import_zod21.z.string()).optional().describe("Tags for the post"),
3481
+ ogData: import_zod21.z.object({
3482
+ title: import_zod21.z.string().optional(),
3483
+ description: import_zod21.z.string().optional(),
3484
+ image: import_zod21.z.string().optional()
3355
3485
  }).optional().describe("Open Graph data for link previews")
3356
3486
  },
3357
3487
  async ({ locationId: locationId2, accountIds, summary, media, status, scheduledAt, tags, ogData }) => {
@@ -3369,16 +3499,16 @@ function registerSocialPlannerTools(server2, client) {
3369
3499
  }
3370
3500
 
3371
3501
  // src/tools/courses.ts
3372
- var import_zod21 = require("zod");
3502
+ var import_zod22 = require("zod");
3373
3503
  function registerCourseTools(server2, client) {
3374
3504
  safeTool(
3375
3505
  server2,
3376
3506
  "get_courses",
3377
3507
  "List courses for a location",
3378
3508
  {
3379
- locationId: import_zod21.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3380
- limit: import_zod21.z.number().optional().describe("Max number of courses to return"),
3381
- offset: import_zod21.z.number().optional().describe("Number of courses to skip")
3509
+ locationId: import_zod22.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3510
+ limit: import_zod22.z.number().optional().describe("Max number of courses to return"),
3511
+ offset: import_zod22.z.number().optional().describe("Number of courses to skip")
3382
3512
  },
3383
3513
  async ({ locationId: locationId2, limit, offset }) => {
3384
3514
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3391,14 +3521,14 @@ function registerCourseTools(server2, client) {
3391
3521
  }
3392
3522
 
3393
3523
  // src/tools/businesses.ts
3394
- var import_zod22 = require("zod");
3524
+ var import_zod23 = require("zod");
3395
3525
  function registerBusinessTools(server2, client) {
3396
3526
  safeTool(
3397
3527
  server2,
3398
3528
  "get_businesses",
3399
3529
  "List businesses for a location",
3400
3530
  {
3401
- locationId: import_zod22.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
3531
+ locationId: import_zod23.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
3402
3532
  },
3403
3533
  async ({ locationId: locationId2 }) => {
3404
3534
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3410,7 +3540,7 @@ function registerBusinessTools(server2, client) {
3410
3540
  "get_business",
3411
3541
  "Get a single business by ID",
3412
3542
  {
3413
- businessId: import_zod22.z.string().describe("The business ID")
3543
+ businessId: import_zod23.z.string().describe("The business ID")
3414
3544
  },
3415
3545
  async ({ businessId }) => {
3416
3546
  return client.get(`/businesses/${businessId}`);
@@ -3421,17 +3551,17 @@ function registerBusinessTools(server2, client) {
3421
3551
  "create_business",
3422
3552
  "Create a new business",
3423
3553
  {
3424
- locationId: import_zod22.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3425
- name: import_zod22.z.string().describe("Business name"),
3426
- phone: import_zod22.z.string().optional().describe("Phone number"),
3427
- email: import_zod22.z.string().optional().describe("Email address"),
3428
- website: import_zod22.z.string().optional().describe("Website URL"),
3429
- address: import_zod22.z.string().optional().describe("Street address"),
3430
- city: import_zod22.z.string().optional().describe("City"),
3431
- state: import_zod22.z.string().optional().describe("State"),
3432
- postalCode: import_zod22.z.string().optional().describe("Postal/ZIP code"),
3433
- country: import_zod22.z.string().optional().describe("Country"),
3434
- description: import_zod22.z.string().optional().describe("Business description")
3554
+ locationId: import_zod23.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3555
+ name: import_zod23.z.string().describe("Business name"),
3556
+ phone: import_zod23.z.string().optional().describe("Phone number"),
3557
+ email: import_zod23.z.string().optional().describe("Email address"),
3558
+ website: import_zod23.z.string().optional().describe("Website URL"),
3559
+ address: import_zod23.z.string().optional().describe("Street address"),
3560
+ city: import_zod23.z.string().optional().describe("City"),
3561
+ state: import_zod23.z.string().optional().describe("State"),
3562
+ postalCode: import_zod23.z.string().optional().describe("Postal/ZIP code"),
3563
+ country: import_zod23.z.string().optional().describe("Country"),
3564
+ description: import_zod23.z.string().optional().describe("Business description")
3435
3565
  },
3436
3566
  async ({ locationId: locationId2, name, phone, email, website, address, city, state, postalCode, country, description }) => {
3437
3567
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3453,17 +3583,17 @@ function registerBusinessTools(server2, client) {
3453
3583
  "update_business",
3454
3584
  "Update an existing business",
3455
3585
  {
3456
- businessId: import_zod22.z.string().describe("The business ID to update"),
3457
- name: import_zod22.z.string().optional().describe("Business name"),
3458
- phone: import_zod22.z.string().optional().describe("Phone number"),
3459
- email: import_zod22.z.string().optional().describe("Email address"),
3460
- website: import_zod22.z.string().optional().describe("Website URL"),
3461
- address: import_zod22.z.string().optional().describe("Street address"),
3462
- city: import_zod22.z.string().optional().describe("City"),
3463
- state: import_zod22.z.string().optional().describe("State"),
3464
- postalCode: import_zod22.z.string().optional().describe("Postal/ZIP code"),
3465
- country: import_zod22.z.string().optional().describe("Country"),
3466
- description: import_zod22.z.string().optional().describe("Business description")
3586
+ businessId: import_zod23.z.string().describe("The business ID to update"),
3587
+ name: import_zod23.z.string().optional().describe("Business name"),
3588
+ phone: import_zod23.z.string().optional().describe("Phone number"),
3589
+ email: import_zod23.z.string().optional().describe("Email address"),
3590
+ website: import_zod23.z.string().optional().describe("Website URL"),
3591
+ address: import_zod23.z.string().optional().describe("Street address"),
3592
+ city: import_zod23.z.string().optional().describe("City"),
3593
+ state: import_zod23.z.string().optional().describe("State"),
3594
+ postalCode: import_zod23.z.string().optional().describe("Postal/ZIP code"),
3595
+ country: import_zod23.z.string().optional().describe("Country"),
3596
+ description: import_zod23.z.string().optional().describe("Business description")
3467
3597
  },
3468
3598
  async ({ businessId, name, phone, email, website, address, city, state, postalCode, country, description }) => {
3469
3599
  const body = {};
@@ -3485,8 +3615,8 @@ function registerBusinessTools(server2, client) {
3485
3615
  "delete_business",
3486
3616
  "Permanently delete a business. IRREVERSIBLE.",
3487
3617
  {
3488
- businessId: import_zod22.z.string().describe("The business ID to delete"),
3489
- confirm: import_zod22.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
3618
+ businessId: import_zod23.z.string().describe("The business ID to delete"),
3619
+ confirm: import_zod23.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
3490
3620
  },
3491
3621
  async ({ businessId }) => {
3492
3622
  return client.delete(`/businesses/${businessId}`);
@@ -3495,17 +3625,17 @@ function registerBusinessTools(server2, client) {
3495
3625
  }
3496
3626
 
3497
3627
  // src/tools/blogs.ts
3498
- var import_zod23 = require("zod");
3628
+ var import_zod24 = require("zod");
3499
3629
  function registerBlogTools(server2, client) {
3500
3630
  safeTool(
3501
3631
  server2,
3502
3632
  "get_blog_posts",
3503
3633
  "List blog posts for a location. Offset-based pagination via limit/offset.",
3504
3634
  {
3505
- locationId: import_zod23.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3506
- limit: import_zod23.z.number().optional().describe("Number of posts to return"),
3507
- offset: import_zod23.z.number().optional().describe("Offset for pagination"),
3508
- status: import_zod23.z.enum(["published", "draft", "archived"]).optional().describe("Filter by post status")
3635
+ locationId: import_zod24.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3636
+ limit: import_zod24.z.number().optional().describe("Number of posts to return"),
3637
+ offset: import_zod24.z.number().optional().describe("Offset for pagination"),
3638
+ status: import_zod24.z.enum(["published", "draft", "archived"]).optional().describe("Filter by post status")
3509
3639
  },
3510
3640
  async ({ locationId: locationId2, limit, offset, status }) => {
3511
3641
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3523,8 +3653,8 @@ function registerBlogTools(server2, client) {
3523
3653
  "get_blog_post",
3524
3654
  "Get a specific blog post by ID",
3525
3655
  {
3526
- blogId: import_zod23.z.string().describe("Blog ID"),
3527
- postId: import_zod23.z.string().describe("Post ID")
3656
+ blogId: import_zod24.z.string().describe("Blog ID"),
3657
+ postId: import_zod24.z.string().describe("Post ID")
3528
3658
  },
3529
3659
  async ({ blogId, postId }) => {
3530
3660
  return client.get(`/blogs/${blogId}/posts/${postId}`, {});
@@ -3535,7 +3665,7 @@ function registerBlogTools(server2, client) {
3535
3665
  "get_blog_authors",
3536
3666
  "List blog authors for a location",
3537
3667
  {
3538
- locationId: import_zod23.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
3668
+ locationId: import_zod24.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
3539
3669
  },
3540
3670
  async ({ locationId: locationId2 }) => {
3541
3671
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3549,7 +3679,7 @@ function registerBlogTools(server2, client) {
3549
3679
  "get_blog_categories",
3550
3680
  "List blog categories for a location",
3551
3681
  {
3552
- locationId: import_zod23.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
3682
+ locationId: import_zod24.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
3553
3683
  },
3554
3684
  async ({ locationId: locationId2 }) => {
3555
3685
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3563,8 +3693,8 @@ function registerBlogTools(server2, client) {
3563
3693
  "check_blog_slug",
3564
3694
  "Check if a blog post URL slug already exists",
3565
3695
  {
3566
- locationId: import_zod23.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3567
- urlSlug: import_zod23.z.string().describe("URL slug to check")
3696
+ locationId: import_zod24.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
3697
+ urlSlug: import_zod24.z.string().describe("URL slug to check")
3568
3698
  },
3569
3699
  async ({ locationId: locationId2, urlSlug }) => {
3570
3700
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3576,7 +3706,7 @@ function registerBlogTools(server2, client) {
3576
3706
  }
3577
3707
 
3578
3708
  // src/tools/emails.ts
3579
- var import_zod24 = require("zod");
3709
+ var import_zod25 = require("zod");
3580
3710
  var TEMPLATE_TYPES = ["html", "folder", "import", "builder", "blank", "ai_template", "vibe-editor"];
3581
3711
  var EDITOR_TYPES = ["html", "builder"];
3582
3712
  function registerEmailTools(server2, client) {
@@ -3585,8 +3715,8 @@ function registerEmailTools(server2, client) {
3585
3715
  "get_email_campaigns",
3586
3716
  "List email campaigns / broadcasts (scheduled email sends) for a location. Returns each campaign's id, name, status (draft / scheduled / sent), templateId, send config, and stats. FIXED in v3.12.0: previously hit /emails/ (404); now correctly uses /emails/schedule. For automation campaigns (the older campaign-builder feature), use get_campaigns instead.",
3587
3717
  {
3588
- locationId: import_zod24.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)."),
3589
- limit: import_zod24.z.number().optional().describe("Max campaigns to return.")
3718
+ locationId: import_zod25.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)."),
3719
+ limit: import_zod25.z.number().optional().describe("Max campaigns to return.")
3590
3720
  },
3591
3721
  async ({ locationId: locationId2, limit }) => {
3592
3722
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3600,7 +3730,7 @@ function registerEmailTools(server2, client) {
3600
3730
  "list_email_templates",
3601
3731
  "List email templates ('builders') in a location. Templates power both standalone marketing emails and email actions inside workflows. Returns each template's id, name (display title), type, version, last-updated timestamp, and Firebase storage preview URL.",
3602
3732
  {
3603
- locationId: import_zod24.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set).")
3733
+ locationId: import_zod25.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set).")
3604
3734
  },
3605
3735
  async ({ locationId: locationId2 }) => {
3606
3736
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3614,9 +3744,9 @@ function registerEmailTools(server2, client) {
3614
3744
  "create_email_template",
3615
3745
  "Create a new email template (a 'builder' in GHL's API). Creates the metadata shell; use update_email_template to save HTML content into it. After creation, the response includes the template `id` which you'll use with update_email_template + when referencing the template from workflow email actions.",
3616
3746
  {
3617
- title: import_zod24.z.string().describe("Display name for the template (e.g., 'May Newsletter \u2014 V2'). Shown in the GHL UI. Note: GHL stores this as `name` on read but expects `title` on write."),
3618
- type: import_zod24.z.enum(TEMPLATE_TYPES).describe("Template kind. 'blank' = empty starting point. 'html' = raw HTML import. 'builder' = drag-and-drop builder. 'import' = imported from an external source. 'ai_template' / 'vibe-editor' = AI-generated. 'folder' = organizational folder (no content)."),
3619
- locationId: import_zod24.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
3747
+ title: import_zod25.z.string().describe("Display name for the template (e.g., 'May Newsletter \u2014 V2'). Shown in the GHL UI. Note: GHL stores this as `name` on read but expects `title` on write."),
3748
+ type: import_zod25.z.enum(TEMPLATE_TYPES).describe("Template kind. 'blank' = empty starting point. 'html' = raw HTML import. 'builder' = drag-and-drop builder. 'import' = imported from an external source. 'ai_template' / 'vibe-editor' = AI-generated. 'folder' = organizational folder (no content)."),
3749
+ locationId: import_zod25.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
3620
3750
  },
3621
3751
  async ({ title, type, locationId: locationId2 }) => {
3622
3752
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3630,10 +3760,10 @@ function registerEmailTools(server2, client) {
3630
3760
  "list_message_templates",
3631
3761
  "List snippet-style message templates in a location. Covers SMS, email snippets, and WhatsApp templates \u2014 pass the `type` param to filter. Different from `list_email_templates` (which returns drag-and-drop email-builder templates from a separate system). NOTE: This tool is READ-ONLY by design. Creating/updating/deleting templates at this endpoint requires a scope (`templates.write`) that GHL doesn't grant to Private Integration tokens. Buyers create message templates via the GHL UI (Conversations \u2192 Templates) or via an OAuth integration. This list endpoint works on a standard sub-account Private Integration key.",
3632
3762
  {
3633
- type: import_zod24.z.enum(["sms", "email", "whatsapp"]).optional().describe("Filter by template type. Omit to list all template types in one response. SMS templates are quick-reply text snippets used in the conversations composer. Email here means HTML-snippet templates (NOT email-builder drag-and-drop templates \u2014 those are listed via `list_email_templates`). WhatsApp templates are pre-approved message templates registered with Meta."),
3634
- limit: import_zod24.z.number().optional().describe("Max templates to return. Defaults to 1000."),
3635
- skip: import_zod24.z.number().optional().describe("Skip this many for pagination."),
3636
- locationId: import_zod24.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
3763
+ type: import_zod25.z.enum(["sms", "email", "whatsapp"]).optional().describe("Filter by template type. Omit to list all template types in one response. SMS templates are quick-reply text snippets used in the conversations composer. Email here means HTML-snippet templates (NOT email-builder drag-and-drop templates \u2014 those are listed via `list_email_templates`). WhatsApp templates are pre-approved message templates registered with Meta."),
3764
+ limit: import_zod25.z.number().optional().describe("Max templates to return. Defaults to 1000."),
3765
+ skip: import_zod25.z.number().optional().describe("Skip this many for pagination."),
3766
+ locationId: import_zod25.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
3637
3767
  },
3638
3768
  async ({ type, limit, skip, locationId: locationId2 }) => {
3639
3769
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3649,11 +3779,11 @@ function registerEmailTools(server2, client) {
3649
3779
  "update_email_template",
3650
3780
  "Save HTML content into an existing email template. Use this to update the body of a template after `create_email_template`. The `updatedBy` field is required by GHL; defaults to 'mcp' if not provided. Note: this updates CONTENT only. Renaming the title or deleting the template is not yet possible through the public API \u2014 do those in the GHL UI for now.",
3651
3781
  {
3652
- templateId: import_zod24.z.string().describe("The template ID to update (from create_email_template or list_email_templates)."),
3653
- html: import_zod24.z.string().describe("The full HTML body of the email. Can include merge fields like {{contact.first_name}}."),
3654
- editorType: import_zod24.z.enum(EDITOR_TYPES).describe("Which editor produced this content. 'html' for raw HTML; 'builder' if you're saving a drag-and-drop builder export. After this save, the template will be flagged as the chosen editorType in lists."),
3655
- updatedBy: import_zod24.z.string().optional().describe("Identifier of who's making the change (a user ID or label). Defaults to 'mcp' if omitted. Shown in the GHL audit log for this template."),
3656
- locationId: import_zod24.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
3782
+ templateId: import_zod25.z.string().describe("The template ID to update (from create_email_template or list_email_templates)."),
3783
+ html: import_zod25.z.string().describe("The full HTML body of the email. Can include merge fields like {{contact.first_name}}."),
3784
+ editorType: import_zod25.z.enum(EDITOR_TYPES).describe("Which editor produced this content. 'html' for raw HTML; 'builder' if you're saving a drag-and-drop builder export. After this save, the template will be flagged as the chosen editorType in lists."),
3785
+ updatedBy: import_zod25.z.string().optional().describe("Identifier of who's making the change (a user ID or label). Defaults to 'mcp' if omitted. Shown in the GHL audit log for this template."),
3786
+ locationId: import_zod25.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
3657
3787
  },
3658
3788
  async ({ templateId, html, editorType, updatedBy, locationId: locationId2 }) => {
3659
3789
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3671,14 +3801,14 @@ function registerEmailTools(server2, client) {
3671
3801
  }
3672
3802
 
3673
3803
  // src/tools/trigger-links.ts
3674
- var import_zod25 = require("zod");
3804
+ var import_zod26 = require("zod");
3675
3805
  function registerTriggerLinkTools(server2, client) {
3676
3806
  safeTool(
3677
3807
  server2,
3678
3808
  "get_trigger_links",
3679
3809
  "List trigger links (short tracked URLs) for a location.",
3680
3810
  {
3681
- locationId: import_zod25.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
3811
+ locationId: import_zod26.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
3682
3812
  },
3683
3813
  async ({ locationId: locationId2 }) => {
3684
3814
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3692,9 +3822,9 @@ function registerTriggerLinkTools(server2, client) {
3692
3822
  "create_trigger_link",
3693
3823
  "Create a new trigger link. The link's shortened URL + auto-generated tracking key are returned in the response. Use the link in emails, SMS, social posts, etc.; when contacts click it, GHL fires the workflow trigger type `trigger_link` for any workflow that filters on this link's id.",
3694
3824
  {
3695
- name: import_zod25.z.string().describe("Display name in the GHL UI (e.g., 'May Newsletter \u2014 CTA'). Not visible to recipients."),
3696
- redirectTo: import_zod25.z.string().describe("Destination URL the link should redirect to. Either a static URL (https://example.com) or a contact merge field (e.g., '{{contact.website}}')."),
3697
- locationId: import_zod25.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
3825
+ name: import_zod26.z.string().describe("Display name in the GHL UI (e.g., 'May Newsletter \u2014 CTA'). Not visible to recipients."),
3826
+ redirectTo: import_zod26.z.string().describe("Destination URL the link should redirect to. Either a static URL (https://example.com) or a contact merge field (e.g., '{{contact.website}}')."),
3827
+ locationId: import_zod26.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
3698
3828
  },
3699
3829
  async ({ name, redirectTo, locationId: locationId2 }) => {
3700
3830
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3708,9 +3838,9 @@ function registerTriggerLinkTools(server2, client) {
3708
3838
  "update_trigger_link",
3709
3839
  "Update an existing trigger link's display name or redirect destination. The link's tracking key + short URL stay the same \u2014 buyers who already clicked the link still count, and any workflow filtering on this link's id keeps working.",
3710
3840
  {
3711
- linkId: import_zod25.z.string().describe("The trigger link ID to update."),
3712
- name: import_zod25.z.string().optional().describe("New display name. Pass to change; omit to keep current."),
3713
- redirectTo: import_zod25.z.string().optional().describe("New destination URL. Pass to change; omit to keep current.")
3841
+ linkId: import_zod26.z.string().describe("The trigger link ID to update."),
3842
+ name: import_zod26.z.string().optional().describe("New display name. Pass to change; omit to keep current."),
3843
+ redirectTo: import_zod26.z.string().optional().describe("New destination URL. Pass to change; omit to keep current.")
3714
3844
  },
3715
3845
  async ({ linkId, name, redirectTo }) => {
3716
3846
  const body = {};
@@ -3727,9 +3857,9 @@ function registerTriggerLinkTools(server2, client) {
3727
3857
  "delete_trigger_link",
3728
3858
  "Permanently delete a trigger link. IRREVERSIBLE. The link's short URL stops working immediately \u2014 anyone who clicks it after deletion lands on a 404. Any workflow triggers that filter on this link's id will never fire again.",
3729
3859
  {
3730
- linkId: import_zod25.z.string().describe("The trigger link ID to delete."),
3731
- confirm: import_zod25.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action."),
3732
- locationId: import_zod25.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
3860
+ linkId: import_zod26.z.string().describe("The trigger link ID to delete."),
3861
+ confirm: import_zod26.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action."),
3862
+ locationId: import_zod26.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
3733
3863
  },
3734
3864
  async ({ linkId, locationId: locationId2 }) => {
3735
3865
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3741,14 +3871,14 @@ function registerTriggerLinkTools(server2, client) {
3741
3871
  }
3742
3872
 
3743
3873
  // src/tools/custom-objects.ts
3744
- var import_zod26 = require("zod");
3874
+ var import_zod27 = require("zod");
3745
3875
  function registerCustomObjectTools(server2, client) {
3746
3876
  safeTool(
3747
3877
  server2,
3748
3878
  "list_custom_objects",
3749
3879
  "List all custom object schemas defined in a GHL location.",
3750
3880
  {
3751
- locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
3881
+ locationId: import_zod27.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
3752
3882
  },
3753
3883
  async ({ locationId: locationId2 }) => {
3754
3884
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3762,8 +3892,8 @@ function registerCustomObjectTools(server2, client) {
3762
3892
  "get_custom_object",
3763
3893
  "Retrieve a single custom object schema by its key.",
3764
3894
  {
3765
- schemaKey: import_zod26.z.string().describe("The key of the custom object schema to retrieve."),
3766
- locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
3895
+ schemaKey: import_zod27.z.string().describe("The key of the custom object schema to retrieve."),
3896
+ locationId: import_zod27.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
3767
3897
  },
3768
3898
  async ({ schemaKey, locationId: locationId2 }) => {
3769
3899
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3777,11 +3907,11 @@ function registerCustomObjectTools(server2, client) {
3777
3907
  "search_custom_object_records",
3778
3908
  "Search records of a custom object by schema key. Supports filtering and pagination.",
3779
3909
  {
3780
- schemaKey: import_zod26.z.string().describe("The custom object schema key."),
3781
- locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
3782
- query: import_zod26.z.string().optional().describe("Search query to filter records."),
3783
- limit: import_zod26.z.number().optional().describe("Maximum records to return. Defaults to 20."),
3784
- offset: import_zod26.z.number().optional().describe("Number of records to skip for pagination.")
3910
+ schemaKey: import_zod27.z.string().describe("The custom object schema key."),
3911
+ locationId: import_zod27.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
3912
+ query: import_zod27.z.string().optional().describe("Search query to filter records."),
3913
+ limit: import_zod27.z.number().optional().describe("Maximum records to return. Defaults to 20."),
3914
+ offset: import_zod27.z.number().optional().describe("Number of records to skip for pagination.")
3785
3915
  },
3786
3916
  async ({ schemaKey, locationId: locationId2, query, limit, offset }) => {
3787
3917
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3800,9 +3930,9 @@ function registerCustomObjectTools(server2, client) {
3800
3930
  "get_custom_object_record",
3801
3931
  "Retrieve a single custom object record by schema key and record ID.",
3802
3932
  {
3803
- schemaKey: import_zod26.z.string().describe("The custom object schema key."),
3804
- recordId: import_zod26.z.string().describe("The record ID to retrieve."),
3805
- locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
3933
+ schemaKey: import_zod27.z.string().describe("The custom object schema key."),
3934
+ recordId: import_zod27.z.string().describe("The record ID to retrieve."),
3935
+ locationId: import_zod27.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
3806
3936
  },
3807
3937
  async ({ schemaKey, recordId, locationId: locationId2 }) => {
3808
3938
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3816,9 +3946,9 @@ function registerCustomObjectTools(server2, client) {
3816
3946
  "create_custom_object_record",
3817
3947
  "Create a new record for a custom object.",
3818
3948
  {
3819
- schemaKey: import_zod26.z.string().describe("The custom object schema key."),
3820
- locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
3821
- properties: import_zod26.z.record(import_zod26.z.unknown()).describe("Key-value pairs of field values for the new record.")
3949
+ schemaKey: import_zod27.z.string().describe("The custom object schema key."),
3950
+ locationId: import_zod27.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
3951
+ properties: import_zod27.z.record(import_zod27.z.unknown()).describe("Key-value pairs of field values for the new record.")
3822
3952
  },
3823
3953
  async ({ schemaKey, locationId: locationId2, properties }) => {
3824
3954
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3832,10 +3962,10 @@ function registerCustomObjectTools(server2, client) {
3832
3962
  "update_custom_object_record",
3833
3963
  "Update an existing custom object record.",
3834
3964
  {
3835
- schemaKey: import_zod26.z.string().describe("The custom object schema key."),
3836
- recordId: import_zod26.z.string().describe("The record ID to update."),
3837
- locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
3838
- properties: import_zod26.z.record(import_zod26.z.unknown()).describe("Key-value pairs of field values to update.")
3965
+ schemaKey: import_zod27.z.string().describe("The custom object schema key."),
3966
+ recordId: import_zod27.z.string().describe("The record ID to update."),
3967
+ locationId: import_zod27.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
3968
+ properties: import_zod27.z.record(import_zod27.z.unknown()).describe("Key-value pairs of field values to update.")
3839
3969
  },
3840
3970
  async ({ schemaKey, recordId, locationId: locationId2, properties }) => {
3841
3971
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3849,9 +3979,9 @@ function registerCustomObjectTools(server2, client) {
3849
3979
  "delete_custom_object_record",
3850
3980
  "Delete a custom object record by schema key and record ID.",
3851
3981
  {
3852
- schemaKey: import_zod26.z.string().describe("The custom object schema key."),
3853
- recordId: import_zod26.z.string().describe("The record ID to delete."),
3854
- locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
3982
+ schemaKey: import_zod27.z.string().describe("The custom object schema key."),
3983
+ recordId: import_zod27.z.string().describe("The record ID to delete."),
3984
+ locationId: import_zod27.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
3855
3985
  },
3856
3986
  async ({ schemaKey, recordId, locationId: locationId2 }) => {
3857
3987
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3863,16 +3993,16 @@ function registerCustomObjectTools(server2, client) {
3863
3993
  }
3864
3994
 
3865
3995
  // src/tools/associations.ts
3866
- var import_zod27 = require("zod");
3996
+ var import_zod28 = require("zod");
3867
3997
  function registerAssociationTools(server2, client) {
3868
3998
  safeTool(
3869
3999
  server2,
3870
4000
  "list_associations",
3871
4001
  "List associations for a custom object record \u2014 shows related contacts, opportunities, or other records.",
3872
4002
  {
3873
- schemaKey: import_zod27.z.string().describe("The custom object schema key."),
3874
- recordId: import_zod27.z.string().describe("The record ID to list associations for."),
3875
- locationId: import_zod27.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4003
+ schemaKey: import_zod28.z.string().describe("The custom object schema key."),
4004
+ recordId: import_zod28.z.string().describe("The record ID to list associations for."),
4005
+ locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
3876
4006
  },
3877
4007
  async ({ schemaKey, recordId, locationId: locationId2 }) => {
3878
4008
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3887,11 +4017,11 @@ function registerAssociationTools(server2, client) {
3887
4017
  "create_association",
3888
4018
  "Create an association between a custom object record and another entity (contact, opportunity, or another custom object record).",
3889
4019
  {
3890
- schemaKey: import_zod27.z.string().describe("The custom object schema key of the source record."),
3891
- recordId: import_zod27.z.string().describe("The source record ID."),
3892
- locationId: import_zod27.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
3893
- targetEntityType: import_zod27.z.string().describe("The target entity type (e.g. 'contact', 'opportunity', or a custom object schema key)."),
3894
- targetEntityId: import_zod27.z.string().describe("The ID of the target entity to associate with.")
4020
+ schemaKey: import_zod28.z.string().describe("The custom object schema key of the source record."),
4021
+ recordId: import_zod28.z.string().describe("The source record ID."),
4022
+ locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
4023
+ targetEntityType: import_zod28.z.string().describe("The target entity type (e.g. 'contact', 'opportunity', or a custom object schema key)."),
4024
+ targetEntityId: import_zod28.z.string().describe("The ID of the target entity to associate with.")
3895
4025
  },
3896
4026
  async ({ schemaKey, recordId, locationId: locationId2, targetEntityType, targetEntityId }) => {
3897
4027
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3912,10 +4042,10 @@ function registerAssociationTools(server2, client) {
3912
4042
  "delete_association",
3913
4043
  "Remove an association between a custom object record and another entity.",
3914
4044
  {
3915
- schemaKey: import_zod27.z.string().describe("The custom object schema key of the source record."),
3916
- recordId: import_zod27.z.string().describe("The source record ID."),
3917
- associationId: import_zod27.z.string().describe("The association ID to remove."),
3918
- locationId: import_zod27.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4045
+ schemaKey: import_zod28.z.string().describe("The custom object schema key of the source record."),
4046
+ recordId: import_zod28.z.string().describe("The source record ID."),
4047
+ associationId: import_zod28.z.string().describe("The association ID to remove."),
4048
+ locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
3919
4049
  },
3920
4050
  async ({ schemaKey, recordId, associationId, locationId: locationId2 }) => {
3921
4051
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3928,18 +4058,18 @@ function registerAssociationTools(server2, client) {
3928
4058
  }
3929
4059
 
3930
4060
  // src/tools/estimates.ts
3931
- var import_zod28 = require("zod");
4061
+ var import_zod29 = require("zod");
3932
4062
  function registerEstimateTools(server2, client) {
3933
4063
  safeTool(
3934
4064
  server2,
3935
4065
  "list_estimates",
3936
4066
  "List estimates/quotes in a GHL location. Supports pagination and filtering by status.",
3937
4067
  {
3938
- locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
3939
- status: import_zod28.z.string().optional().describe("Filter by status (e.g. 'draft', 'sent', 'accepted', 'declined')."),
3940
- limit: import_zod28.z.number().optional().describe("Maximum estimates to return. Defaults to 20."),
3941
- offset: import_zod28.z.number().optional().describe("Number of records to skip for pagination."),
3942
- contactId: import_zod28.z.string().optional().describe("Filter estimates by contact ID.")
4068
+ locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
4069
+ status: import_zod29.z.string().optional().describe("Filter by status (e.g. 'draft', 'sent', 'accepted', 'declined')."),
4070
+ limit: import_zod29.z.number().optional().describe("Maximum estimates to return. Defaults to 20."),
4071
+ offset: import_zod29.z.number().optional().describe("Number of records to skip for pagination."),
4072
+ contactId: import_zod29.z.string().optional().describe("Filter estimates by contact ID.")
3943
4073
  },
3944
4074
  async ({ locationId: locationId2, status, limit, offset, contactId }) => {
3945
4075
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3960,8 +4090,8 @@ function registerEstimateTools(server2, client) {
3960
4090
  "get_estimate",
3961
4091
  "Retrieve a single estimate/quote by its ID.",
3962
4092
  {
3963
- estimateId: import_zod28.z.string().describe("The estimate ID to retrieve."),
3964
- locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4093
+ estimateId: import_zod29.z.string().describe("The estimate ID to retrieve."),
4094
+ locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
3965
4095
  },
3966
4096
  async ({ estimateId, locationId: locationId2 }) => {
3967
4097
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -3975,12 +4105,12 @@ function registerEstimateTools(server2, client) {
3975
4105
  "create_estimate",
3976
4106
  "Create a new estimate/quote for a contact.",
3977
4107
  {
3978
- locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
3979
- contactId: import_zod28.z.string().describe("The contact ID this estimate is for."),
3980
- name: import_zod28.z.string().describe("Estimate name/title."),
3981
- title: import_zod28.z.string().optional().describe("Display title for the estimate."),
3982
- items: import_zod28.z.array(import_zod28.z.record(import_zod28.z.unknown())).describe("Line items array. Each item should have name, description, price, qty."),
3983
- discount: import_zod28.z.record(import_zod28.z.unknown()).optional().describe("Discount object (type, value).")
4108
+ locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
4109
+ contactId: import_zod29.z.string().describe("The contact ID this estimate is for."),
4110
+ name: import_zod29.z.string().describe("Estimate name/title."),
4111
+ title: import_zod29.z.string().optional().describe("Display title for the estimate."),
4112
+ items: import_zod29.z.array(import_zod29.z.record(import_zod29.z.unknown())).describe("Line items array. Each item should have name, description, price, qty."),
4113
+ discount: import_zod29.z.record(import_zod29.z.unknown()).optional().describe("Discount object (type, value).")
3984
4114
  },
3985
4115
  async ({ locationId: locationId2, contactId, name, title, items, discount }) => {
3986
4116
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -4002,12 +4132,12 @@ function registerEstimateTools(server2, client) {
4002
4132
  "update_estimate",
4003
4133
  "Update an existing estimate/quote.",
4004
4134
  {
4005
- estimateId: import_zod28.z.string().describe("The estimate ID to update."),
4006
- locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
4007
- name: import_zod28.z.string().optional().describe("Updated estimate name."),
4008
- title: import_zod28.z.string().optional().describe("Updated display title."),
4009
- items: import_zod28.z.array(import_zod28.z.record(import_zod28.z.unknown())).optional().describe("Updated line items array."),
4010
- discount: import_zod28.z.record(import_zod28.z.unknown()).optional().describe("Updated discount object.")
4135
+ estimateId: import_zod29.z.string().describe("The estimate ID to update."),
4136
+ locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
4137
+ name: import_zod29.z.string().optional().describe("Updated estimate name."),
4138
+ title: import_zod29.z.string().optional().describe("Updated display title."),
4139
+ items: import_zod29.z.array(import_zod29.z.record(import_zod29.z.unknown())).optional().describe("Updated line items array."),
4140
+ discount: import_zod29.z.record(import_zod29.z.unknown()).optional().describe("Updated discount object.")
4011
4141
  },
4012
4142
  async ({ estimateId, locationId: locationId2, name, title, items, discount }) => {
4013
4143
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -4027,8 +4157,8 @@ function registerEstimateTools(server2, client) {
4027
4157
  "delete_estimate",
4028
4158
  "Delete an estimate/quote by ID.",
4029
4159
  {
4030
- estimateId: import_zod28.z.string().describe("The estimate ID to delete."),
4031
- locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4160
+ estimateId: import_zod29.z.string().describe("The estimate ID to delete."),
4161
+ locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4032
4162
  },
4033
4163
  async ({ estimateId, locationId: locationId2 }) => {
4034
4164
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -4042,8 +4172,8 @@ function registerEstimateTools(server2, client) {
4042
4172
  "send_estimate",
4043
4173
  "Send an estimate to the contact via email.",
4044
4174
  {
4045
- estimateId: import_zod28.z.string().describe("The estimate ID to send."),
4046
- locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4175
+ estimateId: import_zod29.z.string().describe("The estimate ID to send."),
4176
+ locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4047
4177
  },
4048
4178
  async ({ estimateId, locationId: locationId2 }) => {
4049
4179
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -4055,14 +4185,14 @@ function registerEstimateTools(server2, client) {
4055
4185
  }
4056
4186
 
4057
4187
  // src/tools/coupons.ts
4058
- var import_zod29 = require("zod");
4188
+ var import_zod30 = require("zod");
4059
4189
  function registerCouponTools(server2, client) {
4060
4190
  safeTool(
4061
4191
  server2,
4062
4192
  "list_coupons",
4063
4193
  "List coupons/promo codes in a GHL location.",
4064
4194
  {
4065
- locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4195
+ locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4066
4196
  },
4067
4197
  async ({ locationId: locationId2 }) => {
4068
4198
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -4076,8 +4206,8 @@ function registerCouponTools(server2, client) {
4076
4206
  "get_coupon",
4077
4207
  "Retrieve a single coupon by its ID.",
4078
4208
  {
4079
- couponId: import_zod29.z.string().describe("The coupon ID to retrieve."),
4080
- locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4209
+ couponId: import_zod30.z.string().describe("The coupon ID to retrieve."),
4210
+ locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4081
4211
  },
4082
4212
  async ({ couponId, locationId: locationId2 }) => {
4083
4213
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -4091,14 +4221,14 @@ function registerCouponTools(server2, client) {
4091
4221
  "create_coupon",
4092
4222
  "Create a new coupon/promo code.",
4093
4223
  {
4094
- locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
4095
- name: import_zod29.z.string().describe("Coupon name."),
4096
- code: import_zod29.z.string().describe("Promo code string customers enter."),
4097
- type: import_zod29.z.string().describe("Discount type: 'percentage' or 'fixed'."),
4098
- amount: import_zod29.z.number().describe("Discount amount (percentage value or fixed dollar amount)."),
4099
- duration: import_zod29.z.string().optional().describe("Duration: 'once', 'repeating', or 'forever'. Defaults to 'once'."),
4100
- durationInMonths: import_zod29.z.number().optional().describe("Number of months if duration is 'repeating'."),
4101
- productIds: import_zod29.z.array(import_zod29.z.string()).optional().describe("Product IDs this coupon applies to. If empty, applies to all.")
4224
+ locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
4225
+ name: import_zod30.z.string().describe("Coupon name."),
4226
+ code: import_zod30.z.string().describe("Promo code string customers enter."),
4227
+ type: import_zod30.z.string().describe("Discount type: 'percentage' or 'fixed'."),
4228
+ amount: import_zod30.z.number().describe("Discount amount (percentage value or fixed dollar amount)."),
4229
+ duration: import_zod30.z.string().optional().describe("Duration: 'once', 'repeating', or 'forever'. Defaults to 'once'."),
4230
+ durationInMonths: import_zod30.z.number().optional().describe("Number of months if duration is 'repeating'."),
4231
+ productIds: import_zod30.z.array(import_zod30.z.string()).optional().describe("Product IDs this coupon applies to. If empty, applies to all.")
4102
4232
  },
4103
4233
  async ({ locationId: locationId2, name, code, type, amount, duration, durationInMonths, productIds }) => {
4104
4234
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -4122,10 +4252,10 @@ function registerCouponTools(server2, client) {
4122
4252
  "update_coupon",
4123
4253
  "Update an existing coupon.",
4124
4254
  {
4125
- couponId: import_zod29.z.string().describe("The coupon ID to update."),
4126
- locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
4127
- name: import_zod29.z.string().optional().describe("Updated coupon name."),
4128
- productIds: import_zod29.z.array(import_zod29.z.string()).optional().describe("Updated product IDs this coupon applies to.")
4255
+ couponId: import_zod30.z.string().describe("The coupon ID to update."),
4256
+ locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
4257
+ name: import_zod30.z.string().optional().describe("Updated coupon name."),
4258
+ productIds: import_zod30.z.array(import_zod30.z.string()).optional().describe("Updated product IDs this coupon applies to.")
4129
4259
  },
4130
4260
  async ({ couponId, locationId: locationId2, name, productIds }) => {
4131
4261
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -4143,8 +4273,8 @@ function registerCouponTools(server2, client) {
4143
4273
  "delete_coupon",
4144
4274
  "Delete a coupon by ID.",
4145
4275
  {
4146
- couponId: import_zod29.z.string().describe("The coupon ID to delete."),
4147
- locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4276
+ couponId: import_zod30.z.string().describe("The coupon ID to delete."),
4277
+ locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4148
4278
  },
4149
4279
  async ({ couponId, locationId: locationId2 }) => {
4150
4280
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -4156,14 +4286,14 @@ function registerCouponTools(server2, client) {
4156
4286
  }
4157
4287
 
4158
4288
  // src/tools/webhooks.ts
4159
- var import_zod30 = require("zod");
4289
+ var import_zod31 = require("zod");
4160
4290
  function registerWebhookTools(server2, client) {
4161
4291
  safeTool(
4162
4292
  server2,
4163
4293
  "list_webhooks",
4164
4294
  "List all webhooks configured in a GHL location.",
4165
4295
  {
4166
- locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4296
+ locationId: import_zod31.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4167
4297
  },
4168
4298
  async ({ locationId: locationId2 }) => {
4169
4299
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -4177,8 +4307,8 @@ function registerWebhookTools(server2, client) {
4177
4307
  "get_webhook",
4178
4308
  "Retrieve a single webhook by its ID.",
4179
4309
  {
4180
- webhookId: import_zod30.z.string().describe("The webhook ID to retrieve."),
4181
- locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4310
+ webhookId: import_zod31.z.string().describe("The webhook ID to retrieve."),
4311
+ locationId: import_zod31.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4182
4312
  },
4183
4313
  async ({ webhookId, locationId: locationId2 }) => {
4184
4314
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -4192,10 +4322,10 @@ function registerWebhookTools(server2, client) {
4192
4322
  "create_webhook",
4193
4323
  "Create a new webhook subscription for GHL events.",
4194
4324
  {
4195
- locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
4196
- name: import_zod30.z.string().describe("Webhook name."),
4197
- url: import_zod30.z.string().describe("The URL to POST events to."),
4198
- events: import_zod30.z.array(import_zod30.z.string()).describe(
4325
+ locationId: import_zod31.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
4326
+ name: import_zod31.z.string().describe("Webhook name."),
4327
+ url: import_zod31.z.string().describe("The URL to POST events to."),
4328
+ events: import_zod31.z.array(import_zod31.z.string()).describe(
4199
4329
  "List of event types to subscribe to (e.g. 'ContactCreate', 'AppointmentCreate', 'OpportunityStatusUpdate')."
4200
4330
  )
4201
4331
  },
@@ -4216,11 +4346,11 @@ function registerWebhookTools(server2, client) {
4216
4346
  "update_webhook",
4217
4347
  "Update an existing webhook (name, URL, or subscribed events).",
4218
4348
  {
4219
- webhookId: import_zod30.z.string().describe("The webhook ID to update."),
4220
- locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
4221
- name: import_zod30.z.string().optional().describe("Updated webhook name."),
4222
- url: import_zod30.z.string().optional().describe("Updated webhook URL."),
4223
- events: import_zod30.z.array(import_zod30.z.string()).optional().describe("Updated list of event types.")
4349
+ webhookId: import_zod31.z.string().describe("The webhook ID to update."),
4350
+ locationId: import_zod31.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
4351
+ name: import_zod31.z.string().optional().describe("Updated webhook name."),
4352
+ url: import_zod31.z.string().optional().describe("Updated webhook URL."),
4353
+ events: import_zod31.z.array(import_zod31.z.string()).optional().describe("Updated list of event types.")
4224
4354
  },
4225
4355
  async ({ webhookId, locationId: locationId2, name, url, events }) => {
4226
4356
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -4236,8 +4366,8 @@ function registerWebhookTools(server2, client) {
4236
4366
  "delete_webhook",
4237
4367
  "Delete a webhook subscription by ID.",
4238
4368
  {
4239
- webhookId: import_zod30.z.string().describe("The webhook ID to delete."),
4240
- locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4369
+ webhookId: import_zod31.z.string().describe("The webhook ID to delete."),
4370
+ locationId: import_zod31.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4241
4371
  },
4242
4372
  async ({ webhookId, locationId: locationId2 }) => {
4243
4373
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -4249,16 +4379,16 @@ function registerWebhookTools(server2, client) {
4249
4379
  }
4250
4380
 
4251
4381
  // src/tools/documents.ts
4252
- var import_zod31 = require("zod");
4382
+ var import_zod32 = require("zod");
4253
4383
  function registerDocumentTools(server2, client) {
4254
4384
  safeTool(
4255
4385
  server2,
4256
4386
  "list_documents",
4257
4387
  "List documents and contracts in a GHL location. Supports pagination.",
4258
4388
  {
4259
- locationId: import_zod31.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
4260
- limit: import_zod31.z.number().optional().describe("Maximum documents to return. Defaults to 20."),
4261
- offset: import_zod31.z.number().optional().describe("Number of records to skip for pagination.")
4389
+ locationId: import_zod32.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
4390
+ limit: import_zod32.z.number().optional().describe("Maximum documents to return. Defaults to 20."),
4391
+ offset: import_zod32.z.number().optional().describe("Number of records to skip for pagination.")
4262
4392
  },
4263
4393
  async ({ locationId: locationId2, limit, offset }) => {
4264
4394
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -4276,8 +4406,8 @@ function registerDocumentTools(server2, client) {
4276
4406
  "get_document",
4277
4407
  "Retrieve a single document or contract by its ID, including signature status.",
4278
4408
  {
4279
- documentId: import_zod31.z.string().describe("The document ID to retrieve."),
4280
- locationId: import_zod31.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4409
+ documentId: import_zod32.z.string().describe("The document ID to retrieve."),
4410
+ locationId: import_zod32.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4281
4411
  },
4282
4412
  async ({ documentId, locationId: locationId2 }) => {
4283
4413
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -4291,8 +4421,8 @@ function registerDocumentTools(server2, client) {
4291
4421
  "delete_document",
4292
4422
  "Delete a document or contract by ID.",
4293
4423
  {
4294
- documentId: import_zod31.z.string().describe("The document ID to delete."),
4295
- locationId: import_zod31.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4424
+ documentId: import_zod32.z.string().describe("The document ID to delete."),
4425
+ locationId: import_zod32.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4296
4426
  },
4297
4427
  async ({ documentId, locationId: locationId2 }) => {
4298
4428
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -4306,9 +4436,9 @@ function registerDocumentTools(server2, client) {
4306
4436
  "send_document",
4307
4437
  "Send a document/contract to a contact for electronic signature.",
4308
4438
  {
4309
- documentId: import_zod31.z.string().describe("The document ID to send."),
4310
- contactId: import_zod31.z.string().describe("The contact ID to send the document to."),
4311
- locationId: import_zod31.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4439
+ documentId: import_zod32.z.string().describe("The document ID to send."),
4440
+ contactId: import_zod32.z.string().describe("The contact ID to send the document to."),
4441
+ locationId: import_zod32.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
4312
4442
  },
4313
4443
  async ({ documentId, contactId, locationId: locationId2 }) => {
4314
4444
  const resolvedLocationId = client.resolveLocationId(locationId2);
@@ -4320,19 +4450,19 @@ function registerDocumentTools(server2, client) {
4320
4450
  }
4321
4451
 
4322
4452
  // src/tools/workflow-builder.ts
4323
- var import_zod32 = require("zod");
4324
- var ActionSchema = import_zod32.z.object({
4325
- id: import_zod32.z.string().optional().describe("Action ID (auto-generated if omitted)."),
4326
- name: import_zod32.z.string().describe("Display name for this action step."),
4327
- type: import_zod32.z.string().describe("Action type."),
4328
- attributes: import_zod32.z.record(import_zod32.z.unknown()).optional().describe("Action-specific configuration."),
4329
- next: import_zod32.z.union([import_zod32.z.string(), import_zod32.z.array(import_zod32.z.string())]).optional().describe("Next action id, or branch id array for condition nodes."),
4330
- parent: import_zod32.z.string().optional().describe("Branch parent node id."),
4331
- parentKey: import_zod32.z.string().optional().describe("Previous action id or branch parent id."),
4332
- order: import_zod32.z.number().optional().describe("Order within this chain or branch."),
4333
- cat: import_zod32.z.string().optional().describe("Category for condition, transition, or multi-path nodes."),
4334
- nodeType: import_zod32.z.string().optional().describe("Node type for if/else nodes."),
4335
- sibling: import_zod32.z.array(import_zod32.z.string()).optional().describe("Sibling branch node IDs.")
4453
+ var import_zod33 = require("zod");
4454
+ var ActionSchema = import_zod33.z.object({
4455
+ id: import_zod33.z.string().optional().describe("Action ID (auto-generated if omitted)."),
4456
+ name: import_zod33.z.string().describe("Display name for this action step."),
4457
+ type: import_zod33.z.string().describe("Action type."),
4458
+ attributes: import_zod33.z.record(import_zod33.z.unknown()).optional().describe("Action-specific configuration."),
4459
+ next: import_zod33.z.union([import_zod33.z.string(), import_zod33.z.array(import_zod33.z.string())]).optional().describe("Next action id, or branch id array for condition nodes."),
4460
+ parent: import_zod33.z.string().optional().describe("Branch parent node id."),
4461
+ parentKey: import_zod33.z.string().optional().describe("Previous action id or branch parent id."),
4462
+ order: import_zod33.z.number().optional().describe("Order within this chain or branch."),
4463
+ cat: import_zod33.z.string().optional().describe("Category for condition, transition, or multi-path nodes."),
4464
+ nodeType: import_zod33.z.string().optional().describe("Node type for if/else nodes."),
4465
+ sibling: import_zod33.z.array(import_zod33.z.string()).optional().describe("Sibling branch node IDs.")
4336
4466
  }).passthrough();
4337
4467
  function linkBranchActions(actions, branchId, nextAfterMerge) {
4338
4468
  const prepared = actions.map((action) => ({
@@ -4379,8 +4509,8 @@ function registerWorkflowBuilderTools(server2, client) {
4379
4509
  "list_workflows_full",
4380
4510
  "List all workflows with full metadata including version, permissions, and timestamps. Requires Firebase auth. Use this instead of get_workflows when you need version numbers or internal IDs for update_workflow_actions.",
4381
4511
  {
4382
- limit: import_zod32.z.number().optional().describe("Max workflows to return. Defaults to 50."),
4383
- skip: import_zod32.z.number().optional().describe("Number of workflows to skip for pagination.")
4512
+ limit: import_zod33.z.number().optional().describe("Max workflows to return. Defaults to 50."),
4513
+ skip: import_zod33.z.number().optional().describe("Number of workflows to skip for pagination.")
4384
4514
  },
4385
4515
  async ({ limit, skip }) => {
4386
4516
  try {
@@ -4395,7 +4525,7 @@ function registerWorkflowBuilderTools(server2, client) {
4395
4525
  "get_workflow_full",
4396
4526
  "Get a workflow with full details including all actions (steps), triggers, conditions, if/else branches, and configuration. Requires Firebase auth. ALWAYS call this before update_workflow_actions to see the current state.",
4397
4527
  {
4398
- workflowId: import_zod32.z.string().describe("The workflow ID to retrieve.")
4528
+ workflowId: import_zod33.z.string().describe("The workflow ID to retrieve.")
4399
4529
  },
4400
4530
  async ({ workflowId }) => {
4401
4531
  try {
@@ -4410,9 +4540,9 @@ function registerWorkflowBuilderTools(server2, client) {
4410
4540
  "get_trigger_registry",
4411
4541
  "Return GHL's marketplace catalogue of workflow triggers from 3rd-party apps (Zoom, Shopify, WooCommerce, Monday, etc.). Each app exposes one or more trigger templates with custom variable mappings. Calls /marketplace/core/search/module?type=triggers. NOTE: This is the MARKETPLACE only. GHL's NATIVE trigger types (form_submission, contact_tag, payment_received, opportunity_*, inbound_webhook, etc.) live in the workflow builder frontend bundle, not an API. For the native registry see templates/trigger-schemas.json in this repo.",
4412
4542
  {
4413
- companyId: import_zod32.z.string().describe("Company ID for the location. Find it in any get_workflow_full response under the 'companyId' field."),
4414
- limit: import_zod32.z.number().optional().describe("Max marketplace apps to return. Defaults to 200."),
4415
- installedOnly: import_zod32.z.boolean().optional().describe("If true, returns only apps installed in this location. Defaults to false (full marketplace catalogue, ~85 apps).")
4543
+ companyId: import_zod33.z.string().describe("Company ID for the location. Find it in any get_workflow_full response under the 'companyId' field."),
4544
+ limit: import_zod33.z.number().optional().describe("Max marketplace apps to return. Defaults to 200."),
4545
+ installedOnly: import_zod33.z.boolean().optional().describe("If true, returns only apps installed in this location. Defaults to false (full marketplace catalogue, ~85 apps).")
4416
4546
  },
4417
4547
  async ({ companyId, limit, installedOnly }) => {
4418
4548
  try {
@@ -4444,7 +4574,7 @@ function registerWorkflowBuilderTools(server2, client) {
4444
4574
  "create_workflow",
4445
4575
  "Create a new empty workflow (starts as draft). Requires Firebase auth. Flow: 1) create_workflow \u2192 2) update_workflow_actions (add triggers + steps) \u2192 3) publish_workflow (make it live).",
4446
4576
  {
4447
- name: import_zod32.z.string().describe("Name for the new workflow.")
4577
+ name: import_zod33.z.string().describe("Name for the new workflow.")
4448
4578
  },
4449
4579
  async ({ name }) => {
4450
4580
  try {
@@ -4459,11 +4589,11 @@ function registerWorkflowBuilderTools(server2, client) {
4459
4589
  "update_workflow_actions",
4460
4590
  "Update a workflow's actions (steps), triggers, name, or status. IMPORTANT: Call get_workflow_full first to see the current state before updating. Handles version tracking automatically. Uses the internal builder API (requires Firebase auth). Action types: sms, email, add_contact_tag, remove_contact_tag, wait, webhook, internal_update_opportunity, custom_code, update_contact_field, add_notes, internal_notification, task_notification, remove_from_workflow, add_to_workflow, goto, transition, workflow_goal. For if/else, call build_if_else_branch and include its returned nodes; if_else is a node discriminator, not a standalone action. For goal events (exit-on-condition nodes), call build_goal_event to get a correctly-shaped workflow_goal node \u2014 wire it in by setting the prior action's `next` to the goal node's id. Trigger types: all 57 native GHL trigger types have typed validation; any unknown trigger type passes through via a permissive fallback so reads never crash.",
4461
4591
  {
4462
- workflowId: import_zod32.z.string().describe("The workflow ID to update."),
4463
- name: import_zod32.z.string().optional().describe("New workflow name."),
4464
- status: import_zod32.z.string().optional().describe("New status: 'draft' or 'published'."),
4465
- actions: import_zod32.z.array(ActionSchema).optional().describe("Array of workflow actions/steps. For linear flows, provide in order \u2014 chaining is automatic."),
4466
- triggers: import_zod32.z.array(WorkflowTriggerSchema).optional().describe("Array of workflow triggers.")
4592
+ workflowId: import_zod33.z.string().describe("The workflow ID to update."),
4593
+ name: import_zod33.z.string().optional().describe("New workflow name."),
4594
+ status: import_zod33.z.string().optional().describe("New status: 'draft' or 'published'."),
4595
+ actions: import_zod33.z.array(ActionSchema).optional().describe("Array of workflow actions/steps. For linear flows, provide in order \u2014 chaining is automatic."),
4596
+ triggers: import_zod33.z.array(WorkflowTriggerSchema).optional().describe("Array of workflow triggers.")
4467
4597
  },
4468
4598
  async ({ workflowId, name, status, actions, triggers }) => {
4469
4599
  try {
@@ -4507,12 +4637,12 @@ function registerWorkflowBuilderTools(server2, client) {
4507
4637
  "build_if_else_branch",
4508
4638
  "Build a correctly-shaped GHL if/else branch node set for a tag-based condition (Build Your Own / CUSTOM recipe). Returns a condition-node, branch-yes, branch-no, and branch child actions with parent/parentKey/sibling/order links populated. Shape mirrors what GHL's UI saves so dropdowns render correctly.",
4509
4639
  {
4510
- field: import_zod32.z.string().describe("Condition subtype, currently 'tags' for tag-based conditions."),
4511
- operator: import_zod32.z.string().describe("Condition operator token. Verified: 'index-of-true' (Includes), 'index-of-false' (Does not include), 'has_value' (Is not empty), 'has_no_value' (Is empty). Emptiness operators don't take a value. Tokens must match GHL's exact internal strings or the UI dropdown renders the raw token instead of a label."),
4512
- value: import_zod32.z.union([import_zod32.z.string(), import_zod32.z.array(import_zod32.z.string())]).optional().describe("Tag name(s). Required for index-of-true / index-of-false. Omit for has_value / has_no_value. Single string is auto-wrapped as an array. Tags must already exist in the location's tag library or the UI dropdown will render empty."),
4513
- yes_actions: import_zod32.z.array(ActionSchema).describe("Actions to run in the Yes branch."),
4514
- no_actions: import_zod32.z.array(ActionSchema).describe("Actions to run in the No branch."),
4515
- next_after_merge: import_zod32.z.string().optional().describe("Optional node id to link from each non-empty branch's final child.")
4640
+ field: import_zod33.z.string().describe("Condition subtype, currently 'tags' for tag-based conditions."),
4641
+ operator: import_zod33.z.string().describe("Condition operator token. Verified: 'index-of-true' (Includes), 'index-of-false' (Does not include), 'has_value' (Is not empty), 'has_no_value' (Is empty). Emptiness operators don't take a value. Tokens must match GHL's exact internal strings or the UI dropdown renders the raw token instead of a label."),
4642
+ value: import_zod33.z.union([import_zod33.z.string(), import_zod33.z.array(import_zod33.z.string())]).optional().describe("Tag name(s). Required for index-of-true / index-of-false. Omit for has_value / has_no_value. Single string is auto-wrapped as an array. Tags must already exist in the location's tag library or the UI dropdown will render empty."),
4643
+ yes_actions: import_zod33.z.array(ActionSchema).describe("Actions to run in the Yes branch."),
4644
+ no_actions: import_zod33.z.array(ActionSchema).describe("Actions to run in the No branch."),
4645
+ next_after_merge: import_zod33.z.string().optional().describe("Optional node id to link from each non-empty branch's final child.")
4516
4646
  },
4517
4647
  async ({ field, operator, value, yes_actions, no_actions, next_after_merge }) => {
4518
4648
  try {
@@ -4622,7 +4752,7 @@ function registerWorkflowBuilderTools(server2, client) {
4622
4752
  "build_goal_event",
4623
4753
  "Build a correctly-shaped GHL workflow goal-event node. Goal events sit inline in the action chain \u2014 when the goal condition fires during workflow execution, the configured action runs (default: exit the workflow). The previous action's `next` should point to the goal node's id; the goal node itself does not have a `next`. All 10 goal_condition values are catalogued (from GHL's workflow-builder JS bundle, extracted 2026-05-18): email_event, link_click, add_contact_tag, remove_contact_tag, appointment_status, payment_received, form_submission, document_status, invoice_paid, review_request_clicked. Each one has a different `extras` shape (see the `goal_condition` field's description for details).",
4624
4754
  {
4625
- goal_condition: import_zod32.z.enum([
4755
+ goal_condition: import_zod33.z.enum([
4626
4756
  "email_event",
4627
4757
  "link_click",
4628
4758
  "add_contact_tag",
@@ -4634,11 +4764,11 @@ function registerWorkflowBuilderTools(server2, client) {
4634
4764
  "invoice_paid",
4635
4765
  "review_request_clicked"
4636
4766
  ]).describe("The goal-condition identifier. Extras shape per condition: email_event \u2192 {stepIds:[]}; link_click \u2192 {linkIds:[]}; appointment_status \u2192 {calendarId}; payment_received \u2192 {globalProductIds:[]}; form_submission \u2192 {formIds:[]}; document_status \u2192 {templateId}; invoice_paid \u2192 {invoiceStepId}; review_request_clicked \u2192 {reviewTypes:['sms'|'email'], reviewLinkId}; add_contact_tag/remove_contact_tag \u2192 {tags:[]} (uncaptured but inferred)."),
4637
- extras: import_zod32.z.record(import_zod32.z.unknown()).optional().describe("Goal-condition-specific config. See goal_condition description for the expected shape per value. Pass {} or omit for goal_conditions without extras."),
4638
- action: import_zod32.z.enum(["exit", "continue", "wait"]).default("exit").describe("What happens when the goal fires (per GHL's GoalAction enum). 'exit' terminates the workflow path (verified). 'continue' lets it proceed to a downstream node. 'wait' pauses on the goal."),
4639
- name: import_zod32.z.string().default("Goal").describe("Display name in the GHL UI."),
4640
- op: import_zod32.z.enum(["or", "and"]).default("or").describe("Top-level boolean operator across segments. Default 'or'."),
4641
- inner_op: import_zod32.z.enum(["or", "and"]).default("or").describe("Boolean operator across conditions within a single segment. Default 'or'.")
4767
+ extras: import_zod33.z.record(import_zod33.z.unknown()).optional().describe("Goal-condition-specific config. See goal_condition description for the expected shape per value. Pass {} or omit for goal_conditions without extras."),
4768
+ action: import_zod33.z.enum(["exit", "continue", "wait"]).default("exit").describe("What happens when the goal fires (per GHL's GoalAction enum). 'exit' terminates the workflow path (verified). 'continue' lets it proceed to a downstream node. 'wait' pauses on the goal."),
4769
+ name: import_zod33.z.string().default("Goal").describe("Display name in the GHL UI."),
4770
+ op: import_zod33.z.enum(["or", "and"]).default("or").describe("Top-level boolean operator across segments. Default 'or'."),
4771
+ inner_op: import_zod33.z.enum(["or", "and"]).default("or").describe("Boolean operator across conditions within a single segment. Default 'or'.")
4642
4772
  },
4643
4773
  async ({ goal_condition, extras, action, name, op, inner_op }) => {
4644
4774
  try {
@@ -4673,8 +4803,8 @@ function registerWorkflowBuilderTools(server2, client) {
4673
4803
  "delete_workflow_full",
4674
4804
  "Permanently delete a workflow. IRREVERSIBLE.",
4675
4805
  {
4676
- workflowId: import_zod32.z.string().describe("The workflow ID to delete."),
4677
- confirm: import_zod32.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
4806
+ workflowId: import_zod33.z.string().describe("The workflow ID to delete."),
4807
+ confirm: import_zod33.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
4678
4808
  },
4679
4809
  async ({ workflowId }) => {
4680
4810
  try {
@@ -4689,7 +4819,7 @@ function registerWorkflowBuilderTools(server2, client) {
4689
4819
  "publish_workflow",
4690
4820
  "Publish a draft workflow, making it active and processing contacts.",
4691
4821
  {
4692
- workflowId: import_zod32.z.string().describe("The workflow ID to publish.")
4822
+ workflowId: import_zod33.z.string().describe("The workflow ID to publish.")
4693
4823
  },
4694
4824
  async ({ workflowId }) => {
4695
4825
  try {
@@ -4703,7 +4833,7 @@ function registerWorkflowBuilderTools(server2, client) {
4703
4833
  }
4704
4834
 
4705
4835
  // src/tools/funnel-builder.ts
4706
- var import_zod33 = require("zod");
4836
+ var import_zod34 = require("zod");
4707
4837
  function registerFunnelBuilderTools(server2, builderClient) {
4708
4838
  const client = builderClient;
4709
4839
  if (!client) return;
@@ -4746,7 +4876,7 @@ ${text2}`);
4746
4876
  "list_funnels_full",
4747
4877
  "List all funnels/websites with full details including steps, pages, and metadata. Uses the internal API for richer data than the public API.",
4748
4878
  {
4749
- limit: import_zod33.z.number().optional().describe("Max funnels to return. Defaults to 50.")
4879
+ limit: import_zod34.z.number().optional().describe("Max funnels to return. Defaults to 50.")
4750
4880
  },
4751
4881
  async ({ limit }) => {
4752
4882
  try {
@@ -4766,7 +4896,7 @@ ${text2}`);
4766
4896
  "get_page_full",
4767
4897
  "Get a funnel/website page with full builder data: metadata, version, preview snapshot URL, and page data download URL. To get the actual page content (sections, elements, styles), use get_page_content with the pageDataDownloadUrl from this response.",
4768
4898
  {
4769
- pageId: import_zod33.z.string().describe("The page ID to retrieve.")
4899
+ pageId: import_zod34.z.string().describe("The page ID to retrieve.")
4770
4900
  },
4771
4901
  async ({ pageId }) => {
4772
4902
  try {
@@ -4786,7 +4916,7 @@ ${text2}`);
4786
4916
  "get_page_content",
4787
4917
  "Download the full page builder content from a page's data URL. Returns the complete page structure: sections, elements, settings, styles, tracking codes, and popups. Use get_page_full first to get the pageDataDownloadUrl.",
4788
4918
  {
4789
- pageDataDownloadUrl: import_zod33.z.string().describe("The pageDataDownloadUrl from get_page_full response.")
4919
+ pageDataDownloadUrl: import_zod34.z.string().describe("The pageDataDownloadUrl from get_page_full response.")
4790
4920
  },
4791
4921
  async ({ pageDataDownloadUrl }) => {
4792
4922
  try {
@@ -4808,7 +4938,7 @@ ${text2}`);
4808
4938
  "create_funnel",
4809
4939
  "Create a new funnel/website. Starts empty \u2014 add steps and pages after creation.",
4810
4940
  {
4811
- name: import_zod33.z.string().describe("Name for the new funnel.")
4941
+ name: import_zod34.z.string().describe("Name for the new funnel.")
4812
4942
  },
4813
4943
  async ({ name }) => {
4814
4944
  try {
@@ -4830,21 +4960,21 @@ ${text2}`);
4830
4960
  "update_funnel",
4831
4961
  "Update a funnel's settings: name, path/slug, tracking codes, GDPR + payment + chat widget flags, etc. This is the 'save settings panel' endpoint \u2014 it sends the entire settings object, so the tool fetches current settings first, merges your overrides on top, then POSTs back. To rename a single step (page) inside a funnel, use update_funnel_step instead.",
4832
4962
  {
4833
- funnelId: import_zod33.z.string().describe("The funnel ID to update."),
4834
- name: import_zod33.z.string().optional().describe("New funnel display name."),
4835
- path: import_zod33.z.string().optional().describe("URL slug for the funnel (e.g., '/my-funnel'). Mapped to funnelPath."),
4836
- bodyTrackingCode: import_zod33.z.string().optional().describe("Custom tracking script injected before </body>."),
4837
- headTrackingCode: import_zod33.z.string().optional().describe("Custom tracking script injected before </head>."),
4838
- chatWidgetId: import_zod33.z.string().optional().describe("Chat widget to embed on every page in this funnel."),
4839
- domainId: import_zod33.z.string().optional().describe("Custom domain ID for the funnel."),
4840
- faviconUrl: import_zod33.z.string().optional().describe("Favicon URL for funnel pages."),
4841
- paymentMode: import_zod33.z.boolean().optional().describe("Whether to require a payment mode for the funnel."),
4842
- requireCreditCard: import_zod33.z.boolean().optional().describe("Whether to require a credit card on opt-in steps."),
4843
- isGdprCompliant: import_zod33.z.boolean().optional().describe("Toggle GDPR compliance mode."),
4844
- isOptimisePageLoad: import_zod33.z.boolean().optional().describe("Enable GHL's page-load optimization."),
4845
- imageOptimization: import_zod33.z.boolean().optional().describe("Enable automatic image optimization."),
4846
- allowPaymentModeOption: import_zod33.z.boolean().optional().describe("Allow buyers to choose payment mode on checkout."),
4847
- storeCurrencyFormatting: import_zod33.z.boolean().optional().describe("Use store-wide currency formatting.")
4963
+ funnelId: import_zod34.z.string().describe("The funnel ID to update."),
4964
+ name: import_zod34.z.string().optional().describe("New funnel display name."),
4965
+ path: import_zod34.z.string().optional().describe("URL slug for the funnel (e.g., '/my-funnel'). Mapped to funnelPath."),
4966
+ bodyTrackingCode: import_zod34.z.string().optional().describe("Custom tracking script injected before </body>."),
4967
+ headTrackingCode: import_zod34.z.string().optional().describe("Custom tracking script injected before </head>."),
4968
+ chatWidgetId: import_zod34.z.string().optional().describe("Chat widget to embed on every page in this funnel."),
4969
+ domainId: import_zod34.z.string().optional().describe("Custom domain ID for the funnel."),
4970
+ faviconUrl: import_zod34.z.string().optional().describe("Favicon URL for funnel pages."),
4971
+ paymentMode: import_zod34.z.boolean().optional().describe("Whether to require a payment mode for the funnel."),
4972
+ requireCreditCard: import_zod34.z.boolean().optional().describe("Whether to require a credit card on opt-in steps."),
4973
+ isGdprCompliant: import_zod34.z.boolean().optional().describe("Toggle GDPR compliance mode."),
4974
+ isOptimisePageLoad: import_zod34.z.boolean().optional().describe("Enable GHL's page-load optimization."),
4975
+ imageOptimization: import_zod34.z.boolean().optional().describe("Enable automatic image optimization."),
4976
+ allowPaymentModeOption: import_zod34.z.boolean().optional().describe("Allow buyers to choose payment mode on checkout."),
4977
+ storeCurrencyFormatting: import_zod34.z.boolean().optional().describe("Use store-wide currency formatting.")
4848
4978
  },
4849
4979
  async (args) => {
4850
4980
  try {
@@ -4900,11 +5030,11 @@ ${text2}`);
4900
5030
  "update_funnel_step",
4901
5031
  "Update a single step (page entry) inside a funnel \u2014 display name, URL slug, or attached domain. A step is GHL's container for one or more pages (multiple pages exist when split-testing). Use update_funnel for funnel-level settings instead.",
4902
5032
  {
4903
- funnelId: import_zod33.z.string().describe("The funnel ID containing the step."),
4904
- stepId: import_zod33.z.string().describe("The step ID to update (from get_funnel_pages / list_funnels_full)."),
4905
- name: import_zod33.z.string().optional().describe("New step display name."),
4906
- url: import_zod33.z.string().optional().describe("URL slug for the step (e.g., '/thank-you')."),
4907
- domainName: import_zod33.z.string().optional().describe("Custom domain to attach to this step.")
5033
+ funnelId: import_zod34.z.string().describe("The funnel ID containing the step."),
5034
+ stepId: import_zod34.z.string().describe("The step ID to update (from get_funnel_pages / list_funnels_full)."),
5035
+ name: import_zod34.z.string().optional().describe("New step display name."),
5036
+ url: import_zod34.z.string().optional().describe("URL slug for the step (e.g., '/thank-you')."),
5037
+ domainName: import_zod34.z.string().optional().describe("Custom domain to attach to this step.")
4908
5038
  },
4909
5039
  async ({ funnelId, stepId, name, url, domainName }) => {
4910
5040
  try {
@@ -4923,8 +5053,8 @@ ${text2}`);
4923
5053
  "delete_funnel",
4924
5054
  "Permanently delete a funnel and all its steps/pages. IRREVERSIBLE.",
4925
5055
  {
4926
- funnelId: import_zod33.z.string().describe("The funnel ID to delete."),
4927
- confirm: import_zod33.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
5056
+ funnelId: import_zod34.z.string().describe("The funnel ID to delete."),
5057
+ confirm: import_zod34.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
4928
5058
  },
4929
5059
  async ({ funnelId }) => {
4930
5060
  try {
@@ -4943,10 +5073,10 @@ ${text2}`);
4943
5073
  "create_funnel_page",
4944
5074
  "Create a new step (page entry) in a funnel. The client generates a step UUID locally and sends it in the request; GHL auto-creates a blank page inside the step on the server side. The response includes the new step's id and the page's Firestore reference, which you can then update via update_page_content.",
4945
5075
  {
4946
- funnelId: import_zod33.z.string().describe("The funnel ID to add the step to."),
4947
- name: import_zod33.z.string().describe("Step display name."),
4948
- url: import_zod33.z.string().optional().describe("URL slug for the step. Defaults to '' (blank) like the GHL UI."),
4949
- type: import_zod33.z.string().optional().describe("Step type. Defaults to 'optin_funnel_page'.")
5076
+ funnelId: import_zod34.z.string().describe("The funnel ID to add the step to."),
5077
+ name: import_zod34.z.string().describe("Step display name."),
5078
+ url: import_zod34.z.string().optional().describe("URL slug for the step. Defaults to '' (blank) like the GHL UI."),
5079
+ type: import_zod34.z.string().optional().describe("Step type. Defaults to 'optin_funnel_page'.")
4950
5080
  },
4951
5081
  async ({ funnelId, name, url, type }) => {
4952
5082
  try {
@@ -4974,9 +5104,9 @@ ${text2}`);
4974
5104
  "update_page_content",
4975
5105
  "Update a page's builder content \u2014 sections, elements, settings, pageStyles, trackingCode, popups, popupsList, fontsForPreview. Use get_page_content first to see the current structure, modify it, then pass the full 8-field envelope here. GHL's UI fires three POSTs to this endpoint per save (one collaborative-edit broadcast + two commits); for MCP use, one POST with write=true is enough.",
4976
5106
  {
4977
- pageId: import_zod33.z.string().describe("The page ID to update."),
4978
- content: import_zod33.z.record(import_zod33.z.unknown()).describe("The full page content JSON. Expected fields: sections, settings, general, pageStyles, trackingCode, popups, popupsList, fontsForPreview."),
4979
- isPublished: import_zod33.z.boolean().optional().describe("Whether the page should be marked published after the save. Defaults to false (draft).")
5107
+ pageId: import_zod34.z.string().describe("The page ID to update."),
5108
+ content: import_zod34.z.record(import_zod34.z.unknown()).describe("The full page content JSON. Expected fields: sections, settings, general, pageStyles, trackingCode, popups, popupsList, fontsForPreview."),
5109
+ isPublished: import_zod34.z.boolean().optional().describe("Whether the page should be marked published after the save. Defaults to false (draft).")
4980
5110
  },
4981
5111
  async ({ pageId, content, isPublished }) => {
4982
5112
  try {
@@ -4997,9 +5127,9 @@ ${text2}`);
4997
5127
  "delete_funnel_page",
4998
5128
  "Permanently delete a step (and all its pages) from a funnel. IRREVERSIBLE. SIGNATURE CHANGED in v3.7.0: was pageId, now requires funnelId + stepId to match GHL's actual delete-step endpoint.",
4999
5129
  {
5000
- funnelId: import_zod33.z.string().describe("The funnel ID containing the step."),
5001
- stepId: import_zod33.z.string().describe("The step ID to delete (from get_funnel_pages / list_funnels_full)."),
5002
- confirm: import_zod33.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
5130
+ funnelId: import_zod34.z.string().describe("The funnel ID containing the step."),
5131
+ stepId: import_zod34.z.string().describe("The step ID to delete (from get_funnel_pages / list_funnels_full)."),
5132
+ confirm: import_zod34.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
5003
5133
  },
5004
5134
  async ({ funnelId, stepId }) => {
5005
5135
  try {
@@ -5013,7 +5143,7 @@ ${text2}`);
5013
5143
  }
5014
5144
 
5015
5145
  // src/tools/form-builder.ts
5016
- var import_zod34 = require("zod");
5146
+ var import_zod35 = require("zod");
5017
5147
  function registerFormBuilderTools(server2, builderClient) {
5018
5148
  const client = builderClient;
5019
5149
  if (!client) return;
@@ -5042,7 +5172,7 @@ ${text2}`);
5042
5172
  "get_form_full",
5043
5173
  "Get a form with full builder data: all fields (labels, types, IDs, validation), conditional logic, auto-responder config, email notification settings, styling, and version history. This is the internal API \u2014 it returns everything the form builder UI shows.",
5044
5174
  {
5045
- formId: import_zod34.z.string().describe("The form ID to retrieve.")
5175
+ formId: import_zod35.z.string().describe("The form ID to retrieve.")
5046
5176
  },
5047
5177
  async ({ formId }) => {
5048
5178
  try {
@@ -5059,9 +5189,9 @@ ${text2}`);
5059
5189
  "update_form",
5060
5190
  "Update a form's structure \u2014 fields, labels, conditional logic, auto-responder, email notifications, styling. Use get_form_full first to see the current structure, modify the formData object, and pass it here.",
5061
5191
  {
5062
- formId: import_zod34.z.string().describe("The form ID to update."),
5063
- formData: import_zod34.z.record(import_zod34.z.unknown()).describe("The updated formData object containing form fields, settings, autoResponder config, etc."),
5064
- name: import_zod34.z.string().optional().describe("Updated form name.")
5192
+ formId: import_zod35.z.string().describe("The form ID to update."),
5193
+ formData: import_zod35.z.record(import_zod35.z.unknown()).describe("The updated formData object containing form fields, settings, autoResponder config, etc."),
5194
+ name: import_zod35.z.string().optional().describe("Updated form name.")
5065
5195
  },
5066
5196
  async ({ formId, formData, name }) => {
5067
5197
  try {
@@ -5080,7 +5210,7 @@ ${text2}`);
5080
5210
  "create_form",
5081
5211
  "Create a new form. Starts with a basic structure \u2014 use update_form to add fields and configure settings.",
5082
5212
  {
5083
- name: import_zod34.z.string().describe("Name for the new form.")
5213
+ name: import_zod35.z.string().describe("Name for the new form.")
5084
5214
  },
5085
5215
  async ({ name }) => {
5086
5216
  try {
@@ -5106,8 +5236,8 @@ ${text2}`);
5106
5236
  "delete_form",
5107
5237
  "Permanently delete a form. IRREVERSIBLE.",
5108
5238
  {
5109
- formId: import_zod34.z.string().describe("The form ID to delete."),
5110
- confirm: import_zod34.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
5239
+ formId: import_zod35.z.string().describe("The form ID to delete."),
5240
+ confirm: import_zod35.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
5111
5241
  },
5112
5242
  async ({ formId }) => {
5113
5243
  try {
@@ -5124,9 +5254,9 @@ ${text2}`);
5124
5254
  "get_form_submissions_full",
5125
5255
  "Get form submissions with full field data, contact info, and submission timestamps via the internal API. Offset-based pagination via skip/limit.",
5126
5256
  {
5127
- formId: import_zod34.z.string().optional().describe("Filter by form ID. If omitted, returns all submissions."),
5128
- limit: import_zod34.z.number().optional().describe("Max submissions to return. Defaults to 20."),
5129
- skip: import_zod34.z.number().optional().describe("Number to skip for pagination.")
5257
+ formId: import_zod35.z.string().optional().describe("Filter by form ID. If omitted, returns all submissions."),
5258
+ limit: import_zod35.z.number().optional().describe("Max submissions to return. Defaults to 20."),
5259
+ skip: import_zod35.z.number().optional().describe("Number to skip for pagination.")
5130
5260
  },
5131
5261
  async ({ formId, limit, skip }) => {
5132
5262
  try {
@@ -5145,7 +5275,7 @@ ${text2}`);
5145
5275
  }
5146
5276
 
5147
5277
  // src/tools/pipeline-builder.ts
5148
- var import_zod35 = require("zod");
5278
+ var import_zod36 = require("zod");
5149
5279
  function registerPipelineBuilderTools(server2, builderClient) {
5150
5280
  const client = builderClient;
5151
5281
  if (!client) return;
@@ -5190,7 +5320,7 @@ ${text2}`);
5190
5320
  "get_pipeline_full",
5191
5321
  "Get a single pipeline with complete stage configuration: IDs, names, positions, display settings.",
5192
5322
  {
5193
- pipelineId: import_zod35.z.string().describe("The pipeline ID to retrieve.")
5323
+ pipelineId: import_zod36.z.string().describe("The pipeline ID to retrieve.")
5194
5324
  },
5195
5325
  async ({ pipelineId }) => {
5196
5326
  try {
@@ -5208,17 +5338,17 @@ ${text2}`);
5208
5338
  "create_pipeline",
5209
5339
  "Create a new pipeline with stages. Each stage needs a name and position (0-based).",
5210
5340
  {
5211
- name: import_zod35.z.string().describe("Pipeline name."),
5212
- stages: import_zod35.z.array(
5213
- import_zod35.z.object({
5214
- name: import_zod35.z.string().describe("Stage name."),
5215
- position: import_zod35.z.number().describe("Stage position (0-based)."),
5216
- showInFunnel: import_zod35.z.boolean().optional().describe("Show in funnel view. Defaults to true."),
5217
- showInPieChart: import_zod35.z.boolean().optional().describe("Show in pie chart. Defaults to true.")
5341
+ name: import_zod36.z.string().describe("Pipeline name."),
5342
+ stages: import_zod36.z.array(
5343
+ import_zod36.z.object({
5344
+ name: import_zod36.z.string().describe("Stage name."),
5345
+ position: import_zod36.z.number().describe("Stage position (0-based)."),
5346
+ showInFunnel: import_zod36.z.boolean().optional().describe("Show in funnel view. Defaults to true."),
5347
+ showInPieChart: import_zod36.z.boolean().optional().describe("Show in pie chart. Defaults to true.")
5218
5348
  })
5219
5349
  ).describe("Array of stages in order."),
5220
- showInFunnel: import_zod35.z.boolean().optional().describe("Show pipeline in funnel view. Defaults to true."),
5221
- showInPieChart: import_zod35.z.boolean().optional().describe("Show pipeline in pie chart. Defaults to true.")
5350
+ showInFunnel: import_zod36.z.boolean().optional().describe("Show pipeline in funnel view. Defaults to true."),
5351
+ showInPieChart: import_zod36.z.boolean().optional().describe("Show pipeline in pie chart. Defaults to true.")
5222
5352
  },
5223
5353
  async ({ name, stages, showInFunnel, showInPieChart }) => {
5224
5354
  try {
@@ -5248,19 +5378,19 @@ ${text2}`);
5248
5378
  "update_pipeline",
5249
5379
  "Update a pipeline's name, stages, or display settings. You can add, remove, rename, or reorder stages. Pass the complete stages array \u2014 stages not included will be removed.",
5250
5380
  {
5251
- pipelineId: import_zod35.z.string().describe("The pipeline ID to update."),
5252
- name: import_zod35.z.string().optional().describe("New pipeline name."),
5253
- stages: import_zod35.z.array(
5254
- import_zod35.z.object({
5255
- id: import_zod35.z.string().optional().describe("Existing stage ID (omit for new stages)."),
5256
- name: import_zod35.z.string().describe("Stage name."),
5257
- position: import_zod35.z.number().describe("Stage position (0-based)."),
5258
- showInFunnel: import_zod35.z.boolean().optional().describe("Show in funnel view."),
5259
- showInPieChart: import_zod35.z.boolean().optional().describe("Show in pie chart.")
5381
+ pipelineId: import_zod36.z.string().describe("The pipeline ID to update."),
5382
+ name: import_zod36.z.string().optional().describe("New pipeline name."),
5383
+ stages: import_zod36.z.array(
5384
+ import_zod36.z.object({
5385
+ id: import_zod36.z.string().optional().describe("Existing stage ID (omit for new stages)."),
5386
+ name: import_zod36.z.string().describe("Stage name."),
5387
+ position: import_zod36.z.number().describe("Stage position (0-based)."),
5388
+ showInFunnel: import_zod36.z.boolean().optional().describe("Show in funnel view."),
5389
+ showInPieChart: import_zod36.z.boolean().optional().describe("Show in pie chart.")
5260
5390
  })
5261
5391
  ).optional().describe("Complete stages array. Stages not included will be removed."),
5262
- showInFunnel: import_zod35.z.boolean().optional().describe("Show pipeline in funnel view."),
5263
- showInPieChart: import_zod35.z.boolean().optional().describe("Show pipeline in pie chart.")
5392
+ showInFunnel: import_zod36.z.boolean().optional().describe("Show pipeline in funnel view."),
5393
+ showInPieChart: import_zod36.z.boolean().optional().describe("Show pipeline in pie chart.")
5264
5394
  },
5265
5395
  async ({ pipelineId, name, stages, showInFunnel, showInPieChart }) => {
5266
5396
  try {
@@ -5283,8 +5413,8 @@ ${text2}`);
5283
5413
  "delete_pipeline",
5284
5414
  "Permanently delete a pipeline and all its stages. Opportunities become unassigned. IRREVERSIBLE.",
5285
5415
  {
5286
- pipelineId: import_zod35.z.string().describe("The pipeline ID to delete."),
5287
- confirm: import_zod35.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
5416
+ pipelineId: import_zod36.z.string().describe("The pipeline ID to delete."),
5417
+ confirm: import_zod36.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
5288
5418
  },
5289
5419
  async ({ pipelineId }) => {
5290
5420
  try {
@@ -5301,7 +5431,7 @@ ${text2}`);
5301
5431
  }
5302
5432
 
5303
5433
  // src/tools/location-switcher.ts
5304
- var import_zod36 = require("zod");
5434
+ var import_zod37 = require("zod");
5305
5435
  var switchChain = Promise.resolve();
5306
5436
  function withSwitchLock(fn) {
5307
5437
  const next = switchChain.then(fn, fn);
@@ -5350,7 +5480,7 @@ Token registry: ${registeredCount} location(s) registered${versionLine}`
5350
5480
  "switch_location",
5351
5481
  "Switch the active GHL sub-account. Automatically swaps the API key from the token registry if available. After switching, all tools default to the new location.",
5352
5482
  {
5353
- locationId: import_zod36.z.string().describe("The Location ID to switch to.")
5483
+ locationId: import_zod37.z.string().describe("The Location ID to switch to.")
5354
5484
  },
5355
5485
  async ({ locationId: locationId2 }) => withSwitchLock(async () => {
5356
5486
  const previousId = client.defaultLocationId;
@@ -5415,9 +5545,9 @@ Still on: ${previousId || "none"}${hint}` }],
5415
5545
  "register_location",
5416
5546
  "Add a GHL sub-account to the token registry so switch_location can automatically use its API key. Each sub-account needs its own Private Integration key created in GHL Settings > Integrations.",
5417
5547
  {
5418
- locationId: import_zod36.z.string().describe("The GHL Location ID (from Settings > Business Profile)."),
5419
- name: import_zod36.z.string().describe("A friendly name for this sub-account (e.g. 'PNTracker', 'Med Spa Template')."),
5420
- apiKey: import_zod36.z.string().describe("The Private Integration API key for this sub-account (starts with 'pit-').")
5548
+ locationId: import_zod37.z.string().describe("The GHL Location ID (from Settings > Business Profile)."),
5549
+ name: import_zod37.z.string().describe("A friendly name for this sub-account (e.g. 'PNTracker', 'Med Spa Template')."),
5550
+ apiKey: import_zod37.z.string().describe("The Private Integration API key for this sub-account (starts with 'pit-').")
5421
5551
  },
5422
5552
  async ({ locationId: locationId2, name, apiKey: apiKey2 }) => {
5423
5553
  if (!registry2) {
@@ -5467,7 +5597,7 @@ The API key could not access location ${locationId2}. Make sure:
5467
5597
  "unregister_location",
5468
5598
  "Remove a GHL sub-account from the token registry.",
5469
5599
  {
5470
- locationId: import_zod36.z.string().describe("The Location ID to remove.")
5600
+ locationId: import_zod37.z.string().describe("The Location ID to remove.")
5471
5601
  },
5472
5602
  async ({ locationId: locationId2 }) => {
5473
5603
  if (!registry2) {
@@ -5526,8 +5656,8 @@ ${lines.join("\n")}
5526
5656
  "list_available_locations",
5527
5657
  "List all GHL sub-accounts (locations) accessible with the current or agency API key. Shows locations that exist in the GHL account \u2014 use register_location to add their tokens. Offset-based pagination via skip/limit.",
5528
5658
  {
5529
- limit: import_zod36.z.number().optional().describe("Max locations to return. Defaults to 20."),
5530
- skip: import_zod36.z.number().optional().describe("Number to skip for pagination.")
5659
+ limit: import_zod37.z.number().optional().describe("Max locations to return. Defaults to 20."),
5660
+ skip: import_zod37.z.number().optional().describe("Number to skip for pagination.")
5531
5661
  },
5532
5662
  async ({ limit, skip }) => {
5533
5663
  try {
@@ -5570,7 +5700,7 @@ ${lines.join("\n")}
5570
5700
  }
5571
5701
 
5572
5702
  // src/tools/bulk-operations.ts
5573
- var import_zod37 = require("zod");
5703
+ var import_zod38 = require("zod");
5574
5704
  function delay(ms) {
5575
5705
  return new Promise((resolve5) => setTimeout(resolve5, ms));
5576
5706
  }
@@ -5582,8 +5712,8 @@ function registerBulkOperationTools(server2, client) {
5582
5712
  "bulk_add_tags",
5583
5713
  "Add tags to multiple contacts at once. Rate-limited to avoid API throttling. Returns a summary of successes and failures.",
5584
5714
  {
5585
- contactIds: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to tag."),
5586
- tags: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one tag required.").describe("Tags to add to each contact.")
5715
+ contactIds: import_zod38.z.array(import_zod38.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to tag."),
5716
+ tags: import_zod38.z.array(import_zod38.z.string()).min(1, "At least one tag required.").describe("Tags to add to each contact.")
5587
5717
  },
5588
5718
  async ({ contactIds, tags }) => {
5589
5719
  const results = { success: 0, failed: 0, errors: [] };
@@ -5605,8 +5735,8 @@ function registerBulkOperationTools(server2, client) {
5605
5735
  "bulk_remove_tags",
5606
5736
  "Remove tags from multiple contacts at once. Rate-limited.",
5607
5737
  {
5608
- contactIds: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs."),
5609
- tags: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one tag required.").describe("Tags to remove from each contact.")
5738
+ contactIds: import_zod38.z.array(import_zod38.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs."),
5739
+ tags: import_zod38.z.array(import_zod38.z.string()).min(1, "At least one tag required.").describe("Tags to remove from each contact.")
5610
5740
  },
5611
5741
  async ({ contactIds, tags }) => {
5612
5742
  const results = { success: 0, failed: 0, errors: [] };
@@ -5627,8 +5757,8 @@ function registerBulkOperationTools(server2, client) {
5627
5757
  "bulk_update_contacts",
5628
5758
  "Update the same field(s) on multiple contacts at once. Rate-limited. Example: set a custom field value, change source, update address for a batch of contacts.",
5629
5759
  {
5630
- contactIds: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to update."),
5631
- fields: import_zod37.z.record(import_zod37.z.unknown()).describe("Fields to set on each contact (e.g. {customField: {id: 'xxx', value: 'yyy'}}, {source: 'Import'}).")
5760
+ contactIds: import_zod38.z.array(import_zod38.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to update."),
5761
+ fields: import_zod38.z.record(import_zod38.z.unknown()).describe("Fields to set on each contact (e.g. {customField: {id: 'xxx', value: 'yyy'}}, {source: 'Import'}).")
5632
5762
  },
5633
5763
  async ({ contactIds, fields }) => {
5634
5764
  const results = { success: 0, failed: 0, errors: [] };
@@ -5649,8 +5779,8 @@ function registerBulkOperationTools(server2, client) {
5649
5779
  "bulk_add_to_workflow",
5650
5780
  "Enroll multiple contacts into a workflow at once. Rate-limited.",
5651
5781
  {
5652
- contactIds: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to enroll."),
5653
- workflowId: import_zod37.z.string().describe("The workflow ID to enroll contacts into.")
5782
+ contactIds: import_zod38.z.array(import_zod38.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to enroll."),
5783
+ workflowId: import_zod38.z.string().describe("The workflow ID to enroll contacts into.")
5654
5784
  },
5655
5785
  async ({ contactIds, workflowId }) => {
5656
5786
  const results = { success: 0, failed: 0, errors: [] };
@@ -5671,8 +5801,8 @@ function registerBulkOperationTools(server2, client) {
5671
5801
  "bulk_delete_contacts",
5672
5802
  "Delete multiple contacts at once. IRREVERSIBLE. Rate-limited. Use with extreme caution.",
5673
5803
  {
5674
- contactIds: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to permanently delete."),
5675
- confirm: import_zod37.z.literal("DELETE").describe("Must pass the string 'DELETE' to confirm. This is a safety check.")
5804
+ contactIds: import_zod38.z.array(import_zod38.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to permanently delete."),
5805
+ confirm: import_zod38.z.literal("DELETE").describe("Must pass the string 'DELETE' to confirm. This is a safety check.")
5676
5806
  },
5677
5807
  async ({ contactIds, confirm }) => {
5678
5808
  if (confirm !== "DELETE") {
@@ -5695,7 +5825,7 @@ function registerBulkOperationTools(server2, client) {
5695
5825
  }
5696
5826
 
5697
5827
  // src/tools/account-export.ts
5698
- var import_zod38 = require("zod");
5828
+ var import_zod39 = require("zod");
5699
5829
  function delay2(ms) {
5700
5830
  return new Promise((resolve5) => setTimeout(resolve5, ms));
5701
5831
  }
@@ -5705,8 +5835,8 @@ function registerAccountExportTools(server2, client) {
5705
5835
  "export_account",
5706
5836
  "Export a complete inventory of the GHL sub-account: location info, contacts (count + sample), pipelines with stages, workflows (with full actions if builder auth is configured), funnels with pages, forms, custom fields, custom values, tags, calendars, and users. Returns a comprehensive JSON report for auditing or backup.",
5707
5837
  {
5708
- locationId: import_zod38.z.string().optional().describe("Location ID to export. Uses default if not specified."),
5709
- includeContacts: import_zod38.z.boolean().optional().describe("Include contact list (first 100). Defaults to false for speed.")
5838
+ locationId: import_zod39.z.string().optional().describe("Location ID to export. Uses default if not specified."),
5839
+ includeContacts: import_zod39.z.boolean().optional().describe("Include contact list (first 100). Defaults to false for speed.")
5710
5840
  },
5711
5841
  async ({ locationId: locationId2, includeContacts }) => {
5712
5842
  try {
@@ -5834,8 +5964,8 @@ function registerAccountExportTools(server2, client) {
5834
5964
  "compare_locations",
5835
5965
  "Compare two GHL sub-accounts side by side \u2014 shows differences in pipelines, workflows, custom fields, tags, forms, and funnels. Useful for ensuring consistency across locations or auditing before/after changes.",
5836
5966
  {
5837
- locationA: import_zod38.z.string().describe("First Location ID."),
5838
- locationB: import_zod38.z.string().describe("Second Location ID.")
5967
+ locationA: import_zod39.z.string().describe("First Location ID."),
5968
+ locationB: import_zod39.z.string().describe("Second Location ID.")
5839
5969
  },
5840
5970
  async ({ locationA, locationB }) => {
5841
5971
  try {
@@ -5913,7 +6043,7 @@ function registerAccountExportTools(server2, client) {
5913
6043
  }
5914
6044
 
5915
6045
  // src/tools/workflow-cloner.ts
5916
- var import_zod39 = require("zod");
6046
+ var import_zod40 = require("zod");
5917
6047
  var crypto2 = __toESM(require("crypto"));
5918
6048
  function registerWorkflowClonerTools(server2, builderClient) {
5919
6049
  const client = builderClient;
@@ -5922,8 +6052,8 @@ function registerWorkflowClonerTools(server2, builderClient) {
5922
6052
  "clone_workflow",
5923
6053
  "Deep clone a workflow \u2014 creates an exact copy with new IDs for all actions, triggers, and references. The clone starts as a draft. Useful for creating templates or duplicating workflows across projects.",
5924
6054
  {
5925
- sourceWorkflowId: import_zod39.z.string().describe("The workflow ID to clone."),
5926
- newName: import_zod39.z.string().describe("Name for the cloned workflow.")
6055
+ sourceWorkflowId: import_zod40.z.string().describe("The workflow ID to clone."),
6056
+ newName: import_zod40.z.string().describe("Name for the cloned workflow.")
5927
6057
  },
5928
6058
  async ({ sourceWorkflowId, newName }) => {
5929
6059
  try {
@@ -6012,7 +6142,7 @@ function registerWorkflowClonerTools(server2, builderClient) {
6012
6142
  }
6013
6143
 
6014
6144
  // src/tools/smart-lists.ts
6015
- var import_zod40 = require("zod");
6145
+ var import_zod41 = require("zod");
6016
6146
  var SMARTLIST_BASE = "https://backend.leadconnectorhq.com/lists/dynamic";
6017
6147
  var OBJECT_KEYS = ["contacts", "opportunity"];
6018
6148
  function registerSmartListTools(server2, builderClient) {
@@ -6039,11 +6169,11 @@ ${text2}`);
6039
6169
  "list_smart_lists",
6040
6170
  "List smart lists (dynamic / saved-filter lists) in a location. Smart Lists are saved searches over contacts or opportunities \u2014 agencies use them to segment by complex criteria. Filters and columns aren't returned in the list view; use get_smart_list for the full filter spec.",
6041
6171
  {
6042
- objectKey: import_zod40.z.enum(OBJECT_KEYS).describe("The object type the lists segment over. 'contacts' for contact-segments, 'opportunity' for opportunity-segments. Required \u2014 GHL rejects requests without it."),
6043
- query: import_zod40.z.string().optional().describe("Free-text search across smart list names."),
6044
- limit: import_zod40.z.number().optional().describe("Max smart lists per page. Defaults to 20 on GHL's side."),
6045
- startAfter: import_zod40.z.string().optional().describe("Cursor for pagination \u2014 pass the last list's id from the previous page."),
6046
- locationId: import_zod40.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
6172
+ objectKey: import_zod41.z.enum(OBJECT_KEYS).describe("The object type the lists segment over. 'contacts' for contact-segments, 'opportunity' for opportunity-segments. Required \u2014 GHL rejects requests without it."),
6173
+ query: import_zod41.z.string().optional().describe("Free-text search across smart list names."),
6174
+ limit: import_zod41.z.number().optional().describe("Max smart lists per page. Defaults to 20 on GHL's side."),
6175
+ startAfter: import_zod41.z.string().optional().describe("Cursor for pagination \u2014 pass the last list's id from the previous page."),
6176
+ locationId: import_zod41.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
6047
6177
  },
6048
6178
  async ({ objectKey, query, limit, startAfter, locationId: locationId2 }) => {
6049
6179
  try {
@@ -6063,8 +6193,8 @@ ${text2}`);
6063
6193
  "get_smart_list",
6064
6194
  "Get a single smart list by ID with its full configuration: filters, columns, permissions, and metadata. The filters array is what defines who/what is in the list.",
6065
6195
  {
6066
- listId: import_zod40.z.string().describe("The smart list ID (from list_smart_lists or a previous create_smart_list response)."),
6067
- locationId: import_zod40.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
6196
+ listId: import_zod41.z.string().describe("The smart list ID (from list_smart_lists or a previous create_smart_list response)."),
6197
+ locationId: import_zod41.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
6068
6198
  },
6069
6199
  async ({ listId, locationId: locationId2 }) => {
6070
6200
  try {
@@ -6080,13 +6210,13 @@ ${text2}`);
6080
6210
  "create_smart_list",
6081
6211
  "Create a new smart list (dynamic filter list). Required: name + objectKey. Filters define the saved-search criteria \u2014 pass an empty array to create an empty list and add filters later via update_smart_list. The shape of filters/columns is opaque here; query an existing smart list with get_smart_list to see the format GHL expects.",
6082
6212
  {
6083
- name: import_zod40.z.string().describe("Display name for the smart list."),
6084
- objectKey: import_zod40.z.enum(OBJECT_KEYS).describe("Object type the list segments over. 'contacts' or 'opportunity'."),
6085
- filters: import_zod40.z.array(import_zod40.z.record(import_zod40.z.unknown())).optional().describe("Array of filter objects. Each object has fields like {field, operator, value} \u2014 exact shape varies by filter type. See get_smart_list on an existing list to learn the format."),
6086
- columns: import_zod40.z.array(import_zod40.z.record(import_zod40.z.unknown())).optional().describe("Array of column definitions for the smart list view in GHL UI. Each defines which contact/opportunity field shows as a column. Defaults to GHL's standard columns if omitted."),
6087
- pipelineIds: import_zod40.z.array(import_zod40.z.string()).optional().describe("(opportunity objectKey only) Pipeline IDs to restrict this smart list to. Empty array = all pipelines."),
6088
- defaultInPipelines: import_zod40.z.array(import_zod40.z.string()).optional().describe("(opportunity objectKey only) Pipeline IDs where this list is the default view."),
6089
- locationId: import_zod40.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
6213
+ name: import_zod41.z.string().describe("Display name for the smart list."),
6214
+ objectKey: import_zod41.z.enum(OBJECT_KEYS).describe("Object type the list segments over. 'contacts' or 'opportunity'."),
6215
+ filters: import_zod41.z.array(import_zod41.z.record(import_zod41.z.unknown())).optional().describe("Array of filter objects. Each object has fields like {field, operator, value} \u2014 exact shape varies by filter type. See get_smart_list on an existing list to learn the format."),
6216
+ columns: import_zod41.z.array(import_zod41.z.record(import_zod41.z.unknown())).optional().describe("Array of column definitions for the smart list view in GHL UI. Each defines which contact/opportunity field shows as a column. Defaults to GHL's standard columns if omitted."),
6217
+ pipelineIds: import_zod41.z.array(import_zod41.z.string()).optional().describe("(opportunity objectKey only) Pipeline IDs to restrict this smart list to. Empty array = all pipelines."),
6218
+ defaultInPipelines: import_zod41.z.array(import_zod41.z.string()).optional().describe("(opportunity objectKey only) Pipeline IDs where this list is the default view."),
6219
+ locationId: import_zod41.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
6090
6220
  },
6091
6221
  async ({ name, objectKey, filters, columns, pipelineIds, defaultInPipelines, locationId: locationId2 }) => {
6092
6222
  try {
@@ -6107,13 +6237,13 @@ ${text2}`);
6107
6237
  "update_smart_list",
6108
6238
  "Update an existing smart list's name, filters, or columns. The objectKey CANNOT be changed after creation (GHL rejects with 422 if you try). Use get_smart_list first to inspect the current filters; partial updates work \u2014 pass only the fields you want to change.",
6109
6239
  {
6110
- listId: import_zod40.z.string().describe("The smart list ID to update."),
6111
- name: import_zod40.z.string().optional().describe("New display name."),
6112
- filters: import_zod40.z.array(import_zod40.z.record(import_zod40.z.unknown())).optional().describe("Replace the filter array entirely. To add a filter, fetch the current list, append, and pass the new array."),
6113
- columns: import_zod40.z.array(import_zod40.z.record(import_zod40.z.unknown())).optional().describe("Replace the column array entirely."),
6114
- pipelineIds: import_zod40.z.array(import_zod40.z.string()).optional().describe("(opportunity only) Update the pipeline scope."),
6115
- defaultInPipelines: import_zod40.z.array(import_zod40.z.string()).optional().describe("(opportunity only) Update the default-in-pipelines list."),
6116
- locationId: import_zod40.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
6240
+ listId: import_zod41.z.string().describe("The smart list ID to update."),
6241
+ name: import_zod41.z.string().optional().describe("New display name."),
6242
+ filters: import_zod41.z.array(import_zod41.z.record(import_zod41.z.unknown())).optional().describe("Replace the filter array entirely. To add a filter, fetch the current list, append, and pass the new array."),
6243
+ columns: import_zod41.z.array(import_zod41.z.record(import_zod41.z.unknown())).optional().describe("Replace the column array entirely."),
6244
+ pipelineIds: import_zod41.z.array(import_zod41.z.string()).optional().describe("(opportunity only) Update the pipeline scope."),
6245
+ defaultInPipelines: import_zod41.z.array(import_zod41.z.string()).optional().describe("(opportunity only) Update the default-in-pipelines list."),
6246
+ locationId: import_zod41.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
6117
6247
  },
6118
6248
  async ({ listId, name, filters, columns, pipelineIds, defaultInPipelines, locationId: locationId2 }) => {
6119
6249
  try {
@@ -6138,9 +6268,9 @@ ${text2}`);
6138
6268
  "delete_smart_list",
6139
6269
  "Permanently delete a smart list. IRREVERSIBLE. The list configuration is removed but the contacts/opportunities themselves are NOT touched \u2014 smart lists are just saved filters. Any workflow trigger / dashboard / report that referenced this list by ID will stop working.",
6140
6270
  {
6141
- listId: import_zod40.z.string().describe("The smart list ID to delete."),
6142
- confirm: import_zod40.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action."),
6143
- locationId: import_zod40.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
6271
+ listId: import_zod41.z.string().describe("The smart list ID to delete."),
6272
+ confirm: import_zod41.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action."),
6273
+ locationId: import_zod41.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
6144
6274
  },
6145
6275
  async ({ listId, locationId: locationId2 }) => {
6146
6276
  try {
@@ -6155,7 +6285,7 @@ ${text2}`);
6155
6285
  }
6156
6286
 
6157
6287
  // src/tools/reputation.ts
6158
- var import_zod41 = require("zod");
6288
+ var import_zod42 = require("zod");
6159
6289
  var REPUTATION_BASE = "https://backend.leadconnectorhq.com/reputation";
6160
6290
  function registerReputationTools(server2, builderClient) {
6161
6291
  const client = builderClient;
@@ -6176,7 +6306,7 @@ ${text2}`);
6176
6306
  "get_review_link_list",
6177
6307
  "List the review-link destinations configured for a location \u2014 the platforms (Google, Facebook, etc.) where review requests send contacts. Each entry has a label and the public review URL. Useful for: building review-request workflows (the workflow goal condition `review_request_clicked` references these review-link ids), and auditing which review platforms a sub-account has connected. NOTE: listing the actual reviews that come BACK (and responding to them) is not yet available \u2014 that endpoint needs a DevTools capture against a live account with connected review platforms.",
6178
6308
  {
6179
- locationId: import_zod41.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
6309
+ locationId: import_zod42.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
6180
6310
  },
6181
6311
  async ({ locationId: locationId2 }) => {
6182
6312
  try {
@@ -6191,7 +6321,7 @@ ${text2}`);
6191
6321
  }
6192
6322
 
6193
6323
  // src/tools/email-campaigns.ts
6194
- var import_zod42 = require("zod");
6324
+ var import_zod43 = require("zod");
6195
6325
  var SVC_BASE = "https://services.leadconnectorhq.com";
6196
6326
  function registerEmailCampaignTools(server2, builderClient) {
6197
6327
  const client = builderClient;
@@ -6200,15 +6330,15 @@ function registerEmailCampaignTools(server2, builderClient) {
6200
6330
  "create_email_campaign",
6201
6331
  "Create an email campaign / broadcast DRAFT from an existing email template. Requires a templateId (create one first with create_email_template). The campaign is created as a draft \u2014 to actually SEND or schedule it, finish in the GHL UI: the send/schedule endpoint isn't available through the API yet. There's also no API delete for campaigns, so drafts created here are removed via the GHL UI. Despite those limits, this gets the campaign 90% built \u2014 template, subject, sender, name all set programmatically.",
6202
6332
  {
6203
- templateId: import_zod42.z.string().describe("ID of an email template (from create_email_template or list_email_templates) to use as the campaign body."),
6204
- name: import_zod42.z.string().optional().describe("Internal campaign name (shown in the campaigns list, not to recipients). Defaults to a GHL-generated name."),
6205
- subject: import_zod42.z.string().optional().describe("Email subject line recipients see."),
6206
- fromName: import_zod42.z.string().optional().describe("Sender display name."),
6207
- fromEmail: import_zod42.z.string().optional().describe("Sender email address. Must be a verified sending address in the location."),
6208
- isPlainText: import_zod42.z.boolean().optional().describe("Send as plain text instead of HTML. Defaults to false."),
6209
- enableResendToUnopened: import_zod42.z.boolean().optional().describe("Auto-resend to contacts who didn't open. Defaults to false."),
6210
- hasUtmTracking: import_zod42.z.boolean().optional().describe("Append UTM tracking params to links. Defaults to false."),
6211
- locationId: import_zod42.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
6333
+ templateId: import_zod43.z.string().describe("ID of an email template (from create_email_template or list_email_templates) to use as the campaign body."),
6334
+ name: import_zod43.z.string().optional().describe("Internal campaign name (shown in the campaigns list, not to recipients). Defaults to a GHL-generated name."),
6335
+ subject: import_zod43.z.string().optional().describe("Email subject line recipients see."),
6336
+ fromName: import_zod43.z.string().optional().describe("Sender display name."),
6337
+ fromEmail: import_zod43.z.string().optional().describe("Sender email address. Must be a verified sending address in the location."),
6338
+ isPlainText: import_zod43.z.boolean().optional().describe("Send as plain text instead of HTML. Defaults to false."),
6339
+ enableResendToUnopened: import_zod43.z.boolean().optional().describe("Auto-resend to contacts who didn't open. Defaults to false."),
6340
+ hasUtmTracking: import_zod43.z.boolean().optional().describe("Append UTM tracking params to links. Defaults to false."),
6341
+ locationId: import_zod43.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
6212
6342
  },
6213
6343
  async ({ templateId, name, subject, fromName, fromEmail, isPlainText, enableResendToUnopened, hasUtmTracking, locationId: locationId2 }) => {
6214
6344
  try {
@@ -6245,61 +6375,131 @@ ${text2}`);
6245
6375
  );
6246
6376
  }
6247
6377
 
6378
+ // src/tools/memberships.ts
6379
+ var import_zod44 = require("zod");
6380
+ var MEMBERSHIP_BASE = "https://backend.leadconnectorhq.com/membership";
6381
+ function registerMembershipTools(server2, builderClient) {
6382
+ const client = builderClient;
6383
+ if (!client) return;
6384
+ async function membershipRequest(path6) {
6385
+ const headers = await client.buildHeaders();
6386
+ const response = await fetch(`${MEMBERSHIP_BASE}${path6}`, { method: "GET", headers });
6387
+ if (!response.ok) {
6388
+ const text2 = await response.text();
6389
+ throw new Error(`Membership API Error ${response.status}: GET ${path6}
6390
+ ${text2}`);
6391
+ }
6392
+ const text = await response.text();
6393
+ if (!text) return {};
6394
+ return JSON.parse(text);
6395
+ }
6396
+ server2.tool(
6397
+ "list_membership_offers",
6398
+ "List a location's membership offers and products in one call. Returns { products: [...], offers: [...] }. Products are courses/communities; offers are the access grants (what a contact gets enrolled in). Use the returned ids with membership trigger conditions like offer_access_granted / product_completed. READ-ONLY \u2014 creating offers/products happens in the GHL Memberships UI.",
6399
+ {
6400
+ locationId: import_zod44.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
6401
+ },
6402
+ async ({ locationId: locationId2 }) => {
6403
+ try {
6404
+ const loc = locationId2 ?? client.locationId;
6405
+ const result = await membershipRequest(`/smart-list/offers-products/${loc}`);
6406
+ return jsonResponse(result);
6407
+ } catch (error) {
6408
+ return errorResponse(error);
6409
+ }
6410
+ }
6411
+ );
6412
+ server2.tool(
6413
+ "list_membership_categories",
6414
+ "List all membership/course categories in a location. Categories group lessons inside a course/product. Use the returned ids with the category_completed / category_started trigger conditions. READ-ONLY.",
6415
+ {
6416
+ limit: import_zod44.z.number().optional().describe("Max categories to return. Defaults to a large value (effectively all)."),
6417
+ locationId: import_zod44.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
6418
+ },
6419
+ async ({ limit, locationId: locationId2 }) => {
6420
+ try {
6421
+ const loc = locationId2 ?? client.locationId;
6422
+ const result = await membershipRequest(`/smart-list/location/${loc}/workflow?type=category&limit=${limit ?? 1e5}`);
6423
+ return jsonResponse(result);
6424
+ } catch (error) {
6425
+ return errorResponse(error);
6426
+ }
6427
+ }
6428
+ );
6429
+ server2.tool(
6430
+ "list_membership_lessons",
6431
+ "List all membership/course lessons in a location. Use the returned ids with the lesson_completed / lesson_started trigger conditions. READ-ONLY.",
6432
+ {
6433
+ limit: import_zod44.z.number().optional().describe("Max lessons to return. Defaults to a large value (effectively all)."),
6434
+ locationId: import_zod44.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
6435
+ },
6436
+ async ({ limit, locationId: locationId2 }) => {
6437
+ try {
6438
+ const loc = locationId2 ?? client.locationId;
6439
+ const result = await membershipRequest(`/smart-list/location/${loc}/workflow?type=lesson&limit=${limit ?? 1e5}`);
6440
+ return jsonResponse(result);
6441
+ } catch (error) {
6442
+ return errorResponse(error);
6443
+ }
6444
+ }
6445
+ );
6446
+ }
6447
+
6248
6448
  // src/tools/template-deployer.ts
6249
- var import_zod43 = require("zod");
6250
- var fs3 = __toESM(require("fs"));
6251
- var path3 = __toESM(require("path"));
6449
+ var import_zod45 = require("zod");
6450
+ var fs4 = __toESM(require("fs"));
6451
+ var path4 = __toESM(require("path"));
6252
6452
  function delay3(ms) {
6253
6453
  return new Promise((resolve5) => setTimeout(resolve5, ms));
6254
6454
  }
6255
- var TemplateSchema = import_zod43.z.object({
6256
- templateName: import_zod43.z.string(),
6257
- templateVersion: import_zod43.z.string().optional(),
6258
- description: import_zod43.z.string().optional().default(""),
6259
- questionnaire: import_zod43.z.array(import_zod43.z.object({
6260
- id: import_zod43.z.string(),
6261
- question: import_zod43.z.string(),
6262
- type: import_zod43.z.string(),
6263
- required: import_zod43.z.boolean().optional(),
6264
- placeholder: import_zod43.z.string().optional()
6455
+ var TemplateSchema = import_zod45.z.object({
6456
+ templateName: import_zod45.z.string(),
6457
+ templateVersion: import_zod45.z.string().optional(),
6458
+ description: import_zod45.z.string().optional().default(""),
6459
+ questionnaire: import_zod45.z.array(import_zod45.z.object({
6460
+ id: import_zod45.z.string(),
6461
+ question: import_zod45.z.string(),
6462
+ type: import_zod45.z.string(),
6463
+ required: import_zod45.z.boolean().optional(),
6464
+ placeholder: import_zod45.z.string().optional()
6265
6465
  })).optional().default([]),
6266
- location: import_zod43.z.record(import_zod43.z.unknown()).optional(),
6267
- tags: import_zod43.z.array(import_zod43.z.string()).optional(),
6268
- customFields: import_zod43.z.array(import_zod43.z.object({
6269
- name: import_zod43.z.string(),
6270
- dataType: import_zod43.z.string()
6466
+ location: import_zod45.z.record(import_zod45.z.unknown()).optional(),
6467
+ tags: import_zod45.z.array(import_zod45.z.string()).optional(),
6468
+ customFields: import_zod45.z.array(import_zod45.z.object({
6469
+ name: import_zod45.z.string(),
6470
+ dataType: import_zod45.z.string()
6271
6471
  })).optional(),
6272
- pipelines: import_zod43.z.array(import_zod43.z.object({
6273
- name: import_zod43.z.string(),
6274
- stages: import_zod43.z.array(import_zod43.z.object({ position: import_zod43.z.number(), name: import_zod43.z.string() }))
6472
+ pipelines: import_zod45.z.array(import_zod45.z.object({
6473
+ name: import_zod45.z.string(),
6474
+ stages: import_zod45.z.array(import_zod45.z.object({ position: import_zod45.z.number(), name: import_zod45.z.string() }))
6275
6475
  })).optional(),
6276
- workflows: import_zod43.z.array(import_zod43.z.object({
6277
- name: import_zod43.z.string(),
6278
- condition: import_zod43.z.string().optional(),
6279
- actions: import_zod43.z.array(import_zod43.z.record(import_zod43.z.unknown())).optional().default([])
6476
+ workflows: import_zod45.z.array(import_zod45.z.object({
6477
+ name: import_zod45.z.string(),
6478
+ condition: import_zod45.z.string().optional(),
6479
+ actions: import_zod45.z.array(import_zod45.z.record(import_zod45.z.unknown())).optional().default([])
6280
6480
  })).optional(),
6281
- calendars: import_zod43.z.array(import_zod43.z.object({
6282
- name: import_zod43.z.string(),
6283
- description: import_zod43.z.string().optional()
6481
+ calendars: import_zod45.z.array(import_zod45.z.object({
6482
+ name: import_zod45.z.string(),
6483
+ description: import_zod45.z.string().optional()
6284
6484
  })).optional()
6285
6485
  });
6286
6486
  function registerTemplateDeployerTools(server2, client) {
6287
6487
  const builderClient = WorkflowBuilderClient.fromEnv();
6288
- const templatesDir = path3.resolve(__dirname, "..", "templates");
6488
+ const templatesDir = path4.resolve(__dirname, "..", "templates");
6289
6489
  function validateTemplatePath(templateFile) {
6290
- const resolved = path3.resolve(templateFile);
6291
- const realPath = fs3.existsSync(resolved) ? fs3.realpathSync(resolved) : resolved;
6490
+ const resolved = path4.resolve(templateFile);
6491
+ const realPath = fs4.existsSync(resolved) ? fs4.realpathSync(resolved) : resolved;
6292
6492
  const allowedDirs = [
6293
6493
  templatesDir,
6294
- path3.resolve(process.cwd(), "templates"),
6295
- path3.resolve(__dirname, "..", "..", "templates")
6296
- ].map((d) => fs3.existsSync(d) ? fs3.realpathSync(d) : d);
6297
- const isAllowed = allowedDirs.some((dir) => realPath.startsWith(dir + path3.sep));
6494
+ path4.resolve(process.cwd(), "templates"),
6495
+ path4.resolve(__dirname, "..", "..", "templates")
6496
+ ].map((d) => fs4.existsSync(d) ? fs4.realpathSync(d) : d);
6497
+ const isAllowed = allowedDirs.some((dir) => realPath.startsWith(dir + path4.sep));
6298
6498
  if (!isAllowed) {
6299
6499
  throw new Error(`Template file must be inside a templates/ directory. Got: ${realPath}`);
6300
6500
  }
6301
- if (path3.relative(allowedDirs[0], realPath).startsWith("..")) {
6302
- const otherMatch = allowedDirs.slice(1).some((d) => !path3.relative(d, realPath).startsWith(".."));
6501
+ if (path4.relative(allowedDirs[0], realPath).startsWith("..")) {
6502
+ const otherMatch = allowedDirs.slice(1).some((d) => !path4.relative(d, realPath).startsWith(".."));
6303
6503
  if (!otherMatch) {
6304
6504
  throw new Error(`Template path escapes allowed directory.`);
6305
6505
  }
@@ -6314,19 +6514,19 @@ function registerTemplateDeployerTools(server2, client) {
6314
6514
  try {
6315
6515
  const dirs = [
6316
6516
  templatesDir,
6317
- path3.resolve(process.cwd(), "templates"),
6318
- path3.resolve(__dirname, "..", "..", "templates")
6517
+ path4.resolve(process.cwd(), "templates"),
6518
+ path4.resolve(__dirname, "..", "..", "templates")
6319
6519
  ];
6320
6520
  const templates = [];
6321
6521
  for (const dir of dirs) {
6322
- if (!fs3.existsSync(dir)) continue;
6323
- const files = fs3.readdirSync(dir).filter((f) => f.endsWith(".json"));
6522
+ if (!fs4.existsSync(dir)) continue;
6523
+ const files = fs4.readdirSync(dir).filter((f) => f.endsWith(".json"));
6324
6524
  for (const file of files) {
6325
6525
  try {
6326
- const content = JSON.parse(fs3.readFileSync(path3.join(dir, file), "utf-8"));
6526
+ const content = JSON.parse(fs4.readFileSync(path4.join(dir, file), "utf-8"));
6327
6527
  templates.push({
6328
6528
  name: content.templateName || file,
6329
- file: path3.join(dir, file),
6529
+ file: path4.join(dir, file),
6330
6530
  description: content.description || ""
6331
6531
  });
6332
6532
  } catch {
@@ -6351,12 +6551,12 @@ function registerTemplateDeployerTools(server2, client) {
6351
6551
  "get_template_questionnaire",
6352
6552
  "Get the questionnaire for a specific template. Returns all the questions that need to be answered before deploying. Present these to the user one at a time in a conversational style.",
6353
6553
  {
6354
- templateFile: import_zod43.z.string().describe("Path to the template JSON file (from list_templates).")
6554
+ templateFile: import_zod45.z.string().describe("Path to the template JSON file (from list_templates).")
6355
6555
  },
6356
6556
  async ({ templateFile }) => {
6357
6557
  try {
6358
6558
  const safePath = validateTemplatePath(templateFile);
6359
- const content = JSON.parse(fs3.readFileSync(safePath, "utf-8"));
6559
+ const content = JSON.parse(fs4.readFileSync(safePath, "utf-8"));
6360
6560
  return {
6361
6561
  content: [
6362
6562
  {
@@ -6384,16 +6584,16 @@ function registerTemplateDeployerTools(server2, client) {
6384
6584
  "deploy_template",
6385
6585
  "Deploy a template to set up a GHL sub-account. Creates tags, custom fields, pipelines with stages, calendars, workflows, and forms based on the template and the user's questionnaire answers. This is the main setup automation tool.",
6386
6586
  {
6387
- templateFile: import_zod43.z.string().describe("Path to the template JSON file."),
6388
- answers: import_zod43.z.record(import_zod43.z.unknown()).describe("Questionnaire answers keyed by question ID (e.g. {business_name: 'My Clinic', business_phone: '+15551234567', ...})."),
6389
- locationId: import_zod43.z.string().optional().describe("Location ID to deploy to. Uses default if not specified."),
6390
- dryRun: import_zod43.z.boolean().optional().describe("If true, shows what would be created without actually creating anything. Defaults to false.")
6587
+ templateFile: import_zod45.z.string().describe("Path to the template JSON file."),
6588
+ answers: import_zod45.z.record(import_zod45.z.unknown()).describe("Questionnaire answers keyed by question ID (e.g. {business_name: 'My Clinic', business_phone: '+15551234567', ...})."),
6589
+ locationId: import_zod45.z.string().optional().describe("Location ID to deploy to. Uses default if not specified."),
6590
+ dryRun: import_zod45.z.boolean().optional().describe("If true, shows what would be created without actually creating anything. Defaults to false.")
6391
6591
  },
6392
6592
  async ({ templateFile, answers, locationId: locationId2, dryRun }) => {
6393
6593
  try {
6394
6594
  const locId = client.resolveLocationId(locationId2);
6395
6595
  const safePath = validateTemplatePath(templateFile);
6396
- const template = TemplateSchema.parse(JSON.parse(fs3.readFileSync(safePath, "utf-8")));
6596
+ const template = TemplateSchema.parse(JSON.parse(fs4.readFileSync(safePath, "utf-8")));
6397
6597
  const resolve5 = (text) => {
6398
6598
  if (typeof text !== "string") return text;
6399
6599
  let result = text;
@@ -6633,7 +6833,7 @@ ${errors.join("\n")}` : "\nNo errors!",
6633
6833
  }
6634
6834
 
6635
6835
  // src/tools/validators.ts
6636
- var import_zod44 = require("zod");
6836
+ var import_zod46 = require("zod");
6637
6837
  function extractFromTrigger(trigger, refs) {
6638
6838
  const triggerName = String(trigger.name ?? trigger.type ?? "unnamed trigger");
6639
6839
  const where = `trigger "${triggerName}"`;
@@ -6768,7 +6968,7 @@ function registerValidatorTools(server2, client, builderClient) {
6768
6968
  "validate_workflow",
6769
6969
  "Pre-flight ID validation for a deployed GHL workflow. Scans every trigger and action for references to pipelines, pipeline stages, custom fields, users, workflows, forms, calendars, and surveys; verifies each ID exists in the current location. Use this BEFORE publish_workflow when a workflow has been edited, or whenever a published workflow stops behaving as expected. Catches the silent-failure bug where invalid IDs make GHL skip all subsequent actions without warning. Returns a structured report of valid + missing references.",
6770
6970
  {
6771
- workflowId: import_zod44.z.string().describe("The workflow ID to validate.")
6971
+ workflowId: import_zod46.z.string().describe("The workflow ID to validate.")
6772
6972
  },
6773
6973
  async ({ workflowId }) => {
6774
6974
  try {
@@ -7139,77 +7339,16 @@ function registerAllTools(server2, client, registry2, mcpVersion) {
7139
7339
  registerSmartListTools(server2, builderClient);
7140
7340
  registerReputationTools(server2, builderClient);
7141
7341
  registerEmailCampaignTools(server2, builderClient);
7342
+ registerMembershipTools(server2, builderClient);
7142
7343
  registerValidatorTools(server2, client, builderClient);
7143
7344
  registerDiagnosticTools(server2, mcpVersion ?? "unknown", client, builderClient, registry2 ?? null);
7144
7345
  registerLocationSwitcherTools(server2, client, builderClient, registry2, mcpVersion);
7145
7346
  }
7146
7347
 
7147
- // src/credentials-store.ts
7148
- var fs4 = __toESM(require("fs"));
7149
- var path4 = __toESM(require("path"));
7150
- var os = __toESM(require("os"));
7151
- var import_zod45 = require("zod");
7152
- var APP_NAME = "elitedcs-ghl-mcp";
7153
- var CredentialsSchema = import_zod45.z.object({
7154
- license_key: import_zod45.z.string().min(1),
7155
- email: import_zod45.z.string().email(),
7156
- verified_at: import_zod45.z.string().min(1),
7157
- ghl_api_key: import_zod45.z.string().min(1),
7158
- ghl_location_id: import_zod45.z.string().min(1),
7159
- ghl_company_id: import_zod45.z.string().optional(),
7160
- ghl_user_id: import_zod45.z.string().optional(),
7161
- ghl_firebase_api_key: import_zod45.z.string().optional(),
7162
- ghl_firebase_refresh_token: import_zod45.z.string().optional()
7163
- });
7164
- function appDataDir() {
7165
- const home = os.homedir();
7166
- if (process.platform === "darwin") {
7167
- return path4.join(home, "Library", "Application Support", APP_NAME);
7168
- }
7169
- if (process.platform === "win32") {
7170
- const appData = process.env.APPDATA || path4.join(home, "AppData", "Roaming");
7171
- return path4.join(appData, APP_NAME);
7172
- }
7173
- const xdg = process.env.XDG_CONFIG_HOME || path4.join(home, ".config");
7174
- return path4.join(xdg, APP_NAME);
7175
- }
7176
- function credentialsPath() {
7177
- return path4.join(appDataDir(), "credentials.json");
7178
- }
7179
- function readCredentials() {
7180
- const file = credentialsPath();
7181
- if (!fs4.existsSync(file)) return null;
7182
- try {
7183
- const raw = fs4.readFileSync(file, "utf-8");
7184
- const parsed = JSON.parse(raw);
7185
- return CredentialsSchema.parse(parsed);
7186
- } catch {
7187
- return null;
7188
- }
7189
- }
7190
- function writeCredentials(creds) {
7191
- const dir = appDataDir();
7192
- fs4.mkdirSync(dir, { recursive: true });
7193
- if (process.platform !== "win32") {
7194
- try {
7195
- fs4.chmodSync(dir, 448);
7196
- } catch {
7197
- }
7198
- }
7199
- const file = credentialsPath();
7200
- fs4.writeFileSync(file, JSON.stringify(creds, null, 2) + "\n", "utf-8");
7201
- if (process.platform !== "win32") {
7202
- try {
7203
- fs4.chmodSync(file, 384);
7204
- } catch {
7205
- }
7206
- }
7207
- }
7208
-
7209
7348
  // src/setup-tool.ts
7210
7349
  var os2 = __toESM(require("os"));
7211
7350
  var crypto3 = __toESM(require("crypto"));
7212
- var import_zod46 = require("zod");
7351
+ var import_zod47 = require("zod");
7213
7352
  var LICENSE_API = "https://elitedcs.com/api/validate-license";
7214
7353
  var GHL_API = "https://services.leadconnectorhq.com";
7215
7354
  var FIREBASE_TOKEN_API = "https://securetoken.googleapis.com/v1/token";
@@ -7278,16 +7417,16 @@ async function validateFirebase(firebaseKey, refreshToken) {
7278
7417
  function registerSetupTool(server2) {
7279
7418
  server2.tool(
7280
7419
  "setup_ghl_mcp",
7281
- "First-run setup for GHL Command MCP. Validates your license and GHL credentials, then writes them to a per-user credentials file. Restart Claude after this completes to load all 198 tools (161 if you skip the optional Firebase fields; add Firebase later with enable_workflow_builder).",
7420
+ "First-run setup for GHL Command MCP. Validates your license and GHL credentials, then writes them to a per-user credentials file. Restart Claude after this completes to load all 201 tools (161 if you skip the optional Firebase fields; add Firebase later with enable_workflow_builder).",
7282
7421
  {
7283
- email: import_zod46.z.string().email().describe("Email used at purchase."),
7284
- license_key: import_zod46.z.string().min(20).describe("License key from your purchase email."),
7285
- ghl_api_key: import_zod46.z.string().min(10).describe("GHL Private Integration key (starts with 'pit-'). Created INSIDE the sub-account at Settings > Integrations > Private Integrations."),
7286
- ghl_location_id: import_zod46.z.string().min(10).describe("GHL Location ID (sub-account ID). Found in your GHL URL: /location/THIS_PART/dashboard."),
7287
- ghl_company_id: import_zod46.z.string().optional().describe("(Agency only) Company ID for multi-location access."),
7288
- ghl_user_id: import_zod46.z.string().optional().describe("(Workflow Builder, optional) Firebase User ID. See README for browser capture instructions."),
7289
- ghl_firebase_api_key: import_zod46.z.string().optional().describe("(Workflow Builder, optional) Firebase API Key starting with 'AIza'."),
7290
- ghl_firebase_refresh_token: import_zod46.z.string().optional().describe("(Workflow Builder, optional) Firebase refresh token starting with 'AMf-'.")
7422
+ email: import_zod47.z.string().email().describe("Email used at purchase."),
7423
+ license_key: import_zod47.z.string().min(20).describe("License key from your purchase email."),
7424
+ ghl_api_key: import_zod47.z.string().min(10).describe("GHL Private Integration key (starts with 'pit-'). Created INSIDE the sub-account at Settings > Integrations > Private Integrations."),
7425
+ ghl_location_id: import_zod47.z.string().min(10).describe("GHL Location ID (sub-account ID). Found in your GHL URL: /location/THIS_PART/dashboard."),
7426
+ ghl_company_id: import_zod47.z.string().optional().describe("(Agency only) Company ID for multi-location access."),
7427
+ ghl_user_id: import_zod47.z.string().optional().describe("(Workflow Builder, optional) Firebase User ID. See README for browser capture instructions."),
7428
+ ghl_firebase_api_key: import_zod47.z.string().optional().describe("(Workflow Builder, optional) Firebase API Key starting with 'AIza'."),
7429
+ ghl_firebase_refresh_token: import_zod47.z.string().optional().describe("(Workflow Builder, optional) Firebase refresh token starting with 'AMf-'.")
7291
7430
  },
7292
7431
  async (args) => {
7293
7432
  const lic = await validateLicense(args.email, args.license_key);
@@ -7333,7 +7472,7 @@ Note: Firebase credentials rejected (${fb.error}). Saved without Workflow Builde
7333
7472
  ghl_firebase_api_key: workflowBuilderEnabled ? args.ghl_firebase_api_key?.trim() : void 0,
7334
7473
  ghl_firebase_refresh_token: workflowBuilderEnabled ? args.ghl_firebase_refresh_token?.trim() : void 0
7335
7474
  });
7336
- const toolCount = workflowBuilderEnabled ? "198" : "161";
7475
+ const toolCount = workflowBuilderEnabled ? "201" : "161";
7337
7476
  const wfLine = workflowBuilderEnabled ? "Workflow Builder: enabled." : "Workflow Builder: not configured (optional).";
7338
7477
  const wfTip = workflowBuilderEnabled ? "" : "\nTo enable Workflow Builder later (8 extra tools): run enable_workflow_builder with your three Firebase values. No need to re-enter license/API key/location ID.";
7339
7478
  return {
@@ -7361,11 +7500,11 @@ Note: Firebase credentials rejected (${fb.error}). Saved without Workflow Builde
7361
7500
  function registerEnableWorkflowBuilderTool(server2) {
7362
7501
  server2.tool(
7363
7502
  "enable_workflow_builder",
7364
- "Add Firebase credentials to an existing GHL Command install to unlock 30 additional tools across 6 modules: workflow builder (create/edit/clone/delete/publish/validate workflows, build_if_else_branch, build_goal_event, get_trigger_registry), funnel + page builder (10 tools), form builder (5 tools), pipeline builder (5 tools), and workflow cloning. Requires you've already run setup_ghl_mcp. Capture the three Firebase values from your GHL browser session \u2014 see elitedcs.com/ghl-mcp-firebase for step-by-step DevTools instructions. Tool count goes from 161 to 198 after the next Claude restart.",
7503
+ "Add Firebase credentials to an existing GHL Command install to unlock 30 additional tools across 6 modules: workflow builder (create/edit/clone/delete/publish/validate workflows, build_if_else_branch, build_goal_event, get_trigger_registry), funnel + page builder (10 tools), form builder (5 tools), pipeline builder (5 tools), and workflow cloning. Requires you've already run setup_ghl_mcp. Capture the three Firebase values from your GHL browser session \u2014 see elitedcs.com/ghl-mcp-firebase for step-by-step DevTools instructions. Tool count goes from 161 to 201 after the next Claude restart.",
7365
7504
  {
7366
- ghl_user_id: import_zod46.z.string().min(10).describe("Firebase User ID (uid). DevTools \u2192 Application \u2192 IndexedDB \u2192 firebaseLocalStorageDb \u2192 firebaseLocalStorage \u2192 the value.uid field of the firebase:authUser row."),
7367
- ghl_firebase_api_key: import_zod46.z.string().min(10).describe("Firebase API Key starting with 'AIza'. The string between 'firebase:authUser:' and ':[DEFAULT]' in the row's Key column."),
7368
- ghl_firebase_refresh_token: import_zod46.z.string().min(10).describe("Firebase refresh token. value.stsTokenManager.refreshToken in the firebase:authUser row.")
7505
+ ghl_user_id: import_zod47.z.string().min(10).describe("Firebase User ID (uid). DevTools \u2192 Application \u2192 IndexedDB \u2192 firebaseLocalStorageDb \u2192 firebaseLocalStorage \u2192 the value.uid field of the firebase:authUser row."),
7506
+ ghl_firebase_api_key: import_zod47.z.string().min(10).describe("Firebase API Key starting with 'AIza'. The string between 'firebase:authUser:' and ':[DEFAULT]' in the row's Key column."),
7507
+ ghl_firebase_refresh_token: import_zod47.z.string().min(10).describe("Firebase refresh token. value.stsTokenManager.refreshToken in the firebase:authUser row.")
7369
7508
  },
7370
7509
  async (args) => {
7371
7510
  const existing = readCredentials();
@@ -7408,7 +7547,7 @@ DevTools steps: https://elitedcs.com/ghl-mcp-firebase`
7408
7547
  "",
7409
7548
  "Firebase credentials verified and saved.",
7410
7549
  "",
7411
- "**Restart Claude (quit fully and reopen) to load the workflow builder + funnel builder + pipeline builder + form builder + workflow cloner tools (198 total).**",
7550
+ "**Restart Claude (quit fully and reopen) to load the workflow builder + funnel builder + pipeline builder + form builder + workflow cloner tools (201 total).**",
7412
7551
  "",
7413
7552
  'After restart, try: "List my workflows in full detail" or "Validate workflow <id>".',
7414
7553
  "",
@@ -7460,7 +7599,9 @@ function hardenSecretFilePerms() {
7460
7599
  const repoDir = path5.resolve(__dirname, "..");
7461
7600
  const candidates = [
7462
7601
  { file: path5.join(repoDir, "start-mcp.sh"), mode: 448 },
7463
- { file: path5.join(repoDir, ".ghl-tokens.json"), mode: 384 }
7602
+ // Legacy registry location (pre-migration); new location lives in app-data.
7603
+ { file: path5.join(repoDir, ".ghl-tokens.json"), mode: 384 },
7604
+ { file: tokenRegistryPath(), mode: 384 }
7464
7605
  ];
7465
7606
  for (const { file, mode } of candidates) {
7466
7607
  let current;