conduyt-mcp 4.52.0 → 4.54.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/dist/tools/lifecycle.js
CHANGED
|
@@ -35,6 +35,14 @@ const masterStatusName = z
|
|
|
35
35
|
.min(1)
|
|
36
36
|
.max(40)
|
|
37
37
|
.regex(/^[a-z0-9][a-z0-9 _-]*$/i, "letters, numbers, spaces, - and _ only");
|
|
38
|
+
/** settings.callDispositions.statusMap as stored (string → string), anything malformed dropped */
|
|
39
|
+
function dispositionStatusMapOf(raw) {
|
|
40
|
+
const cd = raw.callDispositions;
|
|
41
|
+
const map = cd && typeof cd === "object" && !Array.isArray(cd) ? cd.statusMap : undefined;
|
|
42
|
+
if (!map || typeof map !== "object" || Array.isArray(map))
|
|
43
|
+
return {};
|
|
44
|
+
return Object.fromEntries(Object.entries(map).filter((e) => typeof e[1] === "string"));
|
|
45
|
+
}
|
|
38
46
|
export function registerLifecycleTools(server, client) {
|
|
39
47
|
server.tool("conduyt_get_lifecycle_settings", "Read the account's Lifecycle configuration (v2 + v3), shaped for read-before-write: dealWorkingMode and lostPropagation say how the tenant works leads and whether lost propagation is live; masterStatuses.effective is the full list a contact's masterStatus may take (the five built-in defaults plus the account's customs — the raw settings key stores only the customs); intakeDeals is the automatic deal-on-intake config, or null with an intakeDealsNote explaining that null can mean either not-configured or not-visible-to-your-key (the setting is admin-visible; member-tier responses omit it).", {}, async () => {
|
|
40
48
|
const result = await client.get("/api/v1/settings");
|
|
@@ -67,6 +75,9 @@ export function registerLifecycleTools(server, client) {
|
|
|
67
75
|
customs,
|
|
68
76
|
effective: [...DEFAULT_MASTER_STATUSES, ...customs.filter((c) => !DEFAULT_MASTER_STATUSES.includes(c.toLowerCase()))],
|
|
69
77
|
},
|
|
78
|
+
// (09-15) disposition → lead status: when a call outcome is picked (by a rep or by AI) the contact's masterStatus becomes the
|
|
79
|
+
// mapped value; keys are disposition values, values are master statuses (defaults or customs); {} = no mappings
|
|
80
|
+
dispositionStatusMap: dispositionStatusMapOf(raw),
|
|
70
81
|
intakeDeals: intakeDeals ?? null,
|
|
71
82
|
intakeDealsNote: intakeDeals === null
|
|
72
83
|
? "null = not configured, OR your key's role cannot read this admin-visible setting; configure/verify with an admin-tier key"
|
|
@@ -89,6 +100,11 @@ export function registerLifecycleTools(server, client) {
|
|
|
89
100
|
server.tool("conduyt_update_lost_propagation", "Turn LOST propagation on or off for this tenant (Lifecycle v3 P2). When on: a contact's masterStatus flips to 'lost' within a minute of its LAST open deal card closing lost (a per-minute resolver applies the rule on the committed state) (carrying that card's lostReason into masterStatusReason), a new open card on a lost/abandoned/disqualified contact reopens it, and a won contact never flips. Forward-only from the first enable (enabledAt is stamped server-side): existing history never flips by itself. A terminal masterStatus silences every drip, sequence and playbook for that contact, so read the nightly shadow report first (job run 'lost-propagation-shadow': contacts that would flip, their reasons, and the automations that would go quiet) before enabling.", {
|
|
90
101
|
enabled: z.boolean().describe("true = flips happen live from now on; false = shadow report only"),
|
|
91
102
|
}, async ({ enabled }) => patchGeneralSettings(client, { lostPropagation: { enabled } }));
|
|
103
|
+
server.tool("conduyt_update_disposition_status_map", "Set which lead status each call disposition sets when it is picked (by a rep after a call or by the AI auto-disposition): e.g. {\"not-interested\": \"lost\", \"sale-closed\": \"won\", \"interested\": \"working\"}. Keys are disposition values (built-ins like interested, not-interested, callback-requested, appointment-set, sale-closed, dnc-requested, voicemail, no-answer, wrong-number, or the account's custom outcomes); values are master statuses (open, won, lost, abandoned, disqualified, or the account's customs from conduyt_update_master_statuses). The map REPLACES the stored map (send the full map; {} clears every mapping); the rest of the account's disposition settings are untouched. An unknown disposition or status is a 422. A lead a deal has WON is never moved by an outcome; mapping to a terminal status (won/lost/abandoned/disqualified) closes the lead and stops its automations. Read the current map with conduyt_get_lifecycle_settings (dispositionStatusMap).", {
|
|
104
|
+
statusMap: z
|
|
105
|
+
.record(z.string().trim().min(1).max(40), z.string().trim().min(1).max(40))
|
|
106
|
+
.describe("Disposition value → master status, the complete map"),
|
|
107
|
+
}, async ({ statusMap }) => patchGeneralSettings(client, { callDispositions: { statusMap } }));
|
|
92
108
|
server.tool("conduyt_update_master_statuses", "Set the account's custom lead lifecycle statuses. The five defaults (open, won, lost, abandoned, disqualified) always exist and cannot be removed; this REPLACES the custom list on top of them (max 20 names, 1-40 chars each, letters/numbers/spaces/-/_ only). Terminal statuses stop all outbound automation for a contact. Requires settings:edit.", {
|
|
93
109
|
statuses: z
|
|
94
110
|
.array(masterStatusName)
|
|
@@ -32,13 +32,17 @@ export function registerSmartViewTools(server, client) {
|
|
|
32
32
|
.optional()
|
|
33
33
|
.describe("Most calls to one lead in a single account-local day (1–20); null removes the daily cap"),
|
|
34
34
|
dialCooldownMinutes: z.number().int().min(0).max(10080).optional().describe("Minutes to wait between calls to the same lead"),
|
|
35
|
+
dialIncludeUnassigned: z
|
|
36
|
+
.boolean()
|
|
37
|
+
.optional()
|
|
38
|
+
.describe("true = this priority also hands out leads nobody owns yet (a shared pool; the lead is assigned to the rep at hand-out); false = the rep's own leads only"),
|
|
35
39
|
dialSchedule: z
|
|
36
40
|
.array(scheduleStepSchema)
|
|
37
41
|
.min(1)
|
|
38
42
|
.max(20)
|
|
39
43
|
.optional()
|
|
40
44
|
.describe('Retry schedule, e.g. [{"attemptNumber":1,"delayMinutes":0},{"attemptNumber":2,"delayMinutes":60},{"attemptNumber":3,"delayMinutes":1440}]'),
|
|
41
|
-
}, async ({ id, dialEnabled, maxDialAttempts, maxDialAttemptsPerDay, dialCooldownMinutes, dialSchedule }) => {
|
|
45
|
+
}, async ({ id, dialEnabled, maxDialAttempts, maxDialAttemptsPerDay, dialCooldownMinutes, dialIncludeUnassigned, dialSchedule }) => {
|
|
42
46
|
// Inline body (undefined fields drop out in JSON) — keeps the shape
|
|
43
47
|
// readable by the contract verifier's static parser.
|
|
44
48
|
const result = await client.patch(`/api/v1/smart-views/${encodeURIComponent(id)}`, {
|
|
@@ -46,6 +50,7 @@ export function registerSmartViewTools(server, client) {
|
|
|
46
50
|
maxDialAttempts,
|
|
47
51
|
maxDialAttemptsPerDay,
|
|
48
52
|
dialCooldownMinutes,
|
|
53
|
+
dialIncludeUnassigned,
|
|
49
54
|
dialSchedule,
|
|
50
55
|
});
|
|
51
56
|
return formatResult(result);
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"generatedAt": "2026-09-
|
|
3
|
-
"toolCount":
|
|
4
|
-
"totalEndpoints":
|
|
2
|
+
"generatedAt": "2026-09-15T12:51:11.678Z",
|
|
3
|
+
"toolCount": 261,
|
|
4
|
+
"totalEndpoints": 974,
|
|
5
5
|
"counts": {
|
|
6
6
|
"covered": 245,
|
|
7
|
-
"excluded":
|
|
7
|
+
"excluded": 288,
|
|
8
8
|
"planned": 441,
|
|
9
9
|
"uncategorized": 0
|
|
10
10
|
},
|
|
@@ -2239,6 +2239,14 @@
|
|
|
2239
2239
|
"status": "excluded",
|
|
2240
2240
|
"reason": "realtime browser dialer (WebRTC tokens, live call control) — needs a live audio session"
|
|
2241
2241
|
},
|
|
2242
|
+
"GET /api/v1/dialer/queue/open": {
|
|
2243
|
+
"status": "excluded",
|
|
2244
|
+
"reason": "realtime browser dialer (WebRTC tokens, live call control) — needs a live audio session"
|
|
2245
|
+
},
|
|
2246
|
+
"POST /api/v1/dialer/queue/release": {
|
|
2247
|
+
"status": "excluded",
|
|
2248
|
+
"reason": "realtime browser dialer (WebRTC tokens, live call control) — needs a live audio session"
|
|
2249
|
+
},
|
|
2242
2250
|
"POST /api/v1/dialer/queue/skip": {
|
|
2243
2251
|
"status": "excluded",
|
|
2244
2252
|
"reason": "realtime browser dialer (WebRTC tokens, live call control) — needs a live audio session"
|