@datasynx/agentic-crm 1.7.0 → 1.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/dist/cli.js +101 -8
- package/dist/cli.js.map +1 -1
- package/dist/daemon/worker.js +3 -3
- package/dist/funnel-B2mwpZE1.js +89 -0
- package/dist/funnel-B2mwpZE1.js.map +1 -0
- package/dist/funnel-CJ7fy7hG.js +2 -0
- package/dist/{index-DcDaz_cu.d.cts → index-BAutNcAT.d.cts} +11 -11
- package/dist/index-BAutNcAT.d.cts.map +1 -0
- package/dist/index.d.cts +11 -11
- package/dist/index.d.cts.map +1 -1
- package/dist/{knowledge-base-Cc0niBFf.js → knowledge-base-yo-BLUcB.js} +3 -1
- package/dist/knowledge-base-yo-BLUcB.js.map +1 -0
- package/dist/{login-yt9OOQQk.js → login-dc_Hqosw.js} +2 -2
- package/dist/{login-yt9OOQQk.js.map → login-dc_Hqosw.js.map} +1 -1
- package/dist/mailbox-config-BU3vib2T.js +2 -0
- package/dist/{mailbox-config-Dn2xTn9N.js → mailbox-config-trjLPHPG.js} +2 -2
- package/dist/{mailbox-config-Dn2xTn9N.js.map → mailbox-config-trjLPHPG.js.map} +1 -1
- package/dist/{mailbox-poll-B8dvFAXT.js → mailbox-poll-Ban7C3X0.js} +3 -3
- package/dist/{mailbox-poll-B8dvFAXT.js.map → mailbox-poll-Ban7C3X0.js.map} +1 -1
- package/dist/mcp-CdTJWTJf.d.cts.map +1 -1
- package/dist/mcp-CdTJWTJf.d.ts.map +1 -1
- package/dist/mcp.cjs +415 -137
- package/dist/mcp.cjs.map +1 -1
- package/dist/mcp.d.cts.map +1 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +415 -137
- package/dist/mcp.js.map +1 -1
- package/dist/{server-BbInMUgp.js → server-DAcwmRPE.js} +195 -133
- package/dist/server-DAcwmRPE.js.map +1 -0
- package/dist/{token-resolver-D98qPOOf.js → token-resolver-CL8-CSgZ.js} +2 -2
- package/dist/{token-resolver-D98qPOOf.js.map → token-resolver-CL8-CSgZ.js.map} +1 -1
- package/dist/{token-store-B0h0USqe.js → token-store-BPDwePNT.js} +13 -2
- package/dist/token-store-BPDwePNT.js.map +1 -0
- package/dist/token-store-D3HCeXmE.js +2 -0
- package/dist/velocity-BtX1l5Gh.js +2 -0
- package/dist/velocity-C2l4cW0K.js +123 -0
- package/dist/velocity-C2l4cW0K.js.map +1 -0
- package/package.json +1 -1
- package/dist/index-DcDaz_cu.d.cts.map +0 -1
- package/dist/knowledge-base-Cc0niBFf.js.map +0 -1
- package/dist/mailbox-config-Bu-J1O4I.js +0 -2
- package/dist/server-BbInMUgp.js.map +0 -1
- package/dist/token-store-B0h0USqe.js.map +0 -1
- package/dist/token-store-CEmz8d-0.js +0 -2
|
@@ -2,7 +2,7 @@ import { a as readMainFacts, i as listCustomerSlugs, n as customerExists, o as w
|
|
|
2
2
|
import { t as writeFileAtomic } from "./atomic-write-8yjqqLtS.js";
|
|
3
3
|
import { i as writeJsonFile } from "./json-store-WWsFzXub.js";
|
|
4
4
|
import { n as getSession } from "./session-store-CEa39Dxs.js";
|
|
5
|
-
import { a as searchKbSimple, n as getKbArticle, o as writeKbArticle, r as getKbMetaForExport, s as CAPABILITIES_TEXT } from "./knowledge-base-
|
|
5
|
+
import { a as searchKbSimple, n as getKbArticle, o as writeKbArticle, r as getKbMetaForExport, s as CAPABILITIES_TEXT } from "./knowledge-base-yo-BLUcB.js";
|
|
6
6
|
import { i as readBackupLog, n as listBackupsInDir, o as runBackup } from "./backup-CTlIxUdO.js";
|
|
7
7
|
import { r as updateSlugSyncState, t as getLastGmailSync } from "./sync-state-DMZgzpez.js";
|
|
8
8
|
import { t as withFileQueue } from "./write-queue-IbsAjUnh.js";
|
|
@@ -24,9 +24,11 @@ import { i as getSurvey, l as savePendingSurvey, n as calcNpsScore, o as loadSur
|
|
|
24
24
|
import { t as buildContext } from "./context-builder-7Uab5-G4.js";
|
|
25
25
|
import { a as loadCustomObjects, i as listRecords, n as defineCustomObject, t as createRecord } from "./custom-objects-CxW1gHwJ.js";
|
|
26
26
|
import { n as runDiagnostics } from "./doctor-BFeelnq8.js";
|
|
27
|
+
import { n as diffAgainstNow } from "./snapshots-CQSOaIMs.js";
|
|
28
|
+
import { t as analyzeFunnel } from "./funnel-B2mwpZE1.js";
|
|
27
29
|
import { r as searchKnowledge } from "./lancedb-CuHKNsNZ.js";
|
|
28
30
|
import { t as buildDailyBriefing } from "./proactive-agent-B7u3Bj_l.js";
|
|
29
|
-
import {
|
|
31
|
+
import { t as analyzeVelocity } from "./velocity-C2l4cW0K.js";
|
|
30
32
|
import { a as protectedResourceMetadata, o as verifyBearer, r as isAuthRequired, s as wwwAuthenticateHeader } from "./auth-DDXZTwS0.js";
|
|
31
33
|
import { i as verifyGmailPubSubSignature, n as decodeGmailPubSubPayload, r as handleGmailPushEvent } from "./gmail-webhook-handler-BzOFbvgh.js";
|
|
32
34
|
import { n as registerUpdateDeal } from "./update-deal-DSzr_Aau.js";
|
|
@@ -256,7 +258,7 @@ function registerGetActiveSession(server) {
|
|
|
256
258
|
}
|
|
257
259
|
//#endregion
|
|
258
260
|
//#region src/mcp/tools/get-customer-context.ts
|
|
259
|
-
const DATA_DIR$
|
|
261
|
+
const DATA_DIR$55 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
260
262
|
function triggerOnQuerySync(dataDir, slug) {
|
|
261
263
|
const auth = getGmailAuth();
|
|
262
264
|
if (!auth) return;
|
|
@@ -277,7 +279,7 @@ function triggerOnQuerySync(dataDir, slug) {
|
|
|
277
279
|
}).then(() => updateSlugSyncState(dataDir, slug, { lastGmailSync: (/* @__PURE__ */ new Date()).toISOString() })).catch(() => {})).catch(() => {});
|
|
278
280
|
} catch {}
|
|
279
281
|
}
|
|
280
|
-
async function handleGetCustomerContext(input, dataDir = DATA_DIR$
|
|
282
|
+
async function handleGetCustomerContext(input, dataDir = DATA_DIR$55) {
|
|
281
283
|
const targetSlug = input.slug ?? getSession()?.customerSlug;
|
|
282
284
|
if (!targetSlug) return {
|
|
283
285
|
content: [{
|
|
@@ -329,8 +331,8 @@ Performance: <3 seconds. Token budget: <3000.`,
|
|
|
329
331
|
}
|
|
330
332
|
//#endregion
|
|
331
333
|
//#region src/mcp/tools/search-customer-knowledge.ts
|
|
332
|
-
const DATA_DIR$
|
|
333
|
-
async function handleSearchCustomerKnowledge(input, dataDir = DATA_DIR$
|
|
334
|
+
const DATA_DIR$54 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
335
|
+
async function handleSearchCustomerKnowledge(input, dataDir = DATA_DIR$54) {
|
|
334
336
|
const limit = input.limit ?? 5;
|
|
335
337
|
try {
|
|
336
338
|
const results = await searchKnowledge(dataDir, input.slug, input.query, limit);
|
|
@@ -378,14 +380,14 @@ If no results: returns empty array with a helpful sync suggestion.`,
|
|
|
378
380
|
}
|
|
379
381
|
//#endregion
|
|
380
382
|
//#region src/mcp/tools/list-customers.ts
|
|
381
|
-
const DATA_DIR$
|
|
383
|
+
const DATA_DIR$53 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
382
384
|
function extractLastInteractionDate(interactionsPath) {
|
|
383
385
|
if (!fs.existsSync(interactionsPath)) return void 0;
|
|
384
386
|
const content = fs.readFileSync(interactionsPath, "utf-8");
|
|
385
387
|
const match = /^## (\d{4}-\d{2}-\d{2})/m.exec(content);
|
|
386
388
|
return match ? match[1] : void 0;
|
|
387
389
|
}
|
|
388
|
-
async function handleListCustomers(input, dataDir = DATA_DIR$
|
|
390
|
+
async function handleListCustomers(input, dataDir = DATA_DIR$53) {
|
|
389
391
|
const customersDir = path.join(dataDir, "customers");
|
|
390
392
|
const customers = [];
|
|
391
393
|
if (!fs.existsSync(customersDir)) return { content: [{
|
|
@@ -446,8 +448,8 @@ Returns: Array of { slug, name, stage, lastInteraction?, dealValue? }`,
|
|
|
446
448
|
}
|
|
447
449
|
//#endregion
|
|
448
450
|
//#region src/mcp/tools/log-interaction.ts
|
|
449
|
-
const DATA_DIR$
|
|
450
|
-
async function handleLogInteraction(input, dataDir = DATA_DIR$
|
|
451
|
+
const DATA_DIR$52 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
452
|
+
async function handleLogInteraction(input, dataDir = DATA_DIR$52) {
|
|
451
453
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
452
454
|
const interactionDate = input.date ?? today;
|
|
453
455
|
const sourceRef = input.source ?? `agent://log/${Date.now()}`;
|
|
@@ -552,12 +554,12 @@ Returns: { success: boolean, path: string, entry: string }`,
|
|
|
552
554
|
}
|
|
553
555
|
//#endregion
|
|
554
556
|
//#region src/mcp/tools/export-customer.ts
|
|
555
|
-
const DATA_DIR$
|
|
557
|
+
const DATA_DIR$51 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
556
558
|
function countInteractions(content) {
|
|
557
559
|
const matches = content.match(/^## \d{4}-\d{2}-\d{2}/gm);
|
|
558
560
|
return matches ? matches.length : 0;
|
|
559
561
|
}
|
|
560
|
-
async function handleExportCustomer(input, dataDir = DATA_DIR$
|
|
562
|
+
async function handleExportCustomer(input, dataDir = DATA_DIR$51) {
|
|
561
563
|
enforceRbac(dataDir, "export_customer");
|
|
562
564
|
const customerDir = path.join(dataDir, "customers", input.slug);
|
|
563
565
|
if (!fs.existsSync(customerDir)) return {
|
|
@@ -670,8 +672,8 @@ Returns:
|
|
|
670
672
|
}
|
|
671
673
|
//#endregion
|
|
672
674
|
//#region src/mcp/tools/update-customer-facts.ts
|
|
673
|
-
const DATA_DIR$
|
|
674
|
-
async function handleUpdateCustomerFacts(input, dataDir = DATA_DIR$
|
|
675
|
+
const DATA_DIR$50 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
676
|
+
async function handleUpdateCustomerFacts(input, dataDir = DATA_DIR$50) {
|
|
675
677
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
676
678
|
try {
|
|
677
679
|
enforceRbac(dataDir, "update_customer_facts");
|
|
@@ -849,8 +851,8 @@ function scoreDealForToday(deal, todayDate) {
|
|
|
849
851
|
}
|
|
850
852
|
//#endregion
|
|
851
853
|
//#region src/mcp/tools/get-deal-health.ts
|
|
852
|
-
const DATA_DIR$
|
|
853
|
-
async function handleGetDealHealth(input, dataDir = DATA_DIR$
|
|
854
|
+
const DATA_DIR$49 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
855
|
+
async function handleGetDealHealth(input, dataDir = DATA_DIR$49) {
|
|
854
856
|
try {
|
|
855
857
|
const deals = await readPipeline(dataDir, input.slug);
|
|
856
858
|
const today = /* @__PURE__ */ new Date();
|
|
@@ -899,8 +901,8 @@ Returns: { slug, deals: [{ deal, stage, score, grade, signals, warnings }] }`,
|
|
|
899
901
|
}
|
|
900
902
|
//#endregion
|
|
901
903
|
//#region src/mcp/tools/get-pipeline-forecast.ts
|
|
902
|
-
const DATA_DIR$
|
|
903
|
-
async function handleGetPipelineForecast(input, dataDir = DATA_DIR$
|
|
904
|
+
const DATA_DIR$48 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
905
|
+
async function handleGetPipelineForecast(input, dataDir = DATA_DIR$48) {
|
|
904
906
|
try {
|
|
905
907
|
const slugs = listCustomerSlugs(dataDir).filter((d) => !input.filter || d.includes(input.filter));
|
|
906
908
|
const allDeals = [];
|
|
@@ -961,8 +963,8 @@ Returns: { deals: [...], totalWeightedValue: number, byStage: { stage: { count,
|
|
|
961
963
|
}
|
|
962
964
|
//#endregion
|
|
963
965
|
//#region src/mcp/tools/summarize-meeting.ts
|
|
964
|
-
const DATA_DIR$
|
|
965
|
-
async function handleSummarizeMeeting(input, dataDir = DATA_DIR$
|
|
966
|
+
const DATA_DIR$47 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
967
|
+
async function handleSummarizeMeeting(input, dataDir = DATA_DIR$47) {
|
|
966
968
|
try {
|
|
967
969
|
let summary = input.transcript.slice(0, 400);
|
|
968
970
|
let nextSteps = [];
|
|
@@ -1037,8 +1039,8 @@ Returns: { success, summary, nextSteps, sourceRef }`,
|
|
|
1037
1039
|
}
|
|
1038
1040
|
//#endregion
|
|
1039
1041
|
//#region src/mcp/tools/get-pipeline-stages.ts
|
|
1040
|
-
const DATA_DIR$
|
|
1041
|
-
async function handleGetPipelineStages(_input, dataDir = DATA_DIR$
|
|
1042
|
+
const DATA_DIR$46 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1043
|
+
async function handleGetPipelineStages(_input, dataDir = DATA_DIR$46) {
|
|
1042
1044
|
const stages = getPipelineStages(dataDir);
|
|
1043
1045
|
return { content: [{
|
|
1044
1046
|
type: "text",
|
|
@@ -1066,8 +1068,8 @@ async function searchAcrossCustomers(dataDir, query, limit = 5, excludeSlug) {
|
|
|
1066
1068
|
}
|
|
1067
1069
|
//#endregion
|
|
1068
1070
|
//#region src/mcp/tools/get-market-intelligence.ts
|
|
1069
|
-
const DATA_DIR$
|
|
1070
|
-
async function handleGetMarketIntelligence(input, dataDir = DATA_DIR$
|
|
1071
|
+
const DATA_DIR$45 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1072
|
+
async function handleGetMarketIntelligence(input, dataDir = DATA_DIR$45) {
|
|
1071
1073
|
const excludeSlug = input.excludeCurrentCustomer ? input.slug : void 0;
|
|
1072
1074
|
const all = listCustomerSlugs(dataDir);
|
|
1073
1075
|
const totalCustomersSearched = excludeSlug ? all.filter((s) => s !== excludeSlug).length : all.length;
|
|
@@ -1098,7 +1100,7 @@ function registerGetMarketIntelligence(server) {
|
|
|
1098
1100
|
}
|
|
1099
1101
|
//#endregion
|
|
1100
1102
|
//#region src/mcp/tools/get-relationship-graph.ts
|
|
1101
|
-
const DATA_DIR$
|
|
1103
|
+
const DATA_DIR$44 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1102
1104
|
function summarizeNode(n) {
|
|
1103
1105
|
return {
|
|
1104
1106
|
id: n.id,
|
|
@@ -1106,7 +1108,7 @@ function summarizeNode(n) {
|
|
|
1106
1108
|
email: n.properties["email"]
|
|
1107
1109
|
};
|
|
1108
1110
|
}
|
|
1109
|
-
async function handleGetRelationshipGraph(input, dataDir = DATA_DIR$
|
|
1111
|
+
async function handleGetRelationshipGraph(input, dataDir = DATA_DIR$44) {
|
|
1110
1112
|
try {
|
|
1111
1113
|
const graph = readGraph(dataDir, input.slug);
|
|
1112
1114
|
const stakeholders = getStakeholders(graph);
|
|
@@ -1174,9 +1176,9 @@ Returns: {
|
|
|
1174
1176
|
}
|
|
1175
1177
|
//#endregion
|
|
1176
1178
|
//#region src/mcp/tools/get-relationship-health.ts
|
|
1177
|
-
const DATA_DIR$
|
|
1179
|
+
const DATA_DIR$43 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1178
1180
|
const MAX_HEALTH_AGE_MS = 3600 * 1e3;
|
|
1179
|
-
async function handleGetRelationshipHealth(input, dataDir = DATA_DIR$
|
|
1181
|
+
async function handleGetRelationshipHealth(input, dataDir = DATA_DIR$43) {
|
|
1180
1182
|
try {
|
|
1181
1183
|
let health = readHealth(dataDir, input.slug);
|
|
1182
1184
|
if (health === null || Date.now() - new Date(health.updatedAt).getTime() > MAX_HEALTH_AGE_MS) {
|
|
@@ -1845,8 +1847,8 @@ async function runDealAgent(config, dataDir, llmFn = callLlm) {
|
|
|
1845
1847
|
}
|
|
1846
1848
|
//#endregion
|
|
1847
1849
|
//#region src/mcp/tools/run-deal-agent.ts
|
|
1848
|
-
const DATA_DIR$
|
|
1849
|
-
async function handleRunDealAgent(input, dataDir = DATA_DIR$
|
|
1850
|
+
const DATA_DIR$42 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1851
|
+
async function handleRunDealAgent(input, dataDir = DATA_DIR$42) {
|
|
1850
1852
|
try {
|
|
1851
1853
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
1852
1854
|
const result = await runDealAgent({
|
|
@@ -1913,8 +1915,8 @@ Returns: { assessment, riskLevel, plan[], actionsQueued[], actionsExecuted[], tr
|
|
|
1913
1915
|
}
|
|
1914
1916
|
//#endregion
|
|
1915
1917
|
//#region src/mcp/tools/approve-agent-action.ts
|
|
1916
|
-
const DATA_DIR$
|
|
1917
|
-
async function handleApproveAgentAction(input, dataDir = DATA_DIR$
|
|
1918
|
+
const DATA_DIR$41 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1919
|
+
async function handleApproveAgentAction(input, dataDir = DATA_DIR$41) {
|
|
1918
1920
|
try {
|
|
1919
1921
|
const queue = readAgentQueue(dataDir, input.slug);
|
|
1920
1922
|
const idx = queue.pendingActions.findIndex((a) => a.actionId === input.actionId);
|
|
@@ -1991,8 +1993,8 @@ Returns: { success, actionId, status }`,
|
|
|
1991
1993
|
}
|
|
1992
1994
|
//#endregion
|
|
1993
1995
|
//#region src/mcp/tools/simulate-revenue.ts
|
|
1994
|
-
const DATA_DIR$
|
|
1995
|
-
async function handleSimulateRevenue(input, dataDir = DATA_DIR$
|
|
1996
|
+
const DATA_DIR$40 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1997
|
+
async function handleSimulateRevenue(input, dataDir = DATA_DIR$40) {
|
|
1996
1998
|
try {
|
|
1997
1999
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
1998
2000
|
const horizon = input.horizon ?? "quarter";
|
|
@@ -2050,8 +2052,8 @@ Returns: { forecast: { p10, p50, p90, expected, stdDev, atRiskRevenue, byCloseMo
|
|
|
2050
2052
|
}
|
|
2051
2053
|
//#endregion
|
|
2052
2054
|
//#region src/mcp/tools/get-playbook.ts
|
|
2053
|
-
const DATA_DIR$
|
|
2054
|
-
async function handleGetPlaybook(input, dataDir = DATA_DIR$
|
|
2055
|
+
const DATA_DIR$39 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2056
|
+
async function handleGetPlaybook(input, dataDir = DATA_DIR$39) {
|
|
2055
2057
|
try {
|
|
2056
2058
|
const playbooks = listPlaybooks(dataDir, input.slug);
|
|
2057
2059
|
if (!(input.stage !== void 0 || input.value !== void 0 || input.healthScore !== void 0)) return { content: [{
|
|
@@ -2136,12 +2138,12 @@ Returns: { matches: [{ name, score, trigger, successRate, usedCount, content }],
|
|
|
2136
2138
|
...healthScore !== void 0 ? { healthScore } : {},
|
|
2137
2139
|
...daysSinceContact !== void 0 ? { daysSinceContact } : {},
|
|
2138
2140
|
...championPresent !== void 0 ? { championPresent } : {}
|
|
2139
|
-
}, DATA_DIR$
|
|
2141
|
+
}, DATA_DIR$39));
|
|
2140
2142
|
}
|
|
2141
2143
|
//#endregion
|
|
2142
2144
|
//#region src/mcp/tools/create-playbook.ts
|
|
2143
|
-
const DATA_DIR$
|
|
2144
|
-
async function handleCreatePlaybook(input, dataDir = DATA_DIR$
|
|
2145
|
+
const DATA_DIR$38 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2146
|
+
async function handleCreatePlaybook(input, dataDir = DATA_DIR$38) {
|
|
2145
2147
|
try {
|
|
2146
2148
|
const name = toKebabCase(input.name);
|
|
2147
2149
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -2214,12 +2216,12 @@ Returns: { success: true, playbook: { name, trigger, successRate, path } }`,
|
|
|
2214
2216
|
trigger,
|
|
2215
2217
|
content,
|
|
2216
2218
|
...successRate !== void 0 ? { successRate } : {}
|
|
2217
|
-
}, DATA_DIR$
|
|
2219
|
+
}, DATA_DIR$38));
|
|
2218
2220
|
}
|
|
2219
2221
|
//#endregion
|
|
2220
2222
|
//#region src/mcp/tools/list-playbooks.ts
|
|
2221
|
-
const DATA_DIR$
|
|
2222
|
-
async function handleListPlaybooks(input, dataDir = DATA_DIR$
|
|
2223
|
+
const DATA_DIR$37 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2224
|
+
async function handleListPlaybooks(input, dataDir = DATA_DIR$37) {
|
|
2223
2225
|
try {
|
|
2224
2226
|
const playbooks = listPlaybooks(dataDir, input.slug);
|
|
2225
2227
|
return { content: [{
|
|
@@ -2258,12 +2260,12 @@ Args:
|
|
|
2258
2260
|
|
|
2259
2261
|
Returns: { playbooks: [{ name, trigger, successRate, usedCount, lastUpdated }], count, slug }`,
|
|
2260
2262
|
inputSchema: z.object({ slug: z.string().describe("Customer ID") })
|
|
2261
|
-
}, async ({ slug }) => handleListPlaybooks({ slug }, DATA_DIR$
|
|
2263
|
+
}, async ({ slug }) => handleListPlaybooks({ slug }, DATA_DIR$37));
|
|
2262
2264
|
}
|
|
2263
2265
|
//#endregion
|
|
2264
2266
|
//#region src/mcp/tools/distill-playbook.ts
|
|
2265
|
-
const DATA_DIR$
|
|
2266
|
-
async function handleDistillPlaybook(input, dataDir = DATA_DIR$
|
|
2267
|
+
const DATA_DIR$36 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2268
|
+
async function handleDistillPlaybook(input, dataDir = DATA_DIR$36, llmFn = callLlm) {
|
|
2267
2269
|
try {
|
|
2268
2270
|
const result = await distillPlaybook(dataDir, input.slug, input.dealName, input.outcome, llmFn);
|
|
2269
2271
|
if (!result.ok) {
|
|
@@ -2322,12 +2324,12 @@ Returns: { success: true, playbook: { name, trigger, successRate, path }, reason
|
|
|
2322
2324
|
slug,
|
|
2323
2325
|
dealName,
|
|
2324
2326
|
outcome
|
|
2325
|
-
}, DATA_DIR$
|
|
2327
|
+
}, DATA_DIR$36));
|
|
2326
2328
|
}
|
|
2327
2329
|
//#endregion
|
|
2328
2330
|
//#region src/mcp/tools/pursue-goal.ts
|
|
2329
|
-
const DATA_DIR$
|
|
2330
|
-
async function handlePursueGoal(input, dataDir = DATA_DIR$
|
|
2331
|
+
const DATA_DIR$35 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2332
|
+
async function handlePursueGoal(input, dataDir = DATA_DIR$35, options = {}) {
|
|
2331
2333
|
try {
|
|
2332
2334
|
enforceRbac(dataDir, "pursue_goal");
|
|
2333
2335
|
const goal = await pursueGoal(dataDir, {
|
|
@@ -2390,12 +2392,12 @@ Returns: { goalId, description, target, deadline, decomposition: { analysis, cur
|
|
|
2390
2392
|
goal,
|
|
2391
2393
|
deadline,
|
|
2392
2394
|
...context !== void 0 ? { context } : {}
|
|
2393
|
-
}, DATA_DIR$
|
|
2395
|
+
}, DATA_DIR$35));
|
|
2394
2396
|
}
|
|
2395
2397
|
//#endregion
|
|
2396
2398
|
//#region src/mcp/tools/get-goal-status.ts
|
|
2397
|
-
const DATA_DIR$
|
|
2398
|
-
async function handleGetGoalStatus(input, dataDir = DATA_DIR$
|
|
2399
|
+
const DATA_DIR$34 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2400
|
+
async function handleGetGoalStatus(input, dataDir = DATA_DIR$34) {
|
|
2399
2401
|
try {
|
|
2400
2402
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2401
2403
|
const allGoals = input.goalId ? readGoals(dataDir).filter((g) => g.id === input.goalId) : getActiveGoals(dataDir);
|
|
@@ -2454,17 +2456,17 @@ Args:
|
|
|
2454
2456
|
|
|
2455
2457
|
Returns: { goals: [{ id, description, target, progress, status, deadline, daysRemaining, subGoals }], activeCount, completedCount }`,
|
|
2456
2458
|
inputSchema: z.object({ goalId: z.string().optional().describe("Specific goal ID (omit for all active goals)") })
|
|
2457
|
-
}, async ({ goalId }) => handleGetGoalStatus({ ...goalId !== void 0 ? { goalId } : {} }, DATA_DIR$
|
|
2459
|
+
}, async ({ goalId }) => handleGetGoalStatus({ ...goalId !== void 0 ? { goalId } : {} }, DATA_DIR$34));
|
|
2458
2460
|
}
|
|
2459
2461
|
//#endregion
|
|
2460
2462
|
//#region src/mcp/tools/register-push-subscription.ts
|
|
2461
|
-
const DATA_DIR$
|
|
2463
|
+
const DATA_DIR$33 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2462
2464
|
const VALID_PROVIDERS = [
|
|
2463
2465
|
"gmail",
|
|
2464
2466
|
"microsoft-graph",
|
|
2465
2467
|
"slack"
|
|
2466
2468
|
];
|
|
2467
|
-
async function handleRegisterPushSubscription(input, dataDir = DATA_DIR$
|
|
2469
|
+
async function handleRegisterPushSubscription(input, dataDir = DATA_DIR$33) {
|
|
2468
2470
|
try {
|
|
2469
2471
|
if (!VALID_PROVIDERS.includes(input.provider)) return { content: [{
|
|
2470
2472
|
type: "text",
|
|
@@ -2550,12 +2552,12 @@ Returns: { subscriptionId, provider, slug, status, expiresAt, createdAt, warning
|
|
|
2550
2552
|
...microsoftResource !== void 0 ? { microsoftResource } : {},
|
|
2551
2553
|
...slackTeamId !== void 0 ? { slackTeamId } : {},
|
|
2552
2554
|
...slackChannelId !== void 0 ? { slackChannelId } : {}
|
|
2553
|
-
}, DATA_DIR$
|
|
2555
|
+
}, DATA_DIR$33));
|
|
2554
2556
|
}
|
|
2555
2557
|
//#endregion
|
|
2556
2558
|
//#region src/mcp/tools/get-push-status.ts
|
|
2557
|
-
const DATA_DIR$
|
|
2558
|
-
async function handleGetPushStatus(input, dataDir = DATA_DIR$
|
|
2559
|
+
const DATA_DIR$32 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2560
|
+
async function handleGetPushStatus(input, dataDir = DATA_DIR$32) {
|
|
2559
2561
|
try {
|
|
2560
2562
|
let subs = await readSubscriptions(dataDir);
|
|
2561
2563
|
if (input.slug) subs = subs.filter((s) => s.slug === input.slug);
|
|
@@ -2627,7 +2629,7 @@ Returns: { subscriptions: [{ id, provider, slug, status, expiresAt, expiresInHou
|
|
|
2627
2629
|
}, async ({ slug, provider }) => handleGetPushStatus({
|
|
2628
2630
|
...slug !== void 0 ? { slug } : {},
|
|
2629
2631
|
...provider !== void 0 ? { provider } : {}
|
|
2630
|
-
}, DATA_DIR$
|
|
2632
|
+
}, DATA_DIR$32));
|
|
2631
2633
|
}
|
|
2632
2634
|
//#endregion
|
|
2633
2635
|
//#region src/core/org-intelligence.ts
|
|
@@ -2693,8 +2695,8 @@ function deriveRecommendation(people, missingRoles) {
|
|
|
2693
2695
|
}
|
|
2694
2696
|
//#endregion
|
|
2695
2697
|
//#region src/mcp/tools/get-org-intelligence.ts
|
|
2696
|
-
const DATA_DIR$
|
|
2697
|
-
async function handleGetOrgIntelligence(input, dataDir = DATA_DIR$
|
|
2698
|
+
const DATA_DIR$31 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2699
|
+
async function handleGetOrgIntelligence(input, dataDir = DATA_DIR$31) {
|
|
2698
2700
|
try {
|
|
2699
2701
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2700
2702
|
const map = buildStakeholderMap(dataDir, input.slug, today, input.dealName);
|
|
@@ -2827,8 +2829,8 @@ function buildExecutiveSummary(slug, dealName, stakeholders, overallHealth, sim,
|
|
|
2827
2829
|
}
|
|
2828
2830
|
//#endregion
|
|
2829
2831
|
//#region src/mcp/tools/open-deal-room.ts
|
|
2830
|
-
const DATA_DIR$
|
|
2831
|
-
async function handleOpenDealRoom(input, dataDir = DATA_DIR$
|
|
2832
|
+
const DATA_DIR$30 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2833
|
+
async function handleOpenDealRoom(input, dataDir = DATA_DIR$30) {
|
|
2832
2834
|
try {
|
|
2833
2835
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2834
2836
|
const brief = await buildDealRoom(dataDir, input.slug, input.dealName, today);
|
|
@@ -2863,8 +2865,8 @@ Returns: { slug, dealName, generatedAt, stakeholders, relationshipHealth, dealHe
|
|
|
2863
2865
|
}
|
|
2864
2866
|
//#endregion
|
|
2865
2867
|
//#region src/mcp/tools/get-proactive-briefing.ts
|
|
2866
|
-
const DATA_DIR$
|
|
2867
|
-
async function handleGetProactiveBriefing(input, dataDir = DATA_DIR$
|
|
2868
|
+
const DATA_DIR$29 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2869
|
+
async function handleGetProactiveBriefing(input, dataDir = DATA_DIR$29) {
|
|
2868
2870
|
try {
|
|
2869
2871
|
const briefing = await buildDailyBriefing(dataDir, input.date ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10));
|
|
2870
2872
|
return { content: [{
|
|
@@ -2892,15 +2894,15 @@ Returns: { date, generatedAt, urgent: string[], opportunities: string[], forecas
|
|
|
2892
2894
|
}
|
|
2893
2895
|
//#endregion
|
|
2894
2896
|
//#region src/mcp/tools/list-email-templates.ts
|
|
2895
|
-
const DATA_DIR$
|
|
2896
|
-
async function handleListEmailTemplates(input, dataDir = DATA_DIR$
|
|
2897
|
+
const DATA_DIR$28 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2898
|
+
async function handleListEmailTemplates(input, dataDir = DATA_DIR$28) {
|
|
2897
2899
|
const summary = listTemplates(dataDir, input.category ? { category: input.category } : {}).map(({ body: _body, ...meta }) => meta);
|
|
2898
2900
|
return { content: [{
|
|
2899
2901
|
type: "text",
|
|
2900
2902
|
text: JSON.stringify(summary, null, 2)
|
|
2901
2903
|
}] };
|
|
2902
2904
|
}
|
|
2903
|
-
function registerListEmailTemplates(server, dataDir = DATA_DIR$
|
|
2905
|
+
function registerListEmailTemplates(server, dataDir = DATA_DIR$28) {
|
|
2904
2906
|
server.registerTool("list_email_templates", {
|
|
2905
2907
|
description: "List available email templates. Optionally filter by category (e.g. 'outreach', 'followup', 'support').",
|
|
2906
2908
|
inputSchema: z.object({ category: z.string().optional().describe("Filter by category") })
|
|
@@ -2908,8 +2910,8 @@ function registerListEmailTemplates(server, dataDir = DATA_DIR$26) {
|
|
|
2908
2910
|
}
|
|
2909
2911
|
//#endregion
|
|
2910
2912
|
//#region src/mcp/tools/get-email-template.ts
|
|
2911
|
-
const DATA_DIR$
|
|
2912
|
-
async function handleGetEmailTemplate(input, dataDir = DATA_DIR$
|
|
2913
|
+
const DATA_DIR$27 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2914
|
+
async function handleGetEmailTemplate(input, dataDir = DATA_DIR$27) {
|
|
2913
2915
|
const tmpl = getTemplate(dataDir, input.id);
|
|
2914
2916
|
if (!tmpl) return { content: [{
|
|
2915
2917
|
type: "text",
|
|
@@ -2925,7 +2927,7 @@ async function handleGetEmailTemplate(input, dataDir = DATA_DIR$25) {
|
|
|
2925
2927
|
}, null, 2)
|
|
2926
2928
|
}] };
|
|
2927
2929
|
}
|
|
2928
|
-
function registerGetEmailTemplate(server, dataDir = DATA_DIR$
|
|
2930
|
+
function registerGetEmailTemplate(server, dataDir = DATA_DIR$27) {
|
|
2929
2931
|
server.registerTool("get_email_template", {
|
|
2930
2932
|
description: "Get a specific email template by ID, including its body and detected variables.",
|
|
2931
2933
|
inputSchema: z.object({ id: z.string().describe("Template ID (e.g. 'enterprise-intro')") })
|
|
@@ -2933,8 +2935,8 @@ function registerGetEmailTemplate(server, dataDir = DATA_DIR$25) {
|
|
|
2933
2935
|
}
|
|
2934
2936
|
//#endregion
|
|
2935
2937
|
//#region src/mcp/tools/draft-email.ts
|
|
2936
|
-
const DATA_DIR$
|
|
2937
|
-
async function handleDraftEmail(input, dataDir = DATA_DIR$
|
|
2938
|
+
const DATA_DIR$26 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2939
|
+
async function handleDraftEmail(input, dataDir = DATA_DIR$26) {
|
|
2938
2940
|
const tmpl = getTemplate(dataDir, input.templateId);
|
|
2939
2941
|
if (!tmpl) return { content: [{
|
|
2940
2942
|
type: "text",
|
|
@@ -2978,7 +2980,7 @@ async function handleDraftEmail(input, dataDir = DATA_DIR$24) {
|
|
|
2978
2980
|
}, null, 2)
|
|
2979
2981
|
}] };
|
|
2980
2982
|
}
|
|
2981
|
-
function registerDraftEmail(server, dataDir = DATA_DIR$
|
|
2983
|
+
function registerDraftEmail(server, dataDir = DATA_DIR$26) {
|
|
2982
2984
|
server.registerTool("draft_email", {
|
|
2983
2985
|
description: `Draft a personalized email for a customer using a stored template.
|
|
2984
2986
|
Variables are auto-filled from the customer's main_facts.md. Override any variable manually.
|
|
@@ -3000,8 +3002,8 @@ Returns: { subject, body, to, tone, polished, resolvedVariables } — does NOT s
|
|
|
3000
3002
|
}
|
|
3001
3003
|
//#endregion
|
|
3002
3004
|
//#region src/mcp/tools/enroll-in-sequence.ts
|
|
3003
|
-
const DATA_DIR$
|
|
3004
|
-
async function handleEnrollInSequence(input, dataDir = DATA_DIR$
|
|
3005
|
+
const DATA_DIR$25 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3006
|
+
async function handleEnrollInSequence(input, dataDir = DATA_DIR$25) {
|
|
3005
3007
|
const sequence = getSequence(dataDir, input.sequenceId);
|
|
3006
3008
|
if (!sequence) return { content: [{
|
|
3007
3009
|
type: "text",
|
|
@@ -3033,7 +3035,7 @@ async function handleEnrollInSequence(input, dataDir = DATA_DIR$23) {
|
|
|
3033
3035
|
})
|
|
3034
3036
|
}] };
|
|
3035
3037
|
}
|
|
3036
|
-
function registerEnrollInSequence(server, dataDir = DATA_DIR$
|
|
3038
|
+
function registerEnrollInSequence(server, dataDir = DATA_DIR$25) {
|
|
3037
3039
|
server.registerTool("enroll_in_sequence", {
|
|
3038
3040
|
description: `Enroll a contact in an email sequence. Validates that the sequence and its first template exist.
|
|
3039
3041
|
Returns: { enrollmentId, sequenceName, totalSteps }`,
|
|
@@ -3050,8 +3052,8 @@ Returns: { enrollmentId, sequenceName, totalSteps }`,
|
|
|
3050
3052
|
}
|
|
3051
3053
|
//#endregion
|
|
3052
3054
|
//#region src/mcp/tools/list-sequence-enrollments.ts
|
|
3053
|
-
const DATA_DIR$
|
|
3054
|
-
async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$
|
|
3055
|
+
const DATA_DIR$24 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3056
|
+
async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$24) {
|
|
3055
3057
|
let enrollments = readEnrollments(dataDir);
|
|
3056
3058
|
if (input.slug !== void 0) enrollments = enrollments.filter((e) => e.slug === input.slug);
|
|
3057
3059
|
if (input.status !== void 0) enrollments = enrollments.filter((e) => e.status === input.status);
|
|
@@ -3060,7 +3062,7 @@ async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$22) {
|
|
|
3060
3062
|
text: JSON.stringify({ enrollments }, null, 2)
|
|
3061
3063
|
}] };
|
|
3062
3064
|
}
|
|
3063
|
-
function registerListSequenceEnrollments(server, dataDir = DATA_DIR$
|
|
3065
|
+
function registerListSequenceEnrollments(server, dataDir = DATA_DIR$24) {
|
|
3064
3066
|
server.registerTool("list_sequence_enrollments", {
|
|
3065
3067
|
description: `List email sequence enrollments. Filter by customer slug or status.
|
|
3066
3068
|
Returns: { enrollments: SequenceEnrollment[] }`,
|
|
@@ -3079,8 +3081,8 @@ Returns: { enrollments: SequenceEnrollment[] }`,
|
|
|
3079
3081
|
}
|
|
3080
3082
|
//#endregion
|
|
3081
3083
|
//#region src/mcp/tools/unenroll-from-sequence.ts
|
|
3082
|
-
const DATA_DIR$
|
|
3083
|
-
async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$
|
|
3084
|
+
const DATA_DIR$23 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3085
|
+
async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$23) {
|
|
3084
3086
|
if (!await updateEnrollment(dataDir, input.enrollmentId, { status: "paused" })) return { content: [{
|
|
3085
3087
|
type: "text",
|
|
3086
3088
|
text: JSON.stringify({
|
|
@@ -3093,7 +3095,7 @@ async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$21) {
|
|
|
3093
3095
|
text: JSON.stringify({ success: true })
|
|
3094
3096
|
}] };
|
|
3095
3097
|
}
|
|
3096
|
-
function registerUnenrollFromSequence(server, dataDir = DATA_DIR$
|
|
3098
|
+
function registerUnenrollFromSequence(server, dataDir = DATA_DIR$23) {
|
|
3097
3099
|
server.registerTool("unenroll_from_sequence", {
|
|
3098
3100
|
description: `Unenroll (pause) a contact from an email sequence. Sets status to "paused" (soft delete).
|
|
3099
3101
|
Returns: { success: boolean }`,
|
|
@@ -3102,8 +3104,8 @@ Returns: { success: boolean }`,
|
|
|
3102
3104
|
}
|
|
3103
3105
|
//#endregion
|
|
3104
3106
|
//#region src/mcp/tools/list-sequences.ts
|
|
3105
|
-
const DATA_DIR$
|
|
3106
|
-
async function handleListSequences(_input, dataDir = DATA_DIR$
|
|
3107
|
+
const DATA_DIR$22 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3108
|
+
async function handleListSequences(_input, dataDir = DATA_DIR$22) {
|
|
3107
3109
|
const sequences = listSequences(dataDir);
|
|
3108
3110
|
const enrollments = readEnrollments(dataDir);
|
|
3109
3111
|
const result = sequences.map((seq) => ({
|
|
@@ -3117,7 +3119,7 @@ async function handleListSequences(_input, dataDir = DATA_DIR$20) {
|
|
|
3117
3119
|
text: JSON.stringify({ sequences: result }, null, 2)
|
|
3118
3120
|
}] };
|
|
3119
3121
|
}
|
|
3120
|
-
function registerListSequences(server, dataDir = DATA_DIR$
|
|
3122
|
+
function registerListSequences(server, dataDir = DATA_DIR$22) {
|
|
3121
3123
|
server.registerTool("list_sequences", {
|
|
3122
3124
|
description: `List all email sequences with step count and enrollment count.
|
|
3123
3125
|
Returns: { sequences: Array<{ id, name, stepCount, enrollmentCount }> }`,
|
|
@@ -3126,8 +3128,8 @@ Returns: { sequences: Array<{ id, name, stepCount, enrollmentCount }> }`,
|
|
|
3126
3128
|
}
|
|
3127
3129
|
//#endregion
|
|
3128
3130
|
//#region src/mcp/tools/generate-quote.ts
|
|
3129
|
-
const DATA_DIR$
|
|
3130
|
-
async function handleGenerateQuote(input, dataDir = DATA_DIR$
|
|
3131
|
+
const DATA_DIR$21 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3132
|
+
async function handleGenerateQuote(input, dataDir = DATA_DIR$21) {
|
|
3131
3133
|
try {
|
|
3132
3134
|
const quote = await generateQuote(dataDir, input);
|
|
3133
3135
|
return { content: [{
|
|
@@ -3151,7 +3153,7 @@ async function handleGenerateQuote(input, dataDir = DATA_DIR$19) {
|
|
|
3151
3153
|
}] };
|
|
3152
3154
|
}
|
|
3153
3155
|
}
|
|
3154
|
-
function registerGenerateQuote(server, dataDir = DATA_DIR$
|
|
3156
|
+
function registerGenerateQuote(server, dataDir = DATA_DIR$21) {
|
|
3155
3157
|
server.registerTool("generate_quote", {
|
|
3156
3158
|
description: `Generate a professional HTML quote/offer for a customer deal.
|
|
3157
3159
|
Calculates subtotal, VAT, and total. Saves JSON + HTML to .agentic/quotes/.
|
|
@@ -3179,8 +3181,8 @@ Returns: { quoteNumber, htmlPath, total, currency, validUntil }`,
|
|
|
3179
3181
|
}
|
|
3180
3182
|
//#endregion
|
|
3181
3183
|
//#region src/mcp/tools/get-quote-status.ts
|
|
3182
|
-
const DATA_DIR$
|
|
3183
|
-
async function handleGetQuoteStatus(input, dataDir = DATA_DIR$
|
|
3184
|
+
const DATA_DIR$20 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3185
|
+
async function handleGetQuoteStatus(input, dataDir = DATA_DIR$20) {
|
|
3184
3186
|
if (input.quoteNumber) {
|
|
3185
3187
|
const quote = readQuote(dataDir, input.quoteNumber);
|
|
3186
3188
|
if (!quote) return { content: [{
|
|
@@ -3198,7 +3200,7 @@ async function handleGetQuoteStatus(input, dataDir = DATA_DIR$18) {
|
|
|
3198
3200
|
text: JSON.stringify({ quotes }, null, 2)
|
|
3199
3201
|
}] };
|
|
3200
3202
|
}
|
|
3201
|
-
function registerGetQuoteStatus(server, dataDir = DATA_DIR$
|
|
3203
|
+
function registerGetQuoteStatus(server, dataDir = DATA_DIR$20) {
|
|
3202
3204
|
server.registerTool("get_quote_status", {
|
|
3203
3205
|
description: `Get quote status and details. Filter by quoteNumber (single quote) or slug (all quotes for a customer).
|
|
3204
3206
|
Returns quote with status: draft | sent | viewed | accepted | declined`,
|
|
@@ -3213,7 +3215,7 @@ Returns quote with status: draft | sent | viewed | accepted | declined`,
|
|
|
3213
3215
|
}
|
|
3214
3216
|
//#endregion
|
|
3215
3217
|
//#region src/mcp/tools/get-booking-link.ts
|
|
3216
|
-
const DATA_DIR$
|
|
3218
|
+
const DATA_DIR$19 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3217
3219
|
function loadCalendlyConfig(dataDir) {
|
|
3218
3220
|
const p = path.join(dataDir, ".agentic", "integrations", "calendly.yaml");
|
|
3219
3221
|
if (!fs.existsSync(p)) return {};
|
|
@@ -3236,7 +3238,7 @@ function readCustomerFacts(dataDir, slug) {
|
|
|
3236
3238
|
...email ? { email } : {}
|
|
3237
3239
|
};
|
|
3238
3240
|
}
|
|
3239
|
-
async function handleGetBookingLink(input, dataDir = DATA_DIR$
|
|
3241
|
+
async function handleGetBookingLink(input, dataDir = DATA_DIR$19) {
|
|
3240
3242
|
const config = loadCalendlyConfig(dataDir);
|
|
3241
3243
|
const apiKey = config.apiKey ?? process.env["CALENDLY_API_KEY"] ?? "";
|
|
3242
3244
|
if (!apiKey) return { content: [{
|
|
@@ -3264,7 +3266,7 @@ async function handleGetBookingLink(input, dataDir = DATA_DIR$17) {
|
|
|
3264
3266
|
}] };
|
|
3265
3267
|
}
|
|
3266
3268
|
}
|
|
3267
|
-
function registerGetBookingLink(server, dataDir = DATA_DIR$
|
|
3269
|
+
function registerGetBookingLink(server, dataDir = DATA_DIR$19) {
|
|
3268
3270
|
server.registerTool("get_booking_link", {
|
|
3269
3271
|
description: `Get a Calendly booking link for a customer. Optionally pre-fills the customer's name/email.
|
|
3270
3272
|
Requires CALENDLY_API_KEY env var or .agentic/integrations/calendly.yaml config.
|
|
@@ -3282,8 +3284,8 @@ Returns: { bookingUrl, eventType, duration }`,
|
|
|
3282
3284
|
}
|
|
3283
3285
|
//#endregion
|
|
3284
3286
|
//#region src/mcp/tools/create-ticket.ts
|
|
3285
|
-
const DATA_DIR$
|
|
3286
|
-
async function handleCreateTicket(input, dataDir = DATA_DIR$
|
|
3287
|
+
const DATA_DIR$18 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3288
|
+
async function handleCreateTicket(input, dataDir = DATA_DIR$18) {
|
|
3287
3289
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
3288
3290
|
const rules = loadSlaRules(dataDir);
|
|
3289
3291
|
const priority = input.priority ?? "normal";
|
|
@@ -3305,7 +3307,7 @@ async function handleCreateTicket(input, dataDir = DATA_DIR$16) {
|
|
|
3305
3307
|
text: JSON.stringify({ ticket }, null, 2)
|
|
3306
3308
|
}] };
|
|
3307
3309
|
}
|
|
3308
|
-
function registerCreateTicket(server, dataDir = DATA_DIR$
|
|
3310
|
+
function registerCreateTicket(server, dataDir = DATA_DIR$18) {
|
|
3309
3311
|
server.registerTool("create_ticket", {
|
|
3310
3312
|
description: `Create a support ticket for a customer. Auto-calculates SLA due date based on priority.
|
|
3311
3313
|
Returns: { ticket } with id T-NNN, status=open, slaDue`,
|
|
@@ -3331,8 +3333,8 @@ Returns: { ticket } with id T-NNN, status=open, slaDue`,
|
|
|
3331
3333
|
}
|
|
3332
3334
|
//#endregion
|
|
3333
3335
|
//#region src/mcp/tools/update-ticket.ts
|
|
3334
|
-
const DATA_DIR$
|
|
3335
|
-
async function handleUpdateTicket(input, dataDir = DATA_DIR$
|
|
3336
|
+
const DATA_DIR$17 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3337
|
+
async function handleUpdateTicket(input, dataDir = DATA_DIR$17) {
|
|
3336
3338
|
const ticket = (await readTickets(dataDir, input.slug)).find((t) => t.id === input.ticketId);
|
|
3337
3339
|
if (!ticket) return { content: [{
|
|
3338
3340
|
type: "text",
|
|
@@ -3351,7 +3353,7 @@ async function handleUpdateTicket(input, dataDir = DATA_DIR$15) {
|
|
|
3351
3353
|
text: JSON.stringify({ ticket: updated }, null, 2)
|
|
3352
3354
|
}] };
|
|
3353
3355
|
}
|
|
3354
|
-
function registerUpdateTicket(server, dataDir = DATA_DIR$
|
|
3356
|
+
function registerUpdateTicket(server, dataDir = DATA_DIR$17) {
|
|
3355
3357
|
server.registerTool("update_ticket", {
|
|
3356
3358
|
description: `Update a ticket's status or assignee. Setting status=resolved auto-sets resolved date.
|
|
3357
3359
|
Returns: { ticket }`,
|
|
@@ -3376,8 +3378,8 @@ Returns: { ticket }`,
|
|
|
3376
3378
|
}
|
|
3377
3379
|
//#endregion
|
|
3378
3380
|
//#region src/mcp/tools/list-tickets.ts
|
|
3379
|
-
const DATA_DIR$
|
|
3380
|
-
async function handleListTickets(input, dataDir = DATA_DIR$
|
|
3381
|
+
const DATA_DIR$16 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3382
|
+
async function handleListTickets(input, dataDir = DATA_DIR$16) {
|
|
3381
3383
|
const results = await listAllTickets(dataDir, {
|
|
3382
3384
|
...input.slug !== void 0 ? { slug: input.slug } : {},
|
|
3383
3385
|
...input.status !== void 0 ? { status: input.status } : {},
|
|
@@ -3389,7 +3391,7 @@ async function handleListTickets(input, dataDir = DATA_DIR$14) {
|
|
|
3389
3391
|
text: JSON.stringify({ tickets: results }, null, 2)
|
|
3390
3392
|
}] };
|
|
3391
3393
|
}
|
|
3392
|
-
function registerListTickets(server, dataDir = DATA_DIR$
|
|
3394
|
+
function registerListTickets(server, dataDir = DATA_DIR$16) {
|
|
3393
3395
|
server.registerTool("list_tickets", {
|
|
3394
3396
|
description: `List support tickets. Filter by customer, status, priority, or assignee. Sorted by priority then date.
|
|
3395
3397
|
Returns: { tickets: Array<{ slug, ticket }> }`,
|
|
@@ -3419,8 +3421,8 @@ Returns: { tickets: Array<{ slug, ticket }> }`,
|
|
|
3419
3421
|
}
|
|
3420
3422
|
//#endregion
|
|
3421
3423
|
//#region src/mcp/tools/close-ticket.ts
|
|
3422
|
-
const DATA_DIR$
|
|
3423
|
-
async function handleCloseTicket(input, dataDir = DATA_DIR$
|
|
3424
|
+
const DATA_DIR$15 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3425
|
+
async function handleCloseTicket(input, dataDir = DATA_DIR$15) {
|
|
3424
3426
|
const ticket = (await readTickets(dataDir, input.slug)).find((t) => t.id === input.ticketId);
|
|
3425
3427
|
if (!ticket) return { content: [{
|
|
3426
3428
|
type: "text",
|
|
@@ -3447,7 +3449,7 @@ async function handleCloseTicket(input, dataDir = DATA_DIR$13) {
|
|
|
3447
3449
|
text: JSON.stringify({ ticket: updated }, null, 2)
|
|
3448
3450
|
}] };
|
|
3449
3451
|
}
|
|
3450
|
-
function registerCloseTicket(server, dataDir = DATA_DIR$
|
|
3452
|
+
function registerCloseTicket(server, dataDir = DATA_DIR$15) {
|
|
3451
3453
|
server.registerTool("close_ticket", {
|
|
3452
3454
|
description: `Close a support ticket. Optionally logs the resolution as an interaction.
|
|
3453
3455
|
Returns: { ticket } with status=closed`,
|
|
@@ -3464,8 +3466,8 @@ Returns: { ticket } with status=closed`,
|
|
|
3464
3466
|
}
|
|
3465
3467
|
//#endregion
|
|
3466
3468
|
//#region src/mcp/tools/send-nps-survey.ts
|
|
3467
|
-
const DATA_DIR$
|
|
3468
|
-
async function handleSendNpsSurvey(input, dataDir = DATA_DIR$
|
|
3469
|
+
const DATA_DIR$14 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3470
|
+
async function handleSendNpsSurvey(input, dataDir = DATA_DIR$14) {
|
|
3469
3471
|
const survey = getSurvey(dataDir, input.surveyId);
|
|
3470
3472
|
if (!survey) return { content: [{
|
|
3471
3473
|
type: "text",
|
|
@@ -3486,7 +3488,7 @@ async function handleSendNpsSurvey(input, dataDir = DATA_DIR$12) {
|
|
|
3486
3488
|
}, null, 2)
|
|
3487
3489
|
}] };
|
|
3488
3490
|
}
|
|
3489
|
-
function registerSendNpsSurvey(server, dataDir = DATA_DIR$
|
|
3491
|
+
function registerSendNpsSurvey(server, dataDir = DATA_DIR$14) {
|
|
3490
3492
|
server.registerTool("send_nps_survey", {
|
|
3491
3493
|
description: `Generate an NPS/CSAT survey email for a customer contact. Returns subject, HTML body, and a token-based response URL.
|
|
3492
3494
|
Does NOT send automatically — returns draft for review.
|
|
@@ -3506,8 +3508,8 @@ Returns: { token, subject, body, surveyUrl }`,
|
|
|
3506
3508
|
}
|
|
3507
3509
|
//#endregion
|
|
3508
3510
|
//#region src/mcp/tools/get-survey-results.ts
|
|
3509
|
-
const DATA_DIR$
|
|
3510
|
-
async function handleGetSurveyResults(input, dataDir = DATA_DIR$
|
|
3511
|
+
const DATA_DIR$13 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3512
|
+
async function handleGetSurveyResults(input, dataDir = DATA_DIR$13) {
|
|
3511
3513
|
const responses = loadSurveyResponses(dataDir, input.surveyId, input.slug);
|
|
3512
3514
|
const nps = calcNpsScore(responses);
|
|
3513
3515
|
const promoters = responses.filter((r) => r.score >= 9).length;
|
|
@@ -3533,7 +3535,7 @@ async function handleGetSurveyResults(input, dataDir = DATA_DIR$11) {
|
|
|
3533
3535
|
}, null, 2)
|
|
3534
3536
|
}] };
|
|
3535
3537
|
}
|
|
3536
|
-
function registerGetSurveyResults(server, dataDir = DATA_DIR$
|
|
3538
|
+
function registerGetSurveyResults(server, dataDir = DATA_DIR$13) {
|
|
3537
3539
|
server.registerTool("get_survey_results", {
|
|
3538
3540
|
description: `Get NPS/CSAT survey results with score breakdown. Calculates Net Promoter Score.
|
|
3539
3541
|
Returns: { npsScore, totalResponses, promoters, passives, detractors, responses[] }`,
|
|
@@ -3548,8 +3550,8 @@ Returns: { npsScore, totalResponses, promoters, passives, detractors, responses[
|
|
|
3548
3550
|
}
|
|
3549
3551
|
//#endregion
|
|
3550
3552
|
//#region src/mcp/tools/search-knowledge-base.ts
|
|
3551
|
-
const DATA_DIR$
|
|
3552
|
-
async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$
|
|
3553
|
+
const DATA_DIR$12 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3554
|
+
async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$12) {
|
|
3553
3555
|
const results = searchKbSimple(dataDir, input.query, { ...input.publicOnly ? { publicOnly: true } : {} });
|
|
3554
3556
|
const limited = (input.category ? results.filter((a) => a.category === input.category) : results).slice(0, input.limit ?? 10);
|
|
3555
3557
|
return { content: [{
|
|
@@ -3564,7 +3566,7 @@ async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$10) {
|
|
|
3564
3566
|
}, null, 2)
|
|
3565
3567
|
}] };
|
|
3566
3568
|
}
|
|
3567
|
-
function registerSearchKnowledgeBase(server, dataDir = DATA_DIR$
|
|
3569
|
+
function registerSearchKnowledgeBase(server, dataDir = DATA_DIR$12) {
|
|
3568
3570
|
server.registerTool("search_knowledge_base", {
|
|
3569
3571
|
description: `Search the knowledge base for articles. Text search on title, body, and tags.
|
|
3570
3572
|
Returns: { count, articles[] } with excerpts`,
|
|
@@ -3583,8 +3585,8 @@ Returns: { count, articles[] } with excerpts`,
|
|
|
3583
3585
|
}
|
|
3584
3586
|
//#endregion
|
|
3585
3587
|
//#region src/mcp/tools/create-kb-article.ts
|
|
3586
|
-
const DATA_DIR$
|
|
3587
|
-
async function handleCreateKbArticle(input, dataDir = DATA_DIR$
|
|
3588
|
+
const DATA_DIR$11 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3589
|
+
async function handleCreateKbArticle(input, dataDir = DATA_DIR$11) {
|
|
3588
3590
|
if (getKbArticle(dataDir, input.id)) return { content: [{
|
|
3589
3591
|
type: "text",
|
|
3590
3592
|
text: JSON.stringify({ error: `Article '${input.id}' already exists` })
|
|
@@ -3612,7 +3614,7 @@ async function handleCreateKbArticle(input, dataDir = DATA_DIR$9) {
|
|
|
3612
3614
|
}, null, 2)
|
|
3613
3615
|
}] };
|
|
3614
3616
|
}
|
|
3615
|
-
function registerCreateKbArticle(server, dataDir = DATA_DIR$
|
|
3617
|
+
function registerCreateKbArticle(server, dataDir = DATA_DIR$11) {
|
|
3616
3618
|
server.registerTool("create_kb_article", {
|
|
3617
3619
|
description: `Create a new knowledge base article. Articles are stored as Markdown files in .agentic/knowledge-base/.
|
|
3618
3620
|
Returns: { id, title, category, path }`,
|
|
@@ -3637,8 +3639,8 @@ Returns: { id, title, category, path }`,
|
|
|
3637
3639
|
}
|
|
3638
3640
|
//#endregion
|
|
3639
3641
|
//#region src/mcp/tools/backup-now.ts
|
|
3640
|
-
const DATA_DIR$
|
|
3641
|
-
async function handleBackupNow(input, dataDir = DATA_DIR$
|
|
3642
|
+
const DATA_DIR$10 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3643
|
+
async function handleBackupNow(input, dataDir = DATA_DIR$10) {
|
|
3642
3644
|
const zipPath = path.join(dataDir, `dxcrm-backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19)}.zip`);
|
|
3643
3645
|
const manifest = await runBackup(zipPath, dataDir, { ...input.remote ? { remote: input.remote } : {} }).catch(() => null);
|
|
3644
3646
|
if (!manifest) return { content: [{
|
|
@@ -3675,8 +3677,8 @@ function registerBackupNow(server) {
|
|
|
3675
3677
|
}
|
|
3676
3678
|
//#endregion
|
|
3677
3679
|
//#region src/mcp/tools/list-backups.ts
|
|
3678
|
-
const DATA_DIR$
|
|
3679
|
-
async function handleListBackups(input, dataDir = DATA_DIR$
|
|
3680
|
+
const DATA_DIR$9 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3681
|
+
async function handleListBackups(input, dataDir = DATA_DIR$9) {
|
|
3680
3682
|
const logEntries = readBackupLog(dataDir);
|
|
3681
3683
|
const fileEntries = listBackupsInDir(dataDir);
|
|
3682
3684
|
const entries = logEntries.length > 0 ? logEntries : fileEntries;
|
|
@@ -3710,8 +3712,8 @@ function registerListBackups(server) {
|
|
|
3710
3712
|
}
|
|
3711
3713
|
//#endregion
|
|
3712
3714
|
//#region src/mcp/tools/trigger-sync.ts
|
|
3713
|
-
const DATA_DIR$
|
|
3714
|
-
async function handleTriggerSync(input, dataDir = DATA_DIR$
|
|
3715
|
+
const DATA_DIR$8 = process.cwd();
|
|
3716
|
+
async function handleTriggerSync(input, dataDir = DATA_DIR$8) {
|
|
3715
3717
|
const auth = getGmailAuth();
|
|
3716
3718
|
if (!auth) return { content: [{
|
|
3717
3719
|
type: "text",
|
|
@@ -3805,8 +3807,8 @@ Returns: { success: boolean, synced: number, skipped: number, customers: [...],
|
|
|
3805
3807
|
}
|
|
3806
3808
|
//#endregion
|
|
3807
3809
|
//#region src/mcp/tools/get-audit-log.ts
|
|
3808
|
-
const DATA_DIR$
|
|
3809
|
-
async function handleGetAuditLog(input, dataDir = DATA_DIR$
|
|
3810
|
+
const DATA_DIR$7 = process.cwd();
|
|
3811
|
+
async function handleGetAuditLog(input, dataDir = DATA_DIR$7) {
|
|
3810
3812
|
const entries = readAuditLog(dataDir);
|
|
3811
3813
|
const filterOpts = { limit: input.limit ?? 50 };
|
|
3812
3814
|
if (input.slug !== void 0) filterOpts.slug = input.slug;
|
|
@@ -3848,8 +3850,8 @@ Returns: { total: number, returned: number, entries: [{timestamp, actor, tool, s
|
|
|
3848
3850
|
}
|
|
3849
3851
|
//#endregion
|
|
3850
3852
|
//#region src/mcp/tools/get-logs.ts
|
|
3851
|
-
const DATA_DIR$
|
|
3852
|
-
async function handleGetLogs(input, dataDir = DATA_DIR$
|
|
3853
|
+
const DATA_DIR$6 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3854
|
+
async function handleGetLogs(input, dataDir = DATA_DIR$6) {
|
|
3853
3855
|
const query = {
|
|
3854
3856
|
...input.level !== void 0 ? { level: input.level } : {},
|
|
3855
3857
|
...input.component !== void 0 ? { component: input.component } : {},
|
|
@@ -3911,8 +3913,8 @@ Returns (summary): { total, byLevel, byComponent, firstTs, lastTs, recentErrors
|
|
|
3911
3913
|
}
|
|
3912
3914
|
//#endregion
|
|
3913
3915
|
//#region src/mcp/tools/get-diagnostics.ts
|
|
3914
|
-
const DATA_DIR$
|
|
3915
|
-
async function handleGetDiagnostics(input, dataDir = DATA_DIR$
|
|
3916
|
+
const DATA_DIR$5 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3917
|
+
async function handleGetDiagnostics(input, dataDir = DATA_DIR$5) {
|
|
3916
3918
|
let cleaned = 0;
|
|
3917
3919
|
if (input.fix) {
|
|
3918
3920
|
const { cleanupTempFiles } = await import("./doctor-CYDaNmFn.js");
|
|
@@ -3945,11 +3947,11 @@ Returns: { ok: boolean, tempFilesRemoved?: number, checks: [{ name, status: "ok"
|
|
|
3945
3947
|
}
|
|
3946
3948
|
//#endregion
|
|
3947
3949
|
//#region src/mcp/tools/get-pipeline-changes.ts
|
|
3948
|
-
const DATA_DIR$
|
|
3950
|
+
const DATA_DIR$4 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3949
3951
|
function daysAgoIso(days) {
|
|
3950
3952
|
return (/* @__PURE__ */ new Date(Date.now() - days * 864e5)).toISOString().slice(0, 10);
|
|
3951
3953
|
}
|
|
3952
|
-
async function handleGetPipelineChanges(input, dataDir = DATA_DIR$
|
|
3954
|
+
async function handleGetPipelineChanges(input, dataDir = DATA_DIR$4) {
|
|
3953
3955
|
const since = input.since ?? daysAgoIso(input.days ?? 7);
|
|
3954
3956
|
const diff = diffAgainstNow(dataDir, since);
|
|
3955
3957
|
const payload = diff ? diff : { error: `No pipeline snapshot at or before ${since}. Snapshots accrue daily via the daemon.` };
|
|
@@ -3984,6 +3986,64 @@ or { error } when no baseline snapshot exists yet.`,
|
|
|
3984
3986
|
});
|
|
3985
3987
|
}
|
|
3986
3988
|
//#endregion
|
|
3989
|
+
//#region src/mcp/tools/get-pipeline-velocity.ts
|
|
3990
|
+
const DATA_DIR$3 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3991
|
+
async function handleGetPipelineVelocity(input, dataDir = DATA_DIR$3) {
|
|
3992
|
+
const opts = {};
|
|
3993
|
+
if (input.stalledDays !== void 0) opts.stalledDays = input.stalledDays;
|
|
3994
|
+
const report = analyzeVelocity(dataDir, opts);
|
|
3995
|
+
return { content: [{
|
|
3996
|
+
type: "text",
|
|
3997
|
+
text: JSON.stringify(report, null, 2)
|
|
3998
|
+
}] };
|
|
3999
|
+
}
|
|
4000
|
+
function registerGetPipelineVelocity(server) {
|
|
4001
|
+
server.registerTool("get_pipeline_velocity", {
|
|
4002
|
+
title: "Get Pipeline Velocity",
|
|
4003
|
+
description: `Pipeline velocity analytics from the daily snapshot history.
|
|
4004
|
+
Reconstructs each deal's stage journey to answer "where do deals get stuck?"
|
|
4005
|
+
and "which deals are rotting?".
|
|
4006
|
+
|
|
4007
|
+
Args:
|
|
4008
|
+
stalledDays: A deal open in the same stage longer than this is "stalled"
|
|
4009
|
+
(default 14).
|
|
4010
|
+
|
|
4011
|
+
Returns: { fromId, toId, snapshotCount, stageDurations[{stage,avgDays,samples}],
|
|
4012
|
+
avgSalesCycleDays, wonCount, stalledDeals[{slug,name,stage,daysInStage,value}],
|
|
4013
|
+
stalledThresholdDays }. snapshotCount is 0 until the daemon has taken snapshots.`,
|
|
4014
|
+
inputSchema: z.object({ stalledDays: z.number().int().min(1).max(365).optional().describe("Days in one stage before a deal counts as stalled (default 14)") })
|
|
4015
|
+
}, async ({ stalledDays }) => {
|
|
4016
|
+
const input = {};
|
|
4017
|
+
if (stalledDays !== void 0) input.stalledDays = stalledDays;
|
|
4018
|
+
return handleGetPipelineVelocity(input);
|
|
4019
|
+
});
|
|
4020
|
+
}
|
|
4021
|
+
//#endregion
|
|
4022
|
+
//#region src/mcp/tools/get-pipeline-funnel.ts
|
|
4023
|
+
const DATA_DIR$2 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
4024
|
+
async function handleGetPipelineFunnel(_input, dataDir = DATA_DIR$2) {
|
|
4025
|
+
const report = analyzeFunnel(dataDir);
|
|
4026
|
+
return { content: [{
|
|
4027
|
+
type: "text",
|
|
4028
|
+
text: JSON.stringify(report, null, 2)
|
|
4029
|
+
}] };
|
|
4030
|
+
}
|
|
4031
|
+
function registerGetPipelineFunnel(server) {
|
|
4032
|
+
server.registerTool("get_pipeline_funnel", {
|
|
4033
|
+
title: "Get Pipeline Funnel",
|
|
4034
|
+
description: `Pipeline conversion funnel & win-rate from the daily snapshot history.
|
|
4035
|
+
For each deal it tracks the furthest stage reached and the win/lost outcome,
|
|
4036
|
+
then builds a cumulative funnel. Answers "where do deals leak out of my
|
|
4037
|
+
pipeline?" and "what's my win rate?".
|
|
4038
|
+
|
|
4039
|
+
Returns: { fromId, toId, snapshotCount,
|
|
4040
|
+
stages[{stage, reached, conversionPctToNext}], wonCount, lostCount, winRatePct,
|
|
4041
|
+
biggestLeak{from,to,conversionPct} }. snapshotCount is 0 until the daemon has
|
|
4042
|
+
taken snapshots.`,
|
|
4043
|
+
inputSchema: z.object({})
|
|
4044
|
+
}, async () => handleGetPipelineFunnel({}));
|
|
4045
|
+
}
|
|
4046
|
+
//#endregion
|
|
3987
4047
|
//#region src/mcp/prompts.ts
|
|
3988
4048
|
/**
|
|
3989
4049
|
* CRM playbook prompts exposed via MCP `prompts/list` + `prompts/get`.
|
|
@@ -4242,6 +4302,8 @@ function createMcpServer() {
|
|
|
4242
4302
|
registerGetLogs(server);
|
|
4243
4303
|
registerGetDiagnostics(server);
|
|
4244
4304
|
registerGetPipelineChanges(server);
|
|
4305
|
+
registerGetPipelineVelocity(server);
|
|
4306
|
+
registerGetPipelineFunnel(server);
|
|
4245
4307
|
registerCustomObjectTools(server);
|
|
4246
4308
|
registerPrompts(server);
|
|
4247
4309
|
registerResources(server);
|
|
@@ -4440,4 +4502,4 @@ else startStdio().catch((err) => {
|
|
|
4440
4502
|
//#endregion
|
|
4441
4503
|
export { startHttp, startStdio };
|
|
4442
4504
|
|
|
4443
|
-
//# sourceMappingURL=server-
|
|
4505
|
+
//# sourceMappingURL=server-DAcwmRPE.js.map
|