@elitedcs/ghl-mcp 3.8.1 → 3.10.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 +98 -0
- package/README.md +4 -4
- package/dist/index.js +665 -441
- 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.10.0",
|
|
35
|
+
description: "GoHighLevel MCP Server for Claude. 190 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,16 @@ function registerBlogTools(server2, client) {
|
|
|
3460
3576
|
}
|
|
3461
3577
|
|
|
3462
3578
|
// src/tools/emails.ts
|
|
3463
|
-
var
|
|
3579
|
+
var import_zod24 = require("zod");
|
|
3580
|
+
var TEMPLATE_TYPES = ["html", "folder", "import", "builder", "blank", "ai_template", "vibe-editor"];
|
|
3581
|
+
var EDITOR_TYPES = ["html", "builder"];
|
|
3464
3582
|
function registerEmailTools(server2, client) {
|
|
3465
3583
|
safeTool(
|
|
3466
3584
|
server2,
|
|
3467
3585
|
"get_email_campaigns",
|
|
3468
|
-
"List email campaigns for a location",
|
|
3586
|
+
"List email campaigns for a location.",
|
|
3469
3587
|
{
|
|
3470
|
-
locationId:
|
|
3588
|
+
locationId: import_zod24.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
|
|
3471
3589
|
},
|
|
3472
3590
|
async ({ locationId: locationId2 }) => {
|
|
3473
3591
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3476,17 +3594,71 @@ function registerEmailTools(server2, client) {
|
|
|
3476
3594
|
});
|
|
3477
3595
|
}
|
|
3478
3596
|
);
|
|
3597
|
+
safeTool(
|
|
3598
|
+
server2,
|
|
3599
|
+
"list_email_templates",
|
|
3600
|
+
"List email templates ('builders') in a location. Templates power both standalone marketing emails and email actions inside workflows. Returns each template's id, name (display title), type, version, last-updated timestamp, and Firebase storage preview URL.",
|
|
3601
|
+
{
|
|
3602
|
+
locationId: import_zod24.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set).")
|
|
3603
|
+
},
|
|
3604
|
+
async ({ locationId: locationId2 }) => {
|
|
3605
|
+
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
3606
|
+
return client.get("/emails/builder", {
|
|
3607
|
+
params: { locationId: resolvedLocationId }
|
|
3608
|
+
});
|
|
3609
|
+
}
|
|
3610
|
+
);
|
|
3611
|
+
safeTool(
|
|
3612
|
+
server2,
|
|
3613
|
+
"create_email_template",
|
|
3614
|
+
"Create a new email template (a 'builder' in GHL's API). Creates the metadata shell; use update_email_template to save HTML content into it. After creation, the response includes the template `id` which you'll use with update_email_template + when referencing the template from workflow email actions.",
|
|
3615
|
+
{
|
|
3616
|
+
title: import_zod24.z.string().describe("Display name for the template (e.g., 'May Newsletter \u2014 V2'). Shown in the GHL UI. Note: GHL stores this as `name` on read but expects `title` on write."),
|
|
3617
|
+
type: import_zod24.z.enum(TEMPLATE_TYPES).describe("Template kind. 'blank' = empty starting point. 'html' = raw HTML import. 'builder' = drag-and-drop builder. 'import' = imported from an external source. 'ai_template' / 'vibe-editor' = AI-generated. 'folder' = organizational folder (no content)."),
|
|
3618
|
+
locationId: import_zod24.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
|
|
3619
|
+
},
|
|
3620
|
+
async ({ title, type, locationId: locationId2 }) => {
|
|
3621
|
+
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
3622
|
+
return client.post("/emails/builder", {
|
|
3623
|
+
body: { locationId: resolvedLocationId, title, type }
|
|
3624
|
+
});
|
|
3625
|
+
}
|
|
3626
|
+
);
|
|
3627
|
+
safeTool(
|
|
3628
|
+
server2,
|
|
3629
|
+
"update_email_template",
|
|
3630
|
+
"Save HTML content into an existing email template. Use this to update the body of a template after `create_email_template`. The `updatedBy` field is required by GHL; defaults to 'mcp' if not provided. Note: this updates CONTENT only. Renaming the title or deleting the template is not yet possible through the public API \u2014 do those in the GHL UI for now.",
|
|
3631
|
+
{
|
|
3632
|
+
templateId: import_zod24.z.string().describe("The template ID to update (from create_email_template or list_email_templates)."),
|
|
3633
|
+
html: import_zod24.z.string().describe("The full HTML body of the email. Can include merge fields like {{contact.first_name}}."),
|
|
3634
|
+
editorType: import_zod24.z.enum(EDITOR_TYPES).describe("Which editor produced this content. 'html' for raw HTML; 'builder' if you're saving a drag-and-drop builder export. After this save, the template will be flagged as the chosen editorType in lists."),
|
|
3635
|
+
updatedBy: import_zod24.z.string().optional().describe("Identifier of who's making the change (a user ID or label). Defaults to 'mcp' if omitted. Shown in the GHL audit log for this template."),
|
|
3636
|
+
locationId: import_zod24.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
|
|
3637
|
+
},
|
|
3638
|
+
async ({ templateId, html, editorType, updatedBy, locationId: locationId2 }) => {
|
|
3639
|
+
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
3640
|
+
return client.post("/emails/builder/data", {
|
|
3641
|
+
body: {
|
|
3642
|
+
locationId: resolvedLocationId,
|
|
3643
|
+
templateId,
|
|
3644
|
+
html,
|
|
3645
|
+
editorType,
|
|
3646
|
+
updatedBy: updatedBy ?? "mcp"
|
|
3647
|
+
}
|
|
3648
|
+
});
|
|
3649
|
+
}
|
|
3650
|
+
);
|
|
3479
3651
|
}
|
|
3480
3652
|
|
|
3481
3653
|
// src/tools/trigger-links.ts
|
|
3482
|
-
var
|
|
3654
|
+
var import_zod25 = require("zod");
|
|
3483
3655
|
function registerTriggerLinkTools(server2, client) {
|
|
3484
3656
|
safeTool(
|
|
3485
3657
|
server2,
|
|
3486
3658
|
"get_trigger_links",
|
|
3487
|
-
"List trigger links for a location",
|
|
3659
|
+
"List trigger links (short tracked URLs) for a location.",
|
|
3488
3660
|
{
|
|
3489
|
-
locationId:
|
|
3661
|
+
locationId: import_zod25.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
|
|
3490
3662
|
},
|
|
3491
3663
|
async ({ locationId: locationId2 }) => {
|
|
3492
3664
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3495,17 +3667,68 @@ function registerTriggerLinkTools(server2, client) {
|
|
|
3495
3667
|
});
|
|
3496
3668
|
}
|
|
3497
3669
|
);
|
|
3670
|
+
safeTool(
|
|
3671
|
+
server2,
|
|
3672
|
+
"create_trigger_link",
|
|
3673
|
+
"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.",
|
|
3674
|
+
{
|
|
3675
|
+
name: import_zod25.z.string().describe("Display name in the GHL UI (e.g., 'May Newsletter \u2014 CTA'). Not visible to recipients."),
|
|
3676
|
+
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}}')."),
|
|
3677
|
+
locationId: import_zod25.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
|
|
3678
|
+
},
|
|
3679
|
+
async ({ name, redirectTo, locationId: locationId2 }) => {
|
|
3680
|
+
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
3681
|
+
return client.post("/links/", {
|
|
3682
|
+
body: { locationId: resolvedLocationId, name, redirectTo }
|
|
3683
|
+
});
|
|
3684
|
+
}
|
|
3685
|
+
);
|
|
3686
|
+
safeTool(
|
|
3687
|
+
server2,
|
|
3688
|
+
"update_trigger_link",
|
|
3689
|
+
"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.",
|
|
3690
|
+
{
|
|
3691
|
+
linkId: import_zod25.z.string().describe("The trigger link ID to update."),
|
|
3692
|
+
name: import_zod25.z.string().optional().describe("New display name. Pass to change; omit to keep current."),
|
|
3693
|
+
redirectTo: import_zod25.z.string().optional().describe("New destination URL. Pass to change; omit to keep current.")
|
|
3694
|
+
},
|
|
3695
|
+
async ({ linkId, name, redirectTo }) => {
|
|
3696
|
+
const body = {};
|
|
3697
|
+
if (name !== void 0) body.name = name;
|
|
3698
|
+
if (redirectTo !== void 0) body.redirectTo = redirectTo;
|
|
3699
|
+
if (Object.keys(body).length === 0) {
|
|
3700
|
+
throw new Error("Pass at least one of: name, redirectTo. Nothing to update.");
|
|
3701
|
+
}
|
|
3702
|
+
return client.put(`/links/${linkId}`, { body });
|
|
3703
|
+
}
|
|
3704
|
+
);
|
|
3705
|
+
safeTool(
|
|
3706
|
+
server2,
|
|
3707
|
+
"delete_trigger_link",
|
|
3708
|
+
"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.",
|
|
3709
|
+
{
|
|
3710
|
+
linkId: import_zod25.z.string().describe("The trigger link ID to delete."),
|
|
3711
|
+
confirm: import_zod25.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action."),
|
|
3712
|
+
locationId: import_zod25.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
|
|
3713
|
+
},
|
|
3714
|
+
async ({ linkId, locationId: locationId2 }) => {
|
|
3715
|
+
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
3716
|
+
return client.delete(`/links/${linkId}`, {
|
|
3717
|
+
params: { locationId: resolvedLocationId }
|
|
3718
|
+
});
|
|
3719
|
+
}
|
|
3720
|
+
);
|
|
3498
3721
|
}
|
|
3499
3722
|
|
|
3500
3723
|
// src/tools/custom-objects.ts
|
|
3501
|
-
var
|
|
3724
|
+
var import_zod26 = require("zod");
|
|
3502
3725
|
function registerCustomObjectTools(server2, client) {
|
|
3503
3726
|
safeTool(
|
|
3504
3727
|
server2,
|
|
3505
3728
|
"list_custom_objects",
|
|
3506
3729
|
"List all custom object schemas defined in a GHL location.",
|
|
3507
3730
|
{
|
|
3508
|
-
locationId:
|
|
3731
|
+
locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3509
3732
|
},
|
|
3510
3733
|
async ({ locationId: locationId2 }) => {
|
|
3511
3734
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3519,8 +3742,8 @@ function registerCustomObjectTools(server2, client) {
|
|
|
3519
3742
|
"get_custom_object",
|
|
3520
3743
|
"Retrieve a single custom object schema by its key.",
|
|
3521
3744
|
{
|
|
3522
|
-
schemaKey:
|
|
3523
|
-
locationId:
|
|
3745
|
+
schemaKey: import_zod26.z.string().describe("The key of the custom object schema to retrieve."),
|
|
3746
|
+
locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3524
3747
|
},
|
|
3525
3748
|
async ({ schemaKey, locationId: locationId2 }) => {
|
|
3526
3749
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3534,11 +3757,11 @@ function registerCustomObjectTools(server2, client) {
|
|
|
3534
3757
|
"search_custom_object_records",
|
|
3535
3758
|
"Search records of a custom object by schema key. Supports filtering and pagination.",
|
|
3536
3759
|
{
|
|
3537
|
-
schemaKey:
|
|
3538
|
-
locationId:
|
|
3539
|
-
query:
|
|
3540
|
-
limit:
|
|
3541
|
-
offset:
|
|
3760
|
+
schemaKey: import_zod26.z.string().describe("The custom object schema key."),
|
|
3761
|
+
locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
3762
|
+
query: import_zod26.z.string().optional().describe("Search query to filter records."),
|
|
3763
|
+
limit: import_zod26.z.number().optional().describe("Maximum records to return. Defaults to 20."),
|
|
3764
|
+
offset: import_zod26.z.number().optional().describe("Number of records to skip for pagination.")
|
|
3542
3765
|
},
|
|
3543
3766
|
async ({ schemaKey, locationId: locationId2, query, limit, offset }) => {
|
|
3544
3767
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3557,9 +3780,9 @@ function registerCustomObjectTools(server2, client) {
|
|
|
3557
3780
|
"get_custom_object_record",
|
|
3558
3781
|
"Retrieve a single custom object record by schema key and record ID.",
|
|
3559
3782
|
{
|
|
3560
|
-
schemaKey:
|
|
3561
|
-
recordId:
|
|
3562
|
-
locationId:
|
|
3783
|
+
schemaKey: import_zod26.z.string().describe("The custom object schema key."),
|
|
3784
|
+
recordId: import_zod26.z.string().describe("The record ID to retrieve."),
|
|
3785
|
+
locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3563
3786
|
},
|
|
3564
3787
|
async ({ schemaKey, recordId, locationId: locationId2 }) => {
|
|
3565
3788
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3573,9 +3796,9 @@ function registerCustomObjectTools(server2, client) {
|
|
|
3573
3796
|
"create_custom_object_record",
|
|
3574
3797
|
"Create a new record for a custom object.",
|
|
3575
3798
|
{
|
|
3576
|
-
schemaKey:
|
|
3577
|
-
locationId:
|
|
3578
|
-
properties:
|
|
3799
|
+
schemaKey: import_zod26.z.string().describe("The custom object schema key."),
|
|
3800
|
+
locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
3801
|
+
properties: import_zod26.z.record(import_zod26.z.unknown()).describe("Key-value pairs of field values for the new record.")
|
|
3579
3802
|
},
|
|
3580
3803
|
async ({ schemaKey, locationId: locationId2, properties }) => {
|
|
3581
3804
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3589,10 +3812,10 @@ function registerCustomObjectTools(server2, client) {
|
|
|
3589
3812
|
"update_custom_object_record",
|
|
3590
3813
|
"Update an existing custom object record.",
|
|
3591
3814
|
{
|
|
3592
|
-
schemaKey:
|
|
3593
|
-
recordId:
|
|
3594
|
-
locationId:
|
|
3595
|
-
properties:
|
|
3815
|
+
schemaKey: import_zod26.z.string().describe("The custom object schema key."),
|
|
3816
|
+
recordId: import_zod26.z.string().describe("The record ID to update."),
|
|
3817
|
+
locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
3818
|
+
properties: import_zod26.z.record(import_zod26.z.unknown()).describe("Key-value pairs of field values to update.")
|
|
3596
3819
|
},
|
|
3597
3820
|
async ({ schemaKey, recordId, locationId: locationId2, properties }) => {
|
|
3598
3821
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3606,9 +3829,9 @@ function registerCustomObjectTools(server2, client) {
|
|
|
3606
3829
|
"delete_custom_object_record",
|
|
3607
3830
|
"Delete a custom object record by schema key and record ID.",
|
|
3608
3831
|
{
|
|
3609
|
-
schemaKey:
|
|
3610
|
-
recordId:
|
|
3611
|
-
locationId:
|
|
3832
|
+
schemaKey: import_zod26.z.string().describe("The custom object schema key."),
|
|
3833
|
+
recordId: import_zod26.z.string().describe("The record ID to delete."),
|
|
3834
|
+
locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3612
3835
|
},
|
|
3613
3836
|
async ({ schemaKey, recordId, locationId: locationId2 }) => {
|
|
3614
3837
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3620,16 +3843,16 @@ function registerCustomObjectTools(server2, client) {
|
|
|
3620
3843
|
}
|
|
3621
3844
|
|
|
3622
3845
|
// src/tools/associations.ts
|
|
3623
|
-
var
|
|
3846
|
+
var import_zod27 = require("zod");
|
|
3624
3847
|
function registerAssociationTools(server2, client) {
|
|
3625
3848
|
safeTool(
|
|
3626
3849
|
server2,
|
|
3627
3850
|
"list_associations",
|
|
3628
3851
|
"List associations for a custom object record \u2014 shows related contacts, opportunities, or other records.",
|
|
3629
3852
|
{
|
|
3630
|
-
schemaKey:
|
|
3631
|
-
recordId:
|
|
3632
|
-
locationId:
|
|
3853
|
+
schemaKey: import_zod27.z.string().describe("The custom object schema key."),
|
|
3854
|
+
recordId: import_zod27.z.string().describe("The record ID to list associations for."),
|
|
3855
|
+
locationId: import_zod27.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3633
3856
|
},
|
|
3634
3857
|
async ({ schemaKey, recordId, locationId: locationId2 }) => {
|
|
3635
3858
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3644,11 +3867,11 @@ function registerAssociationTools(server2, client) {
|
|
|
3644
3867
|
"create_association",
|
|
3645
3868
|
"Create an association between a custom object record and another entity (contact, opportunity, or another custom object record).",
|
|
3646
3869
|
{
|
|
3647
|
-
schemaKey:
|
|
3648
|
-
recordId:
|
|
3649
|
-
locationId:
|
|
3650
|
-
targetEntityType:
|
|
3651
|
-
targetEntityId:
|
|
3870
|
+
schemaKey: import_zod27.z.string().describe("The custom object schema key of the source record."),
|
|
3871
|
+
recordId: import_zod27.z.string().describe("The source record ID."),
|
|
3872
|
+
locationId: import_zod27.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
3873
|
+
targetEntityType: import_zod27.z.string().describe("The target entity type (e.g. 'contact', 'opportunity', or a custom object schema key)."),
|
|
3874
|
+
targetEntityId: import_zod27.z.string().describe("The ID of the target entity to associate with.")
|
|
3652
3875
|
},
|
|
3653
3876
|
async ({ schemaKey, recordId, locationId: locationId2, targetEntityType, targetEntityId }) => {
|
|
3654
3877
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3669,10 +3892,10 @@ function registerAssociationTools(server2, client) {
|
|
|
3669
3892
|
"delete_association",
|
|
3670
3893
|
"Remove an association between a custom object record and another entity.",
|
|
3671
3894
|
{
|
|
3672
|
-
schemaKey:
|
|
3673
|
-
recordId:
|
|
3674
|
-
associationId:
|
|
3675
|
-
locationId:
|
|
3895
|
+
schemaKey: import_zod27.z.string().describe("The custom object schema key of the source record."),
|
|
3896
|
+
recordId: import_zod27.z.string().describe("The source record ID."),
|
|
3897
|
+
associationId: import_zod27.z.string().describe("The association ID to remove."),
|
|
3898
|
+
locationId: import_zod27.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3676
3899
|
},
|
|
3677
3900
|
async ({ schemaKey, recordId, associationId, locationId: locationId2 }) => {
|
|
3678
3901
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3685,18 +3908,18 @@ function registerAssociationTools(server2, client) {
|
|
|
3685
3908
|
}
|
|
3686
3909
|
|
|
3687
3910
|
// src/tools/estimates.ts
|
|
3688
|
-
var
|
|
3911
|
+
var import_zod28 = require("zod");
|
|
3689
3912
|
function registerEstimateTools(server2, client) {
|
|
3690
3913
|
safeTool(
|
|
3691
3914
|
server2,
|
|
3692
3915
|
"list_estimates",
|
|
3693
3916
|
"List estimates/quotes in a GHL location. Supports pagination and filtering by status.",
|
|
3694
3917
|
{
|
|
3695
|
-
locationId:
|
|
3696
|
-
status:
|
|
3697
|
-
limit:
|
|
3698
|
-
offset:
|
|
3699
|
-
contactId:
|
|
3918
|
+
locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
3919
|
+
status: import_zod28.z.string().optional().describe("Filter by status (e.g. 'draft', 'sent', 'accepted', 'declined')."),
|
|
3920
|
+
limit: import_zod28.z.number().optional().describe("Maximum estimates to return. Defaults to 20."),
|
|
3921
|
+
offset: import_zod28.z.number().optional().describe("Number of records to skip for pagination."),
|
|
3922
|
+
contactId: import_zod28.z.string().optional().describe("Filter estimates by contact ID.")
|
|
3700
3923
|
},
|
|
3701
3924
|
async ({ locationId: locationId2, status, limit, offset, contactId }) => {
|
|
3702
3925
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3717,8 +3940,8 @@ function registerEstimateTools(server2, client) {
|
|
|
3717
3940
|
"get_estimate",
|
|
3718
3941
|
"Retrieve a single estimate/quote by its ID.",
|
|
3719
3942
|
{
|
|
3720
|
-
estimateId:
|
|
3721
|
-
locationId:
|
|
3943
|
+
estimateId: import_zod28.z.string().describe("The estimate ID to retrieve."),
|
|
3944
|
+
locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3722
3945
|
},
|
|
3723
3946
|
async ({ estimateId, locationId: locationId2 }) => {
|
|
3724
3947
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3732,12 +3955,12 @@ function registerEstimateTools(server2, client) {
|
|
|
3732
3955
|
"create_estimate",
|
|
3733
3956
|
"Create a new estimate/quote for a contact.",
|
|
3734
3957
|
{
|
|
3735
|
-
locationId:
|
|
3736
|
-
contactId:
|
|
3737
|
-
name:
|
|
3738
|
-
title:
|
|
3739
|
-
items:
|
|
3740
|
-
discount:
|
|
3958
|
+
locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
3959
|
+
contactId: import_zod28.z.string().describe("The contact ID this estimate is for."),
|
|
3960
|
+
name: import_zod28.z.string().describe("Estimate name/title."),
|
|
3961
|
+
title: import_zod28.z.string().optional().describe("Display title for the estimate."),
|
|
3962
|
+
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."),
|
|
3963
|
+
discount: import_zod28.z.record(import_zod28.z.unknown()).optional().describe("Discount object (type, value).")
|
|
3741
3964
|
},
|
|
3742
3965
|
async ({ locationId: locationId2, contactId, name, title, items, discount }) => {
|
|
3743
3966
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3759,12 +3982,12 @@ function registerEstimateTools(server2, client) {
|
|
|
3759
3982
|
"update_estimate",
|
|
3760
3983
|
"Update an existing estimate/quote.",
|
|
3761
3984
|
{
|
|
3762
|
-
estimateId:
|
|
3763
|
-
locationId:
|
|
3764
|
-
name:
|
|
3765
|
-
title:
|
|
3766
|
-
items:
|
|
3767
|
-
discount:
|
|
3985
|
+
estimateId: import_zod28.z.string().describe("The estimate ID to update."),
|
|
3986
|
+
locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
3987
|
+
name: import_zod28.z.string().optional().describe("Updated estimate name."),
|
|
3988
|
+
title: import_zod28.z.string().optional().describe("Updated display title."),
|
|
3989
|
+
items: import_zod28.z.array(import_zod28.z.record(import_zod28.z.unknown())).optional().describe("Updated line items array."),
|
|
3990
|
+
discount: import_zod28.z.record(import_zod28.z.unknown()).optional().describe("Updated discount object.")
|
|
3768
3991
|
},
|
|
3769
3992
|
async ({ estimateId, locationId: locationId2, name, title, items, discount }) => {
|
|
3770
3993
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3784,8 +4007,8 @@ function registerEstimateTools(server2, client) {
|
|
|
3784
4007
|
"delete_estimate",
|
|
3785
4008
|
"Delete an estimate/quote by ID.",
|
|
3786
4009
|
{
|
|
3787
|
-
estimateId:
|
|
3788
|
-
locationId:
|
|
4010
|
+
estimateId: import_zod28.z.string().describe("The estimate ID to delete."),
|
|
4011
|
+
locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3789
4012
|
},
|
|
3790
4013
|
async ({ estimateId, locationId: locationId2 }) => {
|
|
3791
4014
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3799,8 +4022,8 @@ function registerEstimateTools(server2, client) {
|
|
|
3799
4022
|
"send_estimate",
|
|
3800
4023
|
"Send an estimate to the contact via email.",
|
|
3801
4024
|
{
|
|
3802
|
-
estimateId:
|
|
3803
|
-
locationId:
|
|
4025
|
+
estimateId: import_zod28.z.string().describe("The estimate ID to send."),
|
|
4026
|
+
locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3804
4027
|
},
|
|
3805
4028
|
async ({ estimateId, locationId: locationId2 }) => {
|
|
3806
4029
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3812,14 +4035,14 @@ function registerEstimateTools(server2, client) {
|
|
|
3812
4035
|
}
|
|
3813
4036
|
|
|
3814
4037
|
// src/tools/coupons.ts
|
|
3815
|
-
var
|
|
4038
|
+
var import_zod29 = require("zod");
|
|
3816
4039
|
function registerCouponTools(server2, client) {
|
|
3817
4040
|
safeTool(
|
|
3818
4041
|
server2,
|
|
3819
4042
|
"list_coupons",
|
|
3820
4043
|
"List coupons/promo codes in a GHL location.",
|
|
3821
4044
|
{
|
|
3822
|
-
locationId:
|
|
4045
|
+
locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3823
4046
|
},
|
|
3824
4047
|
async ({ locationId: locationId2 }) => {
|
|
3825
4048
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3833,8 +4056,8 @@ function registerCouponTools(server2, client) {
|
|
|
3833
4056
|
"get_coupon",
|
|
3834
4057
|
"Retrieve a single coupon by its ID.",
|
|
3835
4058
|
{
|
|
3836
|
-
couponId:
|
|
3837
|
-
locationId:
|
|
4059
|
+
couponId: import_zod29.z.string().describe("The coupon ID to retrieve."),
|
|
4060
|
+
locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3838
4061
|
},
|
|
3839
4062
|
async ({ couponId, locationId: locationId2 }) => {
|
|
3840
4063
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3848,14 +4071,14 @@ function registerCouponTools(server2, client) {
|
|
|
3848
4071
|
"create_coupon",
|
|
3849
4072
|
"Create a new coupon/promo code.",
|
|
3850
4073
|
{
|
|
3851
|
-
locationId:
|
|
3852
|
-
name:
|
|
3853
|
-
code:
|
|
3854
|
-
type:
|
|
3855
|
-
amount:
|
|
3856
|
-
duration:
|
|
3857
|
-
durationInMonths:
|
|
3858
|
-
productIds:
|
|
4074
|
+
locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
4075
|
+
name: import_zod29.z.string().describe("Coupon name."),
|
|
4076
|
+
code: import_zod29.z.string().describe("Promo code string customers enter."),
|
|
4077
|
+
type: import_zod29.z.string().describe("Discount type: 'percentage' or 'fixed'."),
|
|
4078
|
+
amount: import_zod29.z.number().describe("Discount amount (percentage value or fixed dollar amount)."),
|
|
4079
|
+
duration: import_zod29.z.string().optional().describe("Duration: 'once', 'repeating', or 'forever'. Defaults to 'once'."),
|
|
4080
|
+
durationInMonths: import_zod29.z.number().optional().describe("Number of months if duration is 'repeating'."),
|
|
4081
|
+
productIds: import_zod29.z.array(import_zod29.z.string()).optional().describe("Product IDs this coupon applies to. If empty, applies to all.")
|
|
3859
4082
|
},
|
|
3860
4083
|
async ({ locationId: locationId2, name, code, type, amount, duration, durationInMonths, productIds }) => {
|
|
3861
4084
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3879,10 +4102,10 @@ function registerCouponTools(server2, client) {
|
|
|
3879
4102
|
"update_coupon",
|
|
3880
4103
|
"Update an existing coupon.",
|
|
3881
4104
|
{
|
|
3882
|
-
couponId:
|
|
3883
|
-
locationId:
|
|
3884
|
-
name:
|
|
3885
|
-
productIds:
|
|
4105
|
+
couponId: import_zod29.z.string().describe("The coupon ID to update."),
|
|
4106
|
+
locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
4107
|
+
name: import_zod29.z.string().optional().describe("Updated coupon name."),
|
|
4108
|
+
productIds: import_zod29.z.array(import_zod29.z.string()).optional().describe("Updated product IDs this coupon applies to.")
|
|
3886
4109
|
},
|
|
3887
4110
|
async ({ couponId, locationId: locationId2, name, productIds }) => {
|
|
3888
4111
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3900,8 +4123,8 @@ function registerCouponTools(server2, client) {
|
|
|
3900
4123
|
"delete_coupon",
|
|
3901
4124
|
"Delete a coupon by ID.",
|
|
3902
4125
|
{
|
|
3903
|
-
couponId:
|
|
3904
|
-
locationId:
|
|
4126
|
+
couponId: import_zod29.z.string().describe("The coupon ID to delete."),
|
|
4127
|
+
locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3905
4128
|
},
|
|
3906
4129
|
async ({ couponId, locationId: locationId2 }) => {
|
|
3907
4130
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3913,14 +4136,14 @@ function registerCouponTools(server2, client) {
|
|
|
3913
4136
|
}
|
|
3914
4137
|
|
|
3915
4138
|
// src/tools/webhooks.ts
|
|
3916
|
-
var
|
|
4139
|
+
var import_zod30 = require("zod");
|
|
3917
4140
|
function registerWebhookTools(server2, client) {
|
|
3918
4141
|
safeTool(
|
|
3919
4142
|
server2,
|
|
3920
4143
|
"list_webhooks",
|
|
3921
4144
|
"List all webhooks configured in a GHL location.",
|
|
3922
4145
|
{
|
|
3923
|
-
locationId:
|
|
4146
|
+
locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3924
4147
|
},
|
|
3925
4148
|
async ({ locationId: locationId2 }) => {
|
|
3926
4149
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3934,8 +4157,8 @@ function registerWebhookTools(server2, client) {
|
|
|
3934
4157
|
"get_webhook",
|
|
3935
4158
|
"Retrieve a single webhook by its ID.",
|
|
3936
4159
|
{
|
|
3937
|
-
webhookId:
|
|
3938
|
-
locationId:
|
|
4160
|
+
webhookId: import_zod30.z.string().describe("The webhook ID to retrieve."),
|
|
4161
|
+
locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3939
4162
|
},
|
|
3940
4163
|
async ({ webhookId, locationId: locationId2 }) => {
|
|
3941
4164
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3949,10 +4172,10 @@ function registerWebhookTools(server2, client) {
|
|
|
3949
4172
|
"create_webhook",
|
|
3950
4173
|
"Create a new webhook subscription for GHL events.",
|
|
3951
4174
|
{
|
|
3952
|
-
locationId:
|
|
3953
|
-
name:
|
|
3954
|
-
url:
|
|
3955
|
-
events:
|
|
4175
|
+
locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
4176
|
+
name: import_zod30.z.string().describe("Webhook name."),
|
|
4177
|
+
url: import_zod30.z.string().describe("The URL to POST events to."),
|
|
4178
|
+
events: import_zod30.z.array(import_zod30.z.string()).describe(
|
|
3956
4179
|
"List of event types to subscribe to (e.g. 'ContactCreate', 'AppointmentCreate', 'OpportunityStatusUpdate')."
|
|
3957
4180
|
)
|
|
3958
4181
|
},
|
|
@@ -3973,11 +4196,11 @@ function registerWebhookTools(server2, client) {
|
|
|
3973
4196
|
"update_webhook",
|
|
3974
4197
|
"Update an existing webhook (name, URL, or subscribed events).",
|
|
3975
4198
|
{
|
|
3976
|
-
webhookId:
|
|
3977
|
-
locationId:
|
|
3978
|
-
name:
|
|
3979
|
-
url:
|
|
3980
|
-
events:
|
|
4199
|
+
webhookId: import_zod30.z.string().describe("The webhook ID to update."),
|
|
4200
|
+
locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
4201
|
+
name: import_zod30.z.string().optional().describe("Updated webhook name."),
|
|
4202
|
+
url: import_zod30.z.string().optional().describe("Updated webhook URL."),
|
|
4203
|
+
events: import_zod30.z.array(import_zod30.z.string()).optional().describe("Updated list of event types.")
|
|
3981
4204
|
},
|
|
3982
4205
|
async ({ webhookId, locationId: locationId2, name, url, events }) => {
|
|
3983
4206
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3993,8 +4216,8 @@ function registerWebhookTools(server2, client) {
|
|
|
3993
4216
|
"delete_webhook",
|
|
3994
4217
|
"Delete a webhook subscription by ID.",
|
|
3995
4218
|
{
|
|
3996
|
-
webhookId:
|
|
3997
|
-
locationId:
|
|
4219
|
+
webhookId: import_zod30.z.string().describe("The webhook ID to delete."),
|
|
4220
|
+
locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3998
4221
|
},
|
|
3999
4222
|
async ({ webhookId, locationId: locationId2 }) => {
|
|
4000
4223
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -4006,16 +4229,16 @@ function registerWebhookTools(server2, client) {
|
|
|
4006
4229
|
}
|
|
4007
4230
|
|
|
4008
4231
|
// src/tools/documents.ts
|
|
4009
|
-
var
|
|
4232
|
+
var import_zod31 = require("zod");
|
|
4010
4233
|
function registerDocumentTools(server2, client) {
|
|
4011
4234
|
safeTool(
|
|
4012
4235
|
server2,
|
|
4013
4236
|
"list_documents",
|
|
4014
4237
|
"List documents and contracts in a GHL location. Supports pagination.",
|
|
4015
4238
|
{
|
|
4016
|
-
locationId:
|
|
4017
|
-
limit:
|
|
4018
|
-
offset:
|
|
4239
|
+
locationId: import_zod31.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
4240
|
+
limit: import_zod31.z.number().optional().describe("Maximum documents to return. Defaults to 20."),
|
|
4241
|
+
offset: import_zod31.z.number().optional().describe("Number of records to skip for pagination.")
|
|
4019
4242
|
},
|
|
4020
4243
|
async ({ locationId: locationId2, limit, offset }) => {
|
|
4021
4244
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -4033,8 +4256,8 @@ function registerDocumentTools(server2, client) {
|
|
|
4033
4256
|
"get_document",
|
|
4034
4257
|
"Retrieve a single document or contract by its ID, including signature status.",
|
|
4035
4258
|
{
|
|
4036
|
-
documentId:
|
|
4037
|
-
locationId:
|
|
4259
|
+
documentId: import_zod31.z.string().describe("The document ID to retrieve."),
|
|
4260
|
+
locationId: import_zod31.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
4038
4261
|
},
|
|
4039
4262
|
async ({ documentId, locationId: locationId2 }) => {
|
|
4040
4263
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -4048,8 +4271,8 @@ function registerDocumentTools(server2, client) {
|
|
|
4048
4271
|
"delete_document",
|
|
4049
4272
|
"Delete a document or contract by ID.",
|
|
4050
4273
|
{
|
|
4051
|
-
documentId:
|
|
4052
|
-
locationId:
|
|
4274
|
+
documentId: import_zod31.z.string().describe("The document ID to delete."),
|
|
4275
|
+
locationId: import_zod31.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
4053
4276
|
},
|
|
4054
4277
|
async ({ documentId, locationId: locationId2 }) => {
|
|
4055
4278
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -4063,9 +4286,9 @@ function registerDocumentTools(server2, client) {
|
|
|
4063
4286
|
"send_document",
|
|
4064
4287
|
"Send a document/contract to a contact for electronic signature.",
|
|
4065
4288
|
{
|
|
4066
|
-
documentId:
|
|
4067
|
-
contactId:
|
|
4068
|
-
locationId:
|
|
4289
|
+
documentId: import_zod31.z.string().describe("The document ID to send."),
|
|
4290
|
+
contactId: import_zod31.z.string().describe("The contact ID to send the document to."),
|
|
4291
|
+
locationId: import_zod31.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
4069
4292
|
},
|
|
4070
4293
|
async ({ documentId, contactId, locationId: locationId2 }) => {
|
|
4071
4294
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -4077,19 +4300,19 @@ function registerDocumentTools(server2, client) {
|
|
|
4077
4300
|
}
|
|
4078
4301
|
|
|
4079
4302
|
// 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:
|
|
4303
|
+
var import_zod32 = require("zod");
|
|
4304
|
+
var ActionSchema = import_zod32.z.object({
|
|
4305
|
+
id: import_zod32.z.string().optional().describe("Action ID (auto-generated if omitted)."),
|
|
4306
|
+
name: import_zod32.z.string().describe("Display name for this action step."),
|
|
4307
|
+
type: import_zod32.z.string().describe("Action type."),
|
|
4308
|
+
attributes: import_zod32.z.record(import_zod32.z.unknown()).optional().describe("Action-specific configuration."),
|
|
4309
|
+
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."),
|
|
4310
|
+
parent: import_zod32.z.string().optional().describe("Branch parent node id."),
|
|
4311
|
+
parentKey: import_zod32.z.string().optional().describe("Previous action id or branch parent id."),
|
|
4312
|
+
order: import_zod32.z.number().optional().describe("Order within this chain or branch."),
|
|
4313
|
+
cat: import_zod32.z.string().optional().describe("Category for condition, transition, or multi-path nodes."),
|
|
4314
|
+
nodeType: import_zod32.z.string().optional().describe("Node type for if/else nodes."),
|
|
4315
|
+
sibling: import_zod32.z.array(import_zod32.z.string()).optional().describe("Sibling branch node IDs.")
|
|
4093
4316
|
}).passthrough();
|
|
4094
4317
|
function linkBranchActions(actions, branchId, nextAfterMerge) {
|
|
4095
4318
|
const prepared = actions.map((action) => ({
|
|
@@ -4136,8 +4359,8 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4136
4359
|
"list_workflows_full",
|
|
4137
4360
|
"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
4361
|
{
|
|
4139
|
-
limit:
|
|
4140
|
-
skip:
|
|
4362
|
+
limit: import_zod32.z.number().optional().describe("Max workflows to return. Defaults to 50."),
|
|
4363
|
+
skip: import_zod32.z.number().optional().describe("Number of workflows to skip for pagination.")
|
|
4141
4364
|
},
|
|
4142
4365
|
async ({ limit, skip }) => {
|
|
4143
4366
|
try {
|
|
@@ -4152,7 +4375,7 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4152
4375
|
"get_workflow_full",
|
|
4153
4376
|
"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
4377
|
{
|
|
4155
|
-
workflowId:
|
|
4378
|
+
workflowId: import_zod32.z.string().describe("The workflow ID to retrieve.")
|
|
4156
4379
|
},
|
|
4157
4380
|
async ({ workflowId }) => {
|
|
4158
4381
|
try {
|
|
@@ -4167,9 +4390,9 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4167
4390
|
"get_trigger_registry",
|
|
4168
4391
|
"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
4392
|
{
|
|
4170
|
-
companyId:
|
|
4171
|
-
limit:
|
|
4172
|
-
installedOnly:
|
|
4393
|
+
companyId: import_zod32.z.string().describe("Company ID for the location. Find it in any get_workflow_full response under the 'companyId' field."),
|
|
4394
|
+
limit: import_zod32.z.number().optional().describe("Max marketplace apps to return. Defaults to 200."),
|
|
4395
|
+
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
4396
|
},
|
|
4174
4397
|
async ({ companyId, limit, installedOnly }) => {
|
|
4175
4398
|
try {
|
|
@@ -4201,7 +4424,7 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4201
4424
|
"create_workflow",
|
|
4202
4425
|
"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
4426
|
{
|
|
4204
|
-
name:
|
|
4427
|
+
name: import_zod32.z.string().describe("Name for the new workflow.")
|
|
4205
4428
|
},
|
|
4206
4429
|
async ({ name }) => {
|
|
4207
4430
|
try {
|
|
@@ -4216,11 +4439,11 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4216
4439
|
"update_workflow_actions",
|
|
4217
4440
|
"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
4441
|
{
|
|
4219
|
-
workflowId:
|
|
4220
|
-
name:
|
|
4221
|
-
status:
|
|
4222
|
-
actions:
|
|
4223
|
-
triggers:
|
|
4442
|
+
workflowId: import_zod32.z.string().describe("The workflow ID to update."),
|
|
4443
|
+
name: import_zod32.z.string().optional().describe("New workflow name."),
|
|
4444
|
+
status: import_zod32.z.string().optional().describe("New status: 'draft' or 'published'."),
|
|
4445
|
+
actions: import_zod32.z.array(ActionSchema).optional().describe("Array of workflow actions/steps. For linear flows, provide in order \u2014 chaining is automatic."),
|
|
4446
|
+
triggers: import_zod32.z.array(WorkflowTriggerSchema).optional().describe("Array of workflow triggers.")
|
|
4224
4447
|
},
|
|
4225
4448
|
async ({ workflowId, name, status, actions, triggers }) => {
|
|
4226
4449
|
try {
|
|
@@ -4264,12 +4487,12 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4264
4487
|
"build_if_else_branch",
|
|
4265
4488
|
"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
4489
|
{
|
|
4267
|
-
field:
|
|
4268
|
-
operator:
|
|
4269
|
-
value:
|
|
4270
|
-
yes_actions:
|
|
4271
|
-
no_actions:
|
|
4272
|
-
next_after_merge:
|
|
4490
|
+
field: import_zod32.z.string().describe("Condition subtype, currently 'tags' for tag-based conditions."),
|
|
4491
|
+
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."),
|
|
4492
|
+
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."),
|
|
4493
|
+
yes_actions: import_zod32.z.array(ActionSchema).describe("Actions to run in the Yes branch."),
|
|
4494
|
+
no_actions: import_zod32.z.array(ActionSchema).describe("Actions to run in the No branch."),
|
|
4495
|
+
next_after_merge: import_zod32.z.string().optional().describe("Optional node id to link from each non-empty branch's final child.")
|
|
4273
4496
|
},
|
|
4274
4497
|
async ({ field, operator, value, yes_actions, no_actions, next_after_merge }) => {
|
|
4275
4498
|
try {
|
|
@@ -4379,7 +4602,7 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4379
4602
|
"build_goal_event",
|
|
4380
4603
|
"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
4604
|
{
|
|
4382
|
-
goal_condition:
|
|
4605
|
+
goal_condition: import_zod32.z.enum([
|
|
4383
4606
|
"email_event",
|
|
4384
4607
|
"link_click",
|
|
4385
4608
|
"add_contact_tag",
|
|
@@ -4391,11 +4614,11 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4391
4614
|
"invoice_paid",
|
|
4392
4615
|
"review_request_clicked"
|
|
4393
4616
|
]).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:
|
|
4617
|
+
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."),
|
|
4618
|
+
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."),
|
|
4619
|
+
name: import_zod32.z.string().default("Goal").describe("Display name in the GHL UI."),
|
|
4620
|
+
op: import_zod32.z.enum(["or", "and"]).default("or").describe("Top-level boolean operator across segments. Default 'or'."),
|
|
4621
|
+
inner_op: import_zod32.z.enum(["or", "and"]).default("or").describe("Boolean operator across conditions within a single segment. Default 'or'.")
|
|
4399
4622
|
},
|
|
4400
4623
|
async ({ goal_condition, extras, action, name, op, inner_op }) => {
|
|
4401
4624
|
try {
|
|
@@ -4430,8 +4653,8 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4430
4653
|
"delete_workflow_full",
|
|
4431
4654
|
"Permanently delete a workflow. IRREVERSIBLE.",
|
|
4432
4655
|
{
|
|
4433
|
-
workflowId:
|
|
4434
|
-
confirm:
|
|
4656
|
+
workflowId: import_zod32.z.string().describe("The workflow ID to delete."),
|
|
4657
|
+
confirm: import_zod32.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
|
|
4435
4658
|
},
|
|
4436
4659
|
async ({ workflowId }) => {
|
|
4437
4660
|
try {
|
|
@@ -4446,7 +4669,7 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4446
4669
|
"publish_workflow",
|
|
4447
4670
|
"Publish a draft workflow, making it active and processing contacts.",
|
|
4448
4671
|
{
|
|
4449
|
-
workflowId:
|
|
4672
|
+
workflowId: import_zod32.z.string().describe("The workflow ID to publish.")
|
|
4450
4673
|
},
|
|
4451
4674
|
async ({ workflowId }) => {
|
|
4452
4675
|
try {
|
|
@@ -4460,7 +4683,7 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4460
4683
|
}
|
|
4461
4684
|
|
|
4462
4685
|
// src/tools/funnel-builder.ts
|
|
4463
|
-
var
|
|
4686
|
+
var import_zod33 = require("zod");
|
|
4464
4687
|
function registerFunnelBuilderTools(server2, builderClient) {
|
|
4465
4688
|
const client = builderClient;
|
|
4466
4689
|
if (!client) return;
|
|
@@ -4503,7 +4726,7 @@ ${text2}`);
|
|
|
4503
4726
|
"list_funnels_full",
|
|
4504
4727
|
"List all funnels/websites with full details including steps, pages, and metadata. Uses the internal API for richer data than the public API.",
|
|
4505
4728
|
{
|
|
4506
|
-
limit:
|
|
4729
|
+
limit: import_zod33.z.number().optional().describe("Max funnels to return. Defaults to 50.")
|
|
4507
4730
|
},
|
|
4508
4731
|
async ({ limit }) => {
|
|
4509
4732
|
try {
|
|
@@ -4523,7 +4746,7 @@ ${text2}`);
|
|
|
4523
4746
|
"get_page_full",
|
|
4524
4747
|
"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
4748
|
{
|
|
4526
|
-
pageId:
|
|
4749
|
+
pageId: import_zod33.z.string().describe("The page ID to retrieve.")
|
|
4527
4750
|
},
|
|
4528
4751
|
async ({ pageId }) => {
|
|
4529
4752
|
try {
|
|
@@ -4543,7 +4766,7 @@ ${text2}`);
|
|
|
4543
4766
|
"get_page_content",
|
|
4544
4767
|
"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
4768
|
{
|
|
4546
|
-
pageDataDownloadUrl:
|
|
4769
|
+
pageDataDownloadUrl: import_zod33.z.string().describe("The pageDataDownloadUrl from get_page_full response.")
|
|
4547
4770
|
},
|
|
4548
4771
|
async ({ pageDataDownloadUrl }) => {
|
|
4549
4772
|
try {
|
|
@@ -4565,7 +4788,7 @@ ${text2}`);
|
|
|
4565
4788
|
"create_funnel",
|
|
4566
4789
|
"Create a new funnel/website. Starts empty \u2014 add steps and pages after creation.",
|
|
4567
4790
|
{
|
|
4568
|
-
name:
|
|
4791
|
+
name: import_zod33.z.string().describe("Name for the new funnel.")
|
|
4569
4792
|
},
|
|
4570
4793
|
async ({ name }) => {
|
|
4571
4794
|
try {
|
|
@@ -4587,21 +4810,21 @@ ${text2}`);
|
|
|
4587
4810
|
"update_funnel",
|
|
4588
4811
|
"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
4812
|
{
|
|
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:
|
|
4813
|
+
funnelId: import_zod33.z.string().describe("The funnel ID to update."),
|
|
4814
|
+
name: import_zod33.z.string().optional().describe("New funnel display name."),
|
|
4815
|
+
path: import_zod33.z.string().optional().describe("URL slug for the funnel (e.g., '/my-funnel'). Mapped to funnelPath."),
|
|
4816
|
+
bodyTrackingCode: import_zod33.z.string().optional().describe("Custom tracking script injected before </body>."),
|
|
4817
|
+
headTrackingCode: import_zod33.z.string().optional().describe("Custom tracking script injected before </head>."),
|
|
4818
|
+
chatWidgetId: import_zod33.z.string().optional().describe("Chat widget to embed on every page in this funnel."),
|
|
4819
|
+
domainId: import_zod33.z.string().optional().describe("Custom domain ID for the funnel."),
|
|
4820
|
+
faviconUrl: import_zod33.z.string().optional().describe("Favicon URL for funnel pages."),
|
|
4821
|
+
paymentMode: import_zod33.z.boolean().optional().describe("Whether to require a payment mode for the funnel."),
|
|
4822
|
+
requireCreditCard: import_zod33.z.boolean().optional().describe("Whether to require a credit card on opt-in steps."),
|
|
4823
|
+
isGdprCompliant: import_zod33.z.boolean().optional().describe("Toggle GDPR compliance mode."),
|
|
4824
|
+
isOptimisePageLoad: import_zod33.z.boolean().optional().describe("Enable GHL's page-load optimization."),
|
|
4825
|
+
imageOptimization: import_zod33.z.boolean().optional().describe("Enable automatic image optimization."),
|
|
4826
|
+
allowPaymentModeOption: import_zod33.z.boolean().optional().describe("Allow buyers to choose payment mode on checkout."),
|
|
4827
|
+
storeCurrencyFormatting: import_zod33.z.boolean().optional().describe("Use store-wide currency formatting.")
|
|
4605
4828
|
},
|
|
4606
4829
|
async (args) => {
|
|
4607
4830
|
try {
|
|
@@ -4657,11 +4880,11 @@ ${text2}`);
|
|
|
4657
4880
|
"update_funnel_step",
|
|
4658
4881
|
"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
4882
|
{
|
|
4660
|
-
funnelId:
|
|
4661
|
-
stepId:
|
|
4662
|
-
name:
|
|
4663
|
-
url:
|
|
4664
|
-
domainName:
|
|
4883
|
+
funnelId: import_zod33.z.string().describe("The funnel ID containing the step."),
|
|
4884
|
+
stepId: import_zod33.z.string().describe("The step ID to update (from get_funnel_pages / list_funnels_full)."),
|
|
4885
|
+
name: import_zod33.z.string().optional().describe("New step display name."),
|
|
4886
|
+
url: import_zod33.z.string().optional().describe("URL slug for the step (e.g., '/thank-you')."),
|
|
4887
|
+
domainName: import_zod33.z.string().optional().describe("Custom domain to attach to this step.")
|
|
4665
4888
|
},
|
|
4666
4889
|
async ({ funnelId, stepId, name, url, domainName }) => {
|
|
4667
4890
|
try {
|
|
@@ -4680,8 +4903,8 @@ ${text2}`);
|
|
|
4680
4903
|
"delete_funnel",
|
|
4681
4904
|
"Permanently delete a funnel and all its steps/pages. IRREVERSIBLE.",
|
|
4682
4905
|
{
|
|
4683
|
-
funnelId:
|
|
4684
|
-
confirm:
|
|
4906
|
+
funnelId: import_zod33.z.string().describe("The funnel ID to delete."),
|
|
4907
|
+
confirm: import_zod33.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
|
|
4685
4908
|
},
|
|
4686
4909
|
async ({ funnelId }) => {
|
|
4687
4910
|
try {
|
|
@@ -4700,10 +4923,10 @@ ${text2}`);
|
|
|
4700
4923
|
"create_funnel_page",
|
|
4701
4924
|
"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
4925
|
{
|
|
4703
|
-
funnelId:
|
|
4704
|
-
name:
|
|
4705
|
-
url:
|
|
4706
|
-
type:
|
|
4926
|
+
funnelId: import_zod33.z.string().describe("The funnel ID to add the step to."),
|
|
4927
|
+
name: import_zod33.z.string().describe("Step display name."),
|
|
4928
|
+
url: import_zod33.z.string().optional().describe("URL slug for the step. Defaults to '' (blank) like the GHL UI."),
|
|
4929
|
+
type: import_zod33.z.string().optional().describe("Step type. Defaults to 'optin_funnel_page'.")
|
|
4707
4930
|
},
|
|
4708
4931
|
async ({ funnelId, name, url, type }) => {
|
|
4709
4932
|
try {
|
|
@@ -4731,9 +4954,9 @@ ${text2}`);
|
|
|
4731
4954
|
"update_page_content",
|
|
4732
4955
|
"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
4956
|
{
|
|
4734
|
-
pageId:
|
|
4735
|
-
content:
|
|
4736
|
-
isPublished:
|
|
4957
|
+
pageId: import_zod33.z.string().describe("The page ID to update."),
|
|
4958
|
+
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."),
|
|
4959
|
+
isPublished: import_zod33.z.boolean().optional().describe("Whether the page should be marked published after the save. Defaults to false (draft).")
|
|
4737
4960
|
},
|
|
4738
4961
|
async ({ pageId, content, isPublished }) => {
|
|
4739
4962
|
try {
|
|
@@ -4754,9 +4977,9 @@ ${text2}`);
|
|
|
4754
4977
|
"delete_funnel_page",
|
|
4755
4978
|
"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
4979
|
{
|
|
4757
|
-
funnelId:
|
|
4758
|
-
stepId:
|
|
4759
|
-
confirm:
|
|
4980
|
+
funnelId: import_zod33.z.string().describe("The funnel ID containing the step."),
|
|
4981
|
+
stepId: import_zod33.z.string().describe("The step ID to delete (from get_funnel_pages / list_funnels_full)."),
|
|
4982
|
+
confirm: import_zod33.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
|
|
4760
4983
|
},
|
|
4761
4984
|
async ({ funnelId, stepId }) => {
|
|
4762
4985
|
try {
|
|
@@ -4770,7 +4993,7 @@ ${text2}`);
|
|
|
4770
4993
|
}
|
|
4771
4994
|
|
|
4772
4995
|
// src/tools/form-builder.ts
|
|
4773
|
-
var
|
|
4996
|
+
var import_zod34 = require("zod");
|
|
4774
4997
|
function registerFormBuilderTools(server2, builderClient) {
|
|
4775
4998
|
const client = builderClient;
|
|
4776
4999
|
if (!client) return;
|
|
@@ -4799,7 +5022,7 @@ ${text2}`);
|
|
|
4799
5022
|
"get_form_full",
|
|
4800
5023
|
"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
5024
|
{
|
|
4802
|
-
formId:
|
|
5025
|
+
formId: import_zod34.z.string().describe("The form ID to retrieve.")
|
|
4803
5026
|
},
|
|
4804
5027
|
async ({ formId }) => {
|
|
4805
5028
|
try {
|
|
@@ -4816,9 +5039,9 @@ ${text2}`);
|
|
|
4816
5039
|
"update_form",
|
|
4817
5040
|
"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
5041
|
{
|
|
4819
|
-
formId:
|
|
4820
|
-
formData:
|
|
4821
|
-
name:
|
|
5042
|
+
formId: import_zod34.z.string().describe("The form ID to update."),
|
|
5043
|
+
formData: import_zod34.z.record(import_zod34.z.unknown()).describe("The updated formData object containing form fields, settings, autoResponder config, etc."),
|
|
5044
|
+
name: import_zod34.z.string().optional().describe("Updated form name.")
|
|
4822
5045
|
},
|
|
4823
5046
|
async ({ formId, formData, name }) => {
|
|
4824
5047
|
try {
|
|
@@ -4837,7 +5060,7 @@ ${text2}`);
|
|
|
4837
5060
|
"create_form",
|
|
4838
5061
|
"Create a new form. Starts with a basic structure \u2014 use update_form to add fields and configure settings.",
|
|
4839
5062
|
{
|
|
4840
|
-
name:
|
|
5063
|
+
name: import_zod34.z.string().describe("Name for the new form.")
|
|
4841
5064
|
},
|
|
4842
5065
|
async ({ name }) => {
|
|
4843
5066
|
try {
|
|
@@ -4863,8 +5086,8 @@ ${text2}`);
|
|
|
4863
5086
|
"delete_form",
|
|
4864
5087
|
"Permanently delete a form. IRREVERSIBLE.",
|
|
4865
5088
|
{
|
|
4866
|
-
formId:
|
|
4867
|
-
confirm:
|
|
5089
|
+
formId: import_zod34.z.string().describe("The form ID to delete."),
|
|
5090
|
+
confirm: import_zod34.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
|
|
4868
5091
|
},
|
|
4869
5092
|
async ({ formId }) => {
|
|
4870
5093
|
try {
|
|
@@ -4881,9 +5104,9 @@ ${text2}`);
|
|
|
4881
5104
|
"get_form_submissions_full",
|
|
4882
5105
|
"Get form submissions with full field data, contact info, and submission timestamps via the internal API. Offset-based pagination via skip/limit.",
|
|
4883
5106
|
{
|
|
4884
|
-
formId:
|
|
4885
|
-
limit:
|
|
4886
|
-
skip:
|
|
5107
|
+
formId: import_zod34.z.string().optional().describe("Filter by form ID. If omitted, returns all submissions."),
|
|
5108
|
+
limit: import_zod34.z.number().optional().describe("Max submissions to return. Defaults to 20."),
|
|
5109
|
+
skip: import_zod34.z.number().optional().describe("Number to skip for pagination.")
|
|
4887
5110
|
},
|
|
4888
5111
|
async ({ formId, limit, skip }) => {
|
|
4889
5112
|
try {
|
|
@@ -4902,7 +5125,7 @@ ${text2}`);
|
|
|
4902
5125
|
}
|
|
4903
5126
|
|
|
4904
5127
|
// src/tools/pipeline-builder.ts
|
|
4905
|
-
var
|
|
5128
|
+
var import_zod35 = require("zod");
|
|
4906
5129
|
function registerPipelineBuilderTools(server2, builderClient) {
|
|
4907
5130
|
const client = builderClient;
|
|
4908
5131
|
if (!client) return;
|
|
@@ -4947,7 +5170,7 @@ ${text2}`);
|
|
|
4947
5170
|
"get_pipeline_full",
|
|
4948
5171
|
"Get a single pipeline with complete stage configuration: IDs, names, positions, display settings.",
|
|
4949
5172
|
{
|
|
4950
|
-
pipelineId:
|
|
5173
|
+
pipelineId: import_zod35.z.string().describe("The pipeline ID to retrieve.")
|
|
4951
5174
|
},
|
|
4952
5175
|
async ({ pipelineId }) => {
|
|
4953
5176
|
try {
|
|
@@ -4965,17 +5188,17 @@ ${text2}`);
|
|
|
4965
5188
|
"create_pipeline",
|
|
4966
5189
|
"Create a new pipeline with stages. Each stage needs a name and position (0-based).",
|
|
4967
5190
|
{
|
|
4968
|
-
name:
|
|
4969
|
-
stages:
|
|
4970
|
-
|
|
4971
|
-
name:
|
|
4972
|
-
position:
|
|
4973
|
-
showInFunnel:
|
|
4974
|
-
showInPieChart:
|
|
5191
|
+
name: import_zod35.z.string().describe("Pipeline name."),
|
|
5192
|
+
stages: import_zod35.z.array(
|
|
5193
|
+
import_zod35.z.object({
|
|
5194
|
+
name: import_zod35.z.string().describe("Stage name."),
|
|
5195
|
+
position: import_zod35.z.number().describe("Stage position (0-based)."),
|
|
5196
|
+
showInFunnel: import_zod35.z.boolean().optional().describe("Show in funnel view. Defaults to true."),
|
|
5197
|
+
showInPieChart: import_zod35.z.boolean().optional().describe("Show in pie chart. Defaults to true.")
|
|
4975
5198
|
})
|
|
4976
5199
|
).describe("Array of stages in order."),
|
|
4977
|
-
showInFunnel:
|
|
4978
|
-
showInPieChart:
|
|
5200
|
+
showInFunnel: import_zod35.z.boolean().optional().describe("Show pipeline in funnel view. Defaults to true."),
|
|
5201
|
+
showInPieChart: import_zod35.z.boolean().optional().describe("Show pipeline in pie chart. Defaults to true.")
|
|
4979
5202
|
},
|
|
4980
5203
|
async ({ name, stages, showInFunnel, showInPieChart }) => {
|
|
4981
5204
|
try {
|
|
@@ -5005,19 +5228,19 @@ ${text2}`);
|
|
|
5005
5228
|
"update_pipeline",
|
|
5006
5229
|
"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
5230
|
{
|
|
5008
|
-
pipelineId:
|
|
5009
|
-
name:
|
|
5010
|
-
stages:
|
|
5011
|
-
|
|
5012
|
-
id:
|
|
5013
|
-
name:
|
|
5014
|
-
position:
|
|
5015
|
-
showInFunnel:
|
|
5016
|
-
showInPieChart:
|
|
5231
|
+
pipelineId: import_zod35.z.string().describe("The pipeline ID to update."),
|
|
5232
|
+
name: import_zod35.z.string().optional().describe("New pipeline name."),
|
|
5233
|
+
stages: import_zod35.z.array(
|
|
5234
|
+
import_zod35.z.object({
|
|
5235
|
+
id: import_zod35.z.string().optional().describe("Existing stage ID (omit for new stages)."),
|
|
5236
|
+
name: import_zod35.z.string().describe("Stage name."),
|
|
5237
|
+
position: import_zod35.z.number().describe("Stage position (0-based)."),
|
|
5238
|
+
showInFunnel: import_zod35.z.boolean().optional().describe("Show in funnel view."),
|
|
5239
|
+
showInPieChart: import_zod35.z.boolean().optional().describe("Show in pie chart.")
|
|
5017
5240
|
})
|
|
5018
5241
|
).optional().describe("Complete stages array. Stages not included will be removed."),
|
|
5019
|
-
showInFunnel:
|
|
5020
|
-
showInPieChart:
|
|
5242
|
+
showInFunnel: import_zod35.z.boolean().optional().describe("Show pipeline in funnel view."),
|
|
5243
|
+
showInPieChart: import_zod35.z.boolean().optional().describe("Show pipeline in pie chart.")
|
|
5021
5244
|
},
|
|
5022
5245
|
async ({ pipelineId, name, stages, showInFunnel, showInPieChart }) => {
|
|
5023
5246
|
try {
|
|
@@ -5040,8 +5263,8 @@ ${text2}`);
|
|
|
5040
5263
|
"delete_pipeline",
|
|
5041
5264
|
"Permanently delete a pipeline and all its stages. Opportunities become unassigned. IRREVERSIBLE.",
|
|
5042
5265
|
{
|
|
5043
|
-
pipelineId:
|
|
5044
|
-
confirm:
|
|
5266
|
+
pipelineId: import_zod35.z.string().describe("The pipeline ID to delete."),
|
|
5267
|
+
confirm: import_zod35.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
|
|
5045
5268
|
},
|
|
5046
5269
|
async ({ pipelineId }) => {
|
|
5047
5270
|
try {
|
|
@@ -5058,7 +5281,7 @@ ${text2}`);
|
|
|
5058
5281
|
}
|
|
5059
5282
|
|
|
5060
5283
|
// src/tools/location-switcher.ts
|
|
5061
|
-
var
|
|
5284
|
+
var import_zod36 = require("zod");
|
|
5062
5285
|
var switchChain = Promise.resolve();
|
|
5063
5286
|
function withSwitchLock(fn) {
|
|
5064
5287
|
const next = switchChain.then(fn, fn);
|
|
@@ -5107,7 +5330,7 @@ Token registry: ${registeredCount} location(s) registered${versionLine}`
|
|
|
5107
5330
|
"switch_location",
|
|
5108
5331
|
"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
5332
|
{
|
|
5110
|
-
locationId:
|
|
5333
|
+
locationId: import_zod36.z.string().describe("The Location ID to switch to.")
|
|
5111
5334
|
},
|
|
5112
5335
|
async ({ locationId: locationId2 }) => withSwitchLock(async () => {
|
|
5113
5336
|
const previousId = client.defaultLocationId;
|
|
@@ -5172,9 +5395,9 @@ Still on: ${previousId || "none"}${hint}` }],
|
|
|
5172
5395
|
"register_location",
|
|
5173
5396
|
"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
5397
|
{
|
|
5175
|
-
locationId:
|
|
5176
|
-
name:
|
|
5177
|
-
apiKey:
|
|
5398
|
+
locationId: import_zod36.z.string().describe("The GHL Location ID (from Settings > Business Profile)."),
|
|
5399
|
+
name: import_zod36.z.string().describe("A friendly name for this sub-account (e.g. 'PNTracker', 'Med Spa Template')."),
|
|
5400
|
+
apiKey: import_zod36.z.string().describe("The Private Integration API key for this sub-account (starts with 'pit-').")
|
|
5178
5401
|
},
|
|
5179
5402
|
async ({ locationId: locationId2, name, apiKey: apiKey2 }) => {
|
|
5180
5403
|
if (!registry2) {
|
|
@@ -5224,7 +5447,7 @@ The API key could not access location ${locationId2}. Make sure:
|
|
|
5224
5447
|
"unregister_location",
|
|
5225
5448
|
"Remove a GHL sub-account from the token registry.",
|
|
5226
5449
|
{
|
|
5227
|
-
locationId:
|
|
5450
|
+
locationId: import_zod36.z.string().describe("The Location ID to remove.")
|
|
5228
5451
|
},
|
|
5229
5452
|
async ({ locationId: locationId2 }) => {
|
|
5230
5453
|
if (!registry2) {
|
|
@@ -5283,8 +5506,8 @@ ${lines.join("\n")}
|
|
|
5283
5506
|
"list_available_locations",
|
|
5284
5507
|
"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
5508
|
{
|
|
5286
|
-
limit:
|
|
5287
|
-
skip:
|
|
5509
|
+
limit: import_zod36.z.number().optional().describe("Max locations to return. Defaults to 20."),
|
|
5510
|
+
skip: import_zod36.z.number().optional().describe("Number to skip for pagination.")
|
|
5288
5511
|
},
|
|
5289
5512
|
async ({ limit, skip }) => {
|
|
5290
5513
|
try {
|
|
@@ -5327,7 +5550,7 @@ ${lines.join("\n")}
|
|
|
5327
5550
|
}
|
|
5328
5551
|
|
|
5329
5552
|
// src/tools/bulk-operations.ts
|
|
5330
|
-
var
|
|
5553
|
+
var import_zod37 = require("zod");
|
|
5331
5554
|
function delay(ms) {
|
|
5332
5555
|
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
5333
5556
|
}
|
|
@@ -5339,8 +5562,8 @@ function registerBulkOperationTools(server2, client) {
|
|
|
5339
5562
|
"bulk_add_tags",
|
|
5340
5563
|
"Add tags to multiple contacts at once. Rate-limited to avoid API throttling. Returns a summary of successes and failures.",
|
|
5341
5564
|
{
|
|
5342
|
-
contactIds:
|
|
5343
|
-
tags:
|
|
5565
|
+
contactIds: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to tag."),
|
|
5566
|
+
tags: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one tag required.").describe("Tags to add to each contact.")
|
|
5344
5567
|
},
|
|
5345
5568
|
async ({ contactIds, tags }) => {
|
|
5346
5569
|
const results = { success: 0, failed: 0, errors: [] };
|
|
@@ -5362,8 +5585,8 @@ function registerBulkOperationTools(server2, client) {
|
|
|
5362
5585
|
"bulk_remove_tags",
|
|
5363
5586
|
"Remove tags from multiple contacts at once. Rate-limited.",
|
|
5364
5587
|
{
|
|
5365
|
-
contactIds:
|
|
5366
|
-
tags:
|
|
5588
|
+
contactIds: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs."),
|
|
5589
|
+
tags: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one tag required.").describe("Tags to remove from each contact.")
|
|
5367
5590
|
},
|
|
5368
5591
|
async ({ contactIds, tags }) => {
|
|
5369
5592
|
const results = { success: 0, failed: 0, errors: [] };
|
|
@@ -5384,8 +5607,8 @@ function registerBulkOperationTools(server2, client) {
|
|
|
5384
5607
|
"bulk_update_contacts",
|
|
5385
5608
|
"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
5609
|
{
|
|
5387
|
-
contactIds:
|
|
5388
|
-
fields:
|
|
5610
|
+
contactIds: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to update."),
|
|
5611
|
+
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
5612
|
},
|
|
5390
5613
|
async ({ contactIds, fields }) => {
|
|
5391
5614
|
const results = { success: 0, failed: 0, errors: [] };
|
|
@@ -5406,8 +5629,8 @@ function registerBulkOperationTools(server2, client) {
|
|
|
5406
5629
|
"bulk_add_to_workflow",
|
|
5407
5630
|
"Enroll multiple contacts into a workflow at once. Rate-limited.",
|
|
5408
5631
|
{
|
|
5409
|
-
contactIds:
|
|
5410
|
-
workflowId:
|
|
5632
|
+
contactIds: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to enroll."),
|
|
5633
|
+
workflowId: import_zod37.z.string().describe("The workflow ID to enroll contacts into.")
|
|
5411
5634
|
},
|
|
5412
5635
|
async ({ contactIds, workflowId }) => {
|
|
5413
5636
|
const results = { success: 0, failed: 0, errors: [] };
|
|
@@ -5428,8 +5651,8 @@ function registerBulkOperationTools(server2, client) {
|
|
|
5428
5651
|
"bulk_delete_contacts",
|
|
5429
5652
|
"Delete multiple contacts at once. IRREVERSIBLE. Rate-limited. Use with extreme caution.",
|
|
5430
5653
|
{
|
|
5431
|
-
contactIds:
|
|
5432
|
-
confirm:
|
|
5654
|
+
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."),
|
|
5655
|
+
confirm: import_zod37.z.literal("DELETE").describe("Must pass the string 'DELETE' to confirm. This is a safety check.")
|
|
5433
5656
|
},
|
|
5434
5657
|
async ({ contactIds, confirm }) => {
|
|
5435
5658
|
if (confirm !== "DELETE") {
|
|
@@ -5452,7 +5675,7 @@ function registerBulkOperationTools(server2, client) {
|
|
|
5452
5675
|
}
|
|
5453
5676
|
|
|
5454
5677
|
// src/tools/account-export.ts
|
|
5455
|
-
var
|
|
5678
|
+
var import_zod38 = require("zod");
|
|
5456
5679
|
function delay2(ms) {
|
|
5457
5680
|
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
5458
5681
|
}
|
|
@@ -5462,8 +5685,8 @@ function registerAccountExportTools(server2, client) {
|
|
|
5462
5685
|
"export_account",
|
|
5463
5686
|
"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
5687
|
{
|
|
5465
|
-
locationId:
|
|
5466
|
-
includeContacts:
|
|
5688
|
+
locationId: import_zod38.z.string().optional().describe("Location ID to export. Uses default if not specified."),
|
|
5689
|
+
includeContacts: import_zod38.z.boolean().optional().describe("Include contact list (first 100). Defaults to false for speed.")
|
|
5467
5690
|
},
|
|
5468
5691
|
async ({ locationId: locationId2, includeContacts }) => {
|
|
5469
5692
|
try {
|
|
@@ -5591,8 +5814,8 @@ function registerAccountExportTools(server2, client) {
|
|
|
5591
5814
|
"compare_locations",
|
|
5592
5815
|
"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
5816
|
{
|
|
5594
|
-
locationA:
|
|
5595
|
-
locationB:
|
|
5817
|
+
locationA: import_zod38.z.string().describe("First Location ID."),
|
|
5818
|
+
locationB: import_zod38.z.string().describe("Second Location ID.")
|
|
5596
5819
|
},
|
|
5597
5820
|
async ({ locationA, locationB }) => {
|
|
5598
5821
|
try {
|
|
@@ -5670,7 +5893,7 @@ function registerAccountExportTools(server2, client) {
|
|
|
5670
5893
|
}
|
|
5671
5894
|
|
|
5672
5895
|
// src/tools/workflow-cloner.ts
|
|
5673
|
-
var
|
|
5896
|
+
var import_zod39 = require("zod");
|
|
5674
5897
|
var crypto2 = __toESM(require("crypto"));
|
|
5675
5898
|
function registerWorkflowClonerTools(server2, builderClient) {
|
|
5676
5899
|
const client = builderClient;
|
|
@@ -5679,8 +5902,8 @@ function registerWorkflowClonerTools(server2, builderClient) {
|
|
|
5679
5902
|
"clone_workflow",
|
|
5680
5903
|
"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
5904
|
{
|
|
5682
|
-
sourceWorkflowId:
|
|
5683
|
-
newName:
|
|
5905
|
+
sourceWorkflowId: import_zod39.z.string().describe("The workflow ID to clone."),
|
|
5906
|
+
newName: import_zod39.z.string().describe("Name for the cloned workflow.")
|
|
5684
5907
|
},
|
|
5685
5908
|
async ({ sourceWorkflowId, newName }) => {
|
|
5686
5909
|
try {
|
|
@@ -5769,41 +5992,41 @@ function registerWorkflowClonerTools(server2, builderClient) {
|
|
|
5769
5992
|
}
|
|
5770
5993
|
|
|
5771
5994
|
// src/tools/template-deployer.ts
|
|
5772
|
-
var
|
|
5995
|
+
var import_zod40 = require("zod");
|
|
5773
5996
|
var fs3 = __toESM(require("fs"));
|
|
5774
5997
|
var path3 = __toESM(require("path"));
|
|
5775
5998
|
function delay3(ms) {
|
|
5776
5999
|
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
5777
6000
|
}
|
|
5778
|
-
var TemplateSchema =
|
|
5779
|
-
templateName:
|
|
5780
|
-
templateVersion:
|
|
5781
|
-
description:
|
|
5782
|
-
questionnaire:
|
|
5783
|
-
id:
|
|
5784
|
-
question:
|
|
5785
|
-
type:
|
|
5786
|
-
required:
|
|
5787
|
-
placeholder:
|
|
6001
|
+
var TemplateSchema = import_zod40.z.object({
|
|
6002
|
+
templateName: import_zod40.z.string(),
|
|
6003
|
+
templateVersion: import_zod40.z.string().optional(),
|
|
6004
|
+
description: import_zod40.z.string().optional().default(""),
|
|
6005
|
+
questionnaire: import_zod40.z.array(import_zod40.z.object({
|
|
6006
|
+
id: import_zod40.z.string(),
|
|
6007
|
+
question: import_zod40.z.string(),
|
|
6008
|
+
type: import_zod40.z.string(),
|
|
6009
|
+
required: import_zod40.z.boolean().optional(),
|
|
6010
|
+
placeholder: import_zod40.z.string().optional()
|
|
5788
6011
|
})).optional().default([]),
|
|
5789
|
-
location:
|
|
5790
|
-
tags:
|
|
5791
|
-
customFields:
|
|
5792
|
-
name:
|
|
5793
|
-
dataType:
|
|
6012
|
+
location: import_zod40.z.record(import_zod40.z.unknown()).optional(),
|
|
6013
|
+
tags: import_zod40.z.array(import_zod40.z.string()).optional(),
|
|
6014
|
+
customFields: import_zod40.z.array(import_zod40.z.object({
|
|
6015
|
+
name: import_zod40.z.string(),
|
|
6016
|
+
dataType: import_zod40.z.string()
|
|
5794
6017
|
})).optional(),
|
|
5795
|
-
pipelines:
|
|
5796
|
-
name:
|
|
5797
|
-
stages:
|
|
6018
|
+
pipelines: import_zod40.z.array(import_zod40.z.object({
|
|
6019
|
+
name: import_zod40.z.string(),
|
|
6020
|
+
stages: import_zod40.z.array(import_zod40.z.object({ position: import_zod40.z.number(), name: import_zod40.z.string() }))
|
|
5798
6021
|
})).optional(),
|
|
5799
|
-
workflows:
|
|
5800
|
-
name:
|
|
5801
|
-
condition:
|
|
5802
|
-
actions:
|
|
6022
|
+
workflows: import_zod40.z.array(import_zod40.z.object({
|
|
6023
|
+
name: import_zod40.z.string(),
|
|
6024
|
+
condition: import_zod40.z.string().optional(),
|
|
6025
|
+
actions: import_zod40.z.array(import_zod40.z.record(import_zod40.z.unknown())).optional().default([])
|
|
5803
6026
|
})).optional(),
|
|
5804
|
-
calendars:
|
|
5805
|
-
name:
|
|
5806
|
-
description:
|
|
6027
|
+
calendars: import_zod40.z.array(import_zod40.z.object({
|
|
6028
|
+
name: import_zod40.z.string(),
|
|
6029
|
+
description: import_zod40.z.string().optional()
|
|
5807
6030
|
})).optional()
|
|
5808
6031
|
});
|
|
5809
6032
|
function registerTemplateDeployerTools(server2, client) {
|
|
@@ -5874,7 +6097,7 @@ function registerTemplateDeployerTools(server2, client) {
|
|
|
5874
6097
|
"get_template_questionnaire",
|
|
5875
6098
|
"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
6099
|
{
|
|
5877
|
-
templateFile:
|
|
6100
|
+
templateFile: import_zod40.z.string().describe("Path to the template JSON file (from list_templates).")
|
|
5878
6101
|
},
|
|
5879
6102
|
async ({ templateFile }) => {
|
|
5880
6103
|
try {
|
|
@@ -5907,10 +6130,10 @@ function registerTemplateDeployerTools(server2, client) {
|
|
|
5907
6130
|
"deploy_template",
|
|
5908
6131
|
"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
6132
|
{
|
|
5910
|
-
templateFile:
|
|
5911
|
-
answers:
|
|
5912
|
-
locationId:
|
|
5913
|
-
dryRun:
|
|
6133
|
+
templateFile: import_zod40.z.string().describe("Path to the template JSON file."),
|
|
6134
|
+
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', ...})."),
|
|
6135
|
+
locationId: import_zod40.z.string().optional().describe("Location ID to deploy to. Uses default if not specified."),
|
|
6136
|
+
dryRun: import_zod40.z.boolean().optional().describe("If true, shows what would be created without actually creating anything. Defaults to false.")
|
|
5914
6137
|
},
|
|
5915
6138
|
async ({ templateFile, answers, locationId: locationId2, dryRun }) => {
|
|
5916
6139
|
try {
|
|
@@ -6156,7 +6379,7 @@ ${errors.join("\n")}` : "\nNo errors!",
|
|
|
6156
6379
|
}
|
|
6157
6380
|
|
|
6158
6381
|
// src/tools/validators.ts
|
|
6159
|
-
var
|
|
6382
|
+
var import_zod41 = require("zod");
|
|
6160
6383
|
function extractFromTrigger(trigger, refs) {
|
|
6161
6384
|
const triggerName = String(trigger.name ?? trigger.type ?? "unnamed trigger");
|
|
6162
6385
|
const where = `trigger "${triggerName}"`;
|
|
@@ -6291,7 +6514,7 @@ function registerValidatorTools(server2, client, builderClient) {
|
|
|
6291
6514
|
"validate_workflow",
|
|
6292
6515
|
"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
6516
|
{
|
|
6294
|
-
workflowId:
|
|
6517
|
+
workflowId: import_zod41.z.string().describe("The workflow ID to validate.")
|
|
6295
6518
|
},
|
|
6296
6519
|
async ({ workflowId }) => {
|
|
6297
6520
|
try {
|
|
@@ -6628,6 +6851,7 @@ var publicApiTools = [
|
|
|
6628
6851
|
[registerFormTools, "forms"],
|
|
6629
6852
|
[registerSurveyTools, "surveys"],
|
|
6630
6853
|
[registerPaymentTools, "payments"],
|
|
6854
|
+
[registerProductTools, "products"],
|
|
6631
6855
|
[registerInvoiceTools, "invoices"],
|
|
6632
6856
|
[registerCampaignTools, "campaigns"],
|
|
6633
6857
|
[registerUserTools, "users"],
|
|
@@ -6667,18 +6891,18 @@ function registerAllTools(server2, client, registry2, mcpVersion) {
|
|
|
6667
6891
|
var fs4 = __toESM(require("fs"));
|
|
6668
6892
|
var path4 = __toESM(require("path"));
|
|
6669
6893
|
var os = __toESM(require("os"));
|
|
6670
|
-
var
|
|
6894
|
+
var import_zod42 = require("zod");
|
|
6671
6895
|
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:
|
|
6896
|
+
var CredentialsSchema = import_zod42.z.object({
|
|
6897
|
+
license_key: import_zod42.z.string().min(1),
|
|
6898
|
+
email: import_zod42.z.string().email(),
|
|
6899
|
+
verified_at: import_zod42.z.string().min(1),
|
|
6900
|
+
ghl_api_key: import_zod42.z.string().min(1),
|
|
6901
|
+
ghl_location_id: import_zod42.z.string().min(1),
|
|
6902
|
+
ghl_company_id: import_zod42.z.string().optional(),
|
|
6903
|
+
ghl_user_id: import_zod42.z.string().optional(),
|
|
6904
|
+
ghl_firebase_api_key: import_zod42.z.string().optional(),
|
|
6905
|
+
ghl_firebase_refresh_token: import_zod42.z.string().optional()
|
|
6682
6906
|
});
|
|
6683
6907
|
function appDataDir() {
|
|
6684
6908
|
const home = os.homedir();
|
|
@@ -6728,7 +6952,7 @@ function writeCredentials(creds) {
|
|
|
6728
6952
|
// src/setup-tool.ts
|
|
6729
6953
|
var os2 = __toESM(require("os"));
|
|
6730
6954
|
var crypto3 = __toESM(require("crypto"));
|
|
6731
|
-
var
|
|
6955
|
+
var import_zod43 = require("zod");
|
|
6732
6956
|
var LICENSE_API = "https://elitedcs.com/api/validate-license";
|
|
6733
6957
|
var GHL_API = "https://services.leadconnectorhq.com";
|
|
6734
6958
|
var FIREBASE_TOKEN_API = "https://securetoken.googleapis.com/v1/token";
|
|
@@ -6797,16 +7021,16 @@ async function validateFirebase(firebaseKey, refreshToken) {
|
|
|
6797
7021
|
function registerSetupTool(server2) {
|
|
6798
7022
|
server2.tool(
|
|
6799
7023
|
"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
|
|
7024
|
+
"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 190 tools (160 if you skip the optional Firebase fields; add Firebase later with enable_workflow_builder).",
|
|
6801
7025
|
{
|
|
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:
|
|
7026
|
+
email: import_zod43.z.string().email().describe("Email used at purchase."),
|
|
7027
|
+
license_key: import_zod43.z.string().min(20).describe("License key from your purchase email."),
|
|
7028
|
+
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."),
|
|
7029
|
+
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."),
|
|
7030
|
+
ghl_company_id: import_zod43.z.string().optional().describe("(Agency only) Company ID for multi-location access."),
|
|
7031
|
+
ghl_user_id: import_zod43.z.string().optional().describe("(Workflow Builder, optional) Firebase User ID. See README for browser capture instructions."),
|
|
7032
|
+
ghl_firebase_api_key: import_zod43.z.string().optional().describe("(Workflow Builder, optional) Firebase API Key starting with 'AIza'."),
|
|
7033
|
+
ghl_firebase_refresh_token: import_zod43.z.string().optional().describe("(Workflow Builder, optional) Firebase refresh token starting with 'AMf-'.")
|
|
6810
7034
|
},
|
|
6811
7035
|
async (args) => {
|
|
6812
7036
|
const lic = await validateLicense(args.email, args.license_key);
|
|
@@ -6852,7 +7076,7 @@ Note: Firebase credentials rejected (${fb.error}). Saved without Workflow Builde
|
|
|
6852
7076
|
ghl_firebase_api_key: workflowBuilderEnabled ? args.ghl_firebase_api_key?.trim() : void 0,
|
|
6853
7077
|
ghl_firebase_refresh_token: workflowBuilderEnabled ? args.ghl_firebase_refresh_token?.trim() : void 0
|
|
6854
7078
|
});
|
|
6855
|
-
const toolCount = workflowBuilderEnabled ? "
|
|
7079
|
+
const toolCount = workflowBuilderEnabled ? "190" : "160";
|
|
6856
7080
|
const wfLine = workflowBuilderEnabled ? "Workflow Builder: enabled." : "Workflow Builder: not configured (optional).";
|
|
6857
7081
|
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
7082
|
return {
|
|
@@ -6880,11 +7104,11 @@ Note: Firebase credentials rejected (${fb.error}). Saved without Workflow Builde
|
|
|
6880
7104
|
function registerEnableWorkflowBuilderTool(server2) {
|
|
6881
7105
|
server2.tool(
|
|
6882
7106
|
"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
|
|
7107
|
+
"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 160 to 190 after the next Claude restart.",
|
|
6884
7108
|
{
|
|
6885
|
-
ghl_user_id:
|
|
6886
|
-
ghl_firebase_api_key:
|
|
6887
|
-
ghl_firebase_refresh_token:
|
|
7109
|
+
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."),
|
|
7110
|
+
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."),
|
|
7111
|
+
ghl_firebase_refresh_token: import_zod43.z.string().min(10).describe("Firebase refresh token. value.stsTokenManager.refreshToken in the firebase:authUser row.")
|
|
6888
7112
|
},
|
|
6889
7113
|
async (args) => {
|
|
6890
7114
|
const existing = readCredentials();
|
|
@@ -6927,7 +7151,7 @@ DevTools steps: https://elitedcs.com/ghl-mcp-firebase`
|
|
|
6927
7151
|
"",
|
|
6928
7152
|
"Firebase credentials verified and saved.",
|
|
6929
7153
|
"",
|
|
6930
|
-
"**Restart Claude (quit fully and reopen) to load the workflow builder + funnel builder + pipeline builder + form builder + workflow cloner tools (
|
|
7154
|
+
"**Restart Claude (quit fully and reopen) to load the workflow builder + funnel builder + pipeline builder + form builder + workflow cloner tools (190 total).**",
|
|
6931
7155
|
"",
|
|
6932
7156
|
'After restart, try: "List my workflows in full detail" or "Validate workflow <id>".',
|
|
6933
7157
|
"",
|