@elitedcs/ghl-mcp 3.8.1 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +57 -0
- package/README.md +4 -4
- package/dist/index.js +608 -440
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -31,8 +31,8 @@ var require_package = __commonJS({
|
|
|
31
31
|
"package.json"(exports2, module2) {
|
|
32
32
|
module2.exports = {
|
|
33
33
|
name: "@elitedcs/ghl-mcp",
|
|
34
|
-
version: "3.
|
|
35
|
-
description: "GoHighLevel MCP Server for Claude.
|
|
34
|
+
version: "3.9.0",
|
|
35
|
+
description: "GoHighLevel MCP Server for Claude. 187 tools \u2014 full CRM, automation, marketing control, and the only programmatic GHL workflow builder.",
|
|
36
36
|
main: "dist/index.js",
|
|
37
37
|
bin: {
|
|
38
38
|
"ghl-mcp": "dist/index.js"
|
|
@@ -2849,22 +2849,138 @@ function registerPaymentTools(server2, client) {
|
|
|
2849
2849
|
);
|
|
2850
2850
|
}
|
|
2851
2851
|
|
|
2852
|
-
// src/tools/
|
|
2852
|
+
// src/tools/products.ts
|
|
2853
2853
|
var import_zod15 = require("zod");
|
|
2854
|
+
var PRODUCT_TYPES = ["DIGITAL", "PHYSICAL", "SERVICE", "PHYSICAL/DIGITAL"];
|
|
2855
|
+
function registerProductTools(server2, client) {
|
|
2856
|
+
safeTool(
|
|
2857
|
+
server2,
|
|
2858
|
+
"list_products",
|
|
2859
|
+
"List products in a GHL location's catalog.",
|
|
2860
|
+
{
|
|
2861
|
+
locationId: import_zod15.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var."),
|
|
2862
|
+
limit: import_zod15.z.number().optional().describe("Max products to return. Defaults to 100."),
|
|
2863
|
+
offset: import_zod15.z.number().optional().describe("Skip this many records for pagination."),
|
|
2864
|
+
search: import_zod15.z.string().optional().describe("Free-text search across product names + descriptions.")
|
|
2865
|
+
},
|
|
2866
|
+
async ({ locationId: locationId2, limit, offset, search }) => {
|
|
2867
|
+
const resolved = client.resolveLocationId(locationId2);
|
|
2868
|
+
const params = { locationId: resolved };
|
|
2869
|
+
if (limit !== void 0) params.limit = limit;
|
|
2870
|
+
if (offset !== void 0) params.offset = offset;
|
|
2871
|
+
if (search) params.search = search;
|
|
2872
|
+
return client.get("/products/", { params });
|
|
2873
|
+
}
|
|
2874
|
+
);
|
|
2875
|
+
safeTool(
|
|
2876
|
+
server2,
|
|
2877
|
+
"get_product",
|
|
2878
|
+
"Get a single product by ID with full details (media, variants, taxes, etc.).",
|
|
2879
|
+
{
|
|
2880
|
+
productId: import_zod15.z.string().describe("The product ID."),
|
|
2881
|
+
locationId: import_zod15.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
|
|
2882
|
+
},
|
|
2883
|
+
async ({ productId, locationId: locationId2 }) => {
|
|
2884
|
+
const resolved = client.resolveLocationId(locationId2);
|
|
2885
|
+
return client.get(`/products/${productId}`, { params: { locationId: resolved } });
|
|
2886
|
+
}
|
|
2887
|
+
);
|
|
2888
|
+
safeTool(
|
|
2889
|
+
server2,
|
|
2890
|
+
"create_product",
|
|
2891
|
+
"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
|
+
{
|
|
2893
|
+
name: import_zod15.z.string().describe("Product display name."),
|
|
2894
|
+
productType: import_zod15.z.enum(PRODUCT_TYPES).describe("Type of product. DIGITAL (e-courses, downloads), PHYSICAL (shipped goods), SERVICE (appointments, consultations), or PHYSICAL/DIGITAL (hybrid)."),
|
|
2895
|
+
description: import_zod15.z.string().optional().describe("Product description / marketing copy."),
|
|
2896
|
+
image: import_zod15.z.string().optional().describe("Primary product image URL."),
|
|
2897
|
+
statementDescriptor: import_zod15.z.string().optional().describe("Up to 22 characters shown on the buyer's card statement."),
|
|
2898
|
+
locationId: import_zod15.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
|
|
2899
|
+
},
|
|
2900
|
+
async ({ name, productType, description, image, statementDescriptor, locationId: locationId2 }) => {
|
|
2901
|
+
const resolved = client.resolveLocationId(locationId2);
|
|
2902
|
+
const body = { locationId: resolved, name, productType };
|
|
2903
|
+
if (description !== void 0) body.description = description;
|
|
2904
|
+
if (image !== void 0) body.image = image;
|
|
2905
|
+
if (statementDescriptor !== void 0) body.statementDescriptor = statementDescriptor;
|
|
2906
|
+
return client.post("/products/", { body });
|
|
2907
|
+
}
|
|
2908
|
+
);
|
|
2909
|
+
safeTool(
|
|
2910
|
+
server2,
|
|
2911
|
+
"update_product",
|
|
2912
|
+
"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
|
+
{
|
|
2914
|
+
productId: import_zod15.z.string().describe("The product ID to update."),
|
|
2915
|
+
name: import_zod15.z.string().optional().describe("New product display name."),
|
|
2916
|
+
description: import_zod15.z.string().optional().describe("New product description."),
|
|
2917
|
+
image: import_zod15.z.string().optional().describe("New primary product image URL."),
|
|
2918
|
+
statementDescriptor: import_zod15.z.string().optional().describe("Up to 22 characters shown on the buyer's card statement."),
|
|
2919
|
+
productType: import_zod15.z.enum(PRODUCT_TYPES).optional().describe("Type of product (rarely changed after creation)."),
|
|
2920
|
+
locationId: import_zod15.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
|
|
2921
|
+
},
|
|
2922
|
+
async ({ productId, name, description, image, statementDescriptor, productType, locationId: locationId2 }) => {
|
|
2923
|
+
const resolved = client.resolveLocationId(locationId2);
|
|
2924
|
+
const body = { locationId: resolved };
|
|
2925
|
+
const current = await client.get(`/products/${productId}`, { params: { locationId: resolved } });
|
|
2926
|
+
body.name = name ?? current.name;
|
|
2927
|
+
body.productType = productType ?? current.productType;
|
|
2928
|
+
if (description !== void 0) body.description = description;
|
|
2929
|
+
if (image !== void 0) body.image = image;
|
|
2930
|
+
if (statementDescriptor !== void 0) body.statementDescriptor = statementDescriptor;
|
|
2931
|
+
return client.put(`/products/${productId}`, { body });
|
|
2932
|
+
}
|
|
2933
|
+
);
|
|
2934
|
+
safeTool(
|
|
2935
|
+
server2,
|
|
2936
|
+
"delete_product",
|
|
2937
|
+
"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
|
+
{
|
|
2939
|
+
productId: import_zod15.z.string().describe("The product ID to delete."),
|
|
2940
|
+
confirm: import_zod15.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action."),
|
|
2941
|
+
locationId: import_zod15.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
|
|
2942
|
+
},
|
|
2943
|
+
async ({ productId, locationId: locationId2 }) => {
|
|
2944
|
+
const resolved = client.resolveLocationId(locationId2);
|
|
2945
|
+
return client.delete(`/products/${productId}`, { params: { locationId: resolved } });
|
|
2946
|
+
}
|
|
2947
|
+
);
|
|
2948
|
+
safeTool(
|
|
2949
|
+
server2,
|
|
2950
|
+
"list_product_prices",
|
|
2951
|
+
"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
|
+
{
|
|
2953
|
+
productId: import_zod15.z.string().describe("The product ID."),
|
|
2954
|
+
locationId: import_zod15.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var."),
|
|
2955
|
+
limit: import_zod15.z.number().optional().describe("Max prices to return."),
|
|
2956
|
+
offset: import_zod15.z.number().optional().describe("Skip this many for pagination.")
|
|
2957
|
+
},
|
|
2958
|
+
async ({ productId, locationId: locationId2, limit, offset }) => {
|
|
2959
|
+
const resolved = client.resolveLocationId(locationId2);
|
|
2960
|
+
const params = { locationId: resolved };
|
|
2961
|
+
if (limit !== void 0) params.limit = limit;
|
|
2962
|
+
if (offset !== void 0) params.offset = offset;
|
|
2963
|
+
return client.get(`/products/${productId}/price`, { params });
|
|
2964
|
+
}
|
|
2965
|
+
);
|
|
2966
|
+
}
|
|
2967
|
+
|
|
2968
|
+
// src/tools/invoices.ts
|
|
2969
|
+
var import_zod16 = require("zod");
|
|
2854
2970
|
function registerInvoiceTools(server2, client) {
|
|
2855
2971
|
safeTool(
|
|
2856
2972
|
server2,
|
|
2857
2973
|
"list_invoices",
|
|
2858
2974
|
"List invoices for a location. Offset-based pagination via limit/offset.",
|
|
2859
2975
|
{
|
|
2860
|
-
locationId:
|
|
2861
|
-
limit:
|
|
2862
|
-
offset:
|
|
2863
|
-
status:
|
|
2864
|
-
contactId:
|
|
2865
|
-
startAt:
|
|
2866
|
-
endAt:
|
|
2867
|
-
search:
|
|
2976
|
+
locationId: import_zod16.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
|
|
2977
|
+
limit: import_zod16.z.number().optional().describe("Max number of invoices to return"),
|
|
2978
|
+
offset: import_zod16.z.number().optional().describe("Offset for pagination"),
|
|
2979
|
+
status: import_zod16.z.enum(["draft", "sent", "paid", "void", "partially_paid"]).optional().describe("Filter by invoice status"),
|
|
2980
|
+
contactId: import_zod16.z.string().optional().describe("Filter by contact ID"),
|
|
2981
|
+
startAt: import_zod16.z.string().optional().describe("Start date filter (ISO 8601)"),
|
|
2982
|
+
endAt: import_zod16.z.string().optional().describe("End date filter (ISO 8601)"),
|
|
2983
|
+
search: import_zod16.z.string().optional().describe("Search term")
|
|
2868
2984
|
},
|
|
2869
2985
|
async ({ locationId: locationId2, limit, offset, status, contactId, startAt, endAt, search }) => {
|
|
2870
2986
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -2888,8 +3004,8 @@ function registerInvoiceTools(server2, client) {
|
|
|
2888
3004
|
"get_invoice",
|
|
2889
3005
|
"Get a specific invoice by ID",
|
|
2890
3006
|
{
|
|
2891
|
-
locationId:
|
|
2892
|
-
invoiceId:
|
|
3007
|
+
locationId: import_zod16.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
|
|
3008
|
+
invoiceId: import_zod16.z.string().describe("The invoice ID")
|
|
2893
3009
|
},
|
|
2894
3010
|
async ({ locationId: locationId2, invoiceId }) => {
|
|
2895
3011
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -2905,22 +3021,22 @@ function registerInvoiceTools(server2, client) {
|
|
|
2905
3021
|
"create_invoice",
|
|
2906
3022
|
"Create a new invoice",
|
|
2907
3023
|
{
|
|
2908
|
-
locationId:
|
|
2909
|
-
name:
|
|
2910
|
-
contactId:
|
|
2911
|
-
items:
|
|
2912
|
-
name:
|
|
2913
|
-
description:
|
|
2914
|
-
quantity:
|
|
2915
|
-
price:
|
|
2916
|
-
currency:
|
|
3024
|
+
locationId: import_zod16.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
|
|
3025
|
+
name: import_zod16.z.string().describe("Invoice name"),
|
|
3026
|
+
contactId: import_zod16.z.string().describe("Contact ID for the invoice"),
|
|
3027
|
+
items: import_zod16.z.array(import_zod16.z.object({
|
|
3028
|
+
name: import_zod16.z.string().describe("Item name"),
|
|
3029
|
+
description: import_zod16.z.string().describe("Item description"),
|
|
3030
|
+
quantity: import_zod16.z.number().describe("Item quantity"),
|
|
3031
|
+
price: import_zod16.z.number().describe("Item price"),
|
|
3032
|
+
currency: import_zod16.z.string().describe("Currency code (e.g. USD)")
|
|
2917
3033
|
})).describe("Invoice line items"),
|
|
2918
|
-
discount:
|
|
2919
|
-
type:
|
|
2920
|
-
value:
|
|
3034
|
+
discount: import_zod16.z.object({
|
|
3035
|
+
type: import_zod16.z.string().optional(),
|
|
3036
|
+
value: import_zod16.z.number().optional()
|
|
2921
3037
|
}).optional().describe("Discount to apply"),
|
|
2922
|
-
termsNotes:
|
|
2923
|
-
title:
|
|
3038
|
+
termsNotes: import_zod16.z.string().optional().describe("Terms and notes for the invoice"),
|
|
3039
|
+
title: import_zod16.z.string().optional().describe("Invoice title")
|
|
2924
3040
|
},
|
|
2925
3041
|
async ({ locationId: locationId2, name, contactId, items, discount, termsNotes, title }) => {
|
|
2926
3042
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -2942,22 +3058,22 @@ function registerInvoiceTools(server2, client) {
|
|
|
2942
3058
|
"update_invoice",
|
|
2943
3059
|
"Update an existing invoice",
|
|
2944
3060
|
{
|
|
2945
|
-
locationId:
|
|
2946
|
-
invoiceId:
|
|
2947
|
-
name:
|
|
2948
|
-
items:
|
|
2949
|
-
name:
|
|
2950
|
-
description:
|
|
2951
|
-
quantity:
|
|
2952
|
-
price:
|
|
2953
|
-
currency:
|
|
3061
|
+
locationId: import_zod16.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
|
|
3062
|
+
invoiceId: import_zod16.z.string().describe("The invoice ID to update"),
|
|
3063
|
+
name: import_zod16.z.string().optional().describe("Invoice name"),
|
|
3064
|
+
items: import_zod16.z.array(import_zod16.z.object({
|
|
3065
|
+
name: import_zod16.z.string().describe("Item name"),
|
|
3066
|
+
description: import_zod16.z.string().describe("Item description"),
|
|
3067
|
+
quantity: import_zod16.z.number().describe("Item quantity"),
|
|
3068
|
+
price: import_zod16.z.number().describe("Item price"),
|
|
3069
|
+
currency: import_zod16.z.string().describe("Currency code (e.g. USD)")
|
|
2954
3070
|
})).optional().describe("Invoice line items"),
|
|
2955
|
-
discount:
|
|
2956
|
-
type:
|
|
2957
|
-
value:
|
|
3071
|
+
discount: import_zod16.z.object({
|
|
3072
|
+
type: import_zod16.z.string().optional(),
|
|
3073
|
+
value: import_zod16.z.number().optional()
|
|
2958
3074
|
}).optional().describe("Discount to apply"),
|
|
2959
|
-
termsNotes:
|
|
2960
|
-
title:
|
|
3075
|
+
termsNotes: import_zod16.z.string().optional().describe("Terms and notes for the invoice"),
|
|
3076
|
+
title: import_zod16.z.string().optional().describe("Invoice title")
|
|
2961
3077
|
},
|
|
2962
3078
|
async ({ locationId: locationId2, invoiceId, name, items, discount, termsNotes, title }) => {
|
|
2963
3079
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -2978,8 +3094,8 @@ function registerInvoiceTools(server2, client) {
|
|
|
2978
3094
|
"delete_invoice",
|
|
2979
3095
|
"Delete an invoice",
|
|
2980
3096
|
{
|
|
2981
|
-
locationId:
|
|
2982
|
-
invoiceId:
|
|
3097
|
+
locationId: import_zod16.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
|
|
3098
|
+
invoiceId: import_zod16.z.string().describe("The invoice ID to delete")
|
|
2983
3099
|
},
|
|
2984
3100
|
async ({ locationId: locationId2, invoiceId }) => {
|
|
2985
3101
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -2995,8 +3111,8 @@ function registerInvoiceTools(server2, client) {
|
|
|
2995
3111
|
"send_invoice",
|
|
2996
3112
|
"Send an invoice to the contact",
|
|
2997
3113
|
{
|
|
2998
|
-
locationId:
|
|
2999
|
-
invoiceId:
|
|
3114
|
+
locationId: import_zod16.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
|
|
3115
|
+
invoiceId: import_zod16.z.string().describe("The invoice ID to send")
|
|
3000
3116
|
},
|
|
3001
3117
|
async ({ locationId: locationId2, invoiceId }) => {
|
|
3002
3118
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3012,8 +3128,8 @@ function registerInvoiceTools(server2, client) {
|
|
|
3012
3128
|
"void_invoice",
|
|
3013
3129
|
"Void an invoice",
|
|
3014
3130
|
{
|
|
3015
|
-
locationId:
|
|
3016
|
-
invoiceId:
|
|
3131
|
+
locationId: import_zod16.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
|
|
3132
|
+
invoiceId: import_zod16.z.string().describe("The invoice ID to void")
|
|
3017
3133
|
},
|
|
3018
3134
|
async ({ locationId: locationId2, invoiceId }) => {
|
|
3019
3135
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3029,11 +3145,11 @@ function registerInvoiceTools(server2, client) {
|
|
|
3029
3145
|
"record_invoice_payment",
|
|
3030
3146
|
"Record a manual payment for an invoice",
|
|
3031
3147
|
{
|
|
3032
|
-
locationId:
|
|
3033
|
-
invoiceId:
|
|
3034
|
-
amount:
|
|
3035
|
-
mode:
|
|
3036
|
-
notes:
|
|
3148
|
+
locationId: import_zod16.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
|
|
3149
|
+
invoiceId: import_zod16.z.string().describe("The invoice ID"),
|
|
3150
|
+
amount: import_zod16.z.number().describe("Payment amount"),
|
|
3151
|
+
mode: import_zod16.z.enum(["cash", "cheque", "bank_transfer", "other"]).describe("Payment mode"),
|
|
3152
|
+
notes: import_zod16.z.string().optional().describe("Payment notes")
|
|
3037
3153
|
},
|
|
3038
3154
|
async ({ locationId: locationId2, invoiceId, amount, mode, notes }) => {
|
|
3039
3155
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3050,15 +3166,15 @@ function registerInvoiceTools(server2, client) {
|
|
|
3050
3166
|
}
|
|
3051
3167
|
|
|
3052
3168
|
// src/tools/campaigns.ts
|
|
3053
|
-
var
|
|
3169
|
+
var import_zod17 = require("zod");
|
|
3054
3170
|
function registerCampaignTools(server2, client) {
|
|
3055
3171
|
safeTool(
|
|
3056
3172
|
server2,
|
|
3057
3173
|
"get_campaigns",
|
|
3058
3174
|
"List campaigns for a location",
|
|
3059
3175
|
{
|
|
3060
|
-
locationId:
|
|
3061
|
-
status:
|
|
3176
|
+
locationId: import_zod17.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
|
|
3177
|
+
status: import_zod17.z.string().optional().describe("Filter by campaign status")
|
|
3062
3178
|
},
|
|
3063
3179
|
async ({ locationId: locationId2, status }) => {
|
|
3064
3180
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3070,16 +3186,16 @@ function registerCampaignTools(server2, client) {
|
|
|
3070
3186
|
}
|
|
3071
3187
|
|
|
3072
3188
|
// src/tools/users.ts
|
|
3073
|
-
var
|
|
3189
|
+
var import_zod18 = require("zod");
|
|
3074
3190
|
function registerUserTools(server2, client) {
|
|
3075
3191
|
safeTool(
|
|
3076
3192
|
server2,
|
|
3077
3193
|
"get_users",
|
|
3078
3194
|
"List users for a location",
|
|
3079
3195
|
{
|
|
3080
|
-
locationId:
|
|
3081
|
-
limit:
|
|
3082
|
-
skip:
|
|
3196
|
+
locationId: import_zod18.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
|
|
3197
|
+
limit: import_zod18.z.number().optional().describe("Max number of users to return"),
|
|
3198
|
+
skip: import_zod18.z.number().optional().describe("Number of users to skip")
|
|
3083
3199
|
},
|
|
3084
3200
|
async ({ locationId: locationId2, limit, skip }) => {
|
|
3085
3201
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3094,7 +3210,7 @@ function registerUserTools(server2, client) {
|
|
|
3094
3210
|
"get_user",
|
|
3095
3211
|
"Get a single user by ID",
|
|
3096
3212
|
{
|
|
3097
|
-
userId:
|
|
3213
|
+
userId: import_zod18.z.string().describe("The user ID")
|
|
3098
3214
|
},
|
|
3099
3215
|
async ({ userId }) => {
|
|
3100
3216
|
return client.get(`/users/${userId}`);
|
|
@@ -3103,19 +3219,19 @@ function registerUserTools(server2, client) {
|
|
|
3103
3219
|
}
|
|
3104
3220
|
|
|
3105
3221
|
// src/tools/media.ts
|
|
3106
|
-
var
|
|
3222
|
+
var import_zod19 = require("zod");
|
|
3107
3223
|
function registerMediaTools(server2, client) {
|
|
3108
3224
|
safeTool(
|
|
3109
3225
|
server2,
|
|
3110
3226
|
"get_media_files",
|
|
3111
3227
|
"List media files for a location",
|
|
3112
3228
|
{
|
|
3113
|
-
locationId:
|
|
3114
|
-
sortBy:
|
|
3115
|
-
sortOrder:
|
|
3116
|
-
limit:
|
|
3117
|
-
offset:
|
|
3118
|
-
query:
|
|
3229
|
+
locationId: import_zod19.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
|
|
3230
|
+
sortBy: import_zod19.z.string().optional().describe("Field to sort by"),
|
|
3231
|
+
sortOrder: import_zod19.z.enum(["asc", "desc"]).optional().describe("Sort order"),
|
|
3232
|
+
limit: import_zod19.z.number().optional().describe("Max number of files to return"),
|
|
3233
|
+
offset: import_zod19.z.number().optional().describe("Number of files to skip"),
|
|
3234
|
+
query: import_zod19.z.string().optional().describe("Search query to filter files")
|
|
3119
3235
|
},
|
|
3120
3236
|
async ({ locationId: locationId2, sortBy, sortOrder, limit, offset, query }) => {
|
|
3121
3237
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3133,8 +3249,8 @@ function registerMediaTools(server2, client) {
|
|
|
3133
3249
|
"delete_media_file",
|
|
3134
3250
|
"Delete a media file",
|
|
3135
3251
|
{
|
|
3136
|
-
mediaId:
|
|
3137
|
-
locationId:
|
|
3252
|
+
mediaId: import_zod19.z.string().describe("The media file ID to delete"),
|
|
3253
|
+
locationId: import_zod19.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
|
|
3138
3254
|
},
|
|
3139
3255
|
async ({ mediaId, locationId: locationId2 }) => {
|
|
3140
3256
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3146,20 +3262,20 @@ function registerMediaTools(server2, client) {
|
|
|
3146
3262
|
}
|
|
3147
3263
|
|
|
3148
3264
|
// src/tools/social-planner.ts
|
|
3149
|
-
var
|
|
3265
|
+
var import_zod20 = require("zod");
|
|
3150
3266
|
function registerSocialPlannerTools(server2, client) {
|
|
3151
3267
|
safeTool(
|
|
3152
3268
|
server2,
|
|
3153
3269
|
"get_social_posts",
|
|
3154
3270
|
"List social media posts for a location",
|
|
3155
3271
|
{
|
|
3156
|
-
locationId:
|
|
3157
|
-
type:
|
|
3158
|
-
accounts:
|
|
3159
|
-
fromDate:
|
|
3160
|
-
toDate:
|
|
3161
|
-
includeUsers:
|
|
3162
|
-
status:
|
|
3272
|
+
locationId: import_zod20.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
|
|
3273
|
+
type: import_zod20.z.enum(["post", "story", "reel"]).optional().describe("Post type filter"),
|
|
3274
|
+
accounts: import_zod20.z.string().optional().describe("Comma-separated account IDs to filter by"),
|
|
3275
|
+
fromDate: import_zod20.z.string().optional().describe("Start date filter (ISO string)"),
|
|
3276
|
+
toDate: import_zod20.z.string().optional().describe("End date filter (ISO string)"),
|
|
3277
|
+
includeUsers: import_zod20.z.boolean().optional().describe("Whether to include user details"),
|
|
3278
|
+
status: import_zod20.z.enum(["in_review", "scheduled", "published", "failed", "in_progress"]).optional().describe("Post status filter")
|
|
3163
3279
|
},
|
|
3164
3280
|
async ({ locationId: locationId2, type, accounts, fromDate, toDate, includeUsers, status }) => {
|
|
3165
3281
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3178,7 +3294,7 @@ function registerSocialPlannerTools(server2, client) {
|
|
|
3178
3294
|
"get_social_post",
|
|
3179
3295
|
"Get a single social media post by ID",
|
|
3180
3296
|
{
|
|
3181
|
-
postId:
|
|
3297
|
+
postId: import_zod20.z.string().describe("The social media post ID")
|
|
3182
3298
|
},
|
|
3183
3299
|
async ({ postId }) => {
|
|
3184
3300
|
return client.get(`/social-media-posting/${postId}`);
|
|
@@ -3189,7 +3305,7 @@ function registerSocialPlannerTools(server2, client) {
|
|
|
3189
3305
|
"delete_social_post",
|
|
3190
3306
|
"Delete a social media post",
|
|
3191
3307
|
{
|
|
3192
|
-
postId:
|
|
3308
|
+
postId: import_zod20.z.string().describe("The social media post ID to delete")
|
|
3193
3309
|
},
|
|
3194
3310
|
async ({ postId }) => {
|
|
3195
3311
|
return client.delete(`/social-media-posting/${postId}`);
|
|
@@ -3199,7 +3315,7 @@ function registerSocialPlannerTools(server2, client) {
|
|
|
3199
3315
|
"get_social_media_accounts",
|
|
3200
3316
|
"Get connected social media accounts for a location",
|
|
3201
3317
|
{
|
|
3202
|
-
locationId:
|
|
3318
|
+
locationId: import_zod20.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
|
|
3203
3319
|
},
|
|
3204
3320
|
async ({ locationId: locationId2 }) => {
|
|
3205
3321
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3225,17 +3341,17 @@ function registerSocialPlannerTools(server2, client) {
|
|
|
3225
3341
|
"create_social_post",
|
|
3226
3342
|
"Create a new social media post",
|
|
3227
3343
|
{
|
|
3228
|
-
locationId:
|
|
3229
|
-
accountIds:
|
|
3230
|
-
summary:
|
|
3231
|
-
media:
|
|
3232
|
-
status:
|
|
3233
|
-
scheduledAt:
|
|
3234
|
-
tags:
|
|
3235
|
-
ogData:
|
|
3236
|
-
title:
|
|
3237
|
-
description:
|
|
3238
|
-
image:
|
|
3344
|
+
locationId: import_zod20.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
|
|
3345
|
+
accountIds: import_zod20.z.array(import_zod20.z.string()).describe("Array of social account IDs to post to"),
|
|
3346
|
+
summary: import_zod20.z.string().optional().describe("The post text/caption"),
|
|
3347
|
+
media: import_zod20.z.array(import_zod20.z.string()).optional().describe("Array of media URLs to attach"),
|
|
3348
|
+
status: import_zod20.z.enum(["in_review", "scheduled", "draft"]).optional().describe("Post status"),
|
|
3349
|
+
scheduledAt: import_zod20.z.string().optional().describe("Scheduled publish time (ISO string)"),
|
|
3350
|
+
tags: import_zod20.z.array(import_zod20.z.string()).optional().describe("Tags for the post"),
|
|
3351
|
+
ogData: import_zod20.z.object({
|
|
3352
|
+
title: import_zod20.z.string().optional(),
|
|
3353
|
+
description: import_zod20.z.string().optional(),
|
|
3354
|
+
image: import_zod20.z.string().optional()
|
|
3239
3355
|
}).optional().describe("Open Graph data for link previews")
|
|
3240
3356
|
},
|
|
3241
3357
|
async ({ locationId: locationId2, accountIds, summary, media, status, scheduledAt, tags, ogData }) => {
|
|
@@ -3253,16 +3369,16 @@ function registerSocialPlannerTools(server2, client) {
|
|
|
3253
3369
|
}
|
|
3254
3370
|
|
|
3255
3371
|
// src/tools/courses.ts
|
|
3256
|
-
var
|
|
3372
|
+
var import_zod21 = require("zod");
|
|
3257
3373
|
function registerCourseTools(server2, client) {
|
|
3258
3374
|
safeTool(
|
|
3259
3375
|
server2,
|
|
3260
3376
|
"get_courses",
|
|
3261
3377
|
"List courses for a location",
|
|
3262
3378
|
{
|
|
3263
|
-
locationId:
|
|
3264
|
-
limit:
|
|
3265
|
-
offset:
|
|
3379
|
+
locationId: import_zod21.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
|
|
3380
|
+
limit: import_zod21.z.number().optional().describe("Max number of courses to return"),
|
|
3381
|
+
offset: import_zod21.z.number().optional().describe("Number of courses to skip")
|
|
3266
3382
|
},
|
|
3267
3383
|
async ({ locationId: locationId2, limit, offset }) => {
|
|
3268
3384
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3275,14 +3391,14 @@ function registerCourseTools(server2, client) {
|
|
|
3275
3391
|
}
|
|
3276
3392
|
|
|
3277
3393
|
// src/tools/businesses.ts
|
|
3278
|
-
var
|
|
3394
|
+
var import_zod22 = require("zod");
|
|
3279
3395
|
function registerBusinessTools(server2, client) {
|
|
3280
3396
|
safeTool(
|
|
3281
3397
|
server2,
|
|
3282
3398
|
"get_businesses",
|
|
3283
3399
|
"List businesses for a location",
|
|
3284
3400
|
{
|
|
3285
|
-
locationId:
|
|
3401
|
+
locationId: import_zod22.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
|
|
3286
3402
|
},
|
|
3287
3403
|
async ({ locationId: locationId2 }) => {
|
|
3288
3404
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3294,7 +3410,7 @@ function registerBusinessTools(server2, client) {
|
|
|
3294
3410
|
"get_business",
|
|
3295
3411
|
"Get a single business by ID",
|
|
3296
3412
|
{
|
|
3297
|
-
businessId:
|
|
3413
|
+
businessId: import_zod22.z.string().describe("The business ID")
|
|
3298
3414
|
},
|
|
3299
3415
|
async ({ businessId }) => {
|
|
3300
3416
|
return client.get(`/businesses/${businessId}`);
|
|
@@ -3305,17 +3421,17 @@ function registerBusinessTools(server2, client) {
|
|
|
3305
3421
|
"create_business",
|
|
3306
3422
|
"Create a new business",
|
|
3307
3423
|
{
|
|
3308
|
-
locationId:
|
|
3309
|
-
name:
|
|
3310
|
-
phone:
|
|
3311
|
-
email:
|
|
3312
|
-
website:
|
|
3313
|
-
address:
|
|
3314
|
-
city:
|
|
3315
|
-
state:
|
|
3316
|
-
postalCode:
|
|
3317
|
-
country:
|
|
3318
|
-
description:
|
|
3424
|
+
locationId: import_zod22.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
|
|
3425
|
+
name: import_zod22.z.string().describe("Business name"),
|
|
3426
|
+
phone: import_zod22.z.string().optional().describe("Phone number"),
|
|
3427
|
+
email: import_zod22.z.string().optional().describe("Email address"),
|
|
3428
|
+
website: import_zod22.z.string().optional().describe("Website URL"),
|
|
3429
|
+
address: import_zod22.z.string().optional().describe("Street address"),
|
|
3430
|
+
city: import_zod22.z.string().optional().describe("City"),
|
|
3431
|
+
state: import_zod22.z.string().optional().describe("State"),
|
|
3432
|
+
postalCode: import_zod22.z.string().optional().describe("Postal/ZIP code"),
|
|
3433
|
+
country: import_zod22.z.string().optional().describe("Country"),
|
|
3434
|
+
description: import_zod22.z.string().optional().describe("Business description")
|
|
3319
3435
|
},
|
|
3320
3436
|
async ({ locationId: locationId2, name, phone, email, website, address, city, state, postalCode, country, description }) => {
|
|
3321
3437
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3337,17 +3453,17 @@ function registerBusinessTools(server2, client) {
|
|
|
3337
3453
|
"update_business",
|
|
3338
3454
|
"Update an existing business",
|
|
3339
3455
|
{
|
|
3340
|
-
businessId:
|
|
3341
|
-
name:
|
|
3342
|
-
phone:
|
|
3343
|
-
email:
|
|
3344
|
-
website:
|
|
3345
|
-
address:
|
|
3346
|
-
city:
|
|
3347
|
-
state:
|
|
3348
|
-
postalCode:
|
|
3349
|
-
country:
|
|
3350
|
-
description:
|
|
3456
|
+
businessId: import_zod22.z.string().describe("The business ID to update"),
|
|
3457
|
+
name: import_zod22.z.string().optional().describe("Business name"),
|
|
3458
|
+
phone: import_zod22.z.string().optional().describe("Phone number"),
|
|
3459
|
+
email: import_zod22.z.string().optional().describe("Email address"),
|
|
3460
|
+
website: import_zod22.z.string().optional().describe("Website URL"),
|
|
3461
|
+
address: import_zod22.z.string().optional().describe("Street address"),
|
|
3462
|
+
city: import_zod22.z.string().optional().describe("City"),
|
|
3463
|
+
state: import_zod22.z.string().optional().describe("State"),
|
|
3464
|
+
postalCode: import_zod22.z.string().optional().describe("Postal/ZIP code"),
|
|
3465
|
+
country: import_zod22.z.string().optional().describe("Country"),
|
|
3466
|
+
description: import_zod22.z.string().optional().describe("Business description")
|
|
3351
3467
|
},
|
|
3352
3468
|
async ({ businessId, name, phone, email, website, address, city, state, postalCode, country, description }) => {
|
|
3353
3469
|
const body = {};
|
|
@@ -3369,8 +3485,8 @@ function registerBusinessTools(server2, client) {
|
|
|
3369
3485
|
"delete_business",
|
|
3370
3486
|
"Permanently delete a business. IRREVERSIBLE.",
|
|
3371
3487
|
{
|
|
3372
|
-
businessId:
|
|
3373
|
-
confirm:
|
|
3488
|
+
businessId: import_zod22.z.string().describe("The business ID to delete"),
|
|
3489
|
+
confirm: import_zod22.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
|
|
3374
3490
|
},
|
|
3375
3491
|
async ({ businessId }) => {
|
|
3376
3492
|
return client.delete(`/businesses/${businessId}`);
|
|
@@ -3379,17 +3495,17 @@ function registerBusinessTools(server2, client) {
|
|
|
3379
3495
|
}
|
|
3380
3496
|
|
|
3381
3497
|
// src/tools/blogs.ts
|
|
3382
|
-
var
|
|
3498
|
+
var import_zod23 = require("zod");
|
|
3383
3499
|
function registerBlogTools(server2, client) {
|
|
3384
3500
|
safeTool(
|
|
3385
3501
|
server2,
|
|
3386
3502
|
"get_blog_posts",
|
|
3387
3503
|
"List blog posts for a location. Offset-based pagination via limit/offset.",
|
|
3388
3504
|
{
|
|
3389
|
-
locationId:
|
|
3390
|
-
limit:
|
|
3391
|
-
offset:
|
|
3392
|
-
status:
|
|
3505
|
+
locationId: import_zod23.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
|
|
3506
|
+
limit: import_zod23.z.number().optional().describe("Number of posts to return"),
|
|
3507
|
+
offset: import_zod23.z.number().optional().describe("Offset for pagination"),
|
|
3508
|
+
status: import_zod23.z.enum(["published", "draft", "archived"]).optional().describe("Filter by post status")
|
|
3393
3509
|
},
|
|
3394
3510
|
async ({ locationId: locationId2, limit, offset, status }) => {
|
|
3395
3511
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3407,8 +3523,8 @@ function registerBlogTools(server2, client) {
|
|
|
3407
3523
|
"get_blog_post",
|
|
3408
3524
|
"Get a specific blog post by ID",
|
|
3409
3525
|
{
|
|
3410
|
-
blogId:
|
|
3411
|
-
postId:
|
|
3526
|
+
blogId: import_zod23.z.string().describe("Blog ID"),
|
|
3527
|
+
postId: import_zod23.z.string().describe("Post ID")
|
|
3412
3528
|
},
|
|
3413
3529
|
async ({ blogId, postId }) => {
|
|
3414
3530
|
return client.get(`/blogs/${blogId}/posts/${postId}`, {});
|
|
@@ -3419,7 +3535,7 @@ function registerBlogTools(server2, client) {
|
|
|
3419
3535
|
"get_blog_authors",
|
|
3420
3536
|
"List blog authors for a location",
|
|
3421
3537
|
{
|
|
3422
|
-
locationId:
|
|
3538
|
+
locationId: import_zod23.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
|
|
3423
3539
|
},
|
|
3424
3540
|
async ({ locationId: locationId2 }) => {
|
|
3425
3541
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3433,7 +3549,7 @@ function registerBlogTools(server2, client) {
|
|
|
3433
3549
|
"get_blog_categories",
|
|
3434
3550
|
"List blog categories for a location",
|
|
3435
3551
|
{
|
|
3436
|
-
locationId:
|
|
3552
|
+
locationId: import_zod23.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
|
|
3437
3553
|
},
|
|
3438
3554
|
async ({ locationId: locationId2 }) => {
|
|
3439
3555
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3447,8 +3563,8 @@ function registerBlogTools(server2, client) {
|
|
|
3447
3563
|
"check_blog_slug",
|
|
3448
3564
|
"Check if a blog post URL slug already exists",
|
|
3449
3565
|
{
|
|
3450
|
-
locationId:
|
|
3451
|
-
urlSlug:
|
|
3566
|
+
locationId: import_zod23.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)"),
|
|
3567
|
+
urlSlug: import_zod23.z.string().describe("URL slug to check")
|
|
3452
3568
|
},
|
|
3453
3569
|
async ({ locationId: locationId2, urlSlug }) => {
|
|
3454
3570
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3460,14 +3576,14 @@ function registerBlogTools(server2, client) {
|
|
|
3460
3576
|
}
|
|
3461
3577
|
|
|
3462
3578
|
// src/tools/emails.ts
|
|
3463
|
-
var
|
|
3579
|
+
var import_zod24 = require("zod");
|
|
3464
3580
|
function registerEmailTools(server2, client) {
|
|
3465
3581
|
safeTool(
|
|
3466
3582
|
server2,
|
|
3467
3583
|
"get_email_campaigns",
|
|
3468
3584
|
"List email campaigns for a location",
|
|
3469
3585
|
{
|
|
3470
|
-
locationId:
|
|
3586
|
+
locationId: import_zod24.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
|
|
3471
3587
|
},
|
|
3472
3588
|
async ({ locationId: locationId2 }) => {
|
|
3473
3589
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3479,14 +3595,14 @@ function registerEmailTools(server2, client) {
|
|
|
3479
3595
|
}
|
|
3480
3596
|
|
|
3481
3597
|
// src/tools/trigger-links.ts
|
|
3482
|
-
var
|
|
3598
|
+
var import_zod25 = require("zod");
|
|
3483
3599
|
function registerTriggerLinkTools(server2, client) {
|
|
3484
3600
|
safeTool(
|
|
3485
3601
|
server2,
|
|
3486
3602
|
"get_trigger_links",
|
|
3487
|
-
"List trigger links for a location",
|
|
3603
|
+
"List trigger links (short tracked URLs) for a location.",
|
|
3488
3604
|
{
|
|
3489
|
-
locationId:
|
|
3605
|
+
locationId: import_zod25.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
|
|
3490
3606
|
},
|
|
3491
3607
|
async ({ locationId: locationId2 }) => {
|
|
3492
3608
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3495,17 +3611,68 @@ function registerTriggerLinkTools(server2, client) {
|
|
|
3495
3611
|
});
|
|
3496
3612
|
}
|
|
3497
3613
|
);
|
|
3614
|
+
safeTool(
|
|
3615
|
+
server2,
|
|
3616
|
+
"create_trigger_link",
|
|
3617
|
+
"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.",
|
|
3618
|
+
{
|
|
3619
|
+
name: import_zod25.z.string().describe("Display name in the GHL UI (e.g., 'May Newsletter \u2014 CTA'). Not visible to recipients."),
|
|
3620
|
+
redirectTo: import_zod25.z.string().describe("Destination URL the link should redirect to. Either a static URL (https://example.com) or a contact merge field (e.g., '{{contact.website}}')."),
|
|
3621
|
+
locationId: import_zod25.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
|
|
3622
|
+
},
|
|
3623
|
+
async ({ name, redirectTo, locationId: locationId2 }) => {
|
|
3624
|
+
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
3625
|
+
return client.post("/links/", {
|
|
3626
|
+
body: { locationId: resolvedLocationId, name, redirectTo }
|
|
3627
|
+
});
|
|
3628
|
+
}
|
|
3629
|
+
);
|
|
3630
|
+
safeTool(
|
|
3631
|
+
server2,
|
|
3632
|
+
"update_trigger_link",
|
|
3633
|
+
"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.",
|
|
3634
|
+
{
|
|
3635
|
+
linkId: import_zod25.z.string().describe("The trigger link ID to update."),
|
|
3636
|
+
name: import_zod25.z.string().optional().describe("New display name. Pass to change; omit to keep current."),
|
|
3637
|
+
redirectTo: import_zod25.z.string().optional().describe("New destination URL. Pass to change; omit to keep current.")
|
|
3638
|
+
},
|
|
3639
|
+
async ({ linkId, name, redirectTo }) => {
|
|
3640
|
+
const body = {};
|
|
3641
|
+
if (name !== void 0) body.name = name;
|
|
3642
|
+
if (redirectTo !== void 0) body.redirectTo = redirectTo;
|
|
3643
|
+
if (Object.keys(body).length === 0) {
|
|
3644
|
+
throw new Error("Pass at least one of: name, redirectTo. Nothing to update.");
|
|
3645
|
+
}
|
|
3646
|
+
return client.put(`/links/${linkId}`, { body });
|
|
3647
|
+
}
|
|
3648
|
+
);
|
|
3649
|
+
safeTool(
|
|
3650
|
+
server2,
|
|
3651
|
+
"delete_trigger_link",
|
|
3652
|
+
"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.",
|
|
3653
|
+
{
|
|
3654
|
+
linkId: import_zod25.z.string().describe("The trigger link ID to delete."),
|
|
3655
|
+
confirm: import_zod25.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action."),
|
|
3656
|
+
locationId: import_zod25.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
|
|
3657
|
+
},
|
|
3658
|
+
async ({ linkId, locationId: locationId2 }) => {
|
|
3659
|
+
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
3660
|
+
return client.delete(`/links/${linkId}`, {
|
|
3661
|
+
params: { locationId: resolvedLocationId }
|
|
3662
|
+
});
|
|
3663
|
+
}
|
|
3664
|
+
);
|
|
3498
3665
|
}
|
|
3499
3666
|
|
|
3500
3667
|
// src/tools/custom-objects.ts
|
|
3501
|
-
var
|
|
3668
|
+
var import_zod26 = require("zod");
|
|
3502
3669
|
function registerCustomObjectTools(server2, client) {
|
|
3503
3670
|
safeTool(
|
|
3504
3671
|
server2,
|
|
3505
3672
|
"list_custom_objects",
|
|
3506
3673
|
"List all custom object schemas defined in a GHL location.",
|
|
3507
3674
|
{
|
|
3508
|
-
locationId:
|
|
3675
|
+
locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3509
3676
|
},
|
|
3510
3677
|
async ({ locationId: locationId2 }) => {
|
|
3511
3678
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3519,8 +3686,8 @@ function registerCustomObjectTools(server2, client) {
|
|
|
3519
3686
|
"get_custom_object",
|
|
3520
3687
|
"Retrieve a single custom object schema by its key.",
|
|
3521
3688
|
{
|
|
3522
|
-
schemaKey:
|
|
3523
|
-
locationId:
|
|
3689
|
+
schemaKey: import_zod26.z.string().describe("The key of the custom object schema to retrieve."),
|
|
3690
|
+
locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3524
3691
|
},
|
|
3525
3692
|
async ({ schemaKey, locationId: locationId2 }) => {
|
|
3526
3693
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3534,11 +3701,11 @@ function registerCustomObjectTools(server2, client) {
|
|
|
3534
3701
|
"search_custom_object_records",
|
|
3535
3702
|
"Search records of a custom object by schema key. Supports filtering and pagination.",
|
|
3536
3703
|
{
|
|
3537
|
-
schemaKey:
|
|
3538
|
-
locationId:
|
|
3539
|
-
query:
|
|
3540
|
-
limit:
|
|
3541
|
-
offset:
|
|
3704
|
+
schemaKey: import_zod26.z.string().describe("The custom object schema key."),
|
|
3705
|
+
locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
3706
|
+
query: import_zod26.z.string().optional().describe("Search query to filter records."),
|
|
3707
|
+
limit: import_zod26.z.number().optional().describe("Maximum records to return. Defaults to 20."),
|
|
3708
|
+
offset: import_zod26.z.number().optional().describe("Number of records to skip for pagination.")
|
|
3542
3709
|
},
|
|
3543
3710
|
async ({ schemaKey, locationId: locationId2, query, limit, offset }) => {
|
|
3544
3711
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3557,9 +3724,9 @@ function registerCustomObjectTools(server2, client) {
|
|
|
3557
3724
|
"get_custom_object_record",
|
|
3558
3725
|
"Retrieve a single custom object record by schema key and record ID.",
|
|
3559
3726
|
{
|
|
3560
|
-
schemaKey:
|
|
3561
|
-
recordId:
|
|
3562
|
-
locationId:
|
|
3727
|
+
schemaKey: import_zod26.z.string().describe("The custom object schema key."),
|
|
3728
|
+
recordId: import_zod26.z.string().describe("The record ID to retrieve."),
|
|
3729
|
+
locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3563
3730
|
},
|
|
3564
3731
|
async ({ schemaKey, recordId, locationId: locationId2 }) => {
|
|
3565
3732
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3573,9 +3740,9 @@ function registerCustomObjectTools(server2, client) {
|
|
|
3573
3740
|
"create_custom_object_record",
|
|
3574
3741
|
"Create a new record for a custom object.",
|
|
3575
3742
|
{
|
|
3576
|
-
schemaKey:
|
|
3577
|
-
locationId:
|
|
3578
|
-
properties:
|
|
3743
|
+
schemaKey: import_zod26.z.string().describe("The custom object schema key."),
|
|
3744
|
+
locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
3745
|
+
properties: import_zod26.z.record(import_zod26.z.unknown()).describe("Key-value pairs of field values for the new record.")
|
|
3579
3746
|
},
|
|
3580
3747
|
async ({ schemaKey, locationId: locationId2, properties }) => {
|
|
3581
3748
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3589,10 +3756,10 @@ function registerCustomObjectTools(server2, client) {
|
|
|
3589
3756
|
"update_custom_object_record",
|
|
3590
3757
|
"Update an existing custom object record.",
|
|
3591
3758
|
{
|
|
3592
|
-
schemaKey:
|
|
3593
|
-
recordId:
|
|
3594
|
-
locationId:
|
|
3595
|
-
properties:
|
|
3759
|
+
schemaKey: import_zod26.z.string().describe("The custom object schema key."),
|
|
3760
|
+
recordId: import_zod26.z.string().describe("The record ID to update."),
|
|
3761
|
+
locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
3762
|
+
properties: import_zod26.z.record(import_zod26.z.unknown()).describe("Key-value pairs of field values to update.")
|
|
3596
3763
|
},
|
|
3597
3764
|
async ({ schemaKey, recordId, locationId: locationId2, properties }) => {
|
|
3598
3765
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3606,9 +3773,9 @@ function registerCustomObjectTools(server2, client) {
|
|
|
3606
3773
|
"delete_custom_object_record",
|
|
3607
3774
|
"Delete a custom object record by schema key and record ID.",
|
|
3608
3775
|
{
|
|
3609
|
-
schemaKey:
|
|
3610
|
-
recordId:
|
|
3611
|
-
locationId:
|
|
3776
|
+
schemaKey: import_zod26.z.string().describe("The custom object schema key."),
|
|
3777
|
+
recordId: import_zod26.z.string().describe("The record ID to delete."),
|
|
3778
|
+
locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3612
3779
|
},
|
|
3613
3780
|
async ({ schemaKey, recordId, locationId: locationId2 }) => {
|
|
3614
3781
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3620,16 +3787,16 @@ function registerCustomObjectTools(server2, client) {
|
|
|
3620
3787
|
}
|
|
3621
3788
|
|
|
3622
3789
|
// src/tools/associations.ts
|
|
3623
|
-
var
|
|
3790
|
+
var import_zod27 = require("zod");
|
|
3624
3791
|
function registerAssociationTools(server2, client) {
|
|
3625
3792
|
safeTool(
|
|
3626
3793
|
server2,
|
|
3627
3794
|
"list_associations",
|
|
3628
3795
|
"List associations for a custom object record \u2014 shows related contacts, opportunities, or other records.",
|
|
3629
3796
|
{
|
|
3630
|
-
schemaKey:
|
|
3631
|
-
recordId:
|
|
3632
|
-
locationId:
|
|
3797
|
+
schemaKey: import_zod27.z.string().describe("The custom object schema key."),
|
|
3798
|
+
recordId: import_zod27.z.string().describe("The record ID to list associations for."),
|
|
3799
|
+
locationId: import_zod27.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3633
3800
|
},
|
|
3634
3801
|
async ({ schemaKey, recordId, locationId: locationId2 }) => {
|
|
3635
3802
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3644,11 +3811,11 @@ function registerAssociationTools(server2, client) {
|
|
|
3644
3811
|
"create_association",
|
|
3645
3812
|
"Create an association between a custom object record and another entity (contact, opportunity, or another custom object record).",
|
|
3646
3813
|
{
|
|
3647
|
-
schemaKey:
|
|
3648
|
-
recordId:
|
|
3649
|
-
locationId:
|
|
3650
|
-
targetEntityType:
|
|
3651
|
-
targetEntityId:
|
|
3814
|
+
schemaKey: import_zod27.z.string().describe("The custom object schema key of the source record."),
|
|
3815
|
+
recordId: import_zod27.z.string().describe("The source record ID."),
|
|
3816
|
+
locationId: import_zod27.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
3817
|
+
targetEntityType: import_zod27.z.string().describe("The target entity type (e.g. 'contact', 'opportunity', or a custom object schema key)."),
|
|
3818
|
+
targetEntityId: import_zod27.z.string().describe("The ID of the target entity to associate with.")
|
|
3652
3819
|
},
|
|
3653
3820
|
async ({ schemaKey, recordId, locationId: locationId2, targetEntityType, targetEntityId }) => {
|
|
3654
3821
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3669,10 +3836,10 @@ function registerAssociationTools(server2, client) {
|
|
|
3669
3836
|
"delete_association",
|
|
3670
3837
|
"Remove an association between a custom object record and another entity.",
|
|
3671
3838
|
{
|
|
3672
|
-
schemaKey:
|
|
3673
|
-
recordId:
|
|
3674
|
-
associationId:
|
|
3675
|
-
locationId:
|
|
3839
|
+
schemaKey: import_zod27.z.string().describe("The custom object schema key of the source record."),
|
|
3840
|
+
recordId: import_zod27.z.string().describe("The source record ID."),
|
|
3841
|
+
associationId: import_zod27.z.string().describe("The association ID to remove."),
|
|
3842
|
+
locationId: import_zod27.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3676
3843
|
},
|
|
3677
3844
|
async ({ schemaKey, recordId, associationId, locationId: locationId2 }) => {
|
|
3678
3845
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3685,18 +3852,18 @@ function registerAssociationTools(server2, client) {
|
|
|
3685
3852
|
}
|
|
3686
3853
|
|
|
3687
3854
|
// src/tools/estimates.ts
|
|
3688
|
-
var
|
|
3855
|
+
var import_zod28 = require("zod");
|
|
3689
3856
|
function registerEstimateTools(server2, client) {
|
|
3690
3857
|
safeTool(
|
|
3691
3858
|
server2,
|
|
3692
3859
|
"list_estimates",
|
|
3693
3860
|
"List estimates/quotes in a GHL location. Supports pagination and filtering by status.",
|
|
3694
3861
|
{
|
|
3695
|
-
locationId:
|
|
3696
|
-
status:
|
|
3697
|
-
limit:
|
|
3698
|
-
offset:
|
|
3699
|
-
contactId:
|
|
3862
|
+
locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
3863
|
+
status: import_zod28.z.string().optional().describe("Filter by status (e.g. 'draft', 'sent', 'accepted', 'declined')."),
|
|
3864
|
+
limit: import_zod28.z.number().optional().describe("Maximum estimates to return. Defaults to 20."),
|
|
3865
|
+
offset: import_zod28.z.number().optional().describe("Number of records to skip for pagination."),
|
|
3866
|
+
contactId: import_zod28.z.string().optional().describe("Filter estimates by contact ID.")
|
|
3700
3867
|
},
|
|
3701
3868
|
async ({ locationId: locationId2, status, limit, offset, contactId }) => {
|
|
3702
3869
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3717,8 +3884,8 @@ function registerEstimateTools(server2, client) {
|
|
|
3717
3884
|
"get_estimate",
|
|
3718
3885
|
"Retrieve a single estimate/quote by its ID.",
|
|
3719
3886
|
{
|
|
3720
|
-
estimateId:
|
|
3721
|
-
locationId:
|
|
3887
|
+
estimateId: import_zod28.z.string().describe("The estimate ID to retrieve."),
|
|
3888
|
+
locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3722
3889
|
},
|
|
3723
3890
|
async ({ estimateId, locationId: locationId2 }) => {
|
|
3724
3891
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3732,12 +3899,12 @@ function registerEstimateTools(server2, client) {
|
|
|
3732
3899
|
"create_estimate",
|
|
3733
3900
|
"Create a new estimate/quote for a contact.",
|
|
3734
3901
|
{
|
|
3735
|
-
locationId:
|
|
3736
|
-
contactId:
|
|
3737
|
-
name:
|
|
3738
|
-
title:
|
|
3739
|
-
items:
|
|
3740
|
-
discount:
|
|
3902
|
+
locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
3903
|
+
contactId: import_zod28.z.string().describe("The contact ID this estimate is for."),
|
|
3904
|
+
name: import_zod28.z.string().describe("Estimate name/title."),
|
|
3905
|
+
title: import_zod28.z.string().optional().describe("Display title for the estimate."),
|
|
3906
|
+
items: import_zod28.z.array(import_zod28.z.record(import_zod28.z.unknown())).describe("Line items array. Each item should have name, description, price, qty."),
|
|
3907
|
+
discount: import_zod28.z.record(import_zod28.z.unknown()).optional().describe("Discount object (type, value).")
|
|
3741
3908
|
},
|
|
3742
3909
|
async ({ locationId: locationId2, contactId, name, title, items, discount }) => {
|
|
3743
3910
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3759,12 +3926,12 @@ function registerEstimateTools(server2, client) {
|
|
|
3759
3926
|
"update_estimate",
|
|
3760
3927
|
"Update an existing estimate/quote.",
|
|
3761
3928
|
{
|
|
3762
|
-
estimateId:
|
|
3763
|
-
locationId:
|
|
3764
|
-
name:
|
|
3765
|
-
title:
|
|
3766
|
-
items:
|
|
3767
|
-
discount:
|
|
3929
|
+
estimateId: import_zod28.z.string().describe("The estimate ID to update."),
|
|
3930
|
+
locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
3931
|
+
name: import_zod28.z.string().optional().describe("Updated estimate name."),
|
|
3932
|
+
title: import_zod28.z.string().optional().describe("Updated display title."),
|
|
3933
|
+
items: import_zod28.z.array(import_zod28.z.record(import_zod28.z.unknown())).optional().describe("Updated line items array."),
|
|
3934
|
+
discount: import_zod28.z.record(import_zod28.z.unknown()).optional().describe("Updated discount object.")
|
|
3768
3935
|
},
|
|
3769
3936
|
async ({ estimateId, locationId: locationId2, name, title, items, discount }) => {
|
|
3770
3937
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3784,8 +3951,8 @@ function registerEstimateTools(server2, client) {
|
|
|
3784
3951
|
"delete_estimate",
|
|
3785
3952
|
"Delete an estimate/quote by ID.",
|
|
3786
3953
|
{
|
|
3787
|
-
estimateId:
|
|
3788
|
-
locationId:
|
|
3954
|
+
estimateId: import_zod28.z.string().describe("The estimate ID to delete."),
|
|
3955
|
+
locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3789
3956
|
},
|
|
3790
3957
|
async ({ estimateId, locationId: locationId2 }) => {
|
|
3791
3958
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3799,8 +3966,8 @@ function registerEstimateTools(server2, client) {
|
|
|
3799
3966
|
"send_estimate",
|
|
3800
3967
|
"Send an estimate to the contact via email.",
|
|
3801
3968
|
{
|
|
3802
|
-
estimateId:
|
|
3803
|
-
locationId:
|
|
3969
|
+
estimateId: import_zod28.z.string().describe("The estimate ID to send."),
|
|
3970
|
+
locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3804
3971
|
},
|
|
3805
3972
|
async ({ estimateId, locationId: locationId2 }) => {
|
|
3806
3973
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3812,14 +3979,14 @@ function registerEstimateTools(server2, client) {
|
|
|
3812
3979
|
}
|
|
3813
3980
|
|
|
3814
3981
|
// src/tools/coupons.ts
|
|
3815
|
-
var
|
|
3982
|
+
var import_zod29 = require("zod");
|
|
3816
3983
|
function registerCouponTools(server2, client) {
|
|
3817
3984
|
safeTool(
|
|
3818
3985
|
server2,
|
|
3819
3986
|
"list_coupons",
|
|
3820
3987
|
"List coupons/promo codes in a GHL location.",
|
|
3821
3988
|
{
|
|
3822
|
-
locationId:
|
|
3989
|
+
locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3823
3990
|
},
|
|
3824
3991
|
async ({ locationId: locationId2 }) => {
|
|
3825
3992
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3833,8 +4000,8 @@ function registerCouponTools(server2, client) {
|
|
|
3833
4000
|
"get_coupon",
|
|
3834
4001
|
"Retrieve a single coupon by its ID.",
|
|
3835
4002
|
{
|
|
3836
|
-
couponId:
|
|
3837
|
-
locationId:
|
|
4003
|
+
couponId: import_zod29.z.string().describe("The coupon ID to retrieve."),
|
|
4004
|
+
locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3838
4005
|
},
|
|
3839
4006
|
async ({ couponId, locationId: locationId2 }) => {
|
|
3840
4007
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3848,14 +4015,14 @@ function registerCouponTools(server2, client) {
|
|
|
3848
4015
|
"create_coupon",
|
|
3849
4016
|
"Create a new coupon/promo code.",
|
|
3850
4017
|
{
|
|
3851
|
-
locationId:
|
|
3852
|
-
name:
|
|
3853
|
-
code:
|
|
3854
|
-
type:
|
|
3855
|
-
amount:
|
|
3856
|
-
duration:
|
|
3857
|
-
durationInMonths:
|
|
3858
|
-
productIds:
|
|
4018
|
+
locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
4019
|
+
name: import_zod29.z.string().describe("Coupon name."),
|
|
4020
|
+
code: import_zod29.z.string().describe("Promo code string customers enter."),
|
|
4021
|
+
type: import_zod29.z.string().describe("Discount type: 'percentage' or 'fixed'."),
|
|
4022
|
+
amount: import_zod29.z.number().describe("Discount amount (percentage value or fixed dollar amount)."),
|
|
4023
|
+
duration: import_zod29.z.string().optional().describe("Duration: 'once', 'repeating', or 'forever'. Defaults to 'once'."),
|
|
4024
|
+
durationInMonths: import_zod29.z.number().optional().describe("Number of months if duration is 'repeating'."),
|
|
4025
|
+
productIds: import_zod29.z.array(import_zod29.z.string()).optional().describe("Product IDs this coupon applies to. If empty, applies to all.")
|
|
3859
4026
|
},
|
|
3860
4027
|
async ({ locationId: locationId2, name, code, type, amount, duration, durationInMonths, productIds }) => {
|
|
3861
4028
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3879,10 +4046,10 @@ function registerCouponTools(server2, client) {
|
|
|
3879
4046
|
"update_coupon",
|
|
3880
4047
|
"Update an existing coupon.",
|
|
3881
4048
|
{
|
|
3882
|
-
couponId:
|
|
3883
|
-
locationId:
|
|
3884
|
-
name:
|
|
3885
|
-
productIds:
|
|
4049
|
+
couponId: import_zod29.z.string().describe("The coupon ID to update."),
|
|
4050
|
+
locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
4051
|
+
name: import_zod29.z.string().optional().describe("Updated coupon name."),
|
|
4052
|
+
productIds: import_zod29.z.array(import_zod29.z.string()).optional().describe("Updated product IDs this coupon applies to.")
|
|
3886
4053
|
},
|
|
3887
4054
|
async ({ couponId, locationId: locationId2, name, productIds }) => {
|
|
3888
4055
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3900,8 +4067,8 @@ function registerCouponTools(server2, client) {
|
|
|
3900
4067
|
"delete_coupon",
|
|
3901
4068
|
"Delete a coupon by ID.",
|
|
3902
4069
|
{
|
|
3903
|
-
couponId:
|
|
3904
|
-
locationId:
|
|
4070
|
+
couponId: import_zod29.z.string().describe("The coupon ID to delete."),
|
|
4071
|
+
locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3905
4072
|
},
|
|
3906
4073
|
async ({ couponId, locationId: locationId2 }) => {
|
|
3907
4074
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3913,14 +4080,14 @@ function registerCouponTools(server2, client) {
|
|
|
3913
4080
|
}
|
|
3914
4081
|
|
|
3915
4082
|
// src/tools/webhooks.ts
|
|
3916
|
-
var
|
|
4083
|
+
var import_zod30 = require("zod");
|
|
3917
4084
|
function registerWebhookTools(server2, client) {
|
|
3918
4085
|
safeTool(
|
|
3919
4086
|
server2,
|
|
3920
4087
|
"list_webhooks",
|
|
3921
4088
|
"List all webhooks configured in a GHL location.",
|
|
3922
4089
|
{
|
|
3923
|
-
locationId:
|
|
4090
|
+
locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3924
4091
|
},
|
|
3925
4092
|
async ({ locationId: locationId2 }) => {
|
|
3926
4093
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3934,8 +4101,8 @@ function registerWebhookTools(server2, client) {
|
|
|
3934
4101
|
"get_webhook",
|
|
3935
4102
|
"Retrieve a single webhook by its ID.",
|
|
3936
4103
|
{
|
|
3937
|
-
webhookId:
|
|
3938
|
-
locationId:
|
|
4104
|
+
webhookId: import_zod30.z.string().describe("The webhook ID to retrieve."),
|
|
4105
|
+
locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3939
4106
|
},
|
|
3940
4107
|
async ({ webhookId, locationId: locationId2 }) => {
|
|
3941
4108
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3949,10 +4116,10 @@ function registerWebhookTools(server2, client) {
|
|
|
3949
4116
|
"create_webhook",
|
|
3950
4117
|
"Create a new webhook subscription for GHL events.",
|
|
3951
4118
|
{
|
|
3952
|
-
locationId:
|
|
3953
|
-
name:
|
|
3954
|
-
url:
|
|
3955
|
-
events:
|
|
4119
|
+
locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
4120
|
+
name: import_zod30.z.string().describe("Webhook name."),
|
|
4121
|
+
url: import_zod30.z.string().describe("The URL to POST events to."),
|
|
4122
|
+
events: import_zod30.z.array(import_zod30.z.string()).describe(
|
|
3956
4123
|
"List of event types to subscribe to (e.g. 'ContactCreate', 'AppointmentCreate', 'OpportunityStatusUpdate')."
|
|
3957
4124
|
)
|
|
3958
4125
|
},
|
|
@@ -3973,11 +4140,11 @@ function registerWebhookTools(server2, client) {
|
|
|
3973
4140
|
"update_webhook",
|
|
3974
4141
|
"Update an existing webhook (name, URL, or subscribed events).",
|
|
3975
4142
|
{
|
|
3976
|
-
webhookId:
|
|
3977
|
-
locationId:
|
|
3978
|
-
name:
|
|
3979
|
-
url:
|
|
3980
|
-
events:
|
|
4143
|
+
webhookId: import_zod30.z.string().describe("The webhook ID to update."),
|
|
4144
|
+
locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
4145
|
+
name: import_zod30.z.string().optional().describe("Updated webhook name."),
|
|
4146
|
+
url: import_zod30.z.string().optional().describe("Updated webhook URL."),
|
|
4147
|
+
events: import_zod30.z.array(import_zod30.z.string()).optional().describe("Updated list of event types.")
|
|
3981
4148
|
},
|
|
3982
4149
|
async ({ webhookId, locationId: locationId2, name, url, events }) => {
|
|
3983
4150
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3993,8 +4160,8 @@ function registerWebhookTools(server2, client) {
|
|
|
3993
4160
|
"delete_webhook",
|
|
3994
4161
|
"Delete a webhook subscription by ID.",
|
|
3995
4162
|
{
|
|
3996
|
-
webhookId:
|
|
3997
|
-
locationId:
|
|
4163
|
+
webhookId: import_zod30.z.string().describe("The webhook ID to delete."),
|
|
4164
|
+
locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3998
4165
|
},
|
|
3999
4166
|
async ({ webhookId, locationId: locationId2 }) => {
|
|
4000
4167
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -4006,16 +4173,16 @@ function registerWebhookTools(server2, client) {
|
|
|
4006
4173
|
}
|
|
4007
4174
|
|
|
4008
4175
|
// src/tools/documents.ts
|
|
4009
|
-
var
|
|
4176
|
+
var import_zod31 = require("zod");
|
|
4010
4177
|
function registerDocumentTools(server2, client) {
|
|
4011
4178
|
safeTool(
|
|
4012
4179
|
server2,
|
|
4013
4180
|
"list_documents",
|
|
4014
4181
|
"List documents and contracts in a GHL location. Supports pagination.",
|
|
4015
4182
|
{
|
|
4016
|
-
locationId:
|
|
4017
|
-
limit:
|
|
4018
|
-
offset:
|
|
4183
|
+
locationId: import_zod31.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
4184
|
+
limit: import_zod31.z.number().optional().describe("Maximum documents to return. Defaults to 20."),
|
|
4185
|
+
offset: import_zod31.z.number().optional().describe("Number of records to skip for pagination.")
|
|
4019
4186
|
},
|
|
4020
4187
|
async ({ locationId: locationId2, limit, offset }) => {
|
|
4021
4188
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -4033,8 +4200,8 @@ function registerDocumentTools(server2, client) {
|
|
|
4033
4200
|
"get_document",
|
|
4034
4201
|
"Retrieve a single document or contract by its ID, including signature status.",
|
|
4035
4202
|
{
|
|
4036
|
-
documentId:
|
|
4037
|
-
locationId:
|
|
4203
|
+
documentId: import_zod31.z.string().describe("The document ID to retrieve."),
|
|
4204
|
+
locationId: import_zod31.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
4038
4205
|
},
|
|
4039
4206
|
async ({ documentId, locationId: locationId2 }) => {
|
|
4040
4207
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -4048,8 +4215,8 @@ function registerDocumentTools(server2, client) {
|
|
|
4048
4215
|
"delete_document",
|
|
4049
4216
|
"Delete a document or contract by ID.",
|
|
4050
4217
|
{
|
|
4051
|
-
documentId:
|
|
4052
|
-
locationId:
|
|
4218
|
+
documentId: import_zod31.z.string().describe("The document ID to delete."),
|
|
4219
|
+
locationId: import_zod31.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
4053
4220
|
},
|
|
4054
4221
|
async ({ documentId, locationId: locationId2 }) => {
|
|
4055
4222
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -4063,9 +4230,9 @@ function registerDocumentTools(server2, client) {
|
|
|
4063
4230
|
"send_document",
|
|
4064
4231
|
"Send a document/contract to a contact for electronic signature.",
|
|
4065
4232
|
{
|
|
4066
|
-
documentId:
|
|
4067
|
-
contactId:
|
|
4068
|
-
locationId:
|
|
4233
|
+
documentId: import_zod31.z.string().describe("The document ID to send."),
|
|
4234
|
+
contactId: import_zod31.z.string().describe("The contact ID to send the document to."),
|
|
4235
|
+
locationId: import_zod31.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
4069
4236
|
},
|
|
4070
4237
|
async ({ documentId, contactId, locationId: locationId2 }) => {
|
|
4071
4238
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -4077,19 +4244,19 @@ function registerDocumentTools(server2, client) {
|
|
|
4077
4244
|
}
|
|
4078
4245
|
|
|
4079
4246
|
// src/tools/workflow-builder.ts
|
|
4080
|
-
var
|
|
4081
|
-
var ActionSchema =
|
|
4082
|
-
id:
|
|
4083
|
-
name:
|
|
4084
|
-
type:
|
|
4085
|
-
attributes:
|
|
4086
|
-
next:
|
|
4087
|
-
parent:
|
|
4088
|
-
parentKey:
|
|
4089
|
-
order:
|
|
4090
|
-
cat:
|
|
4091
|
-
nodeType:
|
|
4092
|
-
sibling:
|
|
4247
|
+
var import_zod32 = require("zod");
|
|
4248
|
+
var ActionSchema = import_zod32.z.object({
|
|
4249
|
+
id: import_zod32.z.string().optional().describe("Action ID (auto-generated if omitted)."),
|
|
4250
|
+
name: import_zod32.z.string().describe("Display name for this action step."),
|
|
4251
|
+
type: import_zod32.z.string().describe("Action type."),
|
|
4252
|
+
attributes: import_zod32.z.record(import_zod32.z.unknown()).optional().describe("Action-specific configuration."),
|
|
4253
|
+
next: import_zod32.z.union([import_zod32.z.string(), import_zod32.z.array(import_zod32.z.string())]).optional().describe("Next action id, or branch id array for condition nodes."),
|
|
4254
|
+
parent: import_zod32.z.string().optional().describe("Branch parent node id."),
|
|
4255
|
+
parentKey: import_zod32.z.string().optional().describe("Previous action id or branch parent id."),
|
|
4256
|
+
order: import_zod32.z.number().optional().describe("Order within this chain or branch."),
|
|
4257
|
+
cat: import_zod32.z.string().optional().describe("Category for condition, transition, or multi-path nodes."),
|
|
4258
|
+
nodeType: import_zod32.z.string().optional().describe("Node type for if/else nodes."),
|
|
4259
|
+
sibling: import_zod32.z.array(import_zod32.z.string()).optional().describe("Sibling branch node IDs.")
|
|
4093
4260
|
}).passthrough();
|
|
4094
4261
|
function linkBranchActions(actions, branchId, nextAfterMerge) {
|
|
4095
4262
|
const prepared = actions.map((action) => ({
|
|
@@ -4136,8 +4303,8 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4136
4303
|
"list_workflows_full",
|
|
4137
4304
|
"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.",
|
|
4138
4305
|
{
|
|
4139
|
-
limit:
|
|
4140
|
-
skip:
|
|
4306
|
+
limit: import_zod32.z.number().optional().describe("Max workflows to return. Defaults to 50."),
|
|
4307
|
+
skip: import_zod32.z.number().optional().describe("Number of workflows to skip for pagination.")
|
|
4141
4308
|
},
|
|
4142
4309
|
async ({ limit, skip }) => {
|
|
4143
4310
|
try {
|
|
@@ -4152,7 +4319,7 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4152
4319
|
"get_workflow_full",
|
|
4153
4320
|
"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.",
|
|
4154
4321
|
{
|
|
4155
|
-
workflowId:
|
|
4322
|
+
workflowId: import_zod32.z.string().describe("The workflow ID to retrieve.")
|
|
4156
4323
|
},
|
|
4157
4324
|
async ({ workflowId }) => {
|
|
4158
4325
|
try {
|
|
@@ -4167,9 +4334,9 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4167
4334
|
"get_trigger_registry",
|
|
4168
4335
|
"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.",
|
|
4169
4336
|
{
|
|
4170
|
-
companyId:
|
|
4171
|
-
limit:
|
|
4172
|
-
installedOnly:
|
|
4337
|
+
companyId: import_zod32.z.string().describe("Company ID for the location. Find it in any get_workflow_full response under the 'companyId' field."),
|
|
4338
|
+
limit: import_zod32.z.number().optional().describe("Max marketplace apps to return. Defaults to 200."),
|
|
4339
|
+
installedOnly: import_zod32.z.boolean().optional().describe("If true, returns only apps installed in this location. Defaults to false (full marketplace catalogue, ~85 apps).")
|
|
4173
4340
|
},
|
|
4174
4341
|
async ({ companyId, limit, installedOnly }) => {
|
|
4175
4342
|
try {
|
|
@@ -4201,7 +4368,7 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4201
4368
|
"create_workflow",
|
|
4202
4369
|
"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).",
|
|
4203
4370
|
{
|
|
4204
|
-
name:
|
|
4371
|
+
name: import_zod32.z.string().describe("Name for the new workflow.")
|
|
4205
4372
|
},
|
|
4206
4373
|
async ({ name }) => {
|
|
4207
4374
|
try {
|
|
@@ -4216,11 +4383,11 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4216
4383
|
"update_workflow_actions",
|
|
4217
4384
|
"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.",
|
|
4218
4385
|
{
|
|
4219
|
-
workflowId:
|
|
4220
|
-
name:
|
|
4221
|
-
status:
|
|
4222
|
-
actions:
|
|
4223
|
-
triggers:
|
|
4386
|
+
workflowId: import_zod32.z.string().describe("The workflow ID to update."),
|
|
4387
|
+
name: import_zod32.z.string().optional().describe("New workflow name."),
|
|
4388
|
+
status: import_zod32.z.string().optional().describe("New status: 'draft' or 'published'."),
|
|
4389
|
+
actions: import_zod32.z.array(ActionSchema).optional().describe("Array of workflow actions/steps. For linear flows, provide in order \u2014 chaining is automatic."),
|
|
4390
|
+
triggers: import_zod32.z.array(WorkflowTriggerSchema).optional().describe("Array of workflow triggers.")
|
|
4224
4391
|
},
|
|
4225
4392
|
async ({ workflowId, name, status, actions, triggers }) => {
|
|
4226
4393
|
try {
|
|
@@ -4264,12 +4431,12 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4264
4431
|
"build_if_else_branch",
|
|
4265
4432
|
"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.",
|
|
4266
4433
|
{
|
|
4267
|
-
field:
|
|
4268
|
-
operator:
|
|
4269
|
-
value:
|
|
4270
|
-
yes_actions:
|
|
4271
|
-
no_actions:
|
|
4272
|
-
next_after_merge:
|
|
4434
|
+
field: import_zod32.z.string().describe("Condition subtype, currently 'tags' for tag-based conditions."),
|
|
4435
|
+
operator: import_zod32.z.string().describe("Condition operator token. Verified: 'index-of-true' (Includes), 'index-of-false' (Does not include), 'has_value' (Is not empty), 'has_no_value' (Is empty). Emptiness operators don't take a value. Tokens must match GHL's exact internal strings or the UI dropdown renders the raw token instead of a label."),
|
|
4436
|
+
value: import_zod32.z.union([import_zod32.z.string(), import_zod32.z.array(import_zod32.z.string())]).optional().describe("Tag name(s). Required for index-of-true / index-of-false. Omit for has_value / has_no_value. Single string is auto-wrapped as an array. Tags must already exist in the location's tag library or the UI dropdown will render empty."),
|
|
4437
|
+
yes_actions: import_zod32.z.array(ActionSchema).describe("Actions to run in the Yes branch."),
|
|
4438
|
+
no_actions: import_zod32.z.array(ActionSchema).describe("Actions to run in the No branch."),
|
|
4439
|
+
next_after_merge: import_zod32.z.string().optional().describe("Optional node id to link from each non-empty branch's final child.")
|
|
4273
4440
|
},
|
|
4274
4441
|
async ({ field, operator, value, yes_actions, no_actions, next_after_merge }) => {
|
|
4275
4442
|
try {
|
|
@@ -4379,7 +4546,7 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4379
4546
|
"build_goal_event",
|
|
4380
4547
|
"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).",
|
|
4381
4548
|
{
|
|
4382
|
-
goal_condition:
|
|
4549
|
+
goal_condition: import_zod32.z.enum([
|
|
4383
4550
|
"email_event",
|
|
4384
4551
|
"link_click",
|
|
4385
4552
|
"add_contact_tag",
|
|
@@ -4391,11 +4558,11 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4391
4558
|
"invoice_paid",
|
|
4392
4559
|
"review_request_clicked"
|
|
4393
4560
|
]).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)."),
|
|
4394
|
-
extras:
|
|
4395
|
-
action:
|
|
4396
|
-
name:
|
|
4397
|
-
op:
|
|
4398
|
-
inner_op:
|
|
4561
|
+
extras: import_zod32.z.record(import_zod32.z.unknown()).optional().describe("Goal-condition-specific config. See goal_condition description for the expected shape per value. Pass {} or omit for goal_conditions without extras."),
|
|
4562
|
+
action: import_zod32.z.enum(["exit", "continue", "wait"]).default("exit").describe("What happens when the goal fires (per GHL's GoalAction enum). 'exit' terminates the workflow path (verified). 'continue' lets it proceed to a downstream node. 'wait' pauses on the goal."),
|
|
4563
|
+
name: import_zod32.z.string().default("Goal").describe("Display name in the GHL UI."),
|
|
4564
|
+
op: import_zod32.z.enum(["or", "and"]).default("or").describe("Top-level boolean operator across segments. Default 'or'."),
|
|
4565
|
+
inner_op: import_zod32.z.enum(["or", "and"]).default("or").describe("Boolean operator across conditions within a single segment. Default 'or'.")
|
|
4399
4566
|
},
|
|
4400
4567
|
async ({ goal_condition, extras, action, name, op, inner_op }) => {
|
|
4401
4568
|
try {
|
|
@@ -4430,8 +4597,8 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4430
4597
|
"delete_workflow_full",
|
|
4431
4598
|
"Permanently delete a workflow. IRREVERSIBLE.",
|
|
4432
4599
|
{
|
|
4433
|
-
workflowId:
|
|
4434
|
-
confirm:
|
|
4600
|
+
workflowId: import_zod32.z.string().describe("The workflow ID to delete."),
|
|
4601
|
+
confirm: import_zod32.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
|
|
4435
4602
|
},
|
|
4436
4603
|
async ({ workflowId }) => {
|
|
4437
4604
|
try {
|
|
@@ -4446,7 +4613,7 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4446
4613
|
"publish_workflow",
|
|
4447
4614
|
"Publish a draft workflow, making it active and processing contacts.",
|
|
4448
4615
|
{
|
|
4449
|
-
workflowId:
|
|
4616
|
+
workflowId: import_zod32.z.string().describe("The workflow ID to publish.")
|
|
4450
4617
|
},
|
|
4451
4618
|
async ({ workflowId }) => {
|
|
4452
4619
|
try {
|
|
@@ -4460,7 +4627,7 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4460
4627
|
}
|
|
4461
4628
|
|
|
4462
4629
|
// src/tools/funnel-builder.ts
|
|
4463
|
-
var
|
|
4630
|
+
var import_zod33 = require("zod");
|
|
4464
4631
|
function registerFunnelBuilderTools(server2, builderClient) {
|
|
4465
4632
|
const client = builderClient;
|
|
4466
4633
|
if (!client) return;
|
|
@@ -4503,7 +4670,7 @@ ${text2}`);
|
|
|
4503
4670
|
"list_funnels_full",
|
|
4504
4671
|
"List all funnels/websites with full details including steps, pages, and metadata. Uses the internal API for richer data than the public API.",
|
|
4505
4672
|
{
|
|
4506
|
-
limit:
|
|
4673
|
+
limit: import_zod33.z.number().optional().describe("Max funnels to return. Defaults to 50.")
|
|
4507
4674
|
},
|
|
4508
4675
|
async ({ limit }) => {
|
|
4509
4676
|
try {
|
|
@@ -4523,7 +4690,7 @@ ${text2}`);
|
|
|
4523
4690
|
"get_page_full",
|
|
4524
4691
|
"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.",
|
|
4525
4692
|
{
|
|
4526
|
-
pageId:
|
|
4693
|
+
pageId: import_zod33.z.string().describe("The page ID to retrieve.")
|
|
4527
4694
|
},
|
|
4528
4695
|
async ({ pageId }) => {
|
|
4529
4696
|
try {
|
|
@@ -4543,7 +4710,7 @@ ${text2}`);
|
|
|
4543
4710
|
"get_page_content",
|
|
4544
4711
|
"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.",
|
|
4545
4712
|
{
|
|
4546
|
-
pageDataDownloadUrl:
|
|
4713
|
+
pageDataDownloadUrl: import_zod33.z.string().describe("The pageDataDownloadUrl from get_page_full response.")
|
|
4547
4714
|
},
|
|
4548
4715
|
async ({ pageDataDownloadUrl }) => {
|
|
4549
4716
|
try {
|
|
@@ -4565,7 +4732,7 @@ ${text2}`);
|
|
|
4565
4732
|
"create_funnel",
|
|
4566
4733
|
"Create a new funnel/website. Starts empty \u2014 add steps and pages after creation.",
|
|
4567
4734
|
{
|
|
4568
|
-
name:
|
|
4735
|
+
name: import_zod33.z.string().describe("Name for the new funnel.")
|
|
4569
4736
|
},
|
|
4570
4737
|
async ({ name }) => {
|
|
4571
4738
|
try {
|
|
@@ -4587,21 +4754,21 @@ ${text2}`);
|
|
|
4587
4754
|
"update_funnel",
|
|
4588
4755
|
"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.",
|
|
4589
4756
|
{
|
|
4590
|
-
funnelId:
|
|
4591
|
-
name:
|
|
4592
|
-
path:
|
|
4593
|
-
bodyTrackingCode:
|
|
4594
|
-
headTrackingCode:
|
|
4595
|
-
chatWidgetId:
|
|
4596
|
-
domainId:
|
|
4597
|
-
faviconUrl:
|
|
4598
|
-
paymentMode:
|
|
4599
|
-
requireCreditCard:
|
|
4600
|
-
isGdprCompliant:
|
|
4601
|
-
isOptimisePageLoad:
|
|
4602
|
-
imageOptimization:
|
|
4603
|
-
allowPaymentModeOption:
|
|
4604
|
-
storeCurrencyFormatting:
|
|
4757
|
+
funnelId: import_zod33.z.string().describe("The funnel ID to update."),
|
|
4758
|
+
name: import_zod33.z.string().optional().describe("New funnel display name."),
|
|
4759
|
+
path: import_zod33.z.string().optional().describe("URL slug for the funnel (e.g., '/my-funnel'). Mapped to funnelPath."),
|
|
4760
|
+
bodyTrackingCode: import_zod33.z.string().optional().describe("Custom tracking script injected before </body>."),
|
|
4761
|
+
headTrackingCode: import_zod33.z.string().optional().describe("Custom tracking script injected before </head>."),
|
|
4762
|
+
chatWidgetId: import_zod33.z.string().optional().describe("Chat widget to embed on every page in this funnel."),
|
|
4763
|
+
domainId: import_zod33.z.string().optional().describe("Custom domain ID for the funnel."),
|
|
4764
|
+
faviconUrl: import_zod33.z.string().optional().describe("Favicon URL for funnel pages."),
|
|
4765
|
+
paymentMode: import_zod33.z.boolean().optional().describe("Whether to require a payment mode for the funnel."),
|
|
4766
|
+
requireCreditCard: import_zod33.z.boolean().optional().describe("Whether to require a credit card on opt-in steps."),
|
|
4767
|
+
isGdprCompliant: import_zod33.z.boolean().optional().describe("Toggle GDPR compliance mode."),
|
|
4768
|
+
isOptimisePageLoad: import_zod33.z.boolean().optional().describe("Enable GHL's page-load optimization."),
|
|
4769
|
+
imageOptimization: import_zod33.z.boolean().optional().describe("Enable automatic image optimization."),
|
|
4770
|
+
allowPaymentModeOption: import_zod33.z.boolean().optional().describe("Allow buyers to choose payment mode on checkout."),
|
|
4771
|
+
storeCurrencyFormatting: import_zod33.z.boolean().optional().describe("Use store-wide currency formatting.")
|
|
4605
4772
|
},
|
|
4606
4773
|
async (args) => {
|
|
4607
4774
|
try {
|
|
@@ -4657,11 +4824,11 @@ ${text2}`);
|
|
|
4657
4824
|
"update_funnel_step",
|
|
4658
4825
|
"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.",
|
|
4659
4826
|
{
|
|
4660
|
-
funnelId:
|
|
4661
|
-
stepId:
|
|
4662
|
-
name:
|
|
4663
|
-
url:
|
|
4664
|
-
domainName:
|
|
4827
|
+
funnelId: import_zod33.z.string().describe("The funnel ID containing the step."),
|
|
4828
|
+
stepId: import_zod33.z.string().describe("The step ID to update (from get_funnel_pages / list_funnels_full)."),
|
|
4829
|
+
name: import_zod33.z.string().optional().describe("New step display name."),
|
|
4830
|
+
url: import_zod33.z.string().optional().describe("URL slug for the step (e.g., '/thank-you')."),
|
|
4831
|
+
domainName: import_zod33.z.string().optional().describe("Custom domain to attach to this step.")
|
|
4665
4832
|
},
|
|
4666
4833
|
async ({ funnelId, stepId, name, url, domainName }) => {
|
|
4667
4834
|
try {
|
|
@@ -4680,8 +4847,8 @@ ${text2}`);
|
|
|
4680
4847
|
"delete_funnel",
|
|
4681
4848
|
"Permanently delete a funnel and all its steps/pages. IRREVERSIBLE.",
|
|
4682
4849
|
{
|
|
4683
|
-
funnelId:
|
|
4684
|
-
confirm:
|
|
4850
|
+
funnelId: import_zod33.z.string().describe("The funnel ID to delete."),
|
|
4851
|
+
confirm: import_zod33.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
|
|
4685
4852
|
},
|
|
4686
4853
|
async ({ funnelId }) => {
|
|
4687
4854
|
try {
|
|
@@ -4700,10 +4867,10 @@ ${text2}`);
|
|
|
4700
4867
|
"create_funnel_page",
|
|
4701
4868
|
"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.",
|
|
4702
4869
|
{
|
|
4703
|
-
funnelId:
|
|
4704
|
-
name:
|
|
4705
|
-
url:
|
|
4706
|
-
type:
|
|
4870
|
+
funnelId: import_zod33.z.string().describe("The funnel ID to add the step to."),
|
|
4871
|
+
name: import_zod33.z.string().describe("Step display name."),
|
|
4872
|
+
url: import_zod33.z.string().optional().describe("URL slug for the step. Defaults to '' (blank) like the GHL UI."),
|
|
4873
|
+
type: import_zod33.z.string().optional().describe("Step type. Defaults to 'optin_funnel_page'.")
|
|
4707
4874
|
},
|
|
4708
4875
|
async ({ funnelId, name, url, type }) => {
|
|
4709
4876
|
try {
|
|
@@ -4731,9 +4898,9 @@ ${text2}`);
|
|
|
4731
4898
|
"update_page_content",
|
|
4732
4899
|
"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.",
|
|
4733
4900
|
{
|
|
4734
|
-
pageId:
|
|
4735
|
-
content:
|
|
4736
|
-
isPublished:
|
|
4901
|
+
pageId: import_zod33.z.string().describe("The page ID to update."),
|
|
4902
|
+
content: import_zod33.z.record(import_zod33.z.unknown()).describe("The full page content JSON. Expected fields: sections, settings, general, pageStyles, trackingCode, popups, popupsList, fontsForPreview."),
|
|
4903
|
+
isPublished: import_zod33.z.boolean().optional().describe("Whether the page should be marked published after the save. Defaults to false (draft).")
|
|
4737
4904
|
},
|
|
4738
4905
|
async ({ pageId, content, isPublished }) => {
|
|
4739
4906
|
try {
|
|
@@ -4754,9 +4921,9 @@ ${text2}`);
|
|
|
4754
4921
|
"delete_funnel_page",
|
|
4755
4922
|
"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.",
|
|
4756
4923
|
{
|
|
4757
|
-
funnelId:
|
|
4758
|
-
stepId:
|
|
4759
|
-
confirm:
|
|
4924
|
+
funnelId: import_zod33.z.string().describe("The funnel ID containing the step."),
|
|
4925
|
+
stepId: import_zod33.z.string().describe("The step ID to delete (from get_funnel_pages / list_funnels_full)."),
|
|
4926
|
+
confirm: import_zod33.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
|
|
4760
4927
|
},
|
|
4761
4928
|
async ({ funnelId, stepId }) => {
|
|
4762
4929
|
try {
|
|
@@ -4770,7 +4937,7 @@ ${text2}`);
|
|
|
4770
4937
|
}
|
|
4771
4938
|
|
|
4772
4939
|
// src/tools/form-builder.ts
|
|
4773
|
-
var
|
|
4940
|
+
var import_zod34 = require("zod");
|
|
4774
4941
|
function registerFormBuilderTools(server2, builderClient) {
|
|
4775
4942
|
const client = builderClient;
|
|
4776
4943
|
if (!client) return;
|
|
@@ -4799,7 +4966,7 @@ ${text2}`);
|
|
|
4799
4966
|
"get_form_full",
|
|
4800
4967
|
"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.",
|
|
4801
4968
|
{
|
|
4802
|
-
formId:
|
|
4969
|
+
formId: import_zod34.z.string().describe("The form ID to retrieve.")
|
|
4803
4970
|
},
|
|
4804
4971
|
async ({ formId }) => {
|
|
4805
4972
|
try {
|
|
@@ -4816,9 +4983,9 @@ ${text2}`);
|
|
|
4816
4983
|
"update_form",
|
|
4817
4984
|
"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.",
|
|
4818
4985
|
{
|
|
4819
|
-
formId:
|
|
4820
|
-
formData:
|
|
4821
|
-
name:
|
|
4986
|
+
formId: import_zod34.z.string().describe("The form ID to update."),
|
|
4987
|
+
formData: import_zod34.z.record(import_zod34.z.unknown()).describe("The updated formData object containing form fields, settings, autoResponder config, etc."),
|
|
4988
|
+
name: import_zod34.z.string().optional().describe("Updated form name.")
|
|
4822
4989
|
},
|
|
4823
4990
|
async ({ formId, formData, name }) => {
|
|
4824
4991
|
try {
|
|
@@ -4837,7 +5004,7 @@ ${text2}`);
|
|
|
4837
5004
|
"create_form",
|
|
4838
5005
|
"Create a new form. Starts with a basic structure \u2014 use update_form to add fields and configure settings.",
|
|
4839
5006
|
{
|
|
4840
|
-
name:
|
|
5007
|
+
name: import_zod34.z.string().describe("Name for the new form.")
|
|
4841
5008
|
},
|
|
4842
5009
|
async ({ name }) => {
|
|
4843
5010
|
try {
|
|
@@ -4863,8 +5030,8 @@ ${text2}`);
|
|
|
4863
5030
|
"delete_form",
|
|
4864
5031
|
"Permanently delete a form. IRREVERSIBLE.",
|
|
4865
5032
|
{
|
|
4866
|
-
formId:
|
|
4867
|
-
confirm:
|
|
5033
|
+
formId: import_zod34.z.string().describe("The form ID to delete."),
|
|
5034
|
+
confirm: import_zod34.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
|
|
4868
5035
|
},
|
|
4869
5036
|
async ({ formId }) => {
|
|
4870
5037
|
try {
|
|
@@ -4881,9 +5048,9 @@ ${text2}`);
|
|
|
4881
5048
|
"get_form_submissions_full",
|
|
4882
5049
|
"Get form submissions with full field data, contact info, and submission timestamps via the internal API. Offset-based pagination via skip/limit.",
|
|
4883
5050
|
{
|
|
4884
|
-
formId:
|
|
4885
|
-
limit:
|
|
4886
|
-
skip:
|
|
5051
|
+
formId: import_zod34.z.string().optional().describe("Filter by form ID. If omitted, returns all submissions."),
|
|
5052
|
+
limit: import_zod34.z.number().optional().describe("Max submissions to return. Defaults to 20."),
|
|
5053
|
+
skip: import_zod34.z.number().optional().describe("Number to skip for pagination.")
|
|
4887
5054
|
},
|
|
4888
5055
|
async ({ formId, limit, skip }) => {
|
|
4889
5056
|
try {
|
|
@@ -4902,7 +5069,7 @@ ${text2}`);
|
|
|
4902
5069
|
}
|
|
4903
5070
|
|
|
4904
5071
|
// src/tools/pipeline-builder.ts
|
|
4905
|
-
var
|
|
5072
|
+
var import_zod35 = require("zod");
|
|
4906
5073
|
function registerPipelineBuilderTools(server2, builderClient) {
|
|
4907
5074
|
const client = builderClient;
|
|
4908
5075
|
if (!client) return;
|
|
@@ -4947,7 +5114,7 @@ ${text2}`);
|
|
|
4947
5114
|
"get_pipeline_full",
|
|
4948
5115
|
"Get a single pipeline with complete stage configuration: IDs, names, positions, display settings.",
|
|
4949
5116
|
{
|
|
4950
|
-
pipelineId:
|
|
5117
|
+
pipelineId: import_zod35.z.string().describe("The pipeline ID to retrieve.")
|
|
4951
5118
|
},
|
|
4952
5119
|
async ({ pipelineId }) => {
|
|
4953
5120
|
try {
|
|
@@ -4965,17 +5132,17 @@ ${text2}`);
|
|
|
4965
5132
|
"create_pipeline",
|
|
4966
5133
|
"Create a new pipeline with stages. Each stage needs a name and position (0-based).",
|
|
4967
5134
|
{
|
|
4968
|
-
name:
|
|
4969
|
-
stages:
|
|
4970
|
-
|
|
4971
|
-
name:
|
|
4972
|
-
position:
|
|
4973
|
-
showInFunnel:
|
|
4974
|
-
showInPieChart:
|
|
5135
|
+
name: import_zod35.z.string().describe("Pipeline name."),
|
|
5136
|
+
stages: import_zod35.z.array(
|
|
5137
|
+
import_zod35.z.object({
|
|
5138
|
+
name: import_zod35.z.string().describe("Stage name."),
|
|
5139
|
+
position: import_zod35.z.number().describe("Stage position (0-based)."),
|
|
5140
|
+
showInFunnel: import_zod35.z.boolean().optional().describe("Show in funnel view. Defaults to true."),
|
|
5141
|
+
showInPieChart: import_zod35.z.boolean().optional().describe("Show in pie chart. Defaults to true.")
|
|
4975
5142
|
})
|
|
4976
5143
|
).describe("Array of stages in order."),
|
|
4977
|
-
showInFunnel:
|
|
4978
|
-
showInPieChart:
|
|
5144
|
+
showInFunnel: import_zod35.z.boolean().optional().describe("Show pipeline in funnel view. Defaults to true."),
|
|
5145
|
+
showInPieChart: import_zod35.z.boolean().optional().describe("Show pipeline in pie chart. Defaults to true.")
|
|
4979
5146
|
},
|
|
4980
5147
|
async ({ name, stages, showInFunnel, showInPieChart }) => {
|
|
4981
5148
|
try {
|
|
@@ -5005,19 +5172,19 @@ ${text2}`);
|
|
|
5005
5172
|
"update_pipeline",
|
|
5006
5173
|
"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.",
|
|
5007
5174
|
{
|
|
5008
|
-
pipelineId:
|
|
5009
|
-
name:
|
|
5010
|
-
stages:
|
|
5011
|
-
|
|
5012
|
-
id:
|
|
5013
|
-
name:
|
|
5014
|
-
position:
|
|
5015
|
-
showInFunnel:
|
|
5016
|
-
showInPieChart:
|
|
5175
|
+
pipelineId: import_zod35.z.string().describe("The pipeline ID to update."),
|
|
5176
|
+
name: import_zod35.z.string().optional().describe("New pipeline name."),
|
|
5177
|
+
stages: import_zod35.z.array(
|
|
5178
|
+
import_zod35.z.object({
|
|
5179
|
+
id: import_zod35.z.string().optional().describe("Existing stage ID (omit for new stages)."),
|
|
5180
|
+
name: import_zod35.z.string().describe("Stage name."),
|
|
5181
|
+
position: import_zod35.z.number().describe("Stage position (0-based)."),
|
|
5182
|
+
showInFunnel: import_zod35.z.boolean().optional().describe("Show in funnel view."),
|
|
5183
|
+
showInPieChart: import_zod35.z.boolean().optional().describe("Show in pie chart.")
|
|
5017
5184
|
})
|
|
5018
5185
|
).optional().describe("Complete stages array. Stages not included will be removed."),
|
|
5019
|
-
showInFunnel:
|
|
5020
|
-
showInPieChart:
|
|
5186
|
+
showInFunnel: import_zod35.z.boolean().optional().describe("Show pipeline in funnel view."),
|
|
5187
|
+
showInPieChart: import_zod35.z.boolean().optional().describe("Show pipeline in pie chart.")
|
|
5021
5188
|
},
|
|
5022
5189
|
async ({ pipelineId, name, stages, showInFunnel, showInPieChart }) => {
|
|
5023
5190
|
try {
|
|
@@ -5040,8 +5207,8 @@ ${text2}`);
|
|
|
5040
5207
|
"delete_pipeline",
|
|
5041
5208
|
"Permanently delete a pipeline and all its stages. Opportunities become unassigned. IRREVERSIBLE.",
|
|
5042
5209
|
{
|
|
5043
|
-
pipelineId:
|
|
5044
|
-
confirm:
|
|
5210
|
+
pipelineId: import_zod35.z.string().describe("The pipeline ID to delete."),
|
|
5211
|
+
confirm: import_zod35.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
|
|
5045
5212
|
},
|
|
5046
5213
|
async ({ pipelineId }) => {
|
|
5047
5214
|
try {
|
|
@@ -5058,7 +5225,7 @@ ${text2}`);
|
|
|
5058
5225
|
}
|
|
5059
5226
|
|
|
5060
5227
|
// src/tools/location-switcher.ts
|
|
5061
|
-
var
|
|
5228
|
+
var import_zod36 = require("zod");
|
|
5062
5229
|
var switchChain = Promise.resolve();
|
|
5063
5230
|
function withSwitchLock(fn) {
|
|
5064
5231
|
const next = switchChain.then(fn, fn);
|
|
@@ -5107,7 +5274,7 @@ Token registry: ${registeredCount} location(s) registered${versionLine}`
|
|
|
5107
5274
|
"switch_location",
|
|
5108
5275
|
"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.",
|
|
5109
5276
|
{
|
|
5110
|
-
locationId:
|
|
5277
|
+
locationId: import_zod36.z.string().describe("The Location ID to switch to.")
|
|
5111
5278
|
},
|
|
5112
5279
|
async ({ locationId: locationId2 }) => withSwitchLock(async () => {
|
|
5113
5280
|
const previousId = client.defaultLocationId;
|
|
@@ -5172,9 +5339,9 @@ Still on: ${previousId || "none"}${hint}` }],
|
|
|
5172
5339
|
"register_location",
|
|
5173
5340
|
"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.",
|
|
5174
5341
|
{
|
|
5175
|
-
locationId:
|
|
5176
|
-
name:
|
|
5177
|
-
apiKey:
|
|
5342
|
+
locationId: import_zod36.z.string().describe("The GHL Location ID (from Settings > Business Profile)."),
|
|
5343
|
+
name: import_zod36.z.string().describe("A friendly name for this sub-account (e.g. 'PNTracker', 'Med Spa Template')."),
|
|
5344
|
+
apiKey: import_zod36.z.string().describe("The Private Integration API key for this sub-account (starts with 'pit-').")
|
|
5178
5345
|
},
|
|
5179
5346
|
async ({ locationId: locationId2, name, apiKey: apiKey2 }) => {
|
|
5180
5347
|
if (!registry2) {
|
|
@@ -5224,7 +5391,7 @@ The API key could not access location ${locationId2}. Make sure:
|
|
|
5224
5391
|
"unregister_location",
|
|
5225
5392
|
"Remove a GHL sub-account from the token registry.",
|
|
5226
5393
|
{
|
|
5227
|
-
locationId:
|
|
5394
|
+
locationId: import_zod36.z.string().describe("The Location ID to remove.")
|
|
5228
5395
|
},
|
|
5229
5396
|
async ({ locationId: locationId2 }) => {
|
|
5230
5397
|
if (!registry2) {
|
|
@@ -5283,8 +5450,8 @@ ${lines.join("\n")}
|
|
|
5283
5450
|
"list_available_locations",
|
|
5284
5451
|
"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.",
|
|
5285
5452
|
{
|
|
5286
|
-
limit:
|
|
5287
|
-
skip:
|
|
5453
|
+
limit: import_zod36.z.number().optional().describe("Max locations to return. Defaults to 20."),
|
|
5454
|
+
skip: import_zod36.z.number().optional().describe("Number to skip for pagination.")
|
|
5288
5455
|
},
|
|
5289
5456
|
async ({ limit, skip }) => {
|
|
5290
5457
|
try {
|
|
@@ -5327,7 +5494,7 @@ ${lines.join("\n")}
|
|
|
5327
5494
|
}
|
|
5328
5495
|
|
|
5329
5496
|
// src/tools/bulk-operations.ts
|
|
5330
|
-
var
|
|
5497
|
+
var import_zod37 = require("zod");
|
|
5331
5498
|
function delay(ms) {
|
|
5332
5499
|
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
5333
5500
|
}
|
|
@@ -5339,8 +5506,8 @@ function registerBulkOperationTools(server2, client) {
|
|
|
5339
5506
|
"bulk_add_tags",
|
|
5340
5507
|
"Add tags to multiple contacts at once. Rate-limited to avoid API throttling. Returns a summary of successes and failures.",
|
|
5341
5508
|
{
|
|
5342
|
-
contactIds:
|
|
5343
|
-
tags:
|
|
5509
|
+
contactIds: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to tag."),
|
|
5510
|
+
tags: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one tag required.").describe("Tags to add to each contact.")
|
|
5344
5511
|
},
|
|
5345
5512
|
async ({ contactIds, tags }) => {
|
|
5346
5513
|
const results = { success: 0, failed: 0, errors: [] };
|
|
@@ -5362,8 +5529,8 @@ function registerBulkOperationTools(server2, client) {
|
|
|
5362
5529
|
"bulk_remove_tags",
|
|
5363
5530
|
"Remove tags from multiple contacts at once. Rate-limited.",
|
|
5364
5531
|
{
|
|
5365
|
-
contactIds:
|
|
5366
|
-
tags:
|
|
5532
|
+
contactIds: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs."),
|
|
5533
|
+
tags: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one tag required.").describe("Tags to remove from each contact.")
|
|
5367
5534
|
},
|
|
5368
5535
|
async ({ contactIds, tags }) => {
|
|
5369
5536
|
const results = { success: 0, failed: 0, errors: [] };
|
|
@@ -5384,8 +5551,8 @@ function registerBulkOperationTools(server2, client) {
|
|
|
5384
5551
|
"bulk_update_contacts",
|
|
5385
5552
|
"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.",
|
|
5386
5553
|
{
|
|
5387
|
-
contactIds:
|
|
5388
|
-
fields:
|
|
5554
|
+
contactIds: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to update."),
|
|
5555
|
+
fields: import_zod37.z.record(import_zod37.z.unknown()).describe("Fields to set on each contact (e.g. {customField: {id: 'xxx', value: 'yyy'}}, {source: 'Import'}).")
|
|
5389
5556
|
},
|
|
5390
5557
|
async ({ contactIds, fields }) => {
|
|
5391
5558
|
const results = { success: 0, failed: 0, errors: [] };
|
|
@@ -5406,8 +5573,8 @@ function registerBulkOperationTools(server2, client) {
|
|
|
5406
5573
|
"bulk_add_to_workflow",
|
|
5407
5574
|
"Enroll multiple contacts into a workflow at once. Rate-limited.",
|
|
5408
5575
|
{
|
|
5409
|
-
contactIds:
|
|
5410
|
-
workflowId:
|
|
5576
|
+
contactIds: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to enroll."),
|
|
5577
|
+
workflowId: import_zod37.z.string().describe("The workflow ID to enroll contacts into.")
|
|
5411
5578
|
},
|
|
5412
5579
|
async ({ contactIds, workflowId }) => {
|
|
5413
5580
|
const results = { success: 0, failed: 0, errors: [] };
|
|
@@ -5428,8 +5595,8 @@ function registerBulkOperationTools(server2, client) {
|
|
|
5428
5595
|
"bulk_delete_contacts",
|
|
5429
5596
|
"Delete multiple contacts at once. IRREVERSIBLE. Rate-limited. Use with extreme caution.",
|
|
5430
5597
|
{
|
|
5431
|
-
contactIds:
|
|
5432
|
-
confirm:
|
|
5598
|
+
contactIds: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to permanently delete."),
|
|
5599
|
+
confirm: import_zod37.z.literal("DELETE").describe("Must pass the string 'DELETE' to confirm. This is a safety check.")
|
|
5433
5600
|
},
|
|
5434
5601
|
async ({ contactIds, confirm }) => {
|
|
5435
5602
|
if (confirm !== "DELETE") {
|
|
@@ -5452,7 +5619,7 @@ function registerBulkOperationTools(server2, client) {
|
|
|
5452
5619
|
}
|
|
5453
5620
|
|
|
5454
5621
|
// src/tools/account-export.ts
|
|
5455
|
-
var
|
|
5622
|
+
var import_zod38 = require("zod");
|
|
5456
5623
|
function delay2(ms) {
|
|
5457
5624
|
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
5458
5625
|
}
|
|
@@ -5462,8 +5629,8 @@ function registerAccountExportTools(server2, client) {
|
|
|
5462
5629
|
"export_account",
|
|
5463
5630
|
"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.",
|
|
5464
5631
|
{
|
|
5465
|
-
locationId:
|
|
5466
|
-
includeContacts:
|
|
5632
|
+
locationId: import_zod38.z.string().optional().describe("Location ID to export. Uses default if not specified."),
|
|
5633
|
+
includeContacts: import_zod38.z.boolean().optional().describe("Include contact list (first 100). Defaults to false for speed.")
|
|
5467
5634
|
},
|
|
5468
5635
|
async ({ locationId: locationId2, includeContacts }) => {
|
|
5469
5636
|
try {
|
|
@@ -5591,8 +5758,8 @@ function registerAccountExportTools(server2, client) {
|
|
|
5591
5758
|
"compare_locations",
|
|
5592
5759
|
"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.",
|
|
5593
5760
|
{
|
|
5594
|
-
locationA:
|
|
5595
|
-
locationB:
|
|
5761
|
+
locationA: import_zod38.z.string().describe("First Location ID."),
|
|
5762
|
+
locationB: import_zod38.z.string().describe("Second Location ID.")
|
|
5596
5763
|
},
|
|
5597
5764
|
async ({ locationA, locationB }) => {
|
|
5598
5765
|
try {
|
|
@@ -5670,7 +5837,7 @@ function registerAccountExportTools(server2, client) {
|
|
|
5670
5837
|
}
|
|
5671
5838
|
|
|
5672
5839
|
// src/tools/workflow-cloner.ts
|
|
5673
|
-
var
|
|
5840
|
+
var import_zod39 = require("zod");
|
|
5674
5841
|
var crypto2 = __toESM(require("crypto"));
|
|
5675
5842
|
function registerWorkflowClonerTools(server2, builderClient) {
|
|
5676
5843
|
const client = builderClient;
|
|
@@ -5679,8 +5846,8 @@ function registerWorkflowClonerTools(server2, builderClient) {
|
|
|
5679
5846
|
"clone_workflow",
|
|
5680
5847
|
"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.",
|
|
5681
5848
|
{
|
|
5682
|
-
sourceWorkflowId:
|
|
5683
|
-
newName:
|
|
5849
|
+
sourceWorkflowId: import_zod39.z.string().describe("The workflow ID to clone."),
|
|
5850
|
+
newName: import_zod39.z.string().describe("Name for the cloned workflow.")
|
|
5684
5851
|
},
|
|
5685
5852
|
async ({ sourceWorkflowId, newName }) => {
|
|
5686
5853
|
try {
|
|
@@ -5769,41 +5936,41 @@ function registerWorkflowClonerTools(server2, builderClient) {
|
|
|
5769
5936
|
}
|
|
5770
5937
|
|
|
5771
5938
|
// src/tools/template-deployer.ts
|
|
5772
|
-
var
|
|
5939
|
+
var import_zod40 = require("zod");
|
|
5773
5940
|
var fs3 = __toESM(require("fs"));
|
|
5774
5941
|
var path3 = __toESM(require("path"));
|
|
5775
5942
|
function delay3(ms) {
|
|
5776
5943
|
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
5777
5944
|
}
|
|
5778
|
-
var TemplateSchema =
|
|
5779
|
-
templateName:
|
|
5780
|
-
templateVersion:
|
|
5781
|
-
description:
|
|
5782
|
-
questionnaire:
|
|
5783
|
-
id:
|
|
5784
|
-
question:
|
|
5785
|
-
type:
|
|
5786
|
-
required:
|
|
5787
|
-
placeholder:
|
|
5945
|
+
var TemplateSchema = import_zod40.z.object({
|
|
5946
|
+
templateName: import_zod40.z.string(),
|
|
5947
|
+
templateVersion: import_zod40.z.string().optional(),
|
|
5948
|
+
description: import_zod40.z.string().optional().default(""),
|
|
5949
|
+
questionnaire: import_zod40.z.array(import_zod40.z.object({
|
|
5950
|
+
id: import_zod40.z.string(),
|
|
5951
|
+
question: import_zod40.z.string(),
|
|
5952
|
+
type: import_zod40.z.string(),
|
|
5953
|
+
required: import_zod40.z.boolean().optional(),
|
|
5954
|
+
placeholder: import_zod40.z.string().optional()
|
|
5788
5955
|
})).optional().default([]),
|
|
5789
|
-
location:
|
|
5790
|
-
tags:
|
|
5791
|
-
customFields:
|
|
5792
|
-
name:
|
|
5793
|
-
dataType:
|
|
5956
|
+
location: import_zod40.z.record(import_zod40.z.unknown()).optional(),
|
|
5957
|
+
tags: import_zod40.z.array(import_zod40.z.string()).optional(),
|
|
5958
|
+
customFields: import_zod40.z.array(import_zod40.z.object({
|
|
5959
|
+
name: import_zod40.z.string(),
|
|
5960
|
+
dataType: import_zod40.z.string()
|
|
5794
5961
|
})).optional(),
|
|
5795
|
-
pipelines:
|
|
5796
|
-
name:
|
|
5797
|
-
stages:
|
|
5962
|
+
pipelines: import_zod40.z.array(import_zod40.z.object({
|
|
5963
|
+
name: import_zod40.z.string(),
|
|
5964
|
+
stages: import_zod40.z.array(import_zod40.z.object({ position: import_zod40.z.number(), name: import_zod40.z.string() }))
|
|
5798
5965
|
})).optional(),
|
|
5799
|
-
workflows:
|
|
5800
|
-
name:
|
|
5801
|
-
condition:
|
|
5802
|
-
actions:
|
|
5966
|
+
workflows: import_zod40.z.array(import_zod40.z.object({
|
|
5967
|
+
name: import_zod40.z.string(),
|
|
5968
|
+
condition: import_zod40.z.string().optional(),
|
|
5969
|
+
actions: import_zod40.z.array(import_zod40.z.record(import_zod40.z.unknown())).optional().default([])
|
|
5803
5970
|
})).optional(),
|
|
5804
|
-
calendars:
|
|
5805
|
-
name:
|
|
5806
|
-
description:
|
|
5971
|
+
calendars: import_zod40.z.array(import_zod40.z.object({
|
|
5972
|
+
name: import_zod40.z.string(),
|
|
5973
|
+
description: import_zod40.z.string().optional()
|
|
5807
5974
|
})).optional()
|
|
5808
5975
|
});
|
|
5809
5976
|
function registerTemplateDeployerTools(server2, client) {
|
|
@@ -5874,7 +6041,7 @@ function registerTemplateDeployerTools(server2, client) {
|
|
|
5874
6041
|
"get_template_questionnaire",
|
|
5875
6042
|
"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.",
|
|
5876
6043
|
{
|
|
5877
|
-
templateFile:
|
|
6044
|
+
templateFile: import_zod40.z.string().describe("Path to the template JSON file (from list_templates).")
|
|
5878
6045
|
},
|
|
5879
6046
|
async ({ templateFile }) => {
|
|
5880
6047
|
try {
|
|
@@ -5907,10 +6074,10 @@ function registerTemplateDeployerTools(server2, client) {
|
|
|
5907
6074
|
"deploy_template",
|
|
5908
6075
|
"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.",
|
|
5909
6076
|
{
|
|
5910
|
-
templateFile:
|
|
5911
|
-
answers:
|
|
5912
|
-
locationId:
|
|
5913
|
-
dryRun:
|
|
6077
|
+
templateFile: import_zod40.z.string().describe("Path to the template JSON file."),
|
|
6078
|
+
answers: import_zod40.z.record(import_zod40.z.unknown()).describe("Questionnaire answers keyed by question ID (e.g. {business_name: 'My Clinic', business_phone: '+15551234567', ...})."),
|
|
6079
|
+
locationId: import_zod40.z.string().optional().describe("Location ID to deploy to. Uses default if not specified."),
|
|
6080
|
+
dryRun: import_zod40.z.boolean().optional().describe("If true, shows what would be created without actually creating anything. Defaults to false.")
|
|
5914
6081
|
},
|
|
5915
6082
|
async ({ templateFile, answers, locationId: locationId2, dryRun }) => {
|
|
5916
6083
|
try {
|
|
@@ -6156,7 +6323,7 @@ ${errors.join("\n")}` : "\nNo errors!",
|
|
|
6156
6323
|
}
|
|
6157
6324
|
|
|
6158
6325
|
// src/tools/validators.ts
|
|
6159
|
-
var
|
|
6326
|
+
var import_zod41 = require("zod");
|
|
6160
6327
|
function extractFromTrigger(trigger, refs) {
|
|
6161
6328
|
const triggerName = String(trigger.name ?? trigger.type ?? "unnamed trigger");
|
|
6162
6329
|
const where = `trigger "${triggerName}"`;
|
|
@@ -6291,7 +6458,7 @@ function registerValidatorTools(server2, client, builderClient) {
|
|
|
6291
6458
|
"validate_workflow",
|
|
6292
6459
|
"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.",
|
|
6293
6460
|
{
|
|
6294
|
-
workflowId:
|
|
6461
|
+
workflowId: import_zod41.z.string().describe("The workflow ID to validate.")
|
|
6295
6462
|
},
|
|
6296
6463
|
async ({ workflowId }) => {
|
|
6297
6464
|
try {
|
|
@@ -6628,6 +6795,7 @@ var publicApiTools = [
|
|
|
6628
6795
|
[registerFormTools, "forms"],
|
|
6629
6796
|
[registerSurveyTools, "surveys"],
|
|
6630
6797
|
[registerPaymentTools, "payments"],
|
|
6798
|
+
[registerProductTools, "products"],
|
|
6631
6799
|
[registerInvoiceTools, "invoices"],
|
|
6632
6800
|
[registerCampaignTools, "campaigns"],
|
|
6633
6801
|
[registerUserTools, "users"],
|
|
@@ -6667,18 +6835,18 @@ function registerAllTools(server2, client, registry2, mcpVersion) {
|
|
|
6667
6835
|
var fs4 = __toESM(require("fs"));
|
|
6668
6836
|
var path4 = __toESM(require("path"));
|
|
6669
6837
|
var os = __toESM(require("os"));
|
|
6670
|
-
var
|
|
6838
|
+
var import_zod42 = require("zod");
|
|
6671
6839
|
var APP_NAME = "elitedcs-ghl-mcp";
|
|
6672
|
-
var CredentialsSchema =
|
|
6673
|
-
license_key:
|
|
6674
|
-
email:
|
|
6675
|
-
verified_at:
|
|
6676
|
-
ghl_api_key:
|
|
6677
|
-
ghl_location_id:
|
|
6678
|
-
ghl_company_id:
|
|
6679
|
-
ghl_user_id:
|
|
6680
|
-
ghl_firebase_api_key:
|
|
6681
|
-
ghl_firebase_refresh_token:
|
|
6840
|
+
var CredentialsSchema = import_zod42.z.object({
|
|
6841
|
+
license_key: import_zod42.z.string().min(1),
|
|
6842
|
+
email: import_zod42.z.string().email(),
|
|
6843
|
+
verified_at: import_zod42.z.string().min(1),
|
|
6844
|
+
ghl_api_key: import_zod42.z.string().min(1),
|
|
6845
|
+
ghl_location_id: import_zod42.z.string().min(1),
|
|
6846
|
+
ghl_company_id: import_zod42.z.string().optional(),
|
|
6847
|
+
ghl_user_id: import_zod42.z.string().optional(),
|
|
6848
|
+
ghl_firebase_api_key: import_zod42.z.string().optional(),
|
|
6849
|
+
ghl_firebase_refresh_token: import_zod42.z.string().optional()
|
|
6682
6850
|
});
|
|
6683
6851
|
function appDataDir() {
|
|
6684
6852
|
const home = os.homedir();
|
|
@@ -6728,7 +6896,7 @@ function writeCredentials(creds) {
|
|
|
6728
6896
|
// src/setup-tool.ts
|
|
6729
6897
|
var os2 = __toESM(require("os"));
|
|
6730
6898
|
var crypto3 = __toESM(require("crypto"));
|
|
6731
|
-
var
|
|
6899
|
+
var import_zod43 = require("zod");
|
|
6732
6900
|
var LICENSE_API = "https://elitedcs.com/api/validate-license";
|
|
6733
6901
|
var GHL_API = "https://services.leadconnectorhq.com";
|
|
6734
6902
|
var FIREBASE_TOKEN_API = "https://securetoken.googleapis.com/v1/token";
|
|
@@ -6797,16 +6965,16 @@ async function validateFirebase(firebaseKey, refreshToken) {
|
|
|
6797
6965
|
function registerSetupTool(server2) {
|
|
6798
6966
|
server2.tool(
|
|
6799
6967
|
"setup_ghl_mcp",
|
|
6800
|
-
"First-run setup for GHL Command MCP. Validates your license and GHL credentials, then writes them to a per-user credentials file. Restart Claude after this completes to load all
|
|
6968
|
+
"First-run setup for GHL Command MCP. Validates your license and GHL credentials, then writes them to a per-user credentials file. Restart Claude after this completes to load all 187 tools (157 if you skip the optional Firebase fields; add Firebase later with enable_workflow_builder).",
|
|
6801
6969
|
{
|
|
6802
|
-
email:
|
|
6803
|
-
license_key:
|
|
6804
|
-
ghl_api_key:
|
|
6805
|
-
ghl_location_id:
|
|
6806
|
-
ghl_company_id:
|
|
6807
|
-
ghl_user_id:
|
|
6808
|
-
ghl_firebase_api_key:
|
|
6809
|
-
ghl_firebase_refresh_token:
|
|
6970
|
+
email: import_zod43.z.string().email().describe("Email used at purchase."),
|
|
6971
|
+
license_key: import_zod43.z.string().min(20).describe("License key from your purchase email."),
|
|
6972
|
+
ghl_api_key: import_zod43.z.string().min(10).describe("GHL Private Integration key (starts with 'pit-'). Created INSIDE the sub-account at Settings > Integrations > Private Integrations."),
|
|
6973
|
+
ghl_location_id: import_zod43.z.string().min(10).describe("GHL Location ID (sub-account ID). Found in your GHL URL: /location/THIS_PART/dashboard."),
|
|
6974
|
+
ghl_company_id: import_zod43.z.string().optional().describe("(Agency only) Company ID for multi-location access."),
|
|
6975
|
+
ghl_user_id: import_zod43.z.string().optional().describe("(Workflow Builder, optional) Firebase User ID. See README for browser capture instructions."),
|
|
6976
|
+
ghl_firebase_api_key: import_zod43.z.string().optional().describe("(Workflow Builder, optional) Firebase API Key starting with 'AIza'."),
|
|
6977
|
+
ghl_firebase_refresh_token: import_zod43.z.string().optional().describe("(Workflow Builder, optional) Firebase refresh token starting with 'AMf-'.")
|
|
6810
6978
|
},
|
|
6811
6979
|
async (args) => {
|
|
6812
6980
|
const lic = await validateLicense(args.email, args.license_key);
|
|
@@ -6852,7 +7020,7 @@ Note: Firebase credentials rejected (${fb.error}). Saved without Workflow Builde
|
|
|
6852
7020
|
ghl_firebase_api_key: workflowBuilderEnabled ? args.ghl_firebase_api_key?.trim() : void 0,
|
|
6853
7021
|
ghl_firebase_refresh_token: workflowBuilderEnabled ? args.ghl_firebase_refresh_token?.trim() : void 0
|
|
6854
7022
|
});
|
|
6855
|
-
const toolCount = workflowBuilderEnabled ? "
|
|
7023
|
+
const toolCount = workflowBuilderEnabled ? "187" : "157";
|
|
6856
7024
|
const wfLine = workflowBuilderEnabled ? "Workflow Builder: enabled." : "Workflow Builder: not configured (optional).";
|
|
6857
7025
|
const wfTip = workflowBuilderEnabled ? "" : "\nTo enable Workflow Builder later (8 extra tools): run enable_workflow_builder with your three Firebase values. No need to re-enter license/API key/location ID.";
|
|
6858
7026
|
return {
|
|
@@ -6880,11 +7048,11 @@ Note: Firebase credentials rejected (${fb.error}). Saved without Workflow Builde
|
|
|
6880
7048
|
function registerEnableWorkflowBuilderTool(server2) {
|
|
6881
7049
|
server2.tool(
|
|
6882
7050
|
"enable_workflow_builder",
|
|
6883
|
-
"Add Firebase credentials to an existing GHL Command install to unlock 30 additional tools across 6 modules: workflow builder (create/edit/clone/delete/publish/validate workflows, build_if_else_branch, build_goal_event, get_trigger_registry), funnel + page builder (10 tools), form builder (5 tools), pipeline builder (5 tools), and workflow cloning. Requires you've already run setup_ghl_mcp. Capture the three Firebase values from your GHL browser session \u2014 see elitedcs.com/ghl-mcp-firebase for step-by-step DevTools instructions. Tool count goes from
|
|
7051
|
+
"Add Firebase credentials to an existing GHL Command install to unlock 30 additional tools across 6 modules: workflow builder (create/edit/clone/delete/publish/validate workflows, build_if_else_branch, build_goal_event, get_trigger_registry), funnel + page builder (10 tools), form builder (5 tools), pipeline builder (5 tools), and workflow cloning. Requires you've already run setup_ghl_mcp. Capture the three Firebase values from your GHL browser session \u2014 see elitedcs.com/ghl-mcp-firebase for step-by-step DevTools instructions. Tool count goes from 157 to 187 after the next Claude restart.",
|
|
6884
7052
|
{
|
|
6885
|
-
ghl_user_id:
|
|
6886
|
-
ghl_firebase_api_key:
|
|
6887
|
-
ghl_firebase_refresh_token:
|
|
7053
|
+
ghl_user_id: import_zod43.z.string().min(10).describe("Firebase User ID (uid). DevTools \u2192 Application \u2192 IndexedDB \u2192 firebaseLocalStorageDb \u2192 firebaseLocalStorage \u2192 the value.uid field of the firebase:authUser row."),
|
|
7054
|
+
ghl_firebase_api_key: import_zod43.z.string().min(10).describe("Firebase API Key starting with 'AIza'. The string between 'firebase:authUser:' and ':[DEFAULT]' in the row's Key column."),
|
|
7055
|
+
ghl_firebase_refresh_token: import_zod43.z.string().min(10).describe("Firebase refresh token. value.stsTokenManager.refreshToken in the firebase:authUser row.")
|
|
6888
7056
|
},
|
|
6889
7057
|
async (args) => {
|
|
6890
7058
|
const existing = readCredentials();
|
|
@@ -6927,7 +7095,7 @@ DevTools steps: https://elitedcs.com/ghl-mcp-firebase`
|
|
|
6927
7095
|
"",
|
|
6928
7096
|
"Firebase credentials verified and saved.",
|
|
6929
7097
|
"",
|
|
6930
|
-
"**Restart Claude (quit fully and reopen) to load the workflow builder + funnel builder + pipeline builder + form builder + workflow cloner tools (
|
|
7098
|
+
"**Restart Claude (quit fully and reopen) to load the workflow builder + funnel builder + pipeline builder + form builder + workflow cloner tools (187 total).**",
|
|
6931
7099
|
"",
|
|
6932
7100
|
'After restart, try: "List my workflows in full detail" or "Validate workflow <id>".',
|
|
6933
7101
|
"",
|