@elitedcs/ghl-mcp 3.8.0 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +96 -0
- package/README.md +4 -4
- package/dist/index.js +612 -441
- package/package.json +6 -3
package/dist/index.js
CHANGED
|
@@ -31,8 +31,8 @@ var require_package = __commonJS({
|
|
|
31
31
|
"package.json"(exports2, module2) {
|
|
32
32
|
module2.exports = {
|
|
33
33
|
name: "@elitedcs/ghl-mcp",
|
|
34
|
-
version: "3.
|
|
35
|
-
description: "GoHighLevel MCP Server for Claude.
|
|
34
|
+
version: "3.9.0",
|
|
35
|
+
description: "GoHighLevel MCP Server for Claude. 187 tools \u2014 full CRM, automation, marketing control, and the only programmatic GHL workflow builder.",
|
|
36
36
|
main: "dist/index.js",
|
|
37
37
|
bin: {
|
|
38
38
|
"ghl-mcp": "dist/index.js"
|
|
@@ -50,6 +50,8 @@ var require_package = __commonJS({
|
|
|
50
50
|
setup: "node setup-wizard.mjs",
|
|
51
51
|
start: "node dist/index.js",
|
|
52
52
|
dev: "tsc --watch",
|
|
53
|
+
test: "vitest run",
|
|
54
|
+
"test:watch": "vitest",
|
|
53
55
|
prepublishOnly: "npm run build"
|
|
54
56
|
},
|
|
55
57
|
keywords: [
|
|
@@ -87,7 +89,8 @@ var require_package = __commonJS({
|
|
|
87
89
|
"@types/node": "^22.15.3",
|
|
88
90
|
esbuild: "^0.27.4",
|
|
89
91
|
open: "^11.0.0",
|
|
90
|
-
typescript: "^5.8.3"
|
|
92
|
+
typescript: "^5.8.3",
|
|
93
|
+
vitest: "^4.1.6"
|
|
91
94
|
}
|
|
92
95
|
};
|
|
93
96
|
}
|
|
@@ -2846,22 +2849,138 @@ function registerPaymentTools(server2, client) {
|
|
|
2846
2849
|
);
|
|
2847
2850
|
}
|
|
2848
2851
|
|
|
2849
|
-
// src/tools/
|
|
2852
|
+
// src/tools/products.ts
|
|
2850
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");
|
|
2851
2970
|
function registerInvoiceTools(server2, client) {
|
|
2852
2971
|
safeTool(
|
|
2853
2972
|
server2,
|
|
2854
2973
|
"list_invoices",
|
|
2855
2974
|
"List invoices for a location. Offset-based pagination via limit/offset.",
|
|
2856
2975
|
{
|
|
2857
|
-
locationId:
|
|
2858
|
-
limit:
|
|
2859
|
-
offset:
|
|
2860
|
-
status:
|
|
2861
|
-
contactId:
|
|
2862
|
-
startAt:
|
|
2863
|
-
endAt:
|
|
2864
|
-
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")
|
|
2865
2984
|
},
|
|
2866
2985
|
async ({ locationId: locationId2, limit, offset, status, contactId, startAt, endAt, search }) => {
|
|
2867
2986
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -2885,8 +3004,8 @@ function registerInvoiceTools(server2, client) {
|
|
|
2885
3004
|
"get_invoice",
|
|
2886
3005
|
"Get a specific invoice by ID",
|
|
2887
3006
|
{
|
|
2888
|
-
locationId:
|
|
2889
|
-
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")
|
|
2890
3009
|
},
|
|
2891
3010
|
async ({ locationId: locationId2, invoiceId }) => {
|
|
2892
3011
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -2902,22 +3021,22 @@ function registerInvoiceTools(server2, client) {
|
|
|
2902
3021
|
"create_invoice",
|
|
2903
3022
|
"Create a new invoice",
|
|
2904
3023
|
{
|
|
2905
|
-
locationId:
|
|
2906
|
-
name:
|
|
2907
|
-
contactId:
|
|
2908
|
-
items:
|
|
2909
|
-
name:
|
|
2910
|
-
description:
|
|
2911
|
-
quantity:
|
|
2912
|
-
price:
|
|
2913
|
-
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)")
|
|
2914
3033
|
})).describe("Invoice line items"),
|
|
2915
|
-
discount:
|
|
2916
|
-
type:
|
|
2917
|
-
value:
|
|
3034
|
+
discount: import_zod16.z.object({
|
|
3035
|
+
type: import_zod16.z.string().optional(),
|
|
3036
|
+
value: import_zod16.z.number().optional()
|
|
2918
3037
|
}).optional().describe("Discount to apply"),
|
|
2919
|
-
termsNotes:
|
|
2920
|
-
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")
|
|
2921
3040
|
},
|
|
2922
3041
|
async ({ locationId: locationId2, name, contactId, items, discount, termsNotes, title }) => {
|
|
2923
3042
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -2939,22 +3058,22 @@ function registerInvoiceTools(server2, client) {
|
|
|
2939
3058
|
"update_invoice",
|
|
2940
3059
|
"Update an existing invoice",
|
|
2941
3060
|
{
|
|
2942
|
-
locationId:
|
|
2943
|
-
invoiceId:
|
|
2944
|
-
name:
|
|
2945
|
-
items:
|
|
2946
|
-
name:
|
|
2947
|
-
description:
|
|
2948
|
-
quantity:
|
|
2949
|
-
price:
|
|
2950
|
-
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)")
|
|
2951
3070
|
})).optional().describe("Invoice line items"),
|
|
2952
|
-
discount:
|
|
2953
|
-
type:
|
|
2954
|
-
value:
|
|
3071
|
+
discount: import_zod16.z.object({
|
|
3072
|
+
type: import_zod16.z.string().optional(),
|
|
3073
|
+
value: import_zod16.z.number().optional()
|
|
2955
3074
|
}).optional().describe("Discount to apply"),
|
|
2956
|
-
termsNotes:
|
|
2957
|
-
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")
|
|
2958
3077
|
},
|
|
2959
3078
|
async ({ locationId: locationId2, invoiceId, name, items, discount, termsNotes, title }) => {
|
|
2960
3079
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -2975,8 +3094,8 @@ function registerInvoiceTools(server2, client) {
|
|
|
2975
3094
|
"delete_invoice",
|
|
2976
3095
|
"Delete an invoice",
|
|
2977
3096
|
{
|
|
2978
|
-
locationId:
|
|
2979
|
-
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")
|
|
2980
3099
|
},
|
|
2981
3100
|
async ({ locationId: locationId2, invoiceId }) => {
|
|
2982
3101
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -2992,8 +3111,8 @@ function registerInvoiceTools(server2, client) {
|
|
|
2992
3111
|
"send_invoice",
|
|
2993
3112
|
"Send an invoice to the contact",
|
|
2994
3113
|
{
|
|
2995
|
-
locationId:
|
|
2996
|
-
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")
|
|
2997
3116
|
},
|
|
2998
3117
|
async ({ locationId: locationId2, invoiceId }) => {
|
|
2999
3118
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3009,8 +3128,8 @@ function registerInvoiceTools(server2, client) {
|
|
|
3009
3128
|
"void_invoice",
|
|
3010
3129
|
"Void an invoice",
|
|
3011
3130
|
{
|
|
3012
|
-
locationId:
|
|
3013
|
-
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")
|
|
3014
3133
|
},
|
|
3015
3134
|
async ({ locationId: locationId2, invoiceId }) => {
|
|
3016
3135
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3026,11 +3145,11 @@ function registerInvoiceTools(server2, client) {
|
|
|
3026
3145
|
"record_invoice_payment",
|
|
3027
3146
|
"Record a manual payment for an invoice",
|
|
3028
3147
|
{
|
|
3029
|
-
locationId:
|
|
3030
|
-
invoiceId:
|
|
3031
|
-
amount:
|
|
3032
|
-
mode:
|
|
3033
|
-
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")
|
|
3034
3153
|
},
|
|
3035
3154
|
async ({ locationId: locationId2, invoiceId, amount, mode, notes }) => {
|
|
3036
3155
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3047,15 +3166,15 @@ function registerInvoiceTools(server2, client) {
|
|
|
3047
3166
|
}
|
|
3048
3167
|
|
|
3049
3168
|
// src/tools/campaigns.ts
|
|
3050
|
-
var
|
|
3169
|
+
var import_zod17 = require("zod");
|
|
3051
3170
|
function registerCampaignTools(server2, client) {
|
|
3052
3171
|
safeTool(
|
|
3053
3172
|
server2,
|
|
3054
3173
|
"get_campaigns",
|
|
3055
3174
|
"List campaigns for a location",
|
|
3056
3175
|
{
|
|
3057
|
-
locationId:
|
|
3058
|
-
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")
|
|
3059
3178
|
},
|
|
3060
3179
|
async ({ locationId: locationId2, status }) => {
|
|
3061
3180
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3067,16 +3186,16 @@ function registerCampaignTools(server2, client) {
|
|
|
3067
3186
|
}
|
|
3068
3187
|
|
|
3069
3188
|
// src/tools/users.ts
|
|
3070
|
-
var
|
|
3189
|
+
var import_zod18 = require("zod");
|
|
3071
3190
|
function registerUserTools(server2, client) {
|
|
3072
3191
|
safeTool(
|
|
3073
3192
|
server2,
|
|
3074
3193
|
"get_users",
|
|
3075
3194
|
"List users for a location",
|
|
3076
3195
|
{
|
|
3077
|
-
locationId:
|
|
3078
|
-
limit:
|
|
3079
|
-
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")
|
|
3080
3199
|
},
|
|
3081
3200
|
async ({ locationId: locationId2, limit, skip }) => {
|
|
3082
3201
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3091,7 +3210,7 @@ function registerUserTools(server2, client) {
|
|
|
3091
3210
|
"get_user",
|
|
3092
3211
|
"Get a single user by ID",
|
|
3093
3212
|
{
|
|
3094
|
-
userId:
|
|
3213
|
+
userId: import_zod18.z.string().describe("The user ID")
|
|
3095
3214
|
},
|
|
3096
3215
|
async ({ userId }) => {
|
|
3097
3216
|
return client.get(`/users/${userId}`);
|
|
@@ -3100,19 +3219,19 @@ function registerUserTools(server2, client) {
|
|
|
3100
3219
|
}
|
|
3101
3220
|
|
|
3102
3221
|
// src/tools/media.ts
|
|
3103
|
-
var
|
|
3222
|
+
var import_zod19 = require("zod");
|
|
3104
3223
|
function registerMediaTools(server2, client) {
|
|
3105
3224
|
safeTool(
|
|
3106
3225
|
server2,
|
|
3107
3226
|
"get_media_files",
|
|
3108
3227
|
"List media files for a location",
|
|
3109
3228
|
{
|
|
3110
|
-
locationId:
|
|
3111
|
-
sortBy:
|
|
3112
|
-
sortOrder:
|
|
3113
|
-
limit:
|
|
3114
|
-
offset:
|
|
3115
|
-
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")
|
|
3116
3235
|
},
|
|
3117
3236
|
async ({ locationId: locationId2, sortBy, sortOrder, limit, offset, query }) => {
|
|
3118
3237
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3130,8 +3249,8 @@ function registerMediaTools(server2, client) {
|
|
|
3130
3249
|
"delete_media_file",
|
|
3131
3250
|
"Delete a media file",
|
|
3132
3251
|
{
|
|
3133
|
-
mediaId:
|
|
3134
|
-
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)")
|
|
3135
3254
|
},
|
|
3136
3255
|
async ({ mediaId, locationId: locationId2 }) => {
|
|
3137
3256
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3143,20 +3262,20 @@ function registerMediaTools(server2, client) {
|
|
|
3143
3262
|
}
|
|
3144
3263
|
|
|
3145
3264
|
// src/tools/social-planner.ts
|
|
3146
|
-
var
|
|
3265
|
+
var import_zod20 = require("zod");
|
|
3147
3266
|
function registerSocialPlannerTools(server2, client) {
|
|
3148
3267
|
safeTool(
|
|
3149
3268
|
server2,
|
|
3150
3269
|
"get_social_posts",
|
|
3151
3270
|
"List social media posts for a location",
|
|
3152
3271
|
{
|
|
3153
|
-
locationId:
|
|
3154
|
-
type:
|
|
3155
|
-
accounts:
|
|
3156
|
-
fromDate:
|
|
3157
|
-
toDate:
|
|
3158
|
-
includeUsers:
|
|
3159
|
-
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")
|
|
3160
3279
|
},
|
|
3161
3280
|
async ({ locationId: locationId2, type, accounts, fromDate, toDate, includeUsers, status }) => {
|
|
3162
3281
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3175,7 +3294,7 @@ function registerSocialPlannerTools(server2, client) {
|
|
|
3175
3294
|
"get_social_post",
|
|
3176
3295
|
"Get a single social media post by ID",
|
|
3177
3296
|
{
|
|
3178
|
-
postId:
|
|
3297
|
+
postId: import_zod20.z.string().describe("The social media post ID")
|
|
3179
3298
|
},
|
|
3180
3299
|
async ({ postId }) => {
|
|
3181
3300
|
return client.get(`/social-media-posting/${postId}`);
|
|
@@ -3186,7 +3305,7 @@ function registerSocialPlannerTools(server2, client) {
|
|
|
3186
3305
|
"delete_social_post",
|
|
3187
3306
|
"Delete a social media post",
|
|
3188
3307
|
{
|
|
3189
|
-
postId:
|
|
3308
|
+
postId: import_zod20.z.string().describe("The social media post ID to delete")
|
|
3190
3309
|
},
|
|
3191
3310
|
async ({ postId }) => {
|
|
3192
3311
|
return client.delete(`/social-media-posting/${postId}`);
|
|
@@ -3196,7 +3315,7 @@ function registerSocialPlannerTools(server2, client) {
|
|
|
3196
3315
|
"get_social_media_accounts",
|
|
3197
3316
|
"Get connected social media accounts for a location",
|
|
3198
3317
|
{
|
|
3199
|
-
locationId:
|
|
3318
|
+
locationId: import_zod20.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
|
|
3200
3319
|
},
|
|
3201
3320
|
async ({ locationId: locationId2 }) => {
|
|
3202
3321
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3222,17 +3341,17 @@ function registerSocialPlannerTools(server2, client) {
|
|
|
3222
3341
|
"create_social_post",
|
|
3223
3342
|
"Create a new social media post",
|
|
3224
3343
|
{
|
|
3225
|
-
locationId:
|
|
3226
|
-
accountIds:
|
|
3227
|
-
summary:
|
|
3228
|
-
media:
|
|
3229
|
-
status:
|
|
3230
|
-
scheduledAt:
|
|
3231
|
-
tags:
|
|
3232
|
-
ogData:
|
|
3233
|
-
title:
|
|
3234
|
-
description:
|
|
3235
|
-
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()
|
|
3236
3355
|
}).optional().describe("Open Graph data for link previews")
|
|
3237
3356
|
},
|
|
3238
3357
|
async ({ locationId: locationId2, accountIds, summary, media, status, scheduledAt, tags, ogData }) => {
|
|
@@ -3250,16 +3369,16 @@ function registerSocialPlannerTools(server2, client) {
|
|
|
3250
3369
|
}
|
|
3251
3370
|
|
|
3252
3371
|
// src/tools/courses.ts
|
|
3253
|
-
var
|
|
3372
|
+
var import_zod21 = require("zod");
|
|
3254
3373
|
function registerCourseTools(server2, client) {
|
|
3255
3374
|
safeTool(
|
|
3256
3375
|
server2,
|
|
3257
3376
|
"get_courses",
|
|
3258
3377
|
"List courses for a location",
|
|
3259
3378
|
{
|
|
3260
|
-
locationId:
|
|
3261
|
-
limit:
|
|
3262
|
-
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")
|
|
3263
3382
|
},
|
|
3264
3383
|
async ({ locationId: locationId2, limit, offset }) => {
|
|
3265
3384
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3272,14 +3391,14 @@ function registerCourseTools(server2, client) {
|
|
|
3272
3391
|
}
|
|
3273
3392
|
|
|
3274
3393
|
// src/tools/businesses.ts
|
|
3275
|
-
var
|
|
3394
|
+
var import_zod22 = require("zod");
|
|
3276
3395
|
function registerBusinessTools(server2, client) {
|
|
3277
3396
|
safeTool(
|
|
3278
3397
|
server2,
|
|
3279
3398
|
"get_businesses",
|
|
3280
3399
|
"List businesses for a location",
|
|
3281
3400
|
{
|
|
3282
|
-
locationId:
|
|
3401
|
+
locationId: import_zod22.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
|
|
3283
3402
|
},
|
|
3284
3403
|
async ({ locationId: locationId2 }) => {
|
|
3285
3404
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3291,7 +3410,7 @@ function registerBusinessTools(server2, client) {
|
|
|
3291
3410
|
"get_business",
|
|
3292
3411
|
"Get a single business by ID",
|
|
3293
3412
|
{
|
|
3294
|
-
businessId:
|
|
3413
|
+
businessId: import_zod22.z.string().describe("The business ID")
|
|
3295
3414
|
},
|
|
3296
3415
|
async ({ businessId }) => {
|
|
3297
3416
|
return client.get(`/businesses/${businessId}`);
|
|
@@ -3302,17 +3421,17 @@ function registerBusinessTools(server2, client) {
|
|
|
3302
3421
|
"create_business",
|
|
3303
3422
|
"Create a new business",
|
|
3304
3423
|
{
|
|
3305
|
-
locationId:
|
|
3306
|
-
name:
|
|
3307
|
-
phone:
|
|
3308
|
-
email:
|
|
3309
|
-
website:
|
|
3310
|
-
address:
|
|
3311
|
-
city:
|
|
3312
|
-
state:
|
|
3313
|
-
postalCode:
|
|
3314
|
-
country:
|
|
3315
|
-
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")
|
|
3316
3435
|
},
|
|
3317
3436
|
async ({ locationId: locationId2, name, phone, email, website, address, city, state, postalCode, country, description }) => {
|
|
3318
3437
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3334,17 +3453,17 @@ function registerBusinessTools(server2, client) {
|
|
|
3334
3453
|
"update_business",
|
|
3335
3454
|
"Update an existing business",
|
|
3336
3455
|
{
|
|
3337
|
-
businessId:
|
|
3338
|
-
name:
|
|
3339
|
-
phone:
|
|
3340
|
-
email:
|
|
3341
|
-
website:
|
|
3342
|
-
address:
|
|
3343
|
-
city:
|
|
3344
|
-
state:
|
|
3345
|
-
postalCode:
|
|
3346
|
-
country:
|
|
3347
|
-
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")
|
|
3348
3467
|
},
|
|
3349
3468
|
async ({ businessId, name, phone, email, website, address, city, state, postalCode, country, description }) => {
|
|
3350
3469
|
const body = {};
|
|
@@ -3366,8 +3485,8 @@ function registerBusinessTools(server2, client) {
|
|
|
3366
3485
|
"delete_business",
|
|
3367
3486
|
"Permanently delete a business. IRREVERSIBLE.",
|
|
3368
3487
|
{
|
|
3369
|
-
businessId:
|
|
3370
|
-
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.")
|
|
3371
3490
|
},
|
|
3372
3491
|
async ({ businessId }) => {
|
|
3373
3492
|
return client.delete(`/businesses/${businessId}`);
|
|
@@ -3376,17 +3495,17 @@ function registerBusinessTools(server2, client) {
|
|
|
3376
3495
|
}
|
|
3377
3496
|
|
|
3378
3497
|
// src/tools/blogs.ts
|
|
3379
|
-
var
|
|
3498
|
+
var import_zod23 = require("zod");
|
|
3380
3499
|
function registerBlogTools(server2, client) {
|
|
3381
3500
|
safeTool(
|
|
3382
3501
|
server2,
|
|
3383
3502
|
"get_blog_posts",
|
|
3384
3503
|
"List blog posts for a location. Offset-based pagination via limit/offset.",
|
|
3385
3504
|
{
|
|
3386
|
-
locationId:
|
|
3387
|
-
limit:
|
|
3388
|
-
offset:
|
|
3389
|
-
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")
|
|
3390
3509
|
},
|
|
3391
3510
|
async ({ locationId: locationId2, limit, offset, status }) => {
|
|
3392
3511
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3404,8 +3523,8 @@ function registerBlogTools(server2, client) {
|
|
|
3404
3523
|
"get_blog_post",
|
|
3405
3524
|
"Get a specific blog post by ID",
|
|
3406
3525
|
{
|
|
3407
|
-
blogId:
|
|
3408
|
-
postId:
|
|
3526
|
+
blogId: import_zod23.z.string().describe("Blog ID"),
|
|
3527
|
+
postId: import_zod23.z.string().describe("Post ID")
|
|
3409
3528
|
},
|
|
3410
3529
|
async ({ blogId, postId }) => {
|
|
3411
3530
|
return client.get(`/blogs/${blogId}/posts/${postId}`, {});
|
|
@@ -3416,7 +3535,7 @@ function registerBlogTools(server2, client) {
|
|
|
3416
3535
|
"get_blog_authors",
|
|
3417
3536
|
"List blog authors for a location",
|
|
3418
3537
|
{
|
|
3419
|
-
locationId:
|
|
3538
|
+
locationId: import_zod23.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
|
|
3420
3539
|
},
|
|
3421
3540
|
async ({ locationId: locationId2 }) => {
|
|
3422
3541
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3430,7 +3549,7 @@ function registerBlogTools(server2, client) {
|
|
|
3430
3549
|
"get_blog_categories",
|
|
3431
3550
|
"List blog categories for a location",
|
|
3432
3551
|
{
|
|
3433
|
-
locationId:
|
|
3552
|
+
locationId: import_zod23.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
|
|
3434
3553
|
},
|
|
3435
3554
|
async ({ locationId: locationId2 }) => {
|
|
3436
3555
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3444,8 +3563,8 @@ function registerBlogTools(server2, client) {
|
|
|
3444
3563
|
"check_blog_slug",
|
|
3445
3564
|
"Check if a blog post URL slug already exists",
|
|
3446
3565
|
{
|
|
3447
|
-
locationId:
|
|
3448
|
-
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")
|
|
3449
3568
|
},
|
|
3450
3569
|
async ({ locationId: locationId2, urlSlug }) => {
|
|
3451
3570
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3457,14 +3576,14 @@ function registerBlogTools(server2, client) {
|
|
|
3457
3576
|
}
|
|
3458
3577
|
|
|
3459
3578
|
// src/tools/emails.ts
|
|
3460
|
-
var
|
|
3579
|
+
var import_zod24 = require("zod");
|
|
3461
3580
|
function registerEmailTools(server2, client) {
|
|
3462
3581
|
safeTool(
|
|
3463
3582
|
server2,
|
|
3464
3583
|
"get_email_campaigns",
|
|
3465
3584
|
"List email campaigns for a location",
|
|
3466
3585
|
{
|
|
3467
|
-
locationId:
|
|
3586
|
+
locationId: import_zod24.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
|
|
3468
3587
|
},
|
|
3469
3588
|
async ({ locationId: locationId2 }) => {
|
|
3470
3589
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3476,14 +3595,14 @@ function registerEmailTools(server2, client) {
|
|
|
3476
3595
|
}
|
|
3477
3596
|
|
|
3478
3597
|
// src/tools/trigger-links.ts
|
|
3479
|
-
var
|
|
3598
|
+
var import_zod25 = require("zod");
|
|
3480
3599
|
function registerTriggerLinkTools(server2, client) {
|
|
3481
3600
|
safeTool(
|
|
3482
3601
|
server2,
|
|
3483
3602
|
"get_trigger_links",
|
|
3484
|
-
"List trigger links for a location",
|
|
3603
|
+
"List trigger links (short tracked URLs) for a location.",
|
|
3485
3604
|
{
|
|
3486
|
-
locationId:
|
|
3605
|
+
locationId: import_zod25.z.string().optional().describe("GHL Location ID (optional if GHL_LOCATION_ID is set)")
|
|
3487
3606
|
},
|
|
3488
3607
|
async ({ locationId: locationId2 }) => {
|
|
3489
3608
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3492,17 +3611,68 @@ function registerTriggerLinkTools(server2, client) {
|
|
|
3492
3611
|
});
|
|
3493
3612
|
}
|
|
3494
3613
|
);
|
|
3614
|
+
safeTool(
|
|
3615
|
+
server2,
|
|
3616
|
+
"create_trigger_link",
|
|
3617
|
+
"Create a new trigger link. The link's shortened URL + auto-generated tracking key are returned in the response. Use the link in emails, SMS, social posts, etc.; when contacts click it, GHL fires the workflow trigger type `trigger_link` for any workflow that filters on this link's id.",
|
|
3618
|
+
{
|
|
3619
|
+
name: import_zod25.z.string().describe("Display name in the GHL UI (e.g., 'May Newsletter \u2014 CTA'). Not visible to recipients."),
|
|
3620
|
+
redirectTo: import_zod25.z.string().describe("Destination URL the link should redirect to. Either a static URL (https://example.com) or a contact merge field (e.g., '{{contact.website}}')."),
|
|
3621
|
+
locationId: import_zod25.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
|
|
3622
|
+
},
|
|
3623
|
+
async ({ name, redirectTo, locationId: locationId2 }) => {
|
|
3624
|
+
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
3625
|
+
return client.post("/links/", {
|
|
3626
|
+
body: { locationId: resolvedLocationId, name, redirectTo }
|
|
3627
|
+
});
|
|
3628
|
+
}
|
|
3629
|
+
);
|
|
3630
|
+
safeTool(
|
|
3631
|
+
server2,
|
|
3632
|
+
"update_trigger_link",
|
|
3633
|
+
"Update an existing trigger link's display name or redirect destination. The link's tracking key + short URL stay the same \u2014 buyers who already clicked the link still count, and any workflow filtering on this link's id keeps working.",
|
|
3634
|
+
{
|
|
3635
|
+
linkId: import_zod25.z.string().describe("The trigger link ID to update."),
|
|
3636
|
+
name: import_zod25.z.string().optional().describe("New display name. Pass to change; omit to keep current."),
|
|
3637
|
+
redirectTo: import_zod25.z.string().optional().describe("New destination URL. Pass to change; omit to keep current.")
|
|
3638
|
+
},
|
|
3639
|
+
async ({ linkId, name, redirectTo }) => {
|
|
3640
|
+
const body = {};
|
|
3641
|
+
if (name !== void 0) body.name = name;
|
|
3642
|
+
if (redirectTo !== void 0) body.redirectTo = redirectTo;
|
|
3643
|
+
if (Object.keys(body).length === 0) {
|
|
3644
|
+
throw new Error("Pass at least one of: name, redirectTo. Nothing to update.");
|
|
3645
|
+
}
|
|
3646
|
+
return client.put(`/links/${linkId}`, { body });
|
|
3647
|
+
}
|
|
3648
|
+
);
|
|
3649
|
+
safeTool(
|
|
3650
|
+
server2,
|
|
3651
|
+
"delete_trigger_link",
|
|
3652
|
+
"Permanently delete a trigger link. IRREVERSIBLE. The link's short URL stops working immediately \u2014 anyone who clicks it after deletion lands on a 404. Any workflow triggers that filter on this link's id will never fire again.",
|
|
3653
|
+
{
|
|
3654
|
+
linkId: import_zod25.z.string().describe("The trigger link ID to delete."),
|
|
3655
|
+
confirm: import_zod25.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action."),
|
|
3656
|
+
locationId: import_zod25.z.string().optional().describe("Location ID. Falls back to GHL_LOCATION_ID env var.")
|
|
3657
|
+
},
|
|
3658
|
+
async ({ linkId, locationId: locationId2 }) => {
|
|
3659
|
+
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
3660
|
+
return client.delete(`/links/${linkId}`, {
|
|
3661
|
+
params: { locationId: resolvedLocationId }
|
|
3662
|
+
});
|
|
3663
|
+
}
|
|
3664
|
+
);
|
|
3495
3665
|
}
|
|
3496
3666
|
|
|
3497
3667
|
// src/tools/custom-objects.ts
|
|
3498
|
-
var
|
|
3668
|
+
var import_zod26 = require("zod");
|
|
3499
3669
|
function registerCustomObjectTools(server2, client) {
|
|
3500
3670
|
safeTool(
|
|
3501
3671
|
server2,
|
|
3502
3672
|
"list_custom_objects",
|
|
3503
3673
|
"List all custom object schemas defined in a GHL location.",
|
|
3504
3674
|
{
|
|
3505
|
-
locationId:
|
|
3675
|
+
locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3506
3676
|
},
|
|
3507
3677
|
async ({ locationId: locationId2 }) => {
|
|
3508
3678
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3516,8 +3686,8 @@ function registerCustomObjectTools(server2, client) {
|
|
|
3516
3686
|
"get_custom_object",
|
|
3517
3687
|
"Retrieve a single custom object schema by its key.",
|
|
3518
3688
|
{
|
|
3519
|
-
schemaKey:
|
|
3520
|
-
locationId:
|
|
3689
|
+
schemaKey: import_zod26.z.string().describe("The key of the custom object schema to retrieve."),
|
|
3690
|
+
locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3521
3691
|
},
|
|
3522
3692
|
async ({ schemaKey, locationId: locationId2 }) => {
|
|
3523
3693
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3531,11 +3701,11 @@ function registerCustomObjectTools(server2, client) {
|
|
|
3531
3701
|
"search_custom_object_records",
|
|
3532
3702
|
"Search records of a custom object by schema key. Supports filtering and pagination.",
|
|
3533
3703
|
{
|
|
3534
|
-
schemaKey:
|
|
3535
|
-
locationId:
|
|
3536
|
-
query:
|
|
3537
|
-
limit:
|
|
3538
|
-
offset:
|
|
3704
|
+
schemaKey: import_zod26.z.string().describe("The custom object schema key."),
|
|
3705
|
+
locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
3706
|
+
query: import_zod26.z.string().optional().describe("Search query to filter records."),
|
|
3707
|
+
limit: import_zod26.z.number().optional().describe("Maximum records to return. Defaults to 20."),
|
|
3708
|
+
offset: import_zod26.z.number().optional().describe("Number of records to skip for pagination.")
|
|
3539
3709
|
},
|
|
3540
3710
|
async ({ schemaKey, locationId: locationId2, query, limit, offset }) => {
|
|
3541
3711
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3554,9 +3724,9 @@ function registerCustomObjectTools(server2, client) {
|
|
|
3554
3724
|
"get_custom_object_record",
|
|
3555
3725
|
"Retrieve a single custom object record by schema key and record ID.",
|
|
3556
3726
|
{
|
|
3557
|
-
schemaKey:
|
|
3558
|
-
recordId:
|
|
3559
|
-
locationId:
|
|
3727
|
+
schemaKey: import_zod26.z.string().describe("The custom object schema key."),
|
|
3728
|
+
recordId: import_zod26.z.string().describe("The record ID to retrieve."),
|
|
3729
|
+
locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3560
3730
|
},
|
|
3561
3731
|
async ({ schemaKey, recordId, locationId: locationId2 }) => {
|
|
3562
3732
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3570,9 +3740,9 @@ function registerCustomObjectTools(server2, client) {
|
|
|
3570
3740
|
"create_custom_object_record",
|
|
3571
3741
|
"Create a new record for a custom object.",
|
|
3572
3742
|
{
|
|
3573
|
-
schemaKey:
|
|
3574
|
-
locationId:
|
|
3575
|
-
properties:
|
|
3743
|
+
schemaKey: import_zod26.z.string().describe("The custom object schema key."),
|
|
3744
|
+
locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
3745
|
+
properties: import_zod26.z.record(import_zod26.z.unknown()).describe("Key-value pairs of field values for the new record.")
|
|
3576
3746
|
},
|
|
3577
3747
|
async ({ schemaKey, locationId: locationId2, properties }) => {
|
|
3578
3748
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3586,10 +3756,10 @@ function registerCustomObjectTools(server2, client) {
|
|
|
3586
3756
|
"update_custom_object_record",
|
|
3587
3757
|
"Update an existing custom object record.",
|
|
3588
3758
|
{
|
|
3589
|
-
schemaKey:
|
|
3590
|
-
recordId:
|
|
3591
|
-
locationId:
|
|
3592
|
-
properties:
|
|
3759
|
+
schemaKey: import_zod26.z.string().describe("The custom object schema key."),
|
|
3760
|
+
recordId: import_zod26.z.string().describe("The record ID to update."),
|
|
3761
|
+
locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
3762
|
+
properties: import_zod26.z.record(import_zod26.z.unknown()).describe("Key-value pairs of field values to update.")
|
|
3593
3763
|
},
|
|
3594
3764
|
async ({ schemaKey, recordId, locationId: locationId2, properties }) => {
|
|
3595
3765
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3603,9 +3773,9 @@ function registerCustomObjectTools(server2, client) {
|
|
|
3603
3773
|
"delete_custom_object_record",
|
|
3604
3774
|
"Delete a custom object record by schema key and record ID.",
|
|
3605
3775
|
{
|
|
3606
|
-
schemaKey:
|
|
3607
|
-
recordId:
|
|
3608
|
-
locationId:
|
|
3776
|
+
schemaKey: import_zod26.z.string().describe("The custom object schema key."),
|
|
3777
|
+
recordId: import_zod26.z.string().describe("The record ID to delete."),
|
|
3778
|
+
locationId: import_zod26.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3609
3779
|
},
|
|
3610
3780
|
async ({ schemaKey, recordId, locationId: locationId2 }) => {
|
|
3611
3781
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3617,16 +3787,16 @@ function registerCustomObjectTools(server2, client) {
|
|
|
3617
3787
|
}
|
|
3618
3788
|
|
|
3619
3789
|
// src/tools/associations.ts
|
|
3620
|
-
var
|
|
3790
|
+
var import_zod27 = require("zod");
|
|
3621
3791
|
function registerAssociationTools(server2, client) {
|
|
3622
3792
|
safeTool(
|
|
3623
3793
|
server2,
|
|
3624
3794
|
"list_associations",
|
|
3625
3795
|
"List associations for a custom object record \u2014 shows related contacts, opportunities, or other records.",
|
|
3626
3796
|
{
|
|
3627
|
-
schemaKey:
|
|
3628
|
-
recordId:
|
|
3629
|
-
locationId:
|
|
3797
|
+
schemaKey: import_zod27.z.string().describe("The custom object schema key."),
|
|
3798
|
+
recordId: import_zod27.z.string().describe("The record ID to list associations for."),
|
|
3799
|
+
locationId: import_zod27.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3630
3800
|
},
|
|
3631
3801
|
async ({ schemaKey, recordId, locationId: locationId2 }) => {
|
|
3632
3802
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3641,11 +3811,11 @@ function registerAssociationTools(server2, client) {
|
|
|
3641
3811
|
"create_association",
|
|
3642
3812
|
"Create an association between a custom object record and another entity (contact, opportunity, or another custom object record).",
|
|
3643
3813
|
{
|
|
3644
|
-
schemaKey:
|
|
3645
|
-
recordId:
|
|
3646
|
-
locationId:
|
|
3647
|
-
targetEntityType:
|
|
3648
|
-
targetEntityId:
|
|
3814
|
+
schemaKey: import_zod27.z.string().describe("The custom object schema key of the source record."),
|
|
3815
|
+
recordId: import_zod27.z.string().describe("The source record ID."),
|
|
3816
|
+
locationId: import_zod27.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
3817
|
+
targetEntityType: import_zod27.z.string().describe("The target entity type (e.g. 'contact', 'opportunity', or a custom object schema key)."),
|
|
3818
|
+
targetEntityId: import_zod27.z.string().describe("The ID of the target entity to associate with.")
|
|
3649
3819
|
},
|
|
3650
3820
|
async ({ schemaKey, recordId, locationId: locationId2, targetEntityType, targetEntityId }) => {
|
|
3651
3821
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3666,10 +3836,10 @@ function registerAssociationTools(server2, client) {
|
|
|
3666
3836
|
"delete_association",
|
|
3667
3837
|
"Remove an association between a custom object record and another entity.",
|
|
3668
3838
|
{
|
|
3669
|
-
schemaKey:
|
|
3670
|
-
recordId:
|
|
3671
|
-
associationId:
|
|
3672
|
-
locationId:
|
|
3839
|
+
schemaKey: import_zod27.z.string().describe("The custom object schema key of the source record."),
|
|
3840
|
+
recordId: import_zod27.z.string().describe("The source record ID."),
|
|
3841
|
+
associationId: import_zod27.z.string().describe("The association ID to remove."),
|
|
3842
|
+
locationId: import_zod27.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3673
3843
|
},
|
|
3674
3844
|
async ({ schemaKey, recordId, associationId, locationId: locationId2 }) => {
|
|
3675
3845
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3682,18 +3852,18 @@ function registerAssociationTools(server2, client) {
|
|
|
3682
3852
|
}
|
|
3683
3853
|
|
|
3684
3854
|
// src/tools/estimates.ts
|
|
3685
|
-
var
|
|
3855
|
+
var import_zod28 = require("zod");
|
|
3686
3856
|
function registerEstimateTools(server2, client) {
|
|
3687
3857
|
safeTool(
|
|
3688
3858
|
server2,
|
|
3689
3859
|
"list_estimates",
|
|
3690
3860
|
"List estimates/quotes in a GHL location. Supports pagination and filtering by status.",
|
|
3691
3861
|
{
|
|
3692
|
-
locationId:
|
|
3693
|
-
status:
|
|
3694
|
-
limit:
|
|
3695
|
-
offset:
|
|
3696
|
-
contactId:
|
|
3862
|
+
locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
3863
|
+
status: import_zod28.z.string().optional().describe("Filter by status (e.g. 'draft', 'sent', 'accepted', 'declined')."),
|
|
3864
|
+
limit: import_zod28.z.number().optional().describe("Maximum estimates to return. Defaults to 20."),
|
|
3865
|
+
offset: import_zod28.z.number().optional().describe("Number of records to skip for pagination."),
|
|
3866
|
+
contactId: import_zod28.z.string().optional().describe("Filter estimates by contact ID.")
|
|
3697
3867
|
},
|
|
3698
3868
|
async ({ locationId: locationId2, status, limit, offset, contactId }) => {
|
|
3699
3869
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3714,8 +3884,8 @@ function registerEstimateTools(server2, client) {
|
|
|
3714
3884
|
"get_estimate",
|
|
3715
3885
|
"Retrieve a single estimate/quote by its ID.",
|
|
3716
3886
|
{
|
|
3717
|
-
estimateId:
|
|
3718
|
-
locationId:
|
|
3887
|
+
estimateId: import_zod28.z.string().describe("The estimate ID to retrieve."),
|
|
3888
|
+
locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3719
3889
|
},
|
|
3720
3890
|
async ({ estimateId, locationId: locationId2 }) => {
|
|
3721
3891
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3729,12 +3899,12 @@ function registerEstimateTools(server2, client) {
|
|
|
3729
3899
|
"create_estimate",
|
|
3730
3900
|
"Create a new estimate/quote for a contact.",
|
|
3731
3901
|
{
|
|
3732
|
-
locationId:
|
|
3733
|
-
contactId:
|
|
3734
|
-
name:
|
|
3735
|
-
title:
|
|
3736
|
-
items:
|
|
3737
|
-
discount:
|
|
3902
|
+
locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
3903
|
+
contactId: import_zod28.z.string().describe("The contact ID this estimate is for."),
|
|
3904
|
+
name: import_zod28.z.string().describe("Estimate name/title."),
|
|
3905
|
+
title: import_zod28.z.string().optional().describe("Display title for the estimate."),
|
|
3906
|
+
items: import_zod28.z.array(import_zod28.z.record(import_zod28.z.unknown())).describe("Line items array. Each item should have name, description, price, qty."),
|
|
3907
|
+
discount: import_zod28.z.record(import_zod28.z.unknown()).optional().describe("Discount object (type, value).")
|
|
3738
3908
|
},
|
|
3739
3909
|
async ({ locationId: locationId2, contactId, name, title, items, discount }) => {
|
|
3740
3910
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3756,12 +3926,12 @@ function registerEstimateTools(server2, client) {
|
|
|
3756
3926
|
"update_estimate",
|
|
3757
3927
|
"Update an existing estimate/quote.",
|
|
3758
3928
|
{
|
|
3759
|
-
estimateId:
|
|
3760
|
-
locationId:
|
|
3761
|
-
name:
|
|
3762
|
-
title:
|
|
3763
|
-
items:
|
|
3764
|
-
discount:
|
|
3929
|
+
estimateId: import_zod28.z.string().describe("The estimate ID to update."),
|
|
3930
|
+
locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
3931
|
+
name: import_zod28.z.string().optional().describe("Updated estimate name."),
|
|
3932
|
+
title: import_zod28.z.string().optional().describe("Updated display title."),
|
|
3933
|
+
items: import_zod28.z.array(import_zod28.z.record(import_zod28.z.unknown())).optional().describe("Updated line items array."),
|
|
3934
|
+
discount: import_zod28.z.record(import_zod28.z.unknown()).optional().describe("Updated discount object.")
|
|
3765
3935
|
},
|
|
3766
3936
|
async ({ estimateId, locationId: locationId2, name, title, items, discount }) => {
|
|
3767
3937
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3781,8 +3951,8 @@ function registerEstimateTools(server2, client) {
|
|
|
3781
3951
|
"delete_estimate",
|
|
3782
3952
|
"Delete an estimate/quote by ID.",
|
|
3783
3953
|
{
|
|
3784
|
-
estimateId:
|
|
3785
|
-
locationId:
|
|
3954
|
+
estimateId: import_zod28.z.string().describe("The estimate ID to delete."),
|
|
3955
|
+
locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3786
3956
|
},
|
|
3787
3957
|
async ({ estimateId, locationId: locationId2 }) => {
|
|
3788
3958
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3796,8 +3966,8 @@ function registerEstimateTools(server2, client) {
|
|
|
3796
3966
|
"send_estimate",
|
|
3797
3967
|
"Send an estimate to the contact via email.",
|
|
3798
3968
|
{
|
|
3799
|
-
estimateId:
|
|
3800
|
-
locationId:
|
|
3969
|
+
estimateId: import_zod28.z.string().describe("The estimate ID to send."),
|
|
3970
|
+
locationId: import_zod28.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3801
3971
|
},
|
|
3802
3972
|
async ({ estimateId, locationId: locationId2 }) => {
|
|
3803
3973
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3809,14 +3979,14 @@ function registerEstimateTools(server2, client) {
|
|
|
3809
3979
|
}
|
|
3810
3980
|
|
|
3811
3981
|
// src/tools/coupons.ts
|
|
3812
|
-
var
|
|
3982
|
+
var import_zod29 = require("zod");
|
|
3813
3983
|
function registerCouponTools(server2, client) {
|
|
3814
3984
|
safeTool(
|
|
3815
3985
|
server2,
|
|
3816
3986
|
"list_coupons",
|
|
3817
3987
|
"List coupons/promo codes in a GHL location.",
|
|
3818
3988
|
{
|
|
3819
|
-
locationId:
|
|
3989
|
+
locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3820
3990
|
},
|
|
3821
3991
|
async ({ locationId: locationId2 }) => {
|
|
3822
3992
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3830,8 +4000,8 @@ function registerCouponTools(server2, client) {
|
|
|
3830
4000
|
"get_coupon",
|
|
3831
4001
|
"Retrieve a single coupon by its ID.",
|
|
3832
4002
|
{
|
|
3833
|
-
couponId:
|
|
3834
|
-
locationId:
|
|
4003
|
+
couponId: import_zod29.z.string().describe("The coupon ID to retrieve."),
|
|
4004
|
+
locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3835
4005
|
},
|
|
3836
4006
|
async ({ couponId, locationId: locationId2 }) => {
|
|
3837
4007
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3845,14 +4015,14 @@ function registerCouponTools(server2, client) {
|
|
|
3845
4015
|
"create_coupon",
|
|
3846
4016
|
"Create a new coupon/promo code.",
|
|
3847
4017
|
{
|
|
3848
|
-
locationId:
|
|
3849
|
-
name:
|
|
3850
|
-
code:
|
|
3851
|
-
type:
|
|
3852
|
-
amount:
|
|
3853
|
-
duration:
|
|
3854
|
-
durationInMonths:
|
|
3855
|
-
productIds:
|
|
4018
|
+
locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
4019
|
+
name: import_zod29.z.string().describe("Coupon name."),
|
|
4020
|
+
code: import_zod29.z.string().describe("Promo code string customers enter."),
|
|
4021
|
+
type: import_zod29.z.string().describe("Discount type: 'percentage' or 'fixed'."),
|
|
4022
|
+
amount: import_zod29.z.number().describe("Discount amount (percentage value or fixed dollar amount)."),
|
|
4023
|
+
duration: import_zod29.z.string().optional().describe("Duration: 'once', 'repeating', or 'forever'. Defaults to 'once'."),
|
|
4024
|
+
durationInMonths: import_zod29.z.number().optional().describe("Number of months if duration is 'repeating'."),
|
|
4025
|
+
productIds: import_zod29.z.array(import_zod29.z.string()).optional().describe("Product IDs this coupon applies to. If empty, applies to all.")
|
|
3856
4026
|
},
|
|
3857
4027
|
async ({ locationId: locationId2, name, code, type, amount, duration, durationInMonths, productIds }) => {
|
|
3858
4028
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3876,10 +4046,10 @@ function registerCouponTools(server2, client) {
|
|
|
3876
4046
|
"update_coupon",
|
|
3877
4047
|
"Update an existing coupon.",
|
|
3878
4048
|
{
|
|
3879
|
-
couponId:
|
|
3880
|
-
locationId:
|
|
3881
|
-
name:
|
|
3882
|
-
productIds:
|
|
4049
|
+
couponId: import_zod29.z.string().describe("The coupon ID to update."),
|
|
4050
|
+
locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
4051
|
+
name: import_zod29.z.string().optional().describe("Updated coupon name."),
|
|
4052
|
+
productIds: import_zod29.z.array(import_zod29.z.string()).optional().describe("Updated product IDs this coupon applies to.")
|
|
3883
4053
|
},
|
|
3884
4054
|
async ({ couponId, locationId: locationId2, name, productIds }) => {
|
|
3885
4055
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3897,8 +4067,8 @@ function registerCouponTools(server2, client) {
|
|
|
3897
4067
|
"delete_coupon",
|
|
3898
4068
|
"Delete a coupon by ID.",
|
|
3899
4069
|
{
|
|
3900
|
-
couponId:
|
|
3901
|
-
locationId:
|
|
4070
|
+
couponId: import_zod29.z.string().describe("The coupon ID to delete."),
|
|
4071
|
+
locationId: import_zod29.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3902
4072
|
},
|
|
3903
4073
|
async ({ couponId, locationId: locationId2 }) => {
|
|
3904
4074
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3910,14 +4080,14 @@ function registerCouponTools(server2, client) {
|
|
|
3910
4080
|
}
|
|
3911
4081
|
|
|
3912
4082
|
// src/tools/webhooks.ts
|
|
3913
|
-
var
|
|
4083
|
+
var import_zod30 = require("zod");
|
|
3914
4084
|
function registerWebhookTools(server2, client) {
|
|
3915
4085
|
safeTool(
|
|
3916
4086
|
server2,
|
|
3917
4087
|
"list_webhooks",
|
|
3918
4088
|
"List all webhooks configured in a GHL location.",
|
|
3919
4089
|
{
|
|
3920
|
-
locationId:
|
|
4090
|
+
locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3921
4091
|
},
|
|
3922
4092
|
async ({ locationId: locationId2 }) => {
|
|
3923
4093
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3931,8 +4101,8 @@ function registerWebhookTools(server2, client) {
|
|
|
3931
4101
|
"get_webhook",
|
|
3932
4102
|
"Retrieve a single webhook by its ID.",
|
|
3933
4103
|
{
|
|
3934
|
-
webhookId:
|
|
3935
|
-
locationId:
|
|
4104
|
+
webhookId: import_zod30.z.string().describe("The webhook ID to retrieve."),
|
|
4105
|
+
locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3936
4106
|
},
|
|
3937
4107
|
async ({ webhookId, locationId: locationId2 }) => {
|
|
3938
4108
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3946,10 +4116,10 @@ function registerWebhookTools(server2, client) {
|
|
|
3946
4116
|
"create_webhook",
|
|
3947
4117
|
"Create a new webhook subscription for GHL events.",
|
|
3948
4118
|
{
|
|
3949
|
-
locationId:
|
|
3950
|
-
name:
|
|
3951
|
-
url:
|
|
3952
|
-
events:
|
|
4119
|
+
locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
4120
|
+
name: import_zod30.z.string().describe("Webhook name."),
|
|
4121
|
+
url: import_zod30.z.string().describe("The URL to POST events to."),
|
|
4122
|
+
events: import_zod30.z.array(import_zod30.z.string()).describe(
|
|
3953
4123
|
"List of event types to subscribe to (e.g. 'ContactCreate', 'AppointmentCreate', 'OpportunityStatusUpdate')."
|
|
3954
4124
|
)
|
|
3955
4125
|
},
|
|
@@ -3970,11 +4140,11 @@ function registerWebhookTools(server2, client) {
|
|
|
3970
4140
|
"update_webhook",
|
|
3971
4141
|
"Update an existing webhook (name, URL, or subscribed events).",
|
|
3972
4142
|
{
|
|
3973
|
-
webhookId:
|
|
3974
|
-
locationId:
|
|
3975
|
-
name:
|
|
3976
|
-
url:
|
|
3977
|
-
events:
|
|
4143
|
+
webhookId: import_zod30.z.string().describe("The webhook ID to update."),
|
|
4144
|
+
locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
4145
|
+
name: import_zod30.z.string().optional().describe("Updated webhook name."),
|
|
4146
|
+
url: import_zod30.z.string().optional().describe("Updated webhook URL."),
|
|
4147
|
+
events: import_zod30.z.array(import_zod30.z.string()).optional().describe("Updated list of event types.")
|
|
3978
4148
|
},
|
|
3979
4149
|
async ({ webhookId, locationId: locationId2, name, url, events }) => {
|
|
3980
4150
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -3990,8 +4160,8 @@ function registerWebhookTools(server2, client) {
|
|
|
3990
4160
|
"delete_webhook",
|
|
3991
4161
|
"Delete a webhook subscription by ID.",
|
|
3992
4162
|
{
|
|
3993
|
-
webhookId:
|
|
3994
|
-
locationId:
|
|
4163
|
+
webhookId: import_zod30.z.string().describe("The webhook ID to delete."),
|
|
4164
|
+
locationId: import_zod30.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
3995
4165
|
},
|
|
3996
4166
|
async ({ webhookId, locationId: locationId2 }) => {
|
|
3997
4167
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -4003,16 +4173,16 @@ function registerWebhookTools(server2, client) {
|
|
|
4003
4173
|
}
|
|
4004
4174
|
|
|
4005
4175
|
// src/tools/documents.ts
|
|
4006
|
-
var
|
|
4176
|
+
var import_zod31 = require("zod");
|
|
4007
4177
|
function registerDocumentTools(server2, client) {
|
|
4008
4178
|
safeTool(
|
|
4009
4179
|
server2,
|
|
4010
4180
|
"list_documents",
|
|
4011
4181
|
"List documents and contracts in a GHL location. Supports pagination.",
|
|
4012
4182
|
{
|
|
4013
|
-
locationId:
|
|
4014
|
-
limit:
|
|
4015
|
-
offset:
|
|
4183
|
+
locationId: import_zod31.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env."),
|
|
4184
|
+
limit: import_zod31.z.number().optional().describe("Maximum documents to return. Defaults to 20."),
|
|
4185
|
+
offset: import_zod31.z.number().optional().describe("Number of records to skip for pagination.")
|
|
4016
4186
|
},
|
|
4017
4187
|
async ({ locationId: locationId2, limit, offset }) => {
|
|
4018
4188
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -4030,8 +4200,8 @@ function registerDocumentTools(server2, client) {
|
|
|
4030
4200
|
"get_document",
|
|
4031
4201
|
"Retrieve a single document or contract by its ID, including signature status.",
|
|
4032
4202
|
{
|
|
4033
|
-
documentId:
|
|
4034
|
-
locationId:
|
|
4203
|
+
documentId: import_zod31.z.string().describe("The document ID to retrieve."),
|
|
4204
|
+
locationId: import_zod31.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
4035
4205
|
},
|
|
4036
4206
|
async ({ documentId, locationId: locationId2 }) => {
|
|
4037
4207
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -4045,8 +4215,8 @@ function registerDocumentTools(server2, client) {
|
|
|
4045
4215
|
"delete_document",
|
|
4046
4216
|
"Delete a document or contract by ID.",
|
|
4047
4217
|
{
|
|
4048
|
-
documentId:
|
|
4049
|
-
locationId:
|
|
4218
|
+
documentId: import_zod31.z.string().describe("The document ID to delete."),
|
|
4219
|
+
locationId: import_zod31.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
4050
4220
|
},
|
|
4051
4221
|
async ({ documentId, locationId: locationId2 }) => {
|
|
4052
4222
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -4060,9 +4230,9 @@ function registerDocumentTools(server2, client) {
|
|
|
4060
4230
|
"send_document",
|
|
4061
4231
|
"Send a document/contract to a contact for electronic signature.",
|
|
4062
4232
|
{
|
|
4063
|
-
documentId:
|
|
4064
|
-
contactId:
|
|
4065
|
-
locationId:
|
|
4233
|
+
documentId: import_zod31.z.string().describe("The document ID to send."),
|
|
4234
|
+
contactId: import_zod31.z.string().describe("The contact ID to send the document to."),
|
|
4235
|
+
locationId: import_zod31.z.string().optional().describe("GHL Location ID. Optional if GHL_LOCATION_ID is set in env.")
|
|
4066
4236
|
},
|
|
4067
4237
|
async ({ documentId, contactId, locationId: locationId2 }) => {
|
|
4068
4238
|
const resolvedLocationId = client.resolveLocationId(locationId2);
|
|
@@ -4074,19 +4244,19 @@ function registerDocumentTools(server2, client) {
|
|
|
4074
4244
|
}
|
|
4075
4245
|
|
|
4076
4246
|
// src/tools/workflow-builder.ts
|
|
4077
|
-
var
|
|
4078
|
-
var ActionSchema =
|
|
4079
|
-
id:
|
|
4080
|
-
name:
|
|
4081
|
-
type:
|
|
4082
|
-
attributes:
|
|
4083
|
-
next:
|
|
4084
|
-
parent:
|
|
4085
|
-
parentKey:
|
|
4086
|
-
order:
|
|
4087
|
-
cat:
|
|
4088
|
-
nodeType:
|
|
4089
|
-
sibling:
|
|
4247
|
+
var import_zod32 = require("zod");
|
|
4248
|
+
var ActionSchema = import_zod32.z.object({
|
|
4249
|
+
id: import_zod32.z.string().optional().describe("Action ID (auto-generated if omitted)."),
|
|
4250
|
+
name: import_zod32.z.string().describe("Display name for this action step."),
|
|
4251
|
+
type: import_zod32.z.string().describe("Action type."),
|
|
4252
|
+
attributes: import_zod32.z.record(import_zod32.z.unknown()).optional().describe("Action-specific configuration."),
|
|
4253
|
+
next: import_zod32.z.union([import_zod32.z.string(), import_zod32.z.array(import_zod32.z.string())]).optional().describe("Next action id, or branch id array for condition nodes."),
|
|
4254
|
+
parent: import_zod32.z.string().optional().describe("Branch parent node id."),
|
|
4255
|
+
parentKey: import_zod32.z.string().optional().describe("Previous action id or branch parent id."),
|
|
4256
|
+
order: import_zod32.z.number().optional().describe("Order within this chain or branch."),
|
|
4257
|
+
cat: import_zod32.z.string().optional().describe("Category for condition, transition, or multi-path nodes."),
|
|
4258
|
+
nodeType: import_zod32.z.string().optional().describe("Node type for if/else nodes."),
|
|
4259
|
+
sibling: import_zod32.z.array(import_zod32.z.string()).optional().describe("Sibling branch node IDs.")
|
|
4090
4260
|
}).passthrough();
|
|
4091
4261
|
function linkBranchActions(actions, branchId, nextAfterMerge) {
|
|
4092
4262
|
const prepared = actions.map((action) => ({
|
|
@@ -4133,8 +4303,8 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4133
4303
|
"list_workflows_full",
|
|
4134
4304
|
"List all workflows with full metadata including version, permissions, and timestamps. Requires Firebase auth. Use this instead of get_workflows when you need version numbers or internal IDs for update_workflow_actions.",
|
|
4135
4305
|
{
|
|
4136
|
-
limit:
|
|
4137
|
-
skip:
|
|
4306
|
+
limit: import_zod32.z.number().optional().describe("Max workflows to return. Defaults to 50."),
|
|
4307
|
+
skip: import_zod32.z.number().optional().describe("Number of workflows to skip for pagination.")
|
|
4138
4308
|
},
|
|
4139
4309
|
async ({ limit, skip }) => {
|
|
4140
4310
|
try {
|
|
@@ -4149,7 +4319,7 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4149
4319
|
"get_workflow_full",
|
|
4150
4320
|
"Get a workflow with full details including all actions (steps), triggers, conditions, if/else branches, and configuration. Requires Firebase auth. ALWAYS call this before update_workflow_actions to see the current state.",
|
|
4151
4321
|
{
|
|
4152
|
-
workflowId:
|
|
4322
|
+
workflowId: import_zod32.z.string().describe("The workflow ID to retrieve.")
|
|
4153
4323
|
},
|
|
4154
4324
|
async ({ workflowId }) => {
|
|
4155
4325
|
try {
|
|
@@ -4164,9 +4334,9 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4164
4334
|
"get_trigger_registry",
|
|
4165
4335
|
"Return GHL's marketplace catalogue of workflow triggers from 3rd-party apps (Zoom, Shopify, WooCommerce, Monday, etc.). Each app exposes one or more trigger templates with custom variable mappings. Calls /marketplace/core/search/module?type=triggers. NOTE: This is the MARKETPLACE only. GHL's NATIVE trigger types (form_submission, contact_tag, payment_received, opportunity_*, inbound_webhook, etc.) live in the workflow builder frontend bundle, not an API. For the native registry see templates/trigger-schemas.json in this repo.",
|
|
4166
4336
|
{
|
|
4167
|
-
companyId:
|
|
4168
|
-
limit:
|
|
4169
|
-
installedOnly:
|
|
4337
|
+
companyId: import_zod32.z.string().describe("Company ID for the location. Find it in any get_workflow_full response under the 'companyId' field."),
|
|
4338
|
+
limit: import_zod32.z.number().optional().describe("Max marketplace apps to return. Defaults to 200."),
|
|
4339
|
+
installedOnly: import_zod32.z.boolean().optional().describe("If true, returns only apps installed in this location. Defaults to false (full marketplace catalogue, ~85 apps).")
|
|
4170
4340
|
},
|
|
4171
4341
|
async ({ companyId, limit, installedOnly }) => {
|
|
4172
4342
|
try {
|
|
@@ -4198,7 +4368,7 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4198
4368
|
"create_workflow",
|
|
4199
4369
|
"Create a new empty workflow (starts as draft). Requires Firebase auth. Flow: 1) create_workflow \u2192 2) update_workflow_actions (add triggers + steps) \u2192 3) publish_workflow (make it live).",
|
|
4200
4370
|
{
|
|
4201
|
-
name:
|
|
4371
|
+
name: import_zod32.z.string().describe("Name for the new workflow.")
|
|
4202
4372
|
},
|
|
4203
4373
|
async ({ name }) => {
|
|
4204
4374
|
try {
|
|
@@ -4213,11 +4383,11 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4213
4383
|
"update_workflow_actions",
|
|
4214
4384
|
"Update a workflow's actions (steps), triggers, name, or status. IMPORTANT: Call get_workflow_full first to see the current state before updating. Handles version tracking automatically. Uses the internal builder API (requires Firebase auth). Action types: sms, email, add_contact_tag, remove_contact_tag, wait, webhook, internal_update_opportunity, custom_code, update_contact_field, add_notes, internal_notification, task_notification, remove_from_workflow, add_to_workflow, goto, transition, workflow_goal. For if/else, call build_if_else_branch and include its returned nodes; if_else is a node discriminator, not a standalone action. For goal events (exit-on-condition nodes), call build_goal_event to get a correctly-shaped workflow_goal node \u2014 wire it in by setting the prior action's `next` to the goal node's id. Trigger types: all 57 native GHL trigger types have typed validation; any unknown trigger type passes through via a permissive fallback so reads never crash.",
|
|
4215
4385
|
{
|
|
4216
|
-
workflowId:
|
|
4217
|
-
name:
|
|
4218
|
-
status:
|
|
4219
|
-
actions:
|
|
4220
|
-
triggers:
|
|
4386
|
+
workflowId: import_zod32.z.string().describe("The workflow ID to update."),
|
|
4387
|
+
name: import_zod32.z.string().optional().describe("New workflow name."),
|
|
4388
|
+
status: import_zod32.z.string().optional().describe("New status: 'draft' or 'published'."),
|
|
4389
|
+
actions: import_zod32.z.array(ActionSchema).optional().describe("Array of workflow actions/steps. For linear flows, provide in order \u2014 chaining is automatic."),
|
|
4390
|
+
triggers: import_zod32.z.array(WorkflowTriggerSchema).optional().describe("Array of workflow triggers.")
|
|
4221
4391
|
},
|
|
4222
4392
|
async ({ workflowId, name, status, actions, triggers }) => {
|
|
4223
4393
|
try {
|
|
@@ -4261,12 +4431,12 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4261
4431
|
"build_if_else_branch",
|
|
4262
4432
|
"Build a correctly-shaped GHL if/else branch node set for a tag-based condition (Build Your Own / CUSTOM recipe). Returns a condition-node, branch-yes, branch-no, and branch child actions with parent/parentKey/sibling/order links populated. Shape mirrors what GHL's UI saves so dropdowns render correctly.",
|
|
4263
4433
|
{
|
|
4264
|
-
field:
|
|
4265
|
-
operator:
|
|
4266
|
-
value:
|
|
4267
|
-
yes_actions:
|
|
4268
|
-
no_actions:
|
|
4269
|
-
next_after_merge:
|
|
4434
|
+
field: import_zod32.z.string().describe("Condition subtype, currently 'tags' for tag-based conditions."),
|
|
4435
|
+
operator: import_zod32.z.string().describe("Condition operator token. Verified: 'index-of-true' (Includes), 'index-of-false' (Does not include), 'has_value' (Is not empty), 'has_no_value' (Is empty). Emptiness operators don't take a value. Tokens must match GHL's exact internal strings or the UI dropdown renders the raw token instead of a label."),
|
|
4436
|
+
value: import_zod32.z.union([import_zod32.z.string(), import_zod32.z.array(import_zod32.z.string())]).optional().describe("Tag name(s). Required for index-of-true / index-of-false. Omit for has_value / has_no_value. Single string is auto-wrapped as an array. Tags must already exist in the location's tag library or the UI dropdown will render empty."),
|
|
4437
|
+
yes_actions: import_zod32.z.array(ActionSchema).describe("Actions to run in the Yes branch."),
|
|
4438
|
+
no_actions: import_zod32.z.array(ActionSchema).describe("Actions to run in the No branch."),
|
|
4439
|
+
next_after_merge: import_zod32.z.string().optional().describe("Optional node id to link from each non-empty branch's final child.")
|
|
4270
4440
|
},
|
|
4271
4441
|
async ({ field, operator, value, yes_actions, no_actions, next_after_merge }) => {
|
|
4272
4442
|
try {
|
|
@@ -4376,7 +4546,7 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4376
4546
|
"build_goal_event",
|
|
4377
4547
|
"Build a correctly-shaped GHL workflow goal-event node. Goal events sit inline in the action chain \u2014 when the goal condition fires during workflow execution, the configured action runs (default: exit the workflow). The previous action's `next` should point to the goal node's id; the goal node itself does not have a `next`. All 10 goal_condition values are catalogued (from GHL's workflow-builder JS bundle, extracted 2026-05-18): email_event, link_click, add_contact_tag, remove_contact_tag, appointment_status, payment_received, form_submission, document_status, invoice_paid, review_request_clicked. Each one has a different `extras` shape (see the `goal_condition` field's description for details).",
|
|
4378
4548
|
{
|
|
4379
|
-
goal_condition:
|
|
4549
|
+
goal_condition: import_zod32.z.enum([
|
|
4380
4550
|
"email_event",
|
|
4381
4551
|
"link_click",
|
|
4382
4552
|
"add_contact_tag",
|
|
@@ -4388,11 +4558,11 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4388
4558
|
"invoice_paid",
|
|
4389
4559
|
"review_request_clicked"
|
|
4390
4560
|
]).describe("The goal-condition identifier. Extras shape per condition: email_event \u2192 {stepIds:[]}; link_click \u2192 {linkIds:[]}; appointment_status \u2192 {calendarId}; payment_received \u2192 {globalProductIds:[]}; form_submission \u2192 {formIds:[]}; document_status \u2192 {templateId}; invoice_paid \u2192 {invoiceStepId}; review_request_clicked \u2192 {reviewTypes:['sms'|'email'], reviewLinkId}; add_contact_tag/remove_contact_tag \u2192 {tags:[]} (uncaptured but inferred)."),
|
|
4391
|
-
extras:
|
|
4392
|
-
action:
|
|
4393
|
-
name:
|
|
4394
|
-
op:
|
|
4395
|
-
inner_op:
|
|
4561
|
+
extras: import_zod32.z.record(import_zod32.z.unknown()).optional().describe("Goal-condition-specific config. See goal_condition description for the expected shape per value. Pass {} or omit for goal_conditions without extras."),
|
|
4562
|
+
action: import_zod32.z.enum(["exit", "continue", "wait"]).default("exit").describe("What happens when the goal fires (per GHL's GoalAction enum). 'exit' terminates the workflow path (verified). 'continue' lets it proceed to a downstream node. 'wait' pauses on the goal."),
|
|
4563
|
+
name: import_zod32.z.string().default("Goal").describe("Display name in the GHL UI."),
|
|
4564
|
+
op: import_zod32.z.enum(["or", "and"]).default("or").describe("Top-level boolean operator across segments. Default 'or'."),
|
|
4565
|
+
inner_op: import_zod32.z.enum(["or", "and"]).default("or").describe("Boolean operator across conditions within a single segment. Default 'or'.")
|
|
4396
4566
|
},
|
|
4397
4567
|
async ({ goal_condition, extras, action, name, op, inner_op }) => {
|
|
4398
4568
|
try {
|
|
@@ -4427,8 +4597,8 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4427
4597
|
"delete_workflow_full",
|
|
4428
4598
|
"Permanently delete a workflow. IRREVERSIBLE.",
|
|
4429
4599
|
{
|
|
4430
|
-
workflowId:
|
|
4431
|
-
confirm:
|
|
4600
|
+
workflowId: import_zod32.z.string().describe("The workflow ID to delete."),
|
|
4601
|
+
confirm: import_zod32.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
|
|
4432
4602
|
},
|
|
4433
4603
|
async ({ workflowId }) => {
|
|
4434
4604
|
try {
|
|
@@ -4443,7 +4613,7 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4443
4613
|
"publish_workflow",
|
|
4444
4614
|
"Publish a draft workflow, making it active and processing contacts.",
|
|
4445
4615
|
{
|
|
4446
|
-
workflowId:
|
|
4616
|
+
workflowId: import_zod32.z.string().describe("The workflow ID to publish.")
|
|
4447
4617
|
},
|
|
4448
4618
|
async ({ workflowId }) => {
|
|
4449
4619
|
try {
|
|
@@ -4457,7 +4627,7 @@ function registerWorkflowBuilderTools(server2, client) {
|
|
|
4457
4627
|
}
|
|
4458
4628
|
|
|
4459
4629
|
// src/tools/funnel-builder.ts
|
|
4460
|
-
var
|
|
4630
|
+
var import_zod33 = require("zod");
|
|
4461
4631
|
function registerFunnelBuilderTools(server2, builderClient) {
|
|
4462
4632
|
const client = builderClient;
|
|
4463
4633
|
if (!client) return;
|
|
@@ -4500,7 +4670,7 @@ ${text2}`);
|
|
|
4500
4670
|
"list_funnels_full",
|
|
4501
4671
|
"List all funnels/websites with full details including steps, pages, and metadata. Uses the internal API for richer data than the public API.",
|
|
4502
4672
|
{
|
|
4503
|
-
limit:
|
|
4673
|
+
limit: import_zod33.z.number().optional().describe("Max funnels to return. Defaults to 50.")
|
|
4504
4674
|
},
|
|
4505
4675
|
async ({ limit }) => {
|
|
4506
4676
|
try {
|
|
@@ -4520,7 +4690,7 @@ ${text2}`);
|
|
|
4520
4690
|
"get_page_full",
|
|
4521
4691
|
"Get a funnel/website page with full builder data: metadata, version, preview snapshot URL, and page data download URL. To get the actual page content (sections, elements, styles), use get_page_content with the pageDataDownloadUrl from this response.",
|
|
4522
4692
|
{
|
|
4523
|
-
pageId:
|
|
4693
|
+
pageId: import_zod33.z.string().describe("The page ID to retrieve.")
|
|
4524
4694
|
},
|
|
4525
4695
|
async ({ pageId }) => {
|
|
4526
4696
|
try {
|
|
@@ -4540,7 +4710,7 @@ ${text2}`);
|
|
|
4540
4710
|
"get_page_content",
|
|
4541
4711
|
"Download the full page builder content from a page's data URL. Returns the complete page structure: sections, elements, settings, styles, tracking codes, and popups. Use get_page_full first to get the pageDataDownloadUrl.",
|
|
4542
4712
|
{
|
|
4543
|
-
pageDataDownloadUrl:
|
|
4713
|
+
pageDataDownloadUrl: import_zod33.z.string().describe("The pageDataDownloadUrl from get_page_full response.")
|
|
4544
4714
|
},
|
|
4545
4715
|
async ({ pageDataDownloadUrl }) => {
|
|
4546
4716
|
try {
|
|
@@ -4562,7 +4732,7 @@ ${text2}`);
|
|
|
4562
4732
|
"create_funnel",
|
|
4563
4733
|
"Create a new funnel/website. Starts empty \u2014 add steps and pages after creation.",
|
|
4564
4734
|
{
|
|
4565
|
-
name:
|
|
4735
|
+
name: import_zod33.z.string().describe("Name for the new funnel.")
|
|
4566
4736
|
},
|
|
4567
4737
|
async ({ name }) => {
|
|
4568
4738
|
try {
|
|
@@ -4584,21 +4754,21 @@ ${text2}`);
|
|
|
4584
4754
|
"update_funnel",
|
|
4585
4755
|
"Update a funnel's settings: name, path/slug, tracking codes, GDPR + payment + chat widget flags, etc. This is the 'save settings panel' endpoint \u2014 it sends the entire settings object, so the tool fetches current settings first, merges your overrides on top, then POSTs back. To rename a single step (page) inside a funnel, use update_funnel_step instead.",
|
|
4586
4756
|
{
|
|
4587
|
-
funnelId:
|
|
4588
|
-
name:
|
|
4589
|
-
path:
|
|
4590
|
-
bodyTrackingCode:
|
|
4591
|
-
headTrackingCode:
|
|
4592
|
-
chatWidgetId:
|
|
4593
|
-
domainId:
|
|
4594
|
-
faviconUrl:
|
|
4595
|
-
paymentMode:
|
|
4596
|
-
requireCreditCard:
|
|
4597
|
-
isGdprCompliant:
|
|
4598
|
-
isOptimisePageLoad:
|
|
4599
|
-
imageOptimization:
|
|
4600
|
-
allowPaymentModeOption:
|
|
4601
|
-
storeCurrencyFormatting:
|
|
4757
|
+
funnelId: import_zod33.z.string().describe("The funnel ID to update."),
|
|
4758
|
+
name: import_zod33.z.string().optional().describe("New funnel display name."),
|
|
4759
|
+
path: import_zod33.z.string().optional().describe("URL slug for the funnel (e.g., '/my-funnel'). Mapped to funnelPath."),
|
|
4760
|
+
bodyTrackingCode: import_zod33.z.string().optional().describe("Custom tracking script injected before </body>."),
|
|
4761
|
+
headTrackingCode: import_zod33.z.string().optional().describe("Custom tracking script injected before </head>."),
|
|
4762
|
+
chatWidgetId: import_zod33.z.string().optional().describe("Chat widget to embed on every page in this funnel."),
|
|
4763
|
+
domainId: import_zod33.z.string().optional().describe("Custom domain ID for the funnel."),
|
|
4764
|
+
faviconUrl: import_zod33.z.string().optional().describe("Favicon URL for funnel pages."),
|
|
4765
|
+
paymentMode: import_zod33.z.boolean().optional().describe("Whether to require a payment mode for the funnel."),
|
|
4766
|
+
requireCreditCard: import_zod33.z.boolean().optional().describe("Whether to require a credit card on opt-in steps."),
|
|
4767
|
+
isGdprCompliant: import_zod33.z.boolean().optional().describe("Toggle GDPR compliance mode."),
|
|
4768
|
+
isOptimisePageLoad: import_zod33.z.boolean().optional().describe("Enable GHL's page-load optimization."),
|
|
4769
|
+
imageOptimization: import_zod33.z.boolean().optional().describe("Enable automatic image optimization."),
|
|
4770
|
+
allowPaymentModeOption: import_zod33.z.boolean().optional().describe("Allow buyers to choose payment mode on checkout."),
|
|
4771
|
+
storeCurrencyFormatting: import_zod33.z.boolean().optional().describe("Use store-wide currency formatting.")
|
|
4602
4772
|
},
|
|
4603
4773
|
async (args) => {
|
|
4604
4774
|
try {
|
|
@@ -4654,11 +4824,11 @@ ${text2}`);
|
|
|
4654
4824
|
"update_funnel_step",
|
|
4655
4825
|
"Update a single step (page entry) inside a funnel \u2014 display name, URL slug, or attached domain. A step is GHL's container for one or more pages (multiple pages exist when split-testing). Use update_funnel for funnel-level settings instead.",
|
|
4656
4826
|
{
|
|
4657
|
-
funnelId:
|
|
4658
|
-
stepId:
|
|
4659
|
-
name:
|
|
4660
|
-
url:
|
|
4661
|
-
domainName:
|
|
4827
|
+
funnelId: import_zod33.z.string().describe("The funnel ID containing the step."),
|
|
4828
|
+
stepId: import_zod33.z.string().describe("The step ID to update (from get_funnel_pages / list_funnels_full)."),
|
|
4829
|
+
name: import_zod33.z.string().optional().describe("New step display name."),
|
|
4830
|
+
url: import_zod33.z.string().optional().describe("URL slug for the step (e.g., '/thank-you')."),
|
|
4831
|
+
domainName: import_zod33.z.string().optional().describe("Custom domain to attach to this step.")
|
|
4662
4832
|
},
|
|
4663
4833
|
async ({ funnelId, stepId, name, url, domainName }) => {
|
|
4664
4834
|
try {
|
|
@@ -4677,8 +4847,8 @@ ${text2}`);
|
|
|
4677
4847
|
"delete_funnel",
|
|
4678
4848
|
"Permanently delete a funnel and all its steps/pages. IRREVERSIBLE.",
|
|
4679
4849
|
{
|
|
4680
|
-
funnelId:
|
|
4681
|
-
confirm:
|
|
4850
|
+
funnelId: import_zod33.z.string().describe("The funnel ID to delete."),
|
|
4851
|
+
confirm: import_zod33.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
|
|
4682
4852
|
},
|
|
4683
4853
|
async ({ funnelId }) => {
|
|
4684
4854
|
try {
|
|
@@ -4697,10 +4867,10 @@ ${text2}`);
|
|
|
4697
4867
|
"create_funnel_page",
|
|
4698
4868
|
"Create a new step (page entry) in a funnel. The client generates a step UUID locally and sends it in the request; GHL auto-creates a blank page inside the step on the server side. The response includes the new step's id and the page's Firestore reference, which you can then update via update_page_content.",
|
|
4699
4869
|
{
|
|
4700
|
-
funnelId:
|
|
4701
|
-
name:
|
|
4702
|
-
url:
|
|
4703
|
-
type:
|
|
4870
|
+
funnelId: import_zod33.z.string().describe("The funnel ID to add the step to."),
|
|
4871
|
+
name: import_zod33.z.string().describe("Step display name."),
|
|
4872
|
+
url: import_zod33.z.string().optional().describe("URL slug for the step. Defaults to '' (blank) like the GHL UI."),
|
|
4873
|
+
type: import_zod33.z.string().optional().describe("Step type. Defaults to 'optin_funnel_page'.")
|
|
4704
4874
|
},
|
|
4705
4875
|
async ({ funnelId, name, url, type }) => {
|
|
4706
4876
|
try {
|
|
@@ -4728,9 +4898,9 @@ ${text2}`);
|
|
|
4728
4898
|
"update_page_content",
|
|
4729
4899
|
"Update a page's builder content \u2014 sections, elements, settings, pageStyles, trackingCode, popups, popupsList, fontsForPreview. Use get_page_content first to see the current structure, modify it, then pass the full 8-field envelope here. GHL's UI fires three POSTs to this endpoint per save (one collaborative-edit broadcast + two commits); for MCP use, one POST with write=true is enough.",
|
|
4730
4900
|
{
|
|
4731
|
-
pageId:
|
|
4732
|
-
content:
|
|
4733
|
-
isPublished:
|
|
4901
|
+
pageId: import_zod33.z.string().describe("The page ID to update."),
|
|
4902
|
+
content: import_zod33.z.record(import_zod33.z.unknown()).describe("The full page content JSON. Expected fields: sections, settings, general, pageStyles, trackingCode, popups, popupsList, fontsForPreview."),
|
|
4903
|
+
isPublished: import_zod33.z.boolean().optional().describe("Whether the page should be marked published after the save. Defaults to false (draft).")
|
|
4734
4904
|
},
|
|
4735
4905
|
async ({ pageId, content, isPublished }) => {
|
|
4736
4906
|
try {
|
|
@@ -4751,9 +4921,9 @@ ${text2}`);
|
|
|
4751
4921
|
"delete_funnel_page",
|
|
4752
4922
|
"Permanently delete a step (and all its pages) from a funnel. IRREVERSIBLE. SIGNATURE CHANGED in v3.7.0: was pageId, now requires funnelId + stepId to match GHL's actual delete-step endpoint.",
|
|
4753
4923
|
{
|
|
4754
|
-
funnelId:
|
|
4755
|
-
stepId:
|
|
4756
|
-
confirm:
|
|
4924
|
+
funnelId: import_zod33.z.string().describe("The funnel ID containing the step."),
|
|
4925
|
+
stepId: import_zod33.z.string().describe("The step ID to delete (from get_funnel_pages / list_funnels_full)."),
|
|
4926
|
+
confirm: import_zod33.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
|
|
4757
4927
|
},
|
|
4758
4928
|
async ({ funnelId, stepId }) => {
|
|
4759
4929
|
try {
|
|
@@ -4767,7 +4937,7 @@ ${text2}`);
|
|
|
4767
4937
|
}
|
|
4768
4938
|
|
|
4769
4939
|
// src/tools/form-builder.ts
|
|
4770
|
-
var
|
|
4940
|
+
var import_zod34 = require("zod");
|
|
4771
4941
|
function registerFormBuilderTools(server2, builderClient) {
|
|
4772
4942
|
const client = builderClient;
|
|
4773
4943
|
if (!client) return;
|
|
@@ -4796,7 +4966,7 @@ ${text2}`);
|
|
|
4796
4966
|
"get_form_full",
|
|
4797
4967
|
"Get a form with full builder data: all fields (labels, types, IDs, validation), conditional logic, auto-responder config, email notification settings, styling, and version history. This is the internal API \u2014 it returns everything the form builder UI shows.",
|
|
4798
4968
|
{
|
|
4799
|
-
formId:
|
|
4969
|
+
formId: import_zod34.z.string().describe("The form ID to retrieve.")
|
|
4800
4970
|
},
|
|
4801
4971
|
async ({ formId }) => {
|
|
4802
4972
|
try {
|
|
@@ -4813,9 +4983,9 @@ ${text2}`);
|
|
|
4813
4983
|
"update_form",
|
|
4814
4984
|
"Update a form's structure \u2014 fields, labels, conditional logic, auto-responder, email notifications, styling. Use get_form_full first to see the current structure, modify the formData object, and pass it here.",
|
|
4815
4985
|
{
|
|
4816
|
-
formId:
|
|
4817
|
-
formData:
|
|
4818
|
-
name:
|
|
4986
|
+
formId: import_zod34.z.string().describe("The form ID to update."),
|
|
4987
|
+
formData: import_zod34.z.record(import_zod34.z.unknown()).describe("The updated formData object containing form fields, settings, autoResponder config, etc."),
|
|
4988
|
+
name: import_zod34.z.string().optional().describe("Updated form name.")
|
|
4819
4989
|
},
|
|
4820
4990
|
async ({ formId, formData, name }) => {
|
|
4821
4991
|
try {
|
|
@@ -4834,7 +5004,7 @@ ${text2}`);
|
|
|
4834
5004
|
"create_form",
|
|
4835
5005
|
"Create a new form. Starts with a basic structure \u2014 use update_form to add fields and configure settings.",
|
|
4836
5006
|
{
|
|
4837
|
-
name:
|
|
5007
|
+
name: import_zod34.z.string().describe("Name for the new form.")
|
|
4838
5008
|
},
|
|
4839
5009
|
async ({ name }) => {
|
|
4840
5010
|
try {
|
|
@@ -4860,8 +5030,8 @@ ${text2}`);
|
|
|
4860
5030
|
"delete_form",
|
|
4861
5031
|
"Permanently delete a form. IRREVERSIBLE.",
|
|
4862
5032
|
{
|
|
4863
|
-
formId:
|
|
4864
|
-
confirm:
|
|
5033
|
+
formId: import_zod34.z.string().describe("The form ID to delete."),
|
|
5034
|
+
confirm: import_zod34.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
|
|
4865
5035
|
},
|
|
4866
5036
|
async ({ formId }) => {
|
|
4867
5037
|
try {
|
|
@@ -4878,9 +5048,9 @@ ${text2}`);
|
|
|
4878
5048
|
"get_form_submissions_full",
|
|
4879
5049
|
"Get form submissions with full field data, contact info, and submission timestamps via the internal API. Offset-based pagination via skip/limit.",
|
|
4880
5050
|
{
|
|
4881
|
-
formId:
|
|
4882
|
-
limit:
|
|
4883
|
-
skip:
|
|
5051
|
+
formId: import_zod34.z.string().optional().describe("Filter by form ID. If omitted, returns all submissions."),
|
|
5052
|
+
limit: import_zod34.z.number().optional().describe("Max submissions to return. Defaults to 20."),
|
|
5053
|
+
skip: import_zod34.z.number().optional().describe("Number to skip for pagination.")
|
|
4884
5054
|
},
|
|
4885
5055
|
async ({ formId, limit, skip }) => {
|
|
4886
5056
|
try {
|
|
@@ -4899,7 +5069,7 @@ ${text2}`);
|
|
|
4899
5069
|
}
|
|
4900
5070
|
|
|
4901
5071
|
// src/tools/pipeline-builder.ts
|
|
4902
|
-
var
|
|
5072
|
+
var import_zod35 = require("zod");
|
|
4903
5073
|
function registerPipelineBuilderTools(server2, builderClient) {
|
|
4904
5074
|
const client = builderClient;
|
|
4905
5075
|
if (!client) return;
|
|
@@ -4944,7 +5114,7 @@ ${text2}`);
|
|
|
4944
5114
|
"get_pipeline_full",
|
|
4945
5115
|
"Get a single pipeline with complete stage configuration: IDs, names, positions, display settings.",
|
|
4946
5116
|
{
|
|
4947
|
-
pipelineId:
|
|
5117
|
+
pipelineId: import_zod35.z.string().describe("The pipeline ID to retrieve.")
|
|
4948
5118
|
},
|
|
4949
5119
|
async ({ pipelineId }) => {
|
|
4950
5120
|
try {
|
|
@@ -4962,17 +5132,17 @@ ${text2}`);
|
|
|
4962
5132
|
"create_pipeline",
|
|
4963
5133
|
"Create a new pipeline with stages. Each stage needs a name and position (0-based).",
|
|
4964
5134
|
{
|
|
4965
|
-
name:
|
|
4966
|
-
stages:
|
|
4967
|
-
|
|
4968
|
-
name:
|
|
4969
|
-
position:
|
|
4970
|
-
showInFunnel:
|
|
4971
|
-
showInPieChart:
|
|
5135
|
+
name: import_zod35.z.string().describe("Pipeline name."),
|
|
5136
|
+
stages: import_zod35.z.array(
|
|
5137
|
+
import_zod35.z.object({
|
|
5138
|
+
name: import_zod35.z.string().describe("Stage name."),
|
|
5139
|
+
position: import_zod35.z.number().describe("Stage position (0-based)."),
|
|
5140
|
+
showInFunnel: import_zod35.z.boolean().optional().describe("Show in funnel view. Defaults to true."),
|
|
5141
|
+
showInPieChart: import_zod35.z.boolean().optional().describe("Show in pie chart. Defaults to true.")
|
|
4972
5142
|
})
|
|
4973
5143
|
).describe("Array of stages in order."),
|
|
4974
|
-
showInFunnel:
|
|
4975
|
-
showInPieChart:
|
|
5144
|
+
showInFunnel: import_zod35.z.boolean().optional().describe("Show pipeline in funnel view. Defaults to true."),
|
|
5145
|
+
showInPieChart: import_zod35.z.boolean().optional().describe("Show pipeline in pie chart. Defaults to true.")
|
|
4976
5146
|
},
|
|
4977
5147
|
async ({ name, stages, showInFunnel, showInPieChart }) => {
|
|
4978
5148
|
try {
|
|
@@ -5002,19 +5172,19 @@ ${text2}`);
|
|
|
5002
5172
|
"update_pipeline",
|
|
5003
5173
|
"Update a pipeline's name, stages, or display settings. You can add, remove, rename, or reorder stages. Pass the complete stages array \u2014 stages not included will be removed.",
|
|
5004
5174
|
{
|
|
5005
|
-
pipelineId:
|
|
5006
|
-
name:
|
|
5007
|
-
stages:
|
|
5008
|
-
|
|
5009
|
-
id:
|
|
5010
|
-
name:
|
|
5011
|
-
position:
|
|
5012
|
-
showInFunnel:
|
|
5013
|
-
showInPieChart:
|
|
5175
|
+
pipelineId: import_zod35.z.string().describe("The pipeline ID to update."),
|
|
5176
|
+
name: import_zod35.z.string().optional().describe("New pipeline name."),
|
|
5177
|
+
stages: import_zod35.z.array(
|
|
5178
|
+
import_zod35.z.object({
|
|
5179
|
+
id: import_zod35.z.string().optional().describe("Existing stage ID (omit for new stages)."),
|
|
5180
|
+
name: import_zod35.z.string().describe("Stage name."),
|
|
5181
|
+
position: import_zod35.z.number().describe("Stage position (0-based)."),
|
|
5182
|
+
showInFunnel: import_zod35.z.boolean().optional().describe("Show in funnel view."),
|
|
5183
|
+
showInPieChart: import_zod35.z.boolean().optional().describe("Show in pie chart.")
|
|
5014
5184
|
})
|
|
5015
5185
|
).optional().describe("Complete stages array. Stages not included will be removed."),
|
|
5016
|
-
showInFunnel:
|
|
5017
|
-
showInPieChart:
|
|
5186
|
+
showInFunnel: import_zod35.z.boolean().optional().describe("Show pipeline in funnel view."),
|
|
5187
|
+
showInPieChart: import_zod35.z.boolean().optional().describe("Show pipeline in pie chart.")
|
|
5018
5188
|
},
|
|
5019
5189
|
async ({ pipelineId, name, stages, showInFunnel, showInPieChart }) => {
|
|
5020
5190
|
try {
|
|
@@ -5037,8 +5207,8 @@ ${text2}`);
|
|
|
5037
5207
|
"delete_pipeline",
|
|
5038
5208
|
"Permanently delete a pipeline and all its stages. Opportunities become unassigned. IRREVERSIBLE.",
|
|
5039
5209
|
{
|
|
5040
|
-
pipelineId:
|
|
5041
|
-
confirm:
|
|
5210
|
+
pipelineId: import_zod35.z.string().describe("The pipeline ID to delete."),
|
|
5211
|
+
confirm: import_zod35.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
|
|
5042
5212
|
},
|
|
5043
5213
|
async ({ pipelineId }) => {
|
|
5044
5214
|
try {
|
|
@@ -5055,7 +5225,7 @@ ${text2}`);
|
|
|
5055
5225
|
}
|
|
5056
5226
|
|
|
5057
5227
|
// src/tools/location-switcher.ts
|
|
5058
|
-
var
|
|
5228
|
+
var import_zod36 = require("zod");
|
|
5059
5229
|
var switchChain = Promise.resolve();
|
|
5060
5230
|
function withSwitchLock(fn) {
|
|
5061
5231
|
const next = switchChain.then(fn, fn);
|
|
@@ -5104,7 +5274,7 @@ Token registry: ${registeredCount} location(s) registered${versionLine}`
|
|
|
5104
5274
|
"switch_location",
|
|
5105
5275
|
"Switch the active GHL sub-account. Automatically swaps the API key from the token registry if available. After switching, all tools default to the new location.",
|
|
5106
5276
|
{
|
|
5107
|
-
locationId:
|
|
5277
|
+
locationId: import_zod36.z.string().describe("The Location ID to switch to.")
|
|
5108
5278
|
},
|
|
5109
5279
|
async ({ locationId: locationId2 }) => withSwitchLock(async () => {
|
|
5110
5280
|
const previousId = client.defaultLocationId;
|
|
@@ -5169,9 +5339,9 @@ Still on: ${previousId || "none"}${hint}` }],
|
|
|
5169
5339
|
"register_location",
|
|
5170
5340
|
"Add a GHL sub-account to the token registry so switch_location can automatically use its API key. Each sub-account needs its own Private Integration key created in GHL Settings > Integrations.",
|
|
5171
5341
|
{
|
|
5172
|
-
locationId:
|
|
5173
|
-
name:
|
|
5174
|
-
apiKey:
|
|
5342
|
+
locationId: import_zod36.z.string().describe("The GHL Location ID (from Settings > Business Profile)."),
|
|
5343
|
+
name: import_zod36.z.string().describe("A friendly name for this sub-account (e.g. 'PNTracker', 'Med Spa Template')."),
|
|
5344
|
+
apiKey: import_zod36.z.string().describe("The Private Integration API key for this sub-account (starts with 'pit-').")
|
|
5175
5345
|
},
|
|
5176
5346
|
async ({ locationId: locationId2, name, apiKey: apiKey2 }) => {
|
|
5177
5347
|
if (!registry2) {
|
|
@@ -5221,7 +5391,7 @@ The API key could not access location ${locationId2}. Make sure:
|
|
|
5221
5391
|
"unregister_location",
|
|
5222
5392
|
"Remove a GHL sub-account from the token registry.",
|
|
5223
5393
|
{
|
|
5224
|
-
locationId:
|
|
5394
|
+
locationId: import_zod36.z.string().describe("The Location ID to remove.")
|
|
5225
5395
|
},
|
|
5226
5396
|
async ({ locationId: locationId2 }) => {
|
|
5227
5397
|
if (!registry2) {
|
|
@@ -5280,8 +5450,8 @@ ${lines.join("\n")}
|
|
|
5280
5450
|
"list_available_locations",
|
|
5281
5451
|
"List all GHL sub-accounts (locations) accessible with the current or agency API key. Shows locations that exist in the GHL account \u2014 use register_location to add their tokens. Offset-based pagination via skip/limit.",
|
|
5282
5452
|
{
|
|
5283
|
-
limit:
|
|
5284
|
-
skip:
|
|
5453
|
+
limit: import_zod36.z.number().optional().describe("Max locations to return. Defaults to 20."),
|
|
5454
|
+
skip: import_zod36.z.number().optional().describe("Number to skip for pagination.")
|
|
5285
5455
|
},
|
|
5286
5456
|
async ({ limit, skip }) => {
|
|
5287
5457
|
try {
|
|
@@ -5324,7 +5494,7 @@ ${lines.join("\n")}
|
|
|
5324
5494
|
}
|
|
5325
5495
|
|
|
5326
5496
|
// src/tools/bulk-operations.ts
|
|
5327
|
-
var
|
|
5497
|
+
var import_zod37 = require("zod");
|
|
5328
5498
|
function delay(ms) {
|
|
5329
5499
|
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
5330
5500
|
}
|
|
@@ -5336,8 +5506,8 @@ function registerBulkOperationTools(server2, client) {
|
|
|
5336
5506
|
"bulk_add_tags",
|
|
5337
5507
|
"Add tags to multiple contacts at once. Rate-limited to avoid API throttling. Returns a summary of successes and failures.",
|
|
5338
5508
|
{
|
|
5339
|
-
contactIds:
|
|
5340
|
-
tags:
|
|
5509
|
+
contactIds: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to tag."),
|
|
5510
|
+
tags: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one tag required.").describe("Tags to add to each contact.")
|
|
5341
5511
|
},
|
|
5342
5512
|
async ({ contactIds, tags }) => {
|
|
5343
5513
|
const results = { success: 0, failed: 0, errors: [] };
|
|
@@ -5359,8 +5529,8 @@ function registerBulkOperationTools(server2, client) {
|
|
|
5359
5529
|
"bulk_remove_tags",
|
|
5360
5530
|
"Remove tags from multiple contacts at once. Rate-limited.",
|
|
5361
5531
|
{
|
|
5362
|
-
contactIds:
|
|
5363
|
-
tags:
|
|
5532
|
+
contactIds: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs."),
|
|
5533
|
+
tags: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one tag required.").describe("Tags to remove from each contact.")
|
|
5364
5534
|
},
|
|
5365
5535
|
async ({ contactIds, tags }) => {
|
|
5366
5536
|
const results = { success: 0, failed: 0, errors: [] };
|
|
@@ -5381,8 +5551,8 @@ function registerBulkOperationTools(server2, client) {
|
|
|
5381
5551
|
"bulk_update_contacts",
|
|
5382
5552
|
"Update the same field(s) on multiple contacts at once. Rate-limited. Example: set a custom field value, change source, update address for a batch of contacts.",
|
|
5383
5553
|
{
|
|
5384
|
-
contactIds:
|
|
5385
|
-
fields:
|
|
5554
|
+
contactIds: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to update."),
|
|
5555
|
+
fields: import_zod37.z.record(import_zod37.z.unknown()).describe("Fields to set on each contact (e.g. {customField: {id: 'xxx', value: 'yyy'}}, {source: 'Import'}).")
|
|
5386
5556
|
},
|
|
5387
5557
|
async ({ contactIds, fields }) => {
|
|
5388
5558
|
const results = { success: 0, failed: 0, errors: [] };
|
|
@@ -5403,8 +5573,8 @@ function registerBulkOperationTools(server2, client) {
|
|
|
5403
5573
|
"bulk_add_to_workflow",
|
|
5404
5574
|
"Enroll multiple contacts into a workflow at once. Rate-limited.",
|
|
5405
5575
|
{
|
|
5406
|
-
contactIds:
|
|
5407
|
-
workflowId:
|
|
5576
|
+
contactIds: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to enroll."),
|
|
5577
|
+
workflowId: import_zod37.z.string().describe("The workflow ID to enroll contacts into.")
|
|
5408
5578
|
},
|
|
5409
5579
|
async ({ contactIds, workflowId }) => {
|
|
5410
5580
|
const results = { success: 0, failed: 0, errors: [] };
|
|
@@ -5425,8 +5595,8 @@ function registerBulkOperationTools(server2, client) {
|
|
|
5425
5595
|
"bulk_delete_contacts",
|
|
5426
5596
|
"Delete multiple contacts at once. IRREVERSIBLE. Rate-limited. Use with extreme caution.",
|
|
5427
5597
|
{
|
|
5428
|
-
contactIds:
|
|
5429
|
-
confirm:
|
|
5598
|
+
contactIds: import_zod37.z.array(import_zod37.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to permanently delete."),
|
|
5599
|
+
confirm: import_zod37.z.literal("DELETE").describe("Must pass the string 'DELETE' to confirm. This is a safety check.")
|
|
5430
5600
|
},
|
|
5431
5601
|
async ({ contactIds, confirm }) => {
|
|
5432
5602
|
if (confirm !== "DELETE") {
|
|
@@ -5449,7 +5619,7 @@ function registerBulkOperationTools(server2, client) {
|
|
|
5449
5619
|
}
|
|
5450
5620
|
|
|
5451
5621
|
// src/tools/account-export.ts
|
|
5452
|
-
var
|
|
5622
|
+
var import_zod38 = require("zod");
|
|
5453
5623
|
function delay2(ms) {
|
|
5454
5624
|
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
5455
5625
|
}
|
|
@@ -5459,8 +5629,8 @@ function registerAccountExportTools(server2, client) {
|
|
|
5459
5629
|
"export_account",
|
|
5460
5630
|
"Export a complete inventory of the GHL sub-account: location info, contacts (count + sample), pipelines with stages, workflows (with full actions if builder auth is configured), funnels with pages, forms, custom fields, custom values, tags, calendars, and users. Returns a comprehensive JSON report for auditing or backup.",
|
|
5461
5631
|
{
|
|
5462
|
-
locationId:
|
|
5463
|
-
includeContacts:
|
|
5632
|
+
locationId: import_zod38.z.string().optional().describe("Location ID to export. Uses default if not specified."),
|
|
5633
|
+
includeContacts: import_zod38.z.boolean().optional().describe("Include contact list (first 100). Defaults to false for speed.")
|
|
5464
5634
|
},
|
|
5465
5635
|
async ({ locationId: locationId2, includeContacts }) => {
|
|
5466
5636
|
try {
|
|
@@ -5588,8 +5758,8 @@ function registerAccountExportTools(server2, client) {
|
|
|
5588
5758
|
"compare_locations",
|
|
5589
5759
|
"Compare two GHL sub-accounts side by side \u2014 shows differences in pipelines, workflows, custom fields, tags, forms, and funnels. Useful for ensuring consistency across locations or auditing before/after changes.",
|
|
5590
5760
|
{
|
|
5591
|
-
locationA:
|
|
5592
|
-
locationB:
|
|
5761
|
+
locationA: import_zod38.z.string().describe("First Location ID."),
|
|
5762
|
+
locationB: import_zod38.z.string().describe("Second Location ID.")
|
|
5593
5763
|
},
|
|
5594
5764
|
async ({ locationA, locationB }) => {
|
|
5595
5765
|
try {
|
|
@@ -5667,7 +5837,7 @@ function registerAccountExportTools(server2, client) {
|
|
|
5667
5837
|
}
|
|
5668
5838
|
|
|
5669
5839
|
// src/tools/workflow-cloner.ts
|
|
5670
|
-
var
|
|
5840
|
+
var import_zod39 = require("zod");
|
|
5671
5841
|
var crypto2 = __toESM(require("crypto"));
|
|
5672
5842
|
function registerWorkflowClonerTools(server2, builderClient) {
|
|
5673
5843
|
const client = builderClient;
|
|
@@ -5676,8 +5846,8 @@ function registerWorkflowClonerTools(server2, builderClient) {
|
|
|
5676
5846
|
"clone_workflow",
|
|
5677
5847
|
"Deep clone a workflow \u2014 creates an exact copy with new IDs for all actions, triggers, and references. The clone starts as a draft. Useful for creating templates or duplicating workflows across projects.",
|
|
5678
5848
|
{
|
|
5679
|
-
sourceWorkflowId:
|
|
5680
|
-
newName:
|
|
5849
|
+
sourceWorkflowId: import_zod39.z.string().describe("The workflow ID to clone."),
|
|
5850
|
+
newName: import_zod39.z.string().describe("Name for the cloned workflow.")
|
|
5681
5851
|
},
|
|
5682
5852
|
async ({ sourceWorkflowId, newName }) => {
|
|
5683
5853
|
try {
|
|
@@ -5766,41 +5936,41 @@ function registerWorkflowClonerTools(server2, builderClient) {
|
|
|
5766
5936
|
}
|
|
5767
5937
|
|
|
5768
5938
|
// src/tools/template-deployer.ts
|
|
5769
|
-
var
|
|
5939
|
+
var import_zod40 = require("zod");
|
|
5770
5940
|
var fs3 = __toESM(require("fs"));
|
|
5771
5941
|
var path3 = __toESM(require("path"));
|
|
5772
5942
|
function delay3(ms) {
|
|
5773
5943
|
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
5774
5944
|
}
|
|
5775
|
-
var TemplateSchema =
|
|
5776
|
-
templateName:
|
|
5777
|
-
templateVersion:
|
|
5778
|
-
description:
|
|
5779
|
-
questionnaire:
|
|
5780
|
-
id:
|
|
5781
|
-
question:
|
|
5782
|
-
type:
|
|
5783
|
-
required:
|
|
5784
|
-
placeholder:
|
|
5945
|
+
var TemplateSchema = import_zod40.z.object({
|
|
5946
|
+
templateName: import_zod40.z.string(),
|
|
5947
|
+
templateVersion: import_zod40.z.string().optional(),
|
|
5948
|
+
description: import_zod40.z.string().optional().default(""),
|
|
5949
|
+
questionnaire: import_zod40.z.array(import_zod40.z.object({
|
|
5950
|
+
id: import_zod40.z.string(),
|
|
5951
|
+
question: import_zod40.z.string(),
|
|
5952
|
+
type: import_zod40.z.string(),
|
|
5953
|
+
required: import_zod40.z.boolean().optional(),
|
|
5954
|
+
placeholder: import_zod40.z.string().optional()
|
|
5785
5955
|
})).optional().default([]),
|
|
5786
|
-
location:
|
|
5787
|
-
tags:
|
|
5788
|
-
customFields:
|
|
5789
|
-
name:
|
|
5790
|
-
dataType:
|
|
5956
|
+
location: import_zod40.z.record(import_zod40.z.unknown()).optional(),
|
|
5957
|
+
tags: import_zod40.z.array(import_zod40.z.string()).optional(),
|
|
5958
|
+
customFields: import_zod40.z.array(import_zod40.z.object({
|
|
5959
|
+
name: import_zod40.z.string(),
|
|
5960
|
+
dataType: import_zod40.z.string()
|
|
5791
5961
|
})).optional(),
|
|
5792
|
-
pipelines:
|
|
5793
|
-
name:
|
|
5794
|
-
stages:
|
|
5962
|
+
pipelines: import_zod40.z.array(import_zod40.z.object({
|
|
5963
|
+
name: import_zod40.z.string(),
|
|
5964
|
+
stages: import_zod40.z.array(import_zod40.z.object({ position: import_zod40.z.number(), name: import_zod40.z.string() }))
|
|
5795
5965
|
})).optional(),
|
|
5796
|
-
workflows:
|
|
5797
|
-
name:
|
|
5798
|
-
condition:
|
|
5799
|
-
actions:
|
|
5966
|
+
workflows: import_zod40.z.array(import_zod40.z.object({
|
|
5967
|
+
name: import_zod40.z.string(),
|
|
5968
|
+
condition: import_zod40.z.string().optional(),
|
|
5969
|
+
actions: import_zod40.z.array(import_zod40.z.record(import_zod40.z.unknown())).optional().default([])
|
|
5800
5970
|
})).optional(),
|
|
5801
|
-
calendars:
|
|
5802
|
-
name:
|
|
5803
|
-
description:
|
|
5971
|
+
calendars: import_zod40.z.array(import_zod40.z.object({
|
|
5972
|
+
name: import_zod40.z.string(),
|
|
5973
|
+
description: import_zod40.z.string().optional()
|
|
5804
5974
|
})).optional()
|
|
5805
5975
|
});
|
|
5806
5976
|
function registerTemplateDeployerTools(server2, client) {
|
|
@@ -5871,7 +6041,7 @@ function registerTemplateDeployerTools(server2, client) {
|
|
|
5871
6041
|
"get_template_questionnaire",
|
|
5872
6042
|
"Get the questionnaire for a specific template. Returns all the questions that need to be answered before deploying. Present these to the user one at a time in a conversational style.",
|
|
5873
6043
|
{
|
|
5874
|
-
templateFile:
|
|
6044
|
+
templateFile: import_zod40.z.string().describe("Path to the template JSON file (from list_templates).")
|
|
5875
6045
|
},
|
|
5876
6046
|
async ({ templateFile }) => {
|
|
5877
6047
|
try {
|
|
@@ -5904,10 +6074,10 @@ function registerTemplateDeployerTools(server2, client) {
|
|
|
5904
6074
|
"deploy_template",
|
|
5905
6075
|
"Deploy a template to set up a GHL sub-account. Creates tags, custom fields, pipelines with stages, calendars, workflows, and forms based on the template and the user's questionnaire answers. This is the main setup automation tool.",
|
|
5906
6076
|
{
|
|
5907
|
-
templateFile:
|
|
5908
|
-
answers:
|
|
5909
|
-
locationId:
|
|
5910
|
-
dryRun:
|
|
6077
|
+
templateFile: import_zod40.z.string().describe("Path to the template JSON file."),
|
|
6078
|
+
answers: import_zod40.z.record(import_zod40.z.unknown()).describe("Questionnaire answers keyed by question ID (e.g. {business_name: 'My Clinic', business_phone: '+15551234567', ...})."),
|
|
6079
|
+
locationId: import_zod40.z.string().optional().describe("Location ID to deploy to. Uses default if not specified."),
|
|
6080
|
+
dryRun: import_zod40.z.boolean().optional().describe("If true, shows what would be created without actually creating anything. Defaults to false.")
|
|
5911
6081
|
},
|
|
5912
6082
|
async ({ templateFile, answers, locationId: locationId2, dryRun }) => {
|
|
5913
6083
|
try {
|
|
@@ -6153,7 +6323,7 @@ ${errors.join("\n")}` : "\nNo errors!",
|
|
|
6153
6323
|
}
|
|
6154
6324
|
|
|
6155
6325
|
// src/tools/validators.ts
|
|
6156
|
-
var
|
|
6326
|
+
var import_zod41 = require("zod");
|
|
6157
6327
|
function extractFromTrigger(trigger, refs) {
|
|
6158
6328
|
const triggerName = String(trigger.name ?? trigger.type ?? "unnamed trigger");
|
|
6159
6329
|
const where = `trigger "${triggerName}"`;
|
|
@@ -6288,7 +6458,7 @@ function registerValidatorTools(server2, client, builderClient) {
|
|
|
6288
6458
|
"validate_workflow",
|
|
6289
6459
|
"Pre-flight ID validation for a deployed GHL workflow. Scans every trigger and action for references to pipelines, pipeline stages, custom fields, users, workflows, forms, calendars, and surveys; verifies each ID exists in the current location. Use this BEFORE publish_workflow when a workflow has been edited, or whenever a published workflow stops behaving as expected. Catches the silent-failure bug where invalid IDs make GHL skip all subsequent actions without warning. Returns a structured report of valid + missing references.",
|
|
6290
6460
|
{
|
|
6291
|
-
workflowId:
|
|
6461
|
+
workflowId: import_zod41.z.string().describe("The workflow ID to validate.")
|
|
6292
6462
|
},
|
|
6293
6463
|
async ({ workflowId }) => {
|
|
6294
6464
|
try {
|
|
@@ -6625,6 +6795,7 @@ var publicApiTools = [
|
|
|
6625
6795
|
[registerFormTools, "forms"],
|
|
6626
6796
|
[registerSurveyTools, "surveys"],
|
|
6627
6797
|
[registerPaymentTools, "payments"],
|
|
6798
|
+
[registerProductTools, "products"],
|
|
6628
6799
|
[registerInvoiceTools, "invoices"],
|
|
6629
6800
|
[registerCampaignTools, "campaigns"],
|
|
6630
6801
|
[registerUserTools, "users"],
|
|
@@ -6664,18 +6835,18 @@ function registerAllTools(server2, client, registry2, mcpVersion) {
|
|
|
6664
6835
|
var fs4 = __toESM(require("fs"));
|
|
6665
6836
|
var path4 = __toESM(require("path"));
|
|
6666
6837
|
var os = __toESM(require("os"));
|
|
6667
|
-
var
|
|
6838
|
+
var import_zod42 = require("zod");
|
|
6668
6839
|
var APP_NAME = "elitedcs-ghl-mcp";
|
|
6669
|
-
var CredentialsSchema =
|
|
6670
|
-
license_key:
|
|
6671
|
-
email:
|
|
6672
|
-
verified_at:
|
|
6673
|
-
ghl_api_key:
|
|
6674
|
-
ghl_location_id:
|
|
6675
|
-
ghl_company_id:
|
|
6676
|
-
ghl_user_id:
|
|
6677
|
-
ghl_firebase_api_key:
|
|
6678
|
-
ghl_firebase_refresh_token:
|
|
6840
|
+
var CredentialsSchema = import_zod42.z.object({
|
|
6841
|
+
license_key: import_zod42.z.string().min(1),
|
|
6842
|
+
email: import_zod42.z.string().email(),
|
|
6843
|
+
verified_at: import_zod42.z.string().min(1),
|
|
6844
|
+
ghl_api_key: import_zod42.z.string().min(1),
|
|
6845
|
+
ghl_location_id: import_zod42.z.string().min(1),
|
|
6846
|
+
ghl_company_id: import_zod42.z.string().optional(),
|
|
6847
|
+
ghl_user_id: import_zod42.z.string().optional(),
|
|
6848
|
+
ghl_firebase_api_key: import_zod42.z.string().optional(),
|
|
6849
|
+
ghl_firebase_refresh_token: import_zod42.z.string().optional()
|
|
6679
6850
|
});
|
|
6680
6851
|
function appDataDir() {
|
|
6681
6852
|
const home = os.homedir();
|
|
@@ -6725,7 +6896,7 @@ function writeCredentials(creds) {
|
|
|
6725
6896
|
// src/setup-tool.ts
|
|
6726
6897
|
var os2 = __toESM(require("os"));
|
|
6727
6898
|
var crypto3 = __toESM(require("crypto"));
|
|
6728
|
-
var
|
|
6899
|
+
var import_zod43 = require("zod");
|
|
6729
6900
|
var LICENSE_API = "https://elitedcs.com/api/validate-license";
|
|
6730
6901
|
var GHL_API = "https://services.leadconnectorhq.com";
|
|
6731
6902
|
var FIREBASE_TOKEN_API = "https://securetoken.googleapis.com/v1/token";
|
|
@@ -6794,16 +6965,16 @@ async function validateFirebase(firebaseKey, refreshToken) {
|
|
|
6794
6965
|
function registerSetupTool(server2) {
|
|
6795
6966
|
server2.tool(
|
|
6796
6967
|
"setup_ghl_mcp",
|
|
6797
|
-
"First-run setup for GHL Command MCP. Validates your license and GHL credentials, then writes them to a per-user credentials file. Restart Claude after this completes to load all
|
|
6968
|
+
"First-run setup for GHL Command MCP. Validates your license and GHL credentials, then writes them to a per-user credentials file. Restart Claude after this completes to load all 187 tools (157 if you skip the optional Firebase fields; add Firebase later with enable_workflow_builder).",
|
|
6798
6969
|
{
|
|
6799
|
-
email:
|
|
6800
|
-
license_key:
|
|
6801
|
-
ghl_api_key:
|
|
6802
|
-
ghl_location_id:
|
|
6803
|
-
ghl_company_id:
|
|
6804
|
-
ghl_user_id:
|
|
6805
|
-
ghl_firebase_api_key:
|
|
6806
|
-
ghl_firebase_refresh_token:
|
|
6970
|
+
email: import_zod43.z.string().email().describe("Email used at purchase."),
|
|
6971
|
+
license_key: import_zod43.z.string().min(20).describe("License key from your purchase email."),
|
|
6972
|
+
ghl_api_key: import_zod43.z.string().min(10).describe("GHL Private Integration key (starts with 'pit-'). Created INSIDE the sub-account at Settings > Integrations > Private Integrations."),
|
|
6973
|
+
ghl_location_id: import_zod43.z.string().min(10).describe("GHL Location ID (sub-account ID). Found in your GHL URL: /location/THIS_PART/dashboard."),
|
|
6974
|
+
ghl_company_id: import_zod43.z.string().optional().describe("(Agency only) Company ID for multi-location access."),
|
|
6975
|
+
ghl_user_id: import_zod43.z.string().optional().describe("(Workflow Builder, optional) Firebase User ID. See README for browser capture instructions."),
|
|
6976
|
+
ghl_firebase_api_key: import_zod43.z.string().optional().describe("(Workflow Builder, optional) Firebase API Key starting with 'AIza'."),
|
|
6977
|
+
ghl_firebase_refresh_token: import_zod43.z.string().optional().describe("(Workflow Builder, optional) Firebase refresh token starting with 'AMf-'.")
|
|
6807
6978
|
},
|
|
6808
6979
|
async (args) => {
|
|
6809
6980
|
const lic = await validateLicense(args.email, args.license_key);
|
|
@@ -6849,7 +7020,7 @@ Note: Firebase credentials rejected (${fb.error}). Saved without Workflow Builde
|
|
|
6849
7020
|
ghl_firebase_api_key: workflowBuilderEnabled ? args.ghl_firebase_api_key?.trim() : void 0,
|
|
6850
7021
|
ghl_firebase_refresh_token: workflowBuilderEnabled ? args.ghl_firebase_refresh_token?.trim() : void 0
|
|
6851
7022
|
});
|
|
6852
|
-
const toolCount = workflowBuilderEnabled ? "
|
|
7023
|
+
const toolCount = workflowBuilderEnabled ? "187" : "157";
|
|
6853
7024
|
const wfLine = workflowBuilderEnabled ? "Workflow Builder: enabled." : "Workflow Builder: not configured (optional).";
|
|
6854
7025
|
const wfTip = workflowBuilderEnabled ? "" : "\nTo enable Workflow Builder later (8 extra tools): run enable_workflow_builder with your three Firebase values. No need to re-enter license/API key/location ID.";
|
|
6855
7026
|
return {
|
|
@@ -6877,11 +7048,11 @@ Note: Firebase credentials rejected (${fb.error}). Saved without Workflow Builde
|
|
|
6877
7048
|
function registerEnableWorkflowBuilderTool(server2) {
|
|
6878
7049
|
server2.tool(
|
|
6879
7050
|
"enable_workflow_builder",
|
|
6880
|
-
"Add Firebase credentials to an existing GHL Command install to unlock 30 additional tools across 6 modules: workflow builder (create/edit/clone/delete/publish/validate workflows, build_if_else_branch, build_goal_event, get_trigger_registry), funnel + page builder (10 tools), form builder (5 tools), pipeline builder (5 tools), and workflow cloning. Requires you've already run setup_ghl_mcp. Capture the three Firebase values from your GHL browser session \u2014 see elitedcs.com/ghl-mcp-firebase for step-by-step DevTools instructions. Tool count goes from
|
|
7051
|
+
"Add Firebase credentials to an existing GHL Command install to unlock 30 additional tools across 6 modules: workflow builder (create/edit/clone/delete/publish/validate workflows, build_if_else_branch, build_goal_event, get_trigger_registry), funnel + page builder (10 tools), form builder (5 tools), pipeline builder (5 tools), and workflow cloning. Requires you've already run setup_ghl_mcp. Capture the three Firebase values from your GHL browser session \u2014 see elitedcs.com/ghl-mcp-firebase for step-by-step DevTools instructions. Tool count goes from 157 to 187 after the next Claude restart.",
|
|
6881
7052
|
{
|
|
6882
|
-
ghl_user_id:
|
|
6883
|
-
ghl_firebase_api_key:
|
|
6884
|
-
ghl_firebase_refresh_token:
|
|
7053
|
+
ghl_user_id: import_zod43.z.string().min(10).describe("Firebase User ID (uid). DevTools \u2192 Application \u2192 IndexedDB \u2192 firebaseLocalStorageDb \u2192 firebaseLocalStorage \u2192 the value.uid field of the firebase:authUser row."),
|
|
7054
|
+
ghl_firebase_api_key: import_zod43.z.string().min(10).describe("Firebase API Key starting with 'AIza'. The string between 'firebase:authUser:' and ':[DEFAULT]' in the row's Key column."),
|
|
7055
|
+
ghl_firebase_refresh_token: import_zod43.z.string().min(10).describe("Firebase refresh token. value.stsTokenManager.refreshToken in the firebase:authUser row.")
|
|
6885
7056
|
},
|
|
6886
7057
|
async (args) => {
|
|
6887
7058
|
const existing = readCredentials();
|
|
@@ -6924,7 +7095,7 @@ DevTools steps: https://elitedcs.com/ghl-mcp-firebase`
|
|
|
6924
7095
|
"",
|
|
6925
7096
|
"Firebase credentials verified and saved.",
|
|
6926
7097
|
"",
|
|
6927
|
-
"**Restart Claude (quit fully and reopen) to load the workflow builder + funnel builder + pipeline builder + form builder + workflow cloner tools (
|
|
7098
|
+
"**Restart Claude (quit fully and reopen) to load the workflow builder + funnel builder + pipeline builder + form builder + workflow cloner tools (187 total).**",
|
|
6928
7099
|
"",
|
|
6929
7100
|
'After restart, try: "List my workflows in full detail" or "Validate workflow <id>".',
|
|
6930
7101
|
"",
|