@elitedcs/ghl-mcp 3.0.3 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,55 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.1.1 — Auto-update visibility
4
+
5
+ **173 tools across 36 modules. Bundle: 249.7 KB.**
6
+
7
+ The v3.0 install email promises the MCP auto-updates on Claude restart, and it does. But the old `checkForUpdates()` only worked for local git-checkout dev installs — for buyers running `npx -y @elitedcs/ghl-mcp@latest` it silently returned. This release makes the upgrade visible and verifiable.
8
+
9
+ ### `checkForUpdates` rewritten for the npm install path
10
+ - Queries `registry.npmjs.org/@elitedcs/ghl-mcp/latest` instead of running `git fetch`.
11
+ - Writes a clear stderr line when a newer version is available: `Update available: vX → vY. Fully quit Claude (Cmd+Q on Mac) and reopen to upgrade.`
12
+ - 5 s timeout, non-blocking.
13
+
14
+ ### `get_mcp_version` tool (NEW)
15
+ - Returns installed version, latest published version on npm, and the one-line restart instruction if not current.
16
+ - Registered in BOTH bootstrap and normal modes — buyers without configured GHL credentials can still verify their MCP version.
17
+ - Use case: "Hey Claude, check your version" → instant confirmation an upgrade landed.
18
+
19
+ ### Version baked into `get_current_location`
20
+ - Adds `MCP version: vX.Y.Z` line to the response so the version surfaces naturally on the first GHL tool call of a session, no separate query needed.
21
+
22
+ ### Files changed
23
+ - `src/index.ts` — replaced git-based update check with npm registry check; registers meta tools in both modes; threads version into `registerAllTools`.
24
+ - `src/version-check.ts` — NEW: shared `fetchLatestVersion()` + `getVersionStatus()` used by startup banner and the tool.
25
+ - `src/tools/meta.ts` — NEW: `get_mcp_version` tool.
26
+ - `src/tools/index.ts` — `registerAllTools` accepts optional `mcpVersion` and threads it to the location switcher.
27
+ - `src/tools/location-switcher.ts` — appends `MCP version: vX.Y.Z` to `get_current_location` response.
28
+
29
+ ## 3.1.0 — Workflow trigger read-side coverage
30
+
31
+ **172 tools across 35 modules.**
32
+
33
+ GHL ships 57 native trigger types. The MCP previously typed only 4 (`customer_reply`, `appointment`, `contact_tag`, `pipeline_stage_updated`). Workflows using any of the other 53 — `form_submission`, `payment_received`, `opportunity_*`, `inbound_webhook`, etc. — threw Zod errors on `get_workflow_full`. This release unlocks all of them on the read side.
34
+
35
+ ### Permissive `WorkflowTriggerSchema`
36
+ - `z.union` of the 4 typed variants plus an `UnknownTriggerSchema` fallback that accepts any string-keyed `type` and a `conditions` array of arbitrary records.
37
+ - Write side is unchanged — typed triggers still get their typed conditions; unknown triggers pass through untouched on save.
38
+ - Defined in BOTH `src/workflow-builder-client.ts` and `src/tools/workflow-builder.ts` (read path + tool input schema).
39
+
40
+ ### `get_trigger_registry` tool (NEW)
41
+ - Calls GHL's marketplace endpoint `/marketplace/core/search/module?type=triggers` and returns ~85 third-party apps (Zoom, WooCommerce, Shopify, Monday, etc.) with their available triggers and `customVars`.
42
+ - Use case: discovering which marketplace triggers a sub-account can wire into workflows.
43
+ - `installedOnly` flag defaults to false (full catalogue).
44
+
45
+ ### `templates/trigger-schemas.json` reference (dev-side)
46
+ - Full catalogue: 57 native trigger types + 85 marketplace apps + 434 marketplace trigger entries, captured from the workflow-builder JS bundle + the marketplace API.
47
+ - Not shipped to npm consumers (excluded from `package.json` `files[]`) — kept in-repo as the source of truth for future typed-trigger work.
48
+
49
+ ### Coverage delta
50
+ - Before: 4 / 57 native trigger types typed (7%).
51
+ - After: 4 typed + 53 reachable via the permissive fallback (100% read coverage).
52
+
3
53
  ## 2.7.0 — Complete Type Safety (Boris Cherny A+)
4
54
 
5
55
  **171 tools across 35 modules. Bundle: 214KB.**
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # GHL Command — GoHighLevel MCP Server
2
2
 
3
- **Full GoHighLevel API access for Claude.** 171 tools across 35 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.
3
+ **Full GoHighLevel API access for Claude.** 173 tools across 36 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.
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
 
@@ -98,7 +98,7 @@ Run setup_ghl_mcp to activate GHL Command:
98
98
  ghl_location_id: YOUR_LOCATION_ID
99
99
  ```
100
100
 
101
- Approve the tool call. Server validates your license, verifies your GHL credentials, writes them to a per-user config file. **Quit Claude one more time and reopen** — all 165 tools are now unlocked.
101
+ Approve the tool call. Server validates your license, verifies your GHL credentials, writes them to a per-user config file. **Quit Claude one more time and reopen** — all 166 tools are now unlocked.
102
102
 
103
103
  ### 4. Try it
104
104
 
@@ -138,9 +138,19 @@ https://app.gohighlevel.com/v2/location/YOUR_LOCATION_ID/dashboard
138
138
 
139
139
  ## Enable Workflow Builder (Optional)
140
140
 
141
- The 6 workflow builder tools use GHL'''s internal API and require Firebase credentials. Without them, the other 165 tools work fine — you just won'''t have workflow editing.
141
+ The 7 workflow builder tools use GHL'''s internal API and require Firebase credentials. Without them, the other 166 tools work fine — you just won'''t have workflow editing.
142
142
 
143
- **The easy way:** [elitedcs.com/ghl-mcp-firebase](https://elitedcs.com/ghl-mcp-firebase) — drag the bookmarklet, click it inside GHL, your three values appear automatically. Then re-run `setup_ghl_mcp` with the extra fields:
143
+ Grab the three values from your GHL browser session, then re-run `setup_ghl_mcp` with them:
144
+
145
+ 1. Open `app.gohighlevel.com` in Chrome (or any Chromium browser), log in.
146
+ 2. Open DevTools (Cmd+Opt+I on Mac, F12 on Windows) → **Application** tab → **IndexedDB** in the left panel.
147
+ 3. Expand: `firebaseLocalStorageDb` → `firebaseLocalStorage`.
148
+ 4. Find the row whose key starts with `firebase:authUser:`.
149
+ 5. The part between `authUser:` and `:[DEFAULT]` is your **ghl_firebase_api_key** (starts with `AIza`).
150
+ 6. Inside that row's value object: `uid` is your **ghl_user_id**.
151
+ 7. Inside `value.stsTokenManager.refreshToken` is your **ghl_firebase_refresh_token**.
152
+
153
+ Then in Claude:
144
154
 
145
155
  ```
146
156
  Re-run setup_ghl_mcp with workflow builder:
@@ -148,16 +158,16 @@ Re-run setup_ghl_mcp with workflow builder:
148
158
  license_key: YOUR_LICENSE_KEY
149
159
  ghl_api_key: YOUR_GHL_API_KEY
150
160
  ghl_location_id: YOUR_LOCATION_ID
151
- ghl_user_id: FROM_FIREBASE_CAPTURE
152
- ghl_firebase_api_key: FROM_FIREBASE_CAPTURE
153
- ghl_firebase_refresh_token: FROM_FIREBASE_CAPTURE
161
+ ghl_user_id: FROM_STEP_6
162
+ ghl_firebase_api_key: FROM_STEP_5
163
+ ghl_firebase_refresh_token: FROM_STEP_7
154
164
  ```
155
165
 
156
- > Firebase refresh tokens can rotate. If workflow tools stop working after a few weeks, run the capture again and re-run setup_ghl_mcp with the fresh values.
166
+ > Firebase refresh tokens can rotate. If workflow tools stop working after a few weeks, repeat steps 1–7 and re-run setup_ghl_mcp with fresh values.
157
167
 
158
168
  ---
159
169
 
160
- ## Tools (171)
170
+ ## Tools (173)
161
171
 
162
172
  ### CRM & Contacts (15 tools)
163
173
 
@@ -322,7 +332,7 @@ Re-run setup_ghl_mcp with workflow builder:
322
332
  | `get_subscriptions` | List active subscriptions |
323
333
  | `get_transactions` | View transaction history |
324
334
 
325
- ### Workflow Builder (6 tools) — Internal API
335
+ ### Workflow Builder (7 tools) — Internal API
326
336
 
327
337
  > **This is the flagship feature.** GHL's public API has **zero** workflow write endpoints. These tools use GHL's internal backend API — the same API their own UI calls — reverse-engineered to give Claude full workflow CRUD. No other GHL integration, Zapier connector, or third-party tool can create or edit workflows programmatically. Requires additional Firebase auth setup (see "Enable Workflow Builder" in Quick Start above).
328
338
 
@@ -334,12 +344,13 @@ Re-run setup_ghl_mcp with workflow builder:
334
344
  | `update_workflow_actions` | Add, edit, or remove actions, triggers, and branches in an existing workflow |
335
345
  | `delete_workflow_full` | Permanently delete a workflow |
336
346
  | `publish_workflow` | Publish a draft workflow to make it active |
347
+ | `get_trigger_registry` | Discover GHL's marketplace trigger apps (Zoom, WooCommerce, Shopify, etc.) and their available trigger templates |
337
348
 
338
349
  **What you can build:** Complete automation sequences — lead nurture drip campaigns, appointment reminder sequences, onboarding flows, re-engagement workflows, internal notification chains. Tell Claude what you want and it builds the workflow action by action.
339
350
 
340
351
  **Supported action types:** `sms`, `email`, `add_contact_tag`, `remove_contact_tag`, `update_contact_field`, `wait`, `if_else`, `webhook`, `create_opportunity`, `custom_code`, `add_notes`, `internal_notification`, `task-notification`, `remove_from_workflow`, and more.
341
352
 
342
- **Supported trigger types:** `contact_tag`, `contact_created`, `form_submission`, `customer_reply`, `appointment`, `inbound_webhook`, `payment_received`, and more.
353
+ **Supported trigger types:** All 57 native GHL trigger types read cleanly (form_submission, payment_received, opportunity_created/changed/status_changed, inbound_webhook, contact_tag, appointment, customer_reply, and 50 more). 4 are deeply typed; the rest pass through a permissive schema so workflows never fail to read regardless of trigger type. Plus 434 marketplace trigger entries across 85 third-party apps — query them via `get_trigger_registry`.
343
354
 
344
355
  ### Pipeline Builder (5 tools) — Internal API
345
356
 
@@ -399,6 +410,12 @@ Re-run setup_ghl_mcp with workflow builder:
399
410
  | `get_template_questionnaire` | Get the questionnaire for a template — present to user conversationally |
400
411
  | `deploy_template` | Deploy a complete sub-account setup from a template (tags, fields, pipelines, workflows, forms). Supports dry-run mode. |
401
412
 
413
+ ### Meta (1 tool)
414
+
415
+ | Tool | What It Does |
416
+ |---|---|
417
+ | `get_mcp_version` | Check installed version against the latest published to npm. Confirms an upgrade landed after restarting Claude. Available even before GHL credentials are configured. |
418
+
402
419
  ### Other Modules
403
420
 
404
421
  | Module | Tools | What It Does |
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.0.3",
35
- description: "GoHighLevel MCP Server for Claude. 171 tools \u2014 full CRM, automation, marketing control, and the only programmatic GHL workflow builder.",
34
+ version: "3.1.1",
35
+ description: "GoHighLevel MCP Server for Claude. 173 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"
@@ -96,7 +96,6 @@ var require_package = __commonJS({
96
96
  var dotenv2 = __toESM(require("dotenv"));
97
97
  var path5 = __toESM(require("path"));
98
98
  var fs5 = __toESM(require("fs"));
99
- var import_child_process = require("child_process");
100
99
  var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
101
100
  var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
102
101
 
@@ -460,11 +459,16 @@ var PipelineStageUpdatedTriggerSchema = TriggerCommonSchema.extend({
460
459
  type: import_zod2.z.literal("pipeline_stage_updated"),
461
460
  conditions: import_zod2.z.array(PipelineStageUpdatedTriggerConditionSchema).optional()
462
461
  });
463
- var WorkflowTriggerSchema = import_zod2.z.discriminatedUnion("type", [
462
+ var UnknownTriggerSchema = TriggerCommonSchema.extend({
463
+ type: import_zod2.z.string(),
464
+ conditions: import_zod2.z.array(import_zod2.z.record(import_zod2.z.unknown())).optional()
465
+ });
466
+ var WorkflowTriggerSchema = import_zod2.z.union([
464
467
  CustomerReplyTriggerSchema,
465
468
  AppointmentTriggerSchema,
466
469
  ContactTagTriggerSchema,
467
- PipelineStageUpdatedTriggerSchema
470
+ PipelineStageUpdatedTriggerSchema,
471
+ UnknownTriggerSchema
468
472
  ]);
469
473
  var WorkflowActionSchema = import_zod2.z.custom(
470
474
  (value) => typeof value === "object" && value !== null && "type" in value
@@ -3795,11 +3799,16 @@ var PipelineStageUpdatedTriggerSchema2 = TriggerCommonSchema2.extend({
3795
3799
  id: import_zod30.z.string().optional()
3796
3800
  }).passthrough()).optional()
3797
3801
  });
3798
- var WorkflowTriggerSchema2 = import_zod30.z.discriminatedUnion("type", [
3802
+ var UnknownTriggerSchema2 = TriggerCommonSchema2.extend({
3803
+ type: import_zod30.z.string(),
3804
+ conditions: import_zod30.z.array(import_zod30.z.record(import_zod30.z.unknown())).optional()
3805
+ });
3806
+ var WorkflowTriggerSchema2 = import_zod30.z.union([
3799
3807
  CustomerReplyTriggerSchema2,
3800
3808
  AppointmentTriggerSchema2,
3801
3809
  ContactTagTriggerSchema2,
3802
- PipelineStageUpdatedTriggerSchema2
3810
+ PipelineStageUpdatedTriggerSchema2,
3811
+ UnknownTriggerSchema2
3803
3812
  ]);
3804
3813
  function linkBranchActions(actions, branchId, nextAfterMerge) {
3805
3814
  const prepared = actions.map((action) => ({
@@ -3873,6 +3882,40 @@ function registerWorkflowBuilderTools(server2, client) {
3873
3882
  }
3874
3883
  }
3875
3884
  );
3885
+ server2.tool(
3886
+ "get_trigger_registry",
3887
+ "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.",
3888
+ {
3889
+ companyId: import_zod30.z.string().describe("Company ID for the location. Find it in any get_workflow_full response under the 'companyId' field."),
3890
+ limit: import_zod30.z.number().optional().describe("Max marketplace apps to return. Defaults to 200."),
3891
+ installedOnly: import_zod30.z.boolean().optional().describe("If true, returns only apps installed in this location. Defaults to false (full marketplace catalogue, ~85 apps).")
3892
+ },
3893
+ async ({ companyId, limit, installedOnly }) => {
3894
+ try {
3895
+ const headers = await client.buildHeaders();
3896
+ const params = new URLSearchParams({
3897
+ locationId: client.locationId,
3898
+ companyId,
3899
+ type: "triggers",
3900
+ skip: "0",
3901
+ limit: String(limit ?? 200)
3902
+ });
3903
+ if (installedOnly) {
3904
+ params.set("isInstalled", "true");
3905
+ }
3906
+ const url = `https://backend.leadconnectorhq.com/marketplace/core/search/module?${params.toString()}`;
3907
+ const response = await fetch(url, { headers });
3908
+ if (!response.ok) {
3909
+ const text = await response.text();
3910
+ throw new Error(`Trigger registry API error ${response.status}: ${text}`);
3911
+ }
3912
+ const data = await response.json();
3913
+ return jsonResponse(data);
3914
+ } catch (error) {
3915
+ return errorResponse(error);
3916
+ }
3917
+ }
3918
+ );
3876
3919
  server2.tool(
3877
3920
  "create_workflow",
3878
3921
  "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).",
@@ -3890,7 +3933,7 @@ function registerWorkflowBuilderTools(server2, client) {
3890
3933
  );
3891
3934
  server2.tool(
3892
3935
  "update_workflow_actions",
3893
- "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. For if/else, call build_if_else_branch and include its returned nodes; if_else is a node discriminator, not a standalone action. Trigger types: customer_reply, appointment, contact_tag, pipeline_stage_updated.",
3936
+ "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. For if/else, call build_if_else_branch and include its returned nodes; if_else is a node discriminator, not a standalone action. Trigger types: customer_reply, appointment, contact_tag, and pipeline_stage_updated have typed validation. Any other GHL trigger type (form_submitted, opportunity_created, payment_received, inbound_webhook, etc.) passes through with a permissive schema \u2014 the payload reaches GHL untouched.",
3894
3937
  {
3895
3938
  workflowId: import_zod30.z.string().describe("The workflow ID to update."),
3896
3939
  name: import_zod30.z.string().optional().describe("New workflow name."),
@@ -4607,10 +4650,12 @@ function withSwitchLock(fn) {
4607
4650
  switchChain = next.catch(() => void 0);
4608
4651
  return next;
4609
4652
  }
4610
- function registerLocationSwitcherTools(server2, client, builderClient, registry2) {
4653
+ function registerLocationSwitcherTools(server2, client, builderClient, registry2, mcpVersion) {
4654
+ const versionLine = mcpVersion ? `
4655
+ MCP version: v${mcpVersion}` : "";
4611
4656
  server2.tool(
4612
4657
  "get_current_location",
4613
- "Show which GHL sub-account (location) is currently active, including API key status. All tools use this location by default unless you specify a different one.",
4658
+ "Show which GHL sub-account (location) is currently active, including API key status and installed MCP version. All tools use this location by default unless you specify a different one.",
4614
4659
  {},
4615
4660
  async () => {
4616
4661
  const locId = client.defaultLocationId || "NOT SET";
@@ -4628,17 +4673,17 @@ ID: ${client.defaultLocationId}
4628
4673
  API Key: ${client.getApiKeyPrefix()}
4629
4674
  Address: ${loc?.address || "N/A"}
4630
4675
  Email: ${loc?.email || "N/A"}
4631
- Token registry: ${registeredCount} location(s) registered`
4676
+ Token registry: ${registeredCount} location(s) registered${versionLine}`
4632
4677
  }
4633
4678
  ]
4634
4679
  };
4635
4680
  }
4636
4681
  return {
4637
- content: [{ type: "text", text: `No default location set. Pass locationId to tools or use switch_location.` }]
4682
+ content: [{ type: "text", text: `No default location set. Pass locationId to tools or use switch_location.${versionLine}` }]
4638
4683
  };
4639
4684
  } catch (error) {
4640
4685
  return {
4641
- content: [{ type: "text", text: `Current location ID: ${locId} (could not fetch details \u2014 API key may not have access)` }]
4686
+ content: [{ type: "text", text: `Current location ID: ${locId} (could not fetch details \u2014 API key may not have access)${versionLine}` }]
4642
4687
  };
4643
4688
  }
4644
4689
  }
@@ -5727,7 +5772,7 @@ var publicApiTools = [
5727
5772
  [registerAccountExportTools, "account-export"],
5728
5773
  [registerTemplateDeployerTools, "template-deployer"]
5729
5774
  ];
5730
- function registerAllTools(server2, client, registry2) {
5775
+ function registerAllTools(server2, client, registry2, mcpVersion) {
5731
5776
  for (const [register] of publicApiTools) {
5732
5777
  register(server2, client);
5733
5778
  }
@@ -5737,7 +5782,7 @@ function registerAllTools(server2, client, registry2) {
5737
5782
  registerFormBuilderTools(server2, builderClient);
5738
5783
  registerPipelineBuilderTools(server2, builderClient);
5739
5784
  registerWorkflowClonerTools(server2, builderClient);
5740
- registerLocationSwitcherTools(server2, client, builderClient, registry2);
5785
+ registerLocationSwitcherTools(server2, client, builderClient, registry2, mcpVersion);
5741
5786
  }
5742
5787
 
5743
5788
  // src/credentials-store.ts
@@ -5954,6 +5999,58 @@ Note: Firebase credentials rejected (${fb.error}). Saved without Workflow Builde
5954
5999
  );
5955
6000
  }
5956
6001
 
6002
+ // src/version-check.ts
6003
+ var REGISTRY_URL = "https://registry.npmjs.org/@elitedcs/ghl-mcp/latest";
6004
+ async function fetchLatestVersion(timeoutMs = 5e3) {
6005
+ try {
6006
+ const response = await fetch(REGISTRY_URL, {
6007
+ headers: { Accept: "application/json" },
6008
+ signal: AbortSignal.timeout(timeoutMs)
6009
+ });
6010
+ if (!response.ok) return null;
6011
+ const body = await response.json();
6012
+ return typeof body.version === "string" ? body.version : null;
6013
+ } catch {
6014
+ return null;
6015
+ }
6016
+ }
6017
+ async function getVersionStatus(installed) {
6018
+ const latest = await fetchLatestVersion();
6019
+ if (latest === null) {
6020
+ return { installed, latest: null, upToDate: null, fetchError: "Could not reach npm registry" };
6021
+ }
6022
+ return { installed, latest, upToDate: installed === latest };
6023
+ }
6024
+
6025
+ // src/tools/meta.ts
6026
+ function registerMetaTools(server2, installedVersion) {
6027
+ server2.tool(
6028
+ "get_mcp_version",
6029
+ "Check the installed version of GHL Command (the GoHighLevel MCP server) against the latest version published to npm. Use this to confirm an upgrade landed after restarting Claude. Returns installed version, latest version, whether up-to-date, and the one-line restart instruction if not.",
6030
+ {},
6031
+ async () => {
6032
+ const status = await getVersionStatus(installedVersion);
6033
+ const lines = [`Installed: v${status.installed}`];
6034
+ if (status.latest === null) {
6035
+ lines.push(`Latest: unknown (${status.fetchError ?? "npm registry unreachable"})`);
6036
+ lines.push(`Cannot confirm whether an update is available.`);
6037
+ } else if (status.upToDate) {
6038
+ lines.push(`Latest: v${status.latest}`);
6039
+ lines.push(`Status: Up to date.`);
6040
+ } else {
6041
+ lines.push(`Latest: v${status.latest}`);
6042
+ lines.push(`Status: UPDATE AVAILABLE.`);
6043
+ lines.push(``);
6044
+ lines.push(`To upgrade: fully quit Claude Desktop (Cmd+Q on Mac, fully exit on Windows) and reopen it.`);
6045
+ lines.push(`The @latest tag in your config fetches the new version on next launch \u2014 no reinstall, no config edit.`);
6046
+ lines.push(``);
6047
+ lines.push(`If a restart doesn't pick up the new version, run this in a terminal once: npx clear-npx-cache`);
6048
+ }
6049
+ return { content: [{ type: "text", text: lines.join("\n") }] };
6050
+ }
6051
+ );
6052
+ }
6053
+
5957
6054
  // src/index.ts
5958
6055
  var pkg = require_package();
5959
6056
  dotenv2.config();
@@ -6015,17 +6112,18 @@ var server = new import_mcp.McpServer({
6015
6112
  version: pkg.version
6016
6113
  });
6017
6114
  var inBootstrapMode = !apiKey || !locationId;
6115
+ registerMetaTools(server, pkg.version);
6018
6116
  if (inBootstrapMode) {
6019
6117
  process.stderr.write(
6020
6118
  `[ghl-mcp] Bootstrap mode: no credentials found.
6021
6119
  [ghl-mcp] Looked for env vars (GHL_API_KEY, GHL_LOCATION_ID) and credentials file (${credentialsPath()}).
6022
- [ghl-mcp] Only the setup_ghl_mcp tool is available. Run it from Claude with your license + GHL credentials.
6120
+ [ghl-mcp] Only setup_ghl_mcp and get_mcp_version are available. Run setup_ghl_mcp from Claude with your license + GHL credentials.
6023
6121
  `
6024
6122
  );
6025
6123
  registerSetupTool(server);
6026
6124
  } else {
6027
6125
  const client = new GHLClient({ apiKey, locationId });
6028
- registerAllTools(server, client, registry);
6126
+ registerAllTools(server, client, registry, pkg.version);
6029
6127
  if (fileCreds && !process.env.GHL_API_KEY) {
6030
6128
  process.stderr.write(`[ghl-mcp] Loaded credentials from ${credentialsPath()}
6031
6129
  `);
@@ -6052,24 +6150,14 @@ async function validateApiKey() {
6052
6150
  } catch {
6053
6151
  }
6054
6152
  }
6055
- function checkForUpdates() {
6056
- const repoDir = path5.resolve(__dirname, "..");
6057
- (0, import_child_process.execFile)("git", ["-C", repoDir, "fetch", "--quiet"], { timeout: 1e4 }, (fetchErr) => {
6058
- if (fetchErr) return;
6059
- (0, import_child_process.execFile)("git", ["-C", repoDir, "rev-parse", "HEAD"], (_, localOut) => {
6060
- (0, import_child_process.execFile)("git", ["-C", repoDir, "rev-parse", "@{u}"], (__, remoteOut) => {
6061
- if (!localOut || !remoteOut) return;
6062
- const local = localOut.toString().trim();
6063
- const remote = remoteOut.toString().trim();
6064
- if (local !== remote) {
6065
- process.stderr.write(
6066
- `[ghl-mcp] Update available! Run: cd ${repoDir} && git pull && npm run build
6153
+ async function checkForUpdates() {
6154
+ const latest = await fetchLatestVersion();
6155
+ if (latest && latest !== pkg.version) {
6156
+ process.stderr.write(
6157
+ `[ghl-mcp] Update available: v${pkg.version} \u2192 v${latest}. Fully quit Claude (Cmd+Q on Mac) and reopen to upgrade.
6067
6158
  `
6068
- );
6069
- }
6070
- });
6071
- });
6072
- });
6159
+ );
6160
+ }
6073
6161
  }
6074
6162
  async function main() {
6075
6163
  const transport = new import_stdio.StdioServerTransport();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@elitedcs/ghl-mcp",
3
- "version": "3.0.3",
4
- "description": "GoHighLevel MCP Server for Claude. 171 tools — full CRM, automation, marketing control, and the only programmatic GHL workflow builder.",
3
+ "version": "3.1.1",
4
+ "description": "GoHighLevel MCP Server for Claude. 173 tools — full CRM, automation, marketing control, and the only programmatic GHL workflow builder.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
7
  "ghl-mcp": "dist/index.js"