@elitedcs/ghl-mcp 3.14.0 → 3.15.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 CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.15.0 — Email-template delete, rename, archive (Firebase-gated)
4
+
5
+ **206 tools across 43 modules (+3). Manage email templates without leaving Claude.**
6
+
7
+ Until now you could create and update email templates through the public API, but deleting or renaming one meant clicking through the GHL UI — the public bearer API 404s on both. Those mutations live on the internal API behind Firebase auth. Confirmed working 2026-05-24 against the MCP Testing sandbox and verified end-to-end (create → rename → archive → unarchive → delete, round-trip clean).
8
+
9
+ ### New tools (3, all require Firebase configured)
10
+
11
+ - **`delete_email_template`** — hard delete a template by id. Irreversible. Breaks any workflow email action or draft campaign that references it.
12
+ - **`rename_email_template`** — change a template's display title only; HTML content and sender settings untouched.
13
+ - **`archive_email_template`** — archive (`archived: true`) or restore (`archived: false`) a template. Removes it from the active list without deleting it — the reversible alternative to delete.
14
+
15
+ All three hit `backend.leadconnectorhq.com/emails/builder` with the workflow-builder Firebase token (the GHL UI persists via Firestore, but the REST routes exist server-side). Registered by `registerEmailBuilderInternalTools` in the internal-API block. `update_email_template`'s description now points at `rename_email_template` / `delete_email_template` instead of telling you to use the UI.
16
+
3
17
  ## 3.14.0 — Multi-tenant Firebase: run the workflow builder in clients' accounts
4
18
 
5
19
  **203 tools across 43 modules (+2). The workflow builder is no longer single-company.**
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # GHL Command — GoHighLevel MCP Server
2
2
 
3
- **Full GoHighLevel API access for Claude.** 203 tools across 43 modules — manage contacts, conversations, pipelines, calendars, funnels, workflows, invoices, custom objects, webhooks, and more. **Includes full workflow builder, funnel/page editor, form builder, pipeline builder, bulk operations, account export, and workflow cloning** — capabilities no other GHL tool offers. **Multi-tenant:** one install can run the workflow builder across multiple clients' GHL accounts.
3
+ **Full GoHighLevel API access for Claude.** 206 tools across 43 modules — manage contacts, conversations, pipelines, calendars, funnels, workflows, invoices, custom objects, webhooks, and more. **Includes full workflow builder, funnel/page editor, form builder, pipeline builder, bulk operations, account export, and workflow cloning** — capabilities no other GHL tool offers. **Multi-tenant:** one install can run the workflow builder across multiple clients' GHL accounts.
4
4
 
5
5
  **Distributed via npm as [`@elitedcs/ghl-mcp`](https://www.npmjs.com/package/@elitedcs/ghl-mcp).** Buyers install with one config block — no git, no Node.js setup, no terminal commands. Updates flow automatically (`npx @latest` re-resolves on every Claude restart).
6
6
 
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.14.0",
35
- description: "GoHighLevel MCP Server for Claude. 203 tools \u2014 full CRM, automation, marketing control, and the only programmatic GHL workflow builder, now multi-tenant across client accounts.",
34
+ version: "3.15.0",
35
+ description: "GoHighLevel MCP Server for Claude. 206 tools \u2014 full CRM, automation, marketing control, and the only programmatic GHL workflow builder, now multi-tenant across client accounts.",
36
36
  main: "dist/index.js",
37
37
  bin: {
38
38
  "ghl-mcp": "dist/index.js"
@@ -3860,6 +3860,7 @@ function registerBlogTools(server2, client) {
3860
3860
 
3861
3861
  // src/tools/emails.ts
3862
3862
  var import_zod25 = require("zod");
3863
+ var EMAIL_BUILDER_BASE = "https://backend.leadconnectorhq.com/emails/builder";
3863
3864
  var TEMPLATE_TYPES = ["html", "folder", "import", "builder", "blank", "ai_template", "vibe-editor"];
3864
3865
  var EDITOR_TYPES = ["html", "builder"];
3865
3866
  function registerEmailTools(server2, client) {
@@ -3930,7 +3931,7 @@ function registerEmailTools(server2, client) {
3930
3931
  safeTool(
3931
3932
  server2,
3932
3933
  "update_email_template",
3933
- "Save HTML content into an existing email template. Use this to update the body of a template after `create_email_template`. The `updatedBy` field is required by GHL; defaults to 'mcp' if not provided. Note: this updates CONTENT only. Renaming the title or deleting the template is not yet possible through the public API \u2014 do those in the GHL UI for now.",
3934
+ "Save HTML content into an existing email template. Use this to update the body of a template after `create_email_template`. The `updatedBy` field is required by GHL; defaults to 'mcp' if not provided. Note: this updates CONTENT only. To rename a template use `rename_email_template`; to delete it use `delete_email_template` (both Firebase-gated).",
3934
3935
  {
3935
3936
  templateId: import_zod25.z.string().describe("The template ID to update (from create_email_template or list_email_templates)."),
3936
3937
  html: import_zod25.z.string().describe("The full HTML body of the email. Can include merge fields like {{contact.first_name}}."),
@@ -3952,6 +3953,78 @@ function registerEmailTools(server2, client) {
3952
3953
  }
3953
3954
  );
3954
3955
  }
3956
+ function registerEmailBuilderInternalTools(server2, builderClient) {
3957
+ const client = builderClient;
3958
+ if (!client) return;
3959
+ async function builderRequest(method, path6, body) {
3960
+ const headers = await client.buildHeaders();
3961
+ const response = await fetch(`${EMAIL_BUILDER_BASE}${path6}`, {
3962
+ method,
3963
+ headers,
3964
+ body: body ? JSON.stringify(body) : void 0
3965
+ });
3966
+ if (!response.ok) {
3967
+ const text2 = await response.text();
3968
+ throw new Error(`Email Builder API Error ${response.status}: ${method} /emails/builder${path6}
3969
+ ${text2}`);
3970
+ }
3971
+ const text = await response.text();
3972
+ return text ? JSON.parse(text) : { ok: true };
3973
+ }
3974
+ server2.tool(
3975
+ "delete_email_template",
3976
+ "Permanently delete an email template ('builder') by id. This is a HARD delete \u2014 the template is removed, not archived (use archive_email_template if you want a reversible remove). Requires Firebase auth; the public bearer API can't do this. Get the templateId from list_email_templates. WARNING: irreversible. If the template is referenced by a workflow email action or a draft campaign, deleting it will break that reference.",
3977
+ {
3978
+ templateId: import_zod25.z.string().describe("The template id to delete (from list_email_templates, the `id` field)."),
3979
+ locationId: import_zod25.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
3980
+ },
3981
+ async ({ templateId, locationId: locationId2 }) => {
3982
+ try {
3983
+ const loc = locationId2 ?? client.locationId;
3984
+ const result = await builderRequest("DELETE", `/data/${templateId}?locationId=${loc}`);
3985
+ return jsonResponse(result);
3986
+ } catch (error) {
3987
+ return errorResponse(error);
3988
+ }
3989
+ }
3990
+ );
3991
+ server2.tool(
3992
+ "rename_email_template",
3993
+ "Rename an existing email template ('builder'). Updates the display title only; the HTML content and sender settings are left untouched. Requires Firebase auth; the public bearer API can't do this. Get the templateId from list_email_templates.",
3994
+ {
3995
+ templateId: import_zod25.z.string().describe("The template id to rename (from list_email_templates, the `id` field)."),
3996
+ name: import_zod25.z.string().describe("The new display name for the template (e.g., 'May Newsletter \u2014 Final')."),
3997
+ locationId: import_zod25.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
3998
+ },
3999
+ async ({ templateId, name, locationId: locationId2 }) => {
4000
+ try {
4001
+ const loc = locationId2 ?? client.locationId;
4002
+ const result = await builderRequest("PATCH", `/${templateId}`, { locationId: loc, name });
4003
+ return jsonResponse(result);
4004
+ } catch (error) {
4005
+ return errorResponse(error);
4006
+ }
4007
+ }
4008
+ );
4009
+ server2.tool(
4010
+ "archive_email_template",
4011
+ "Archive (or unarchive) an email template ('builder'). Archiving removes it from the active templates list without deleting it \u2014 a reversible alternative to delete_email_template. Requires Firebase auth. Get the templateId from list_email_templates.",
4012
+ {
4013
+ templateId: import_zod25.z.string().describe("The template id to archive/unarchive (from list_email_templates, the `id` field)."),
4014
+ archived: import_zod25.z.boolean().optional().describe("true to archive (default), false to restore from archive."),
4015
+ locationId: import_zod25.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
4016
+ },
4017
+ async ({ templateId, archived, locationId: locationId2 }) => {
4018
+ try {
4019
+ const loc = locationId2 ?? client.locationId;
4020
+ const result = await builderRequest("PATCH", `/${templateId}`, { locationId: loc, archived: archived ?? true });
4021
+ return jsonResponse(result);
4022
+ } catch (error) {
4023
+ return errorResponse(error);
4024
+ }
4025
+ }
4026
+ );
4027
+ }
3955
4028
 
3956
4029
  // src/tools/trigger-links.ts
3957
4030
  var import_zod26 = require("zod");
@@ -5658,7 +5731,7 @@ async function validateFirebase(firebaseKey, refreshToken) {
5658
5731
  function registerSetupTool(server2) {
5659
5732
  server2.tool(
5660
5733
  "setup_ghl_mcp",
5661
- "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 203 tools (163 if you skip the optional Firebase fields; add Firebase later with enable_workflow_builder).",
5734
+ "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 206 tools (163 if you skip the optional Firebase fields; add Firebase later with enable_workflow_builder).",
5662
5735
  {
5663
5736
  email: import_zod37.z.string().email().describe("Email used at purchase."),
5664
5737
  license_key: import_zod37.z.string().min(20).describe("License key from your purchase email."),
@@ -5713,7 +5786,7 @@ Note: Firebase credentials rejected (${fb.error}). Saved without Workflow Builde
5713
5786
  ghl_firebase_api_key: workflowBuilderEnabled ? args.ghl_firebase_api_key?.trim() : void 0,
5714
5787
  ghl_firebase_refresh_token: workflowBuilderEnabled ? args.ghl_firebase_refresh_token?.trim() : void 0
5715
5788
  });
5716
- const toolCount = workflowBuilderEnabled ? "203" : "163";
5789
+ const toolCount = workflowBuilderEnabled ? "206" : "163";
5717
5790
  const wfLine = workflowBuilderEnabled ? "Workflow Builder: enabled." : "Workflow Builder: not configured (optional).";
5718
5791
  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.";
5719
5792
  return {
@@ -7863,6 +7936,7 @@ function registerAllTools(server2, client, registry2, mcpVersion) {
7863
7936
  registerSmartListTools(server2, builderClient);
7864
7937
  registerReputationTools(server2, builderClient);
7865
7938
  registerEmailCampaignTools(server2, builderClient);
7939
+ registerEmailBuilderInternalTools(server2, builderClient);
7866
7940
  registerMembershipTools(server2, builderClient);
7867
7941
  registerValidatorTools(server2, client, builderClient);
7868
7942
  registerDiagnosticTools(server2, mcpVersion ?? "unknown", client, builderClient, registry2 ?? null);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@elitedcs/ghl-mcp",
3
- "version": "3.14.0",
4
- "description": "GoHighLevel MCP Server for Claude. 203 tools — full CRM, automation, marketing control, and the only programmatic GHL workflow builder, now multi-tenant across client accounts.",
3
+ "version": "3.15.0",
4
+ "description": "GoHighLevel MCP Server for Claude. 206 tools — full CRM, automation, marketing control, and the only programmatic GHL workflow builder, now multi-tenant across client accounts.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
7
  "ghl-mcp": "dist/index.js"