@elitedcs/ghl-mcp 3.13.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/CHANGELOG.md +18 -0
- package/dist/index.js +1138 -1068
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -31,7 +31,7 @@ var require_package = __commonJS({
|
|
|
31
31
|
"package.json"(exports2, module2) {
|
|
32
32
|
module2.exports = {
|
|
33
33
|
name: "@elitedcs/ghl-mcp",
|
|
34
|
-
version: "3.13.
|
|
34
|
+
version: "3.13.1",
|
|
35
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: {
|
|
@@ -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
|
|
273
|
+
var os = __toESM(require("os"));
|
|
268
274
|
var import_zod = require("zod");
|
|
269
|
-
var
|
|
270
|
-
var
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
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
|
-
|
|
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 (
|
|
289
|
-
const raw =
|
|
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
|
-
|
|
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
|
-
|
|
309
|
-
|
|
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
|
-
|
|
425
|
+
fs2.chmodSync(this.filePath, 384);
|
|
312
426
|
} catch {
|
|
313
427
|
}
|
|
314
428
|
} catch (error) {
|
|
315
429
|
try {
|
|
316
|
-
|
|
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
|
|
387
|
-
var
|
|
500
|
+
var fs3 = __toESM(require("fs"));
|
|
501
|
+
var path3 = __toESM(require("path"));
|
|
388
502
|
var dotenv = __toESM(require("dotenv"));
|
|
389
|
-
var
|
|
503
|
+
var import_zod4 = require("zod");
|
|
390
504
|
|
|
391
505
|
// src/trigger-schemas.ts
|
|
392
|
-
var
|
|
393
|
-
var TriggerActionSchema =
|
|
394
|
-
workflow_id:
|
|
395
|
-
type:
|
|
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 =
|
|
398
|
-
id:
|
|
399
|
-
date_added:
|
|
400
|
-
deleted:
|
|
401
|
-
belongs_to:
|
|
402
|
-
location_id:
|
|
403
|
-
origin_id:
|
|
404
|
-
active:
|
|
405
|
-
workflow_id:
|
|
406
|
-
masterType:
|
|
407
|
-
name:
|
|
408
|
-
actions:
|
|
409
|
-
schedule_config:
|
|
410
|
-
date_updated:
|
|
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:
|
|
428
|
-
conditions:
|
|
429
|
-
operator:
|
|
430
|
-
field:
|
|
431
|
-
value:
|
|
432
|
-
title:
|
|
433
|
-
type:
|
|
434
|
-
id:
|
|
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:
|
|
440
|
-
conditions:
|
|
441
|
-
operator:
|
|
442
|
-
field:
|
|
443
|
-
value:
|
|
444
|
-
title:
|
|
445
|
-
type:
|
|
446
|
-
id:
|
|
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:
|
|
689
|
-
conditions:
|
|
690
|
-
operator:
|
|
691
|
-
field:
|
|
692
|
-
value:
|
|
693
|
-
title:
|
|
694
|
-
type:
|
|
695
|
-
id:
|
|
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:
|
|
700
|
-
conditions:
|
|
701
|
-
operator:
|
|
702
|
-
field:
|
|
703
|
-
value:
|
|
704
|
-
title:
|
|
705
|
-
type:
|
|
706
|
-
id:
|
|
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:
|
|
713
|
-
conditions:
|
|
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 =
|
|
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 =
|
|
782
|
-
id_token:
|
|
783
|
-
refresh_token:
|
|
784
|
-
expires_in:
|
|
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 =
|
|
900
|
+
var WorkflowActionSchema = import_zod4.z.custom(
|
|
787
901
|
(value) => typeof value === "object" && value !== null && "type" in value
|
|
788
902
|
);
|
|
789
|
-
var WorkflowFullSchema =
|
|
790
|
-
_id:
|
|
791
|
-
name:
|
|
792
|
-
status:
|
|
793
|
-
version:
|
|
794
|
-
dataVersion:
|
|
795
|
-
timezone:
|
|
796
|
-
workflowData:
|
|
797
|
-
triggers:
|
|
798
|
-
createdAt:
|
|
799
|
-
updatedAt:
|
|
800
|
-
locationId:
|
|
801
|
-
stopOnResponse:
|
|
802
|
-
allowMultiple:
|
|
803
|
-
allowMultipleOpportunity:
|
|
804
|
-
autoMarkAsRead:
|
|
805
|
-
removeContactFromLastStep:
|
|
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 =
|
|
921
|
+
var CreateWorkflowResponseSchema = import_zod4.z.union([
|
|
808
922
|
WorkflowFullSchema,
|
|
809
|
-
|
|
810
|
-
|
|
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
|
|
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
|
|
1031
|
-
if (
|
|
1032
|
-
|
|
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
|
-
|
|
1039
|
-
|
|
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
|
|
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
|
|
1371
|
-
var ContactSchema =
|
|
1372
|
-
id:
|
|
1373
|
-
locationId:
|
|
1374
|
-
firstName:
|
|
1375
|
-
lastName:
|
|
1376
|
-
name:
|
|
1377
|
-
email:
|
|
1378
|
-
phone:
|
|
1379
|
-
tags:
|
|
1380
|
-
source:
|
|
1381
|
-
dateAdded:
|
|
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 =
|
|
1384
|
-
contacts:
|
|
1385
|
-
meta:
|
|
1386
|
-
total:
|
|
1387
|
-
count:
|
|
1388
|
-
currentPage:
|
|
1389
|
-
nextPage:
|
|
1390
|
-
prevPage:
|
|
1391
|
-
startAfterId:
|
|
1392
|
-
startAfter:
|
|
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 =
|
|
1525
|
+
var ContactResponseSchema = import_zod5.z.object({
|
|
1396
1526
|
contact: ContactSchema
|
|
1397
1527
|
}).passthrough();
|
|
1398
|
-
var PipelineStageSchema =
|
|
1399
|
-
id:
|
|
1400
|
-
name:
|
|
1401
|
-
position:
|
|
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 =
|
|
1404
|
-
id:
|
|
1405
|
-
name:
|
|
1406
|
-
stages:
|
|
1407
|
-
locationId:
|
|
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 =
|
|
1410
|
-
pipelines:
|
|
1539
|
+
var PipelinesResponseSchema = import_zod5.z.object({
|
|
1540
|
+
pipelines: import_zod5.z.array(PipelineSchema)
|
|
1411
1541
|
}).passthrough();
|
|
1412
|
-
var CalendarSchema =
|
|
1413
|
-
id:
|
|
1414
|
-
name:
|
|
1415
|
-
locationId:
|
|
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 =
|
|
1418
|
-
calendars:
|
|
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:
|
|
1429
|
-
query:
|
|
1430
|
-
limit:
|
|
1431
|
-
startAfterId:
|
|
1432
|
-
sortBy:
|
|
1433
|
-
sortOrder:
|
|
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:
|
|
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:
|
|
1468
|
-
firstName:
|
|
1469
|
-
lastName:
|
|
1470
|
-
name:
|
|
1471
|
-
email:
|
|
1472
|
-
phone:
|
|
1473
|
-
tags:
|
|
1474
|
-
source:
|
|
1475
|
-
companyName:
|
|
1476
|
-
address1:
|
|
1477
|
-
city:
|
|
1478
|
-
state:
|
|
1479
|
-
postalCode:
|
|
1480
|
-
website:
|
|
1481
|
-
timezone:
|
|
1482
|
-
customFields:
|
|
1483
|
-
|
|
1484
|
-
id:
|
|
1485
|
-
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:
|
|
1507
|
-
firstName:
|
|
1508
|
-
lastName:
|
|
1509
|
-
name:
|
|
1510
|
-
email:
|
|
1511
|
-
phone:
|
|
1512
|
-
tags:
|
|
1513
|
-
source:
|
|
1514
|
-
companyName:
|
|
1515
|
-
address1:
|
|
1516
|
-
city:
|
|
1517
|
-
state:
|
|
1518
|
-
postalCode:
|
|
1519
|
-
website:
|
|
1520
|
-
timezone:
|
|
1521
|
-
customFields:
|
|
1522
|
-
|
|
1523
|
-
id:
|
|
1524
|
-
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:
|
|
1544
|
-
confirm:
|
|
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:
|
|
1556
|
-
firstName:
|
|
1557
|
-
lastName:
|
|
1558
|
-
name:
|
|
1559
|
-
email:
|
|
1560
|
-
phone:
|
|
1561
|
-
tags:
|
|
1562
|
-
source:
|
|
1563
|
-
companyName:
|
|
1564
|
-
address1:
|
|
1565
|
-
city:
|
|
1566
|
-
state:
|
|
1567
|
-
postalCode:
|
|
1568
|
-
website:
|
|
1569
|
-
timezone:
|
|
1570
|
-
customFields:
|
|
1571
|
-
|
|
1572
|
-
id:
|
|
1573
|
-
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:
|
|
1595
|
-
tags:
|
|
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:
|
|
1609
|
-
tags:
|
|
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:
|
|
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:
|
|
1634
|
-
title:
|
|
1635
|
-
body:
|
|
1636
|
-
dueDate:
|
|
1637
|
-
completed:
|
|
1638
|
-
assignedTo:
|
|
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:
|
|
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:
|
|
1668
|
-
body:
|
|
1669
|
-
userId:
|
|
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:
|
|
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:
|
|
1696
|
-
workflowId:
|
|
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:
|
|
1710
|
-
workflowId:
|
|
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
|
|
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:
|
|
1729
|
-
contactId:
|
|
1730
|
-
assignedTo:
|
|
1731
|
-
query:
|
|
1732
|
-
status:
|
|
1733
|
-
limit:
|
|
1734
|
-
startAfterDate:
|
|
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:
|
|
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:
|
|
1768
|
-
contactId:
|
|
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:
|
|
1783
|
-
limit:
|
|
1784
|
-
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:
|
|
1798
|
-
contactId:
|
|
1799
|
-
message:
|
|
1800
|
-
subject:
|
|
1801
|
-
html:
|
|
1802
|
-
emailFrom:
|
|
1803
|
-
emailTo:
|
|
1804
|
-
emailCc:
|
|
1805
|
-
emailBcc:
|
|
1806
|
-
attachments:
|
|
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:
|
|
1827
|
-
conversationId:
|
|
1828
|
-
conversationProviderId:
|
|
1829
|
-
message:
|
|
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:
|
|
1843
|
-
status:
|
|
1844
|
-
error:
|
|
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:
|
|
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
|
|
1867
|
-
var statusEnum =
|
|
1868
|
-
var statusEnumWithAll =
|
|
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:
|
|
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:
|
|
1879
|
-
pipelineStageId:
|
|
1880
|
-
contactId:
|
|
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:
|
|
1883
|
-
query:
|
|
1884
|
-
limit:
|
|
1885
|
-
startAfter:
|
|
1886
|
-
startAfterId:
|
|
1887
|
-
order:
|
|
1888
|
-
endDate:
|
|
1889
|
-
startDate:
|
|
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:
|
|
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:
|
|
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:
|
|
1932
|
-
pipelineStageId:
|
|
1933
|
-
contactId:
|
|
1934
|
-
name:
|
|
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:
|
|
1937
|
-
assignedTo:
|
|
1938
|
-
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:
|
|
1963
|
-
pipelineId:
|
|
1964
|
-
pipelineStageId:
|
|
1965
|
-
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:
|
|
1968
|
-
assignedTo:
|
|
1969
|
-
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:
|
|
1993
|
-
confirm:
|
|
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:
|
|
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:
|
|
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
|
|
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:
|
|
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:
|
|
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:
|
|
2068
|
-
name:
|
|
2069
|
-
description:
|
|
2070
|
-
slug:
|
|
2071
|
-
widgetSlug:
|
|
2072
|
-
calendarType:
|
|
2073
|
-
teamMembers:
|
|
2074
|
-
eventTitle:
|
|
2075
|
-
eventColor:
|
|
2076
|
-
slotDuration:
|
|
2077
|
-
slotBuffer:
|
|
2078
|
-
slotInterval:
|
|
2079
|
-
appointmentPerSlot:
|
|
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:
|
|
2107
|
-
name:
|
|
2108
|
-
description:
|
|
2109
|
-
slug:
|
|
2110
|
-
widgetSlug:
|
|
2111
|
-
calendarType:
|
|
2112
|
-
teamMembers:
|
|
2113
|
-
eventTitle:
|
|
2114
|
-
eventColor:
|
|
2115
|
-
slotDuration:
|
|
2116
|
-
slotBuffer:
|
|
2117
|
-
slotInterval:
|
|
2118
|
-
appointmentPerSlot:
|
|
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:
|
|
2143
|
-
confirm:
|
|
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:
|
|
2155
|
-
startDate:
|
|
2156
|
-
endDate:
|
|
2157
|
-
timezone:
|
|
2158
|
-
userId:
|
|
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:
|
|
2175
|
-
startTime:
|
|
2176
|
-
endTime:
|
|
2177
|
-
calendarId:
|
|
2178
|
-
userId:
|
|
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:
|
|
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:
|
|
2211
|
-
locationId:
|
|
2212
|
-
contactId:
|
|
2213
|
-
startTime:
|
|
2214
|
-
endTime:
|
|
2215
|
-
title:
|
|
2216
|
-
appointmentStatus:
|
|
2217
|
-
assignedUserId:
|
|
2218
|
-
address:
|
|
2219
|
-
notes:
|
|
2220
|
-
toNotify:
|
|
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:
|
|
2248
|
-
calendarId:
|
|
2249
|
-
startTime:
|
|
2250
|
-
endTime:
|
|
2251
|
-
title:
|
|
2252
|
-
appointmentStatus:
|
|
2253
|
-
assignedUserId:
|
|
2254
|
-
address:
|
|
2255
|
-
notes:
|
|
2256
|
-
toNotify:
|
|
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:
|
|
2281
|
-
confirm:
|
|
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
|
|
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:
|
|
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:
|
|
2311
|
-
name:
|
|
2312
|
-
address:
|
|
2313
|
-
city:
|
|
2314
|
-
state:
|
|
2315
|
-
postalCode:
|
|
2316
|
-
country:
|
|
2317
|
-
website:
|
|
2318
|
-
timezone:
|
|
2319
|
-
phone:
|
|
2320
|
-
email:
|
|
2321
|
-
settings:
|
|
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:
|
|
2345
|
-
limit:
|
|
2346
|
-
skip:
|
|
2347
|
-
order:
|
|
2348
|
-
isActive:
|
|
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:
|
|
2362
|
-
limit:
|
|
2363
|
-
skip:
|
|
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:
|
|
2378
|
-
name:
|
|
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:
|
|
2393
|
-
tagId:
|
|
2394
|
-
name:
|
|
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:
|
|
2409
|
-
tagId:
|
|
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:
|
|
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:
|
|
2434
|
-
name:
|
|
2435
|
-
dataType:
|
|
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:
|
|
2451
|
-
position:
|
|
2452
|
-
options:
|
|
2453
|
-
model:
|
|
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:
|
|
2471
|
-
fieldId:
|
|
2472
|
-
name:
|
|
2473
|
-
dataType:
|
|
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:
|
|
2489
|
-
position:
|
|
2490
|
-
options:
|
|
2491
|
-
model:
|
|
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:
|
|
2511
|
-
fieldId:
|
|
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:
|
|
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:
|
|
2536
|
-
name:
|
|
2537
|
-
value:
|
|
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:
|
|
2552
|
-
valueId:
|
|
2553
|
-
name:
|
|
2554
|
-
value:
|
|
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:
|
|
2570
|
-
valueId:
|
|
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
|
|
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:
|
|
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
|
|
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:
|
|
2607
|
-
limit:
|
|
2608
|
-
offset:
|
|
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:
|
|
2624
|
-
funnelId:
|
|
2625
|
-
limit:
|
|
2626
|
-
offset:
|
|
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
|
|
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:
|
|
2650
|
-
limit:
|
|
2651
|
-
skip:
|
|
2652
|
-
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:
|
|
2669
|
-
page:
|
|
2670
|
-
limit:
|
|
2671
|
-
formId:
|
|
2672
|
-
q:
|
|
2673
|
-
startAt:
|
|
2674
|
-
endAt:
|
|
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
|
|
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:
|
|
2699
|
-
limit:
|
|
2700
|
-
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:
|
|
2716
|
-
page:
|
|
2717
|
-
limit:
|
|
2718
|
-
surveyId:
|
|
2719
|
-
q:
|
|
2720
|
-
startAt:
|
|
2721
|
-
endAt:
|
|
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
|
|
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:
|
|
2746
|
-
limit:
|
|
2747
|
-
offset:
|
|
2748
|
-
startAt:
|
|
2749
|
-
endAt:
|
|
2750
|
-
search:
|
|
2751
|
-
contactId:
|
|
2752
|
-
paymentMode:
|
|
2753
|
-
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:
|
|
2779
|
-
orderId:
|
|
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:
|
|
2796
|
-
limit:
|
|
2797
|
-
offset:
|
|
2798
|
-
search:
|
|
2799
|
-
contactId:
|
|
2800
|
-
entityId:
|
|
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:
|
|
2822
|
-
limit:
|
|
2823
|
-
offset:
|
|
2824
|
-
startAt:
|
|
2825
|
-
endAt:
|
|
2826
|
-
search:
|
|
2827
|
-
entityId:
|
|
2828
|
-
paymentMode:
|
|
2829
|
-
contactId:
|
|
2830
|
-
subscriptionId:
|
|
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
|
|
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:
|
|
2862
|
-
limit:
|
|
2863
|
-
offset:
|
|
2864
|
-
search:
|
|
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:
|
|
2881
|
-
locationId:
|
|
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:
|
|
2894
|
-
productType:
|
|
2895
|
-
description:
|
|
2896
|
-
image:
|
|
2897
|
-
statementDescriptor:
|
|
2898
|
-
locationId:
|
|
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:
|
|
2915
|
-
name:
|
|
2916
|
-
description:
|
|
2917
|
-
image:
|
|
2918
|
-
statementDescriptor:
|
|
2919
|
-
productType:
|
|
2920
|
-
locationId:
|
|
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:
|
|
2940
|
-
confirm:
|
|
2941
|
-
locationId:
|
|
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:
|
|
2954
|
-
locationId:
|
|
2955
|
-
limit:
|
|
2956
|
-
offset:
|
|
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
|
|
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:
|
|
2977
|
-
limit:
|
|
2978
|
-
offset:
|
|
2979
|
-
status:
|
|
2980
|
-
contactId:
|
|
2981
|
-
startAt:
|
|
2982
|
-
endAt:
|
|
2983
|
-
search:
|
|
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:
|
|
3008
|
-
invoiceId:
|
|
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:
|
|
3025
|
-
name:
|
|
3026
|
-
contactId:
|
|
3027
|
-
items:
|
|
3028
|
-
name:
|
|
3029
|
-
description:
|
|
3030
|
-
quantity:
|
|
3031
|
-
price:
|
|
3032
|
-
currency:
|
|
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:
|
|
3035
|
-
type:
|
|
3036
|
-
value:
|
|
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:
|
|
3039
|
-
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:
|
|
3062
|
-
invoiceId:
|
|
3063
|
-
name:
|
|
3064
|
-
items:
|
|
3065
|
-
name:
|
|
3066
|
-
description:
|
|
3067
|
-
quantity:
|
|
3068
|
-
price:
|
|
3069
|
-
currency:
|
|
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:
|
|
3072
|
-
type:
|
|
3073
|
-
value:
|
|
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:
|
|
3076
|
-
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:
|
|
3098
|
-
invoiceId:
|
|
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:
|
|
3115
|
-
invoiceId:
|
|
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:
|
|
3132
|
-
invoiceId:
|
|
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:
|
|
3149
|
-
invoiceId:
|
|
3150
|
-
amount:
|
|
3151
|
-
mode:
|
|
3152
|
-
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
|
|
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:
|
|
3177
|
-
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
|
|
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:
|
|
3197
|
-
limit:
|
|
3198
|
-
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:
|
|
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
|
|
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:
|
|
3230
|
-
sortBy:
|
|
3231
|
-
sortOrder:
|
|
3232
|
-
limit:
|
|
3233
|
-
offset:
|
|
3234
|
-
query:
|
|
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:
|
|
3253
|
-
locationId:
|
|
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
|
|
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:
|
|
3273
|
-
type:
|
|
3274
|
-
accounts:
|
|
3275
|
-
fromDate:
|
|
3276
|
-
toDate:
|
|
3277
|
-
includeUsers:
|
|
3278
|
-
status:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
3345
|
-
accountIds:
|
|
3346
|
-
summary:
|
|
3347
|
-
media:
|
|
3348
|
-
status:
|
|
3349
|
-
scheduledAt:
|
|
3350
|
-
tags:
|
|
3351
|
-
ogData:
|
|
3352
|
-
title:
|
|
3353
|
-
description:
|
|
3354
|
-
image:
|
|
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
|
|
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:
|
|
3380
|
-
limit:
|
|
3381
|
-
offset:
|
|
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
|
|
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:
|
|
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:
|
|
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:
|
|
3425
|
-
name:
|
|
3426
|
-
phone:
|
|
3427
|
-
email:
|
|
3428
|
-
website:
|
|
3429
|
-
address:
|
|
3430
|
-
city:
|
|
3431
|
-
state:
|
|
3432
|
-
postalCode:
|
|
3433
|
-
country:
|
|
3434
|
-
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:
|
|
3457
|
-
name:
|
|
3458
|
-
phone:
|
|
3459
|
-
email:
|
|
3460
|
-
website:
|
|
3461
|
-
address:
|
|
3462
|
-
city:
|
|
3463
|
-
state:
|
|
3464
|
-
postalCode:
|
|
3465
|
-
country:
|
|
3466
|
-
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:
|
|
3489
|
-
confirm:
|
|
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
|
|
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:
|
|
3506
|
-
limit:
|
|
3507
|
-
offset:
|
|
3508
|
-
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:
|
|
3527
|
-
postId:
|
|
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:
|
|
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:
|
|
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:
|
|
3567
|
-
urlSlug:
|
|
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
|
|
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:
|
|
3589
|
-
limit:
|
|
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:
|
|
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:
|
|
3618
|
-
type:
|
|
3619
|
-
locationId:
|
|
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:
|
|
3634
|
-
limit:
|
|
3635
|
-
skip:
|
|
3636
|
-
locationId:
|
|
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:
|
|
3653
|
-
html:
|
|
3654
|
-
editorType:
|
|
3655
|
-
updatedBy:
|
|
3656
|
-
locationId:
|
|
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
|
|
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:
|
|
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:
|
|
3696
|
-
redirectTo:
|
|
3697
|
-
locationId:
|
|
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:
|
|
3712
|
-
name:
|
|
3713
|
-
redirectTo:
|
|
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:
|
|
3731
|
-
confirm:
|
|
3732
|
-
locationId:
|
|
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
|
|
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:
|
|
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:
|
|
3766
|
-
locationId:
|
|
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:
|
|
3781
|
-
locationId:
|
|
3782
|
-
query:
|
|
3783
|
-
limit:
|
|
3784
|
-
offset:
|
|
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:
|
|
3804
|
-
recordId:
|
|
3805
|
-
locationId:
|
|
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:
|
|
3820
|
-
locationId:
|
|
3821
|
-
properties:
|
|
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:
|
|
3836
|
-
recordId:
|
|
3837
|
-
locationId:
|
|
3838
|
-
properties:
|
|
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:
|
|
3853
|
-
recordId:
|
|
3854
|
-
locationId:
|
|
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
|
|
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:
|
|
3874
|
-
recordId:
|
|
3875
|
-
locationId:
|
|
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:
|
|
3891
|
-
recordId:
|
|
3892
|
-
locationId:
|
|
3893
|
-
targetEntityType:
|
|
3894
|
-
targetEntityId:
|
|
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:
|
|
3916
|
-
recordId:
|
|
3917
|
-
associationId:
|
|
3918
|
-
locationId:
|
|
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
|
|
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:
|
|
3939
|
-
status:
|
|
3940
|
-
limit:
|
|
3941
|
-
offset:
|
|
3942
|
-
contactId:
|
|
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:
|
|
3964
|
-
locationId:
|
|
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:
|
|
3979
|
-
contactId:
|
|
3980
|
-
name:
|
|
3981
|
-
title:
|
|
3982
|
-
items:
|
|
3983
|
-
discount:
|
|
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:
|
|
4006
|
-
locationId:
|
|
4007
|
-
name:
|
|
4008
|
-
title:
|
|
4009
|
-
items:
|
|
4010
|
-
discount:
|
|
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:
|
|
4031
|
-
locationId:
|
|
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:
|
|
4046
|
-
locationId:
|
|
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
|
|
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:
|
|
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:
|
|
4080
|
-
locationId:
|
|
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:
|
|
4095
|
-
name:
|
|
4096
|
-
code:
|
|
4097
|
-
type:
|
|
4098
|
-
amount:
|
|
4099
|
-
duration:
|
|
4100
|
-
durationInMonths:
|
|
4101
|
-
productIds:
|
|
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:
|
|
4126
|
-
locationId:
|
|
4127
|
-
name:
|
|
4128
|
-
productIds:
|
|
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:
|
|
4147
|
-
locationId:
|
|
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
|
|
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:
|
|
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:
|
|
4181
|
-
locationId:
|
|
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:
|
|
4196
|
-
name:
|
|
4197
|
-
url:
|
|
4198
|
-
events:
|
|
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:
|
|
4220
|
-
locationId:
|
|
4221
|
-
name:
|
|
4222
|
-
url:
|
|
4223
|
-
events:
|
|
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:
|
|
4240
|
-
locationId:
|
|
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
|
|
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:
|
|
4260
|
-
limit:
|
|
4261
|
-
offset:
|
|
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:
|
|
4280
|
-
locationId:
|
|
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:
|
|
4295
|
-
locationId:
|
|
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:
|
|
4310
|
-
contactId:
|
|
4311
|
-
locationId:
|
|
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
|
|
4324
|
-
var ActionSchema =
|
|
4325
|
-
id:
|
|
4326
|
-
name:
|
|
4327
|
-
type:
|
|
4328
|
-
attributes:
|
|
4329
|
-
next:
|
|
4330
|
-
parent:
|
|
4331
|
-
parentKey:
|
|
4332
|
-
order:
|
|
4333
|
-
cat:
|
|
4334
|
-
nodeType:
|
|
4335
|
-
sibling:
|
|
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:
|
|
4383
|
-
skip:
|
|
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:
|
|
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:
|
|
4414
|
-
limit:
|
|
4415
|
-
installedOnly:
|
|
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:
|
|
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:
|
|
4463
|
-
name:
|
|
4464
|
-
status:
|
|
4465
|
-
actions:
|
|
4466
|
-
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:
|
|
4511
|
-
operator:
|
|
4512
|
-
value:
|
|
4513
|
-
yes_actions:
|
|
4514
|
-
no_actions:
|
|
4515
|
-
next_after_merge:
|
|
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:
|
|
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:
|
|
4638
|
-
action:
|
|
4639
|
-
name:
|
|
4640
|
-
op:
|
|
4641
|
-
inner_op:
|
|
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:
|
|
4677
|
-
confirm:
|
|
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:
|
|
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
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
4834
|
-
name:
|
|
4835
|
-
path:
|
|
4836
|
-
bodyTrackingCode:
|
|
4837
|
-
headTrackingCode:
|
|
4838
|
-
chatWidgetId:
|
|
4839
|
-
domainId:
|
|
4840
|
-
faviconUrl:
|
|
4841
|
-
paymentMode:
|
|
4842
|
-
requireCreditCard:
|
|
4843
|
-
isGdprCompliant:
|
|
4844
|
-
isOptimisePageLoad:
|
|
4845
|
-
imageOptimization:
|
|
4846
|
-
allowPaymentModeOption:
|
|
4847
|
-
storeCurrencyFormatting:
|
|
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:
|
|
4904
|
-
stepId:
|
|
4905
|
-
name:
|
|
4906
|
-
url:
|
|
4907
|
-
domainName:
|
|
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:
|
|
4927
|
-
confirm:
|
|
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:
|
|
4947
|
-
name:
|
|
4948
|
-
url:
|
|
4949
|
-
type:
|
|
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:
|
|
4978
|
-
content:
|
|
4979
|
-
isPublished:
|
|
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:
|
|
5001
|
-
stepId:
|
|
5002
|
-
confirm:
|
|
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
|
|
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:
|
|
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:
|
|
5063
|
-
formData:
|
|
5064
|
-
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:
|
|
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:
|
|
5110
|
-
confirm:
|
|
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:
|
|
5128
|
-
limit:
|
|
5129
|
-
skip:
|
|
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
|
|
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:
|
|
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:
|
|
5212
|
-
stages:
|
|
5213
|
-
|
|
5214
|
-
name:
|
|
5215
|
-
position:
|
|
5216
|
-
showInFunnel:
|
|
5217
|
-
showInPieChart:
|
|
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:
|
|
5221
|
-
showInPieChart:
|
|
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:
|
|
5252
|
-
name:
|
|
5253
|
-
stages:
|
|
5254
|
-
|
|
5255
|
-
id:
|
|
5256
|
-
name:
|
|
5257
|
-
position:
|
|
5258
|
-
showInFunnel:
|
|
5259
|
-
showInPieChart:
|
|
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:
|
|
5263
|
-
showInPieChart:
|
|
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:
|
|
5287
|
-
confirm:
|
|
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
|
|
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:
|
|
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:
|
|
5419
|
-
name:
|
|
5420
|
-
apiKey:
|
|
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:
|
|
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:
|
|
5530
|
-
skip:
|
|
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
|
|
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:
|
|
5586
|
-
tags:
|
|
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:
|
|
5609
|
-
tags:
|
|
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:
|
|
5631
|
-
fields:
|
|
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:
|
|
5653
|
-
workflowId:
|
|
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:
|
|
5675
|
-
confirm:
|
|
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
|
|
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:
|
|
5709
|
-
includeContacts:
|
|
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:
|
|
5838
|
-
locationB:
|
|
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
|
|
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:
|
|
5926
|
-
newName:
|
|
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
|
|
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:
|
|
6043
|
-
query:
|
|
6044
|
-
limit:
|
|
6045
|
-
startAfter:
|
|
6046
|
-
locationId:
|
|
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:
|
|
6067
|
-
locationId:
|
|
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:
|
|
6084
|
-
objectKey:
|
|
6085
|
-
filters:
|
|
6086
|
-
columns:
|
|
6087
|
-
pipelineIds:
|
|
6088
|
-
defaultInPipelines:
|
|
6089
|
-
locationId:
|
|
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:
|
|
6111
|
-
name:
|
|
6112
|
-
filters:
|
|
6113
|
-
columns:
|
|
6114
|
-
pipelineIds:
|
|
6115
|
-
defaultInPipelines:
|
|
6116
|
-
locationId:
|
|
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:
|
|
6142
|
-
confirm:
|
|
6143
|
-
locationId:
|
|
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
|
|
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:
|
|
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
|
|
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:
|
|
6204
|
-
name:
|
|
6205
|
-
subject:
|
|
6206
|
-
fromName:
|
|
6207
|
-
fromEmail:
|
|
6208
|
-
isPlainText:
|
|
6209
|
-
enableResendToUnopened:
|
|
6210
|
-
hasUtmTracking:
|
|
6211
|
-
locationId:
|
|
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 {
|
|
@@ -6246,7 +6376,7 @@ ${text2}`);
|
|
|
6246
6376
|
}
|
|
6247
6377
|
|
|
6248
6378
|
// src/tools/memberships.ts
|
|
6249
|
-
var
|
|
6379
|
+
var import_zod44 = require("zod");
|
|
6250
6380
|
var MEMBERSHIP_BASE = "https://backend.leadconnectorhq.com/membership";
|
|
6251
6381
|
function registerMembershipTools(server2, builderClient) {
|
|
6252
6382
|
const client = builderClient;
|
|
@@ -6267,7 +6397,7 @@ ${text2}`);
|
|
|
6267
6397
|
"list_membership_offers",
|
|
6268
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.",
|
|
6269
6399
|
{
|
|
6270
|
-
locationId:
|
|
6400
|
+
locationId: import_zod44.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
|
|
6271
6401
|
},
|
|
6272
6402
|
async ({ locationId: locationId2 }) => {
|
|
6273
6403
|
try {
|
|
@@ -6283,8 +6413,8 @@ ${text2}`);
|
|
|
6283
6413
|
"list_membership_categories",
|
|
6284
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.",
|
|
6285
6415
|
{
|
|
6286
|
-
limit:
|
|
6287
|
-
locationId:
|
|
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.")
|
|
6288
6418
|
},
|
|
6289
6419
|
async ({ limit, locationId: locationId2 }) => {
|
|
6290
6420
|
try {
|
|
@@ -6300,8 +6430,8 @@ ${text2}`);
|
|
|
6300
6430
|
"list_membership_lessons",
|
|
6301
6431
|
"List all membership/course lessons in a location. Use the returned ids with the lesson_completed / lesson_started trigger conditions. READ-ONLY.",
|
|
6302
6432
|
{
|
|
6303
|
-
limit:
|
|
6304
|
-
locationId:
|
|
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.")
|
|
6305
6435
|
},
|
|
6306
6436
|
async ({ limit, locationId: locationId2 }) => {
|
|
6307
6437
|
try {
|
|
@@ -6316,60 +6446,60 @@ ${text2}`);
|
|
|
6316
6446
|
}
|
|
6317
6447
|
|
|
6318
6448
|
// src/tools/template-deployer.ts
|
|
6319
|
-
var
|
|
6320
|
-
var
|
|
6321
|
-
var
|
|
6449
|
+
var import_zod45 = require("zod");
|
|
6450
|
+
var fs4 = __toESM(require("fs"));
|
|
6451
|
+
var path4 = __toESM(require("path"));
|
|
6322
6452
|
function delay3(ms) {
|
|
6323
6453
|
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
6324
6454
|
}
|
|
6325
|
-
var TemplateSchema =
|
|
6326
|
-
templateName:
|
|
6327
|
-
templateVersion:
|
|
6328
|
-
description:
|
|
6329
|
-
questionnaire:
|
|
6330
|
-
id:
|
|
6331
|
-
question:
|
|
6332
|
-
type:
|
|
6333
|
-
required:
|
|
6334
|
-
placeholder:
|
|
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()
|
|
6335
6465
|
})).optional().default([]),
|
|
6336
|
-
location:
|
|
6337
|
-
tags:
|
|
6338
|
-
customFields:
|
|
6339
|
-
name:
|
|
6340
|
-
dataType:
|
|
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()
|
|
6341
6471
|
})).optional(),
|
|
6342
|
-
pipelines:
|
|
6343
|
-
name:
|
|
6344
|
-
stages:
|
|
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() }))
|
|
6345
6475
|
})).optional(),
|
|
6346
|
-
workflows:
|
|
6347
|
-
name:
|
|
6348
|
-
condition:
|
|
6349
|
-
actions:
|
|
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([])
|
|
6350
6480
|
})).optional(),
|
|
6351
|
-
calendars:
|
|
6352
|
-
name:
|
|
6353
|
-
description:
|
|
6481
|
+
calendars: import_zod45.z.array(import_zod45.z.object({
|
|
6482
|
+
name: import_zod45.z.string(),
|
|
6483
|
+
description: import_zod45.z.string().optional()
|
|
6354
6484
|
})).optional()
|
|
6355
6485
|
});
|
|
6356
6486
|
function registerTemplateDeployerTools(server2, client) {
|
|
6357
6487
|
const builderClient = WorkflowBuilderClient.fromEnv();
|
|
6358
|
-
const templatesDir =
|
|
6488
|
+
const templatesDir = path4.resolve(__dirname, "..", "templates");
|
|
6359
6489
|
function validateTemplatePath(templateFile) {
|
|
6360
|
-
const resolved =
|
|
6361
|
-
const realPath =
|
|
6490
|
+
const resolved = path4.resolve(templateFile);
|
|
6491
|
+
const realPath = fs4.existsSync(resolved) ? fs4.realpathSync(resolved) : resolved;
|
|
6362
6492
|
const allowedDirs = [
|
|
6363
6493
|
templatesDir,
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
].map((d) =>
|
|
6367
|
-
const isAllowed = allowedDirs.some((dir) => realPath.startsWith(dir +
|
|
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));
|
|
6368
6498
|
if (!isAllowed) {
|
|
6369
6499
|
throw new Error(`Template file must be inside a templates/ directory. Got: ${realPath}`);
|
|
6370
6500
|
}
|
|
6371
|
-
if (
|
|
6372
|
-
const otherMatch = allowedDirs.slice(1).some((d) => !
|
|
6501
|
+
if (path4.relative(allowedDirs[0], realPath).startsWith("..")) {
|
|
6502
|
+
const otherMatch = allowedDirs.slice(1).some((d) => !path4.relative(d, realPath).startsWith(".."));
|
|
6373
6503
|
if (!otherMatch) {
|
|
6374
6504
|
throw new Error(`Template path escapes allowed directory.`);
|
|
6375
6505
|
}
|
|
@@ -6384,19 +6514,19 @@ function registerTemplateDeployerTools(server2, client) {
|
|
|
6384
6514
|
try {
|
|
6385
6515
|
const dirs = [
|
|
6386
6516
|
templatesDir,
|
|
6387
|
-
|
|
6388
|
-
|
|
6517
|
+
path4.resolve(process.cwd(), "templates"),
|
|
6518
|
+
path4.resolve(__dirname, "..", "..", "templates")
|
|
6389
6519
|
];
|
|
6390
6520
|
const templates = [];
|
|
6391
6521
|
for (const dir of dirs) {
|
|
6392
|
-
if (!
|
|
6393
|
-
const files =
|
|
6522
|
+
if (!fs4.existsSync(dir)) continue;
|
|
6523
|
+
const files = fs4.readdirSync(dir).filter((f) => f.endsWith(".json"));
|
|
6394
6524
|
for (const file of files) {
|
|
6395
6525
|
try {
|
|
6396
|
-
const content = JSON.parse(
|
|
6526
|
+
const content = JSON.parse(fs4.readFileSync(path4.join(dir, file), "utf-8"));
|
|
6397
6527
|
templates.push({
|
|
6398
6528
|
name: content.templateName || file,
|
|
6399
|
-
file:
|
|
6529
|
+
file: path4.join(dir, file),
|
|
6400
6530
|
description: content.description || ""
|
|
6401
6531
|
});
|
|
6402
6532
|
} catch {
|
|
@@ -6421,12 +6551,12 @@ function registerTemplateDeployerTools(server2, client) {
|
|
|
6421
6551
|
"get_template_questionnaire",
|
|
6422
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.",
|
|
6423
6553
|
{
|
|
6424
|
-
templateFile:
|
|
6554
|
+
templateFile: import_zod45.z.string().describe("Path to the template JSON file (from list_templates).")
|
|
6425
6555
|
},
|
|
6426
6556
|
async ({ templateFile }) => {
|
|
6427
6557
|
try {
|
|
6428
6558
|
const safePath = validateTemplatePath(templateFile);
|
|
6429
|
-
const content = JSON.parse(
|
|
6559
|
+
const content = JSON.parse(fs4.readFileSync(safePath, "utf-8"));
|
|
6430
6560
|
return {
|
|
6431
6561
|
content: [
|
|
6432
6562
|
{
|
|
@@ -6454,16 +6584,16 @@ function registerTemplateDeployerTools(server2, client) {
|
|
|
6454
6584
|
"deploy_template",
|
|
6455
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.",
|
|
6456
6586
|
{
|
|
6457
|
-
templateFile:
|
|
6458
|
-
answers:
|
|
6459
|
-
locationId:
|
|
6460
|
-
dryRun:
|
|
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.")
|
|
6461
6591
|
},
|
|
6462
6592
|
async ({ templateFile, answers, locationId: locationId2, dryRun }) => {
|
|
6463
6593
|
try {
|
|
6464
6594
|
const locId = client.resolveLocationId(locationId2);
|
|
6465
6595
|
const safePath = validateTemplatePath(templateFile);
|
|
6466
|
-
const template = TemplateSchema.parse(JSON.parse(
|
|
6596
|
+
const template = TemplateSchema.parse(JSON.parse(fs4.readFileSync(safePath, "utf-8")));
|
|
6467
6597
|
const resolve5 = (text) => {
|
|
6468
6598
|
if (typeof text !== "string") return text;
|
|
6469
6599
|
let result = text;
|
|
@@ -6703,7 +6833,7 @@ ${errors.join("\n")}` : "\nNo errors!",
|
|
|
6703
6833
|
}
|
|
6704
6834
|
|
|
6705
6835
|
// src/tools/validators.ts
|
|
6706
|
-
var
|
|
6836
|
+
var import_zod46 = require("zod");
|
|
6707
6837
|
function extractFromTrigger(trigger, refs) {
|
|
6708
6838
|
const triggerName = String(trigger.name ?? trigger.type ?? "unnamed trigger");
|
|
6709
6839
|
const where = `trigger "${triggerName}"`;
|
|
@@ -6838,7 +6968,7 @@ function registerValidatorTools(server2, client, builderClient) {
|
|
|
6838
6968
|
"validate_workflow",
|
|
6839
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.",
|
|
6840
6970
|
{
|
|
6841
|
-
workflowId:
|
|
6971
|
+
workflowId: import_zod46.z.string().describe("The workflow ID to validate.")
|
|
6842
6972
|
},
|
|
6843
6973
|
async ({ workflowId }) => {
|
|
6844
6974
|
try {
|
|
@@ -7215,68 +7345,6 @@ function registerAllTools(server2, client, registry2, mcpVersion) {
|
|
|
7215
7345
|
registerLocationSwitcherTools(server2, client, builderClient, registry2, mcpVersion);
|
|
7216
7346
|
}
|
|
7217
7347
|
|
|
7218
|
-
// src/credentials-store.ts
|
|
7219
|
-
var fs4 = __toESM(require("fs"));
|
|
7220
|
-
var path4 = __toESM(require("path"));
|
|
7221
|
-
var os = __toESM(require("os"));
|
|
7222
|
-
var import_zod46 = require("zod");
|
|
7223
|
-
var APP_NAME = "elitedcs-ghl-mcp";
|
|
7224
|
-
var CredentialsSchema = import_zod46.z.object({
|
|
7225
|
-
license_key: import_zod46.z.string().min(1),
|
|
7226
|
-
email: import_zod46.z.string().email(),
|
|
7227
|
-
verified_at: import_zod46.z.string().min(1),
|
|
7228
|
-
ghl_api_key: import_zod46.z.string().min(1),
|
|
7229
|
-
ghl_location_id: import_zod46.z.string().min(1),
|
|
7230
|
-
ghl_company_id: import_zod46.z.string().optional(),
|
|
7231
|
-
ghl_user_id: import_zod46.z.string().optional(),
|
|
7232
|
-
ghl_firebase_api_key: import_zod46.z.string().optional(),
|
|
7233
|
-
ghl_firebase_refresh_token: import_zod46.z.string().optional()
|
|
7234
|
-
});
|
|
7235
|
-
function appDataDir() {
|
|
7236
|
-
const home = os.homedir();
|
|
7237
|
-
if (process.platform === "darwin") {
|
|
7238
|
-
return path4.join(home, "Library", "Application Support", APP_NAME);
|
|
7239
|
-
}
|
|
7240
|
-
if (process.platform === "win32") {
|
|
7241
|
-
const appData = process.env.APPDATA || path4.join(home, "AppData", "Roaming");
|
|
7242
|
-
return path4.join(appData, APP_NAME);
|
|
7243
|
-
}
|
|
7244
|
-
const xdg = process.env.XDG_CONFIG_HOME || path4.join(home, ".config");
|
|
7245
|
-
return path4.join(xdg, APP_NAME);
|
|
7246
|
-
}
|
|
7247
|
-
function credentialsPath() {
|
|
7248
|
-
return path4.join(appDataDir(), "credentials.json");
|
|
7249
|
-
}
|
|
7250
|
-
function readCredentials() {
|
|
7251
|
-
const file = credentialsPath();
|
|
7252
|
-
if (!fs4.existsSync(file)) return null;
|
|
7253
|
-
try {
|
|
7254
|
-
const raw = fs4.readFileSync(file, "utf-8");
|
|
7255
|
-
const parsed = JSON.parse(raw);
|
|
7256
|
-
return CredentialsSchema.parse(parsed);
|
|
7257
|
-
} catch {
|
|
7258
|
-
return null;
|
|
7259
|
-
}
|
|
7260
|
-
}
|
|
7261
|
-
function writeCredentials(creds) {
|
|
7262
|
-
const dir = appDataDir();
|
|
7263
|
-
fs4.mkdirSync(dir, { recursive: true });
|
|
7264
|
-
if (process.platform !== "win32") {
|
|
7265
|
-
try {
|
|
7266
|
-
fs4.chmodSync(dir, 448);
|
|
7267
|
-
} catch {
|
|
7268
|
-
}
|
|
7269
|
-
}
|
|
7270
|
-
const file = credentialsPath();
|
|
7271
|
-
fs4.writeFileSync(file, JSON.stringify(creds, null, 2) + "\n", "utf-8");
|
|
7272
|
-
if (process.platform !== "win32") {
|
|
7273
|
-
try {
|
|
7274
|
-
fs4.chmodSync(file, 384);
|
|
7275
|
-
} catch {
|
|
7276
|
-
}
|
|
7277
|
-
}
|
|
7278
|
-
}
|
|
7279
|
-
|
|
7280
7348
|
// src/setup-tool.ts
|
|
7281
7349
|
var os2 = __toESM(require("os"));
|
|
7282
7350
|
var crypto3 = __toESM(require("crypto"));
|
|
@@ -7531,7 +7599,9 @@ function hardenSecretFilePerms() {
|
|
|
7531
7599
|
const repoDir = path5.resolve(__dirname, "..");
|
|
7532
7600
|
const candidates = [
|
|
7533
7601
|
{ file: path5.join(repoDir, "start-mcp.sh"), mode: 448 },
|
|
7534
|
-
|
|
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 }
|
|
7535
7605
|
];
|
|
7536
7606
|
for (const { file, mode } of candidates) {
|
|
7537
7607
|
let current;
|