@agifyai/leadify-mcp 8.6.7 → 8.6.9
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/README.md
CHANGED
|
@@ -289,11 +289,14 @@ Leadify et ne doit jamais être envoyée par un agent MCP.
|
|
|
289
289
|
| `preview_canonical_relationship_migration` | Prévisualiser une migration de champs historiques, divergences et quarantaines comprises, sans mutation. |
|
|
290
290
|
| `apply_canonical_relationship_migration` | Appliquer exactement un plan prévisualisé et borné grâce à son digest. |
|
|
291
291
|
| `rollback_canonical_relationship_migration` | Tombstoner les liens créés par un plan de migration précis. |
|
|
292
|
+
| `configure_lead_group_relations` | Configurer, dans un tenant explicitement vérifié, la projection legacy relue par une migration canonique. |
|
|
293
|
+
| `preview_canonical_identity_backfill` | Prévisualiser le backfill d'identité tenant-scoped d'un groupe et de ses parents Company configurés. |
|
|
294
|
+
| `apply_canonical_identity_backfill` | Appliquer exactement un backfill d'identité relu par digest, sans outreach ni activation. |
|
|
292
295
|
| `update_company_brain_sections` | Modifier uniquement les sections globales encore actives (`identity`, `positioning`, `allowedVocabulary`, `prohibitedVocabulary`, `legalConstraints`). Les anciennes sections Offre/Verticale sont filtrées et refusées. |
|
|
293
296
|
| `publish_context_workspace` | Publier une révision prête du Company Brain après confirmation explicite (`confirm_publish: true`). Admin de l'organisation requis ; les raisons de non-readiness sont renvoyées par le serveur. |
|
|
294
297
|
| `list_persona_contracts` / `get_persona_contract` | Lister ou lire les contrats Persona canoniques d’une organisation explicitement sélectionnée. |
|
|
295
|
-
| `create_persona_contract` | Créer un Persona tenant-scoped et lié à une Verticale depuis un contrat canonique complet. |
|
|
296
|
-
| `replace_persona_contract` / `patch_persona_contract` | Remplacer ou modifier un contrat canonique avec verrou optimiste
|
|
298
|
+
| `create_persona_contract` | Créer un Persona tenant-scoped et lié à une Verticale depuis un contrat canonique v2 complet et strict. Toute clé inconnue est refusée. |
|
|
299
|
+
| `replace_persona_contract` / `patch_persona_contract` | Remplacer ou modifier un contrat canonique v2 avec verrou optimiste. Le document est revalidé intégralement avant l’écriture et aucune colonne Persona historique n’est exposée. |
|
|
297
300
|
| `change_persona_status` | Passer un Persona entre `DRAFT`, `ACTIVE` et `ARCHIVED` avec le même verrou `updated_at`, readiness et protection des références. |
|
|
298
301
|
| `list_data_sources` | Lister toutes les sources de données configurées (par pays puis nom). |
|
|
299
302
|
| `create_data_source` | Créer une nouvelle source de données (admin uniquement). |
|
package/dist/server.js
CHANGED
|
@@ -15,6 +15,7 @@ import { registerFineTuningTools } from "./tools/fine_tuning.js";
|
|
|
15
15
|
import { registerContextWorkspaceTools } from "./tools/context_workspace.js";
|
|
16
16
|
import { registerLeadViewTools } from "./tools/views.js";
|
|
17
17
|
import { registerRelationshipTools } from "./tools/relationships.js";
|
|
18
|
+
import { registerCanonicalBackfillTools } from "./tools/canonical_backfill.js";
|
|
18
19
|
import { registerCommercialTruthTools } from "./tools/commercial_truth.js";
|
|
19
20
|
import { registerEventTools } from "./tools/events.js";
|
|
20
21
|
import { registerContextEntityTools } from "./tools/context_entities.js";
|
|
@@ -30,6 +31,7 @@ export function createServer() {
|
|
|
30
31
|
registerLeadViewTools(server);
|
|
31
32
|
registerLeadTools(server);
|
|
32
33
|
registerRelationshipTools(server);
|
|
34
|
+
registerCanonicalBackfillTools(server);
|
|
33
35
|
registerEventTools(server);
|
|
34
36
|
registerCommercialTruthTools(server);
|
|
35
37
|
registerSchemaTools(server);
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { getClient } from "../client.js";
|
|
3
|
+
import { handleToolError, toolResult } from "../types.js";
|
|
4
|
+
const relationshipType = z.enum(["EMPLOYED_BY", "AFFILIATED_WITH", "PART_OF", "COLLEAGUE_OF"]);
|
|
5
|
+
const relation = z.object({
|
|
6
|
+
field: z.string().trim().min(1),
|
|
7
|
+
lead_group_id: z.string().trim().min(1),
|
|
8
|
+
target_field: z.string().trim().min(1).optional(),
|
|
9
|
+
display_field: z.string().trim().min(1).optional(),
|
|
10
|
+
inverse_field: z.string().trim().min(1).optional(),
|
|
11
|
+
canonical_type: relationshipType.optional(),
|
|
12
|
+
canonical_endpoint_role: z.enum(["SOURCE", "TARGET"]).optional(),
|
|
13
|
+
canonical_label: z.string().trim().min(1).max(120).optional(),
|
|
14
|
+
}).strict().superRefine((value, context) => {
|
|
15
|
+
if (Boolean(value.canonical_type) === Boolean(value.canonical_endpoint_role))
|
|
16
|
+
return;
|
|
17
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: ["canonical_type"], message: "canonical_type and canonical_endpoint_role must be provided together" });
|
|
18
|
+
});
|
|
19
|
+
function apiRelation(value) {
|
|
20
|
+
return {
|
|
21
|
+
field: value.field,
|
|
22
|
+
leadGroupId: value.lead_group_id,
|
|
23
|
+
targetField: value.target_field,
|
|
24
|
+
displayField: value.display_field,
|
|
25
|
+
inverseField: value.inverse_field,
|
|
26
|
+
canonicalType: value.canonical_type,
|
|
27
|
+
canonicalEndpointRole: value.canonical_endpoint_role,
|
|
28
|
+
canonicalLabel: value.canonical_label,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const backfillScope = {
|
|
32
|
+
organization_id: z.string().trim().min(1),
|
|
33
|
+
lead_group_id: z.string().trim().min(1),
|
|
34
|
+
lead_ids: z.array(z.string().trim().min(1)).min(1).max(100),
|
|
35
|
+
};
|
|
36
|
+
export function registerCanonicalBackfillTools(server, client = getClient()) {
|
|
37
|
+
server.tool("configure_lead_group_relations", "Configure the legacy projection that a canonical migration reads. The organization is mandatory and verified against both groups; canonical_type and canonical_endpoint_role must be specified together. This changes no lead, identity, canonical relationship, campaign, or outreach.", { organization_id: z.string().trim().min(1), lead_group_id: z.string().trim().min(1), relations: z.array(relation).max(100) }, async ({ organization_id, lead_group_id, relations }) => {
|
|
38
|
+
try {
|
|
39
|
+
return toolResult(await client.put(`/api/lead-group/${encodeURIComponent(lead_group_id)}/relations`, {
|
|
40
|
+
organizationId: organization_id,
|
|
41
|
+
relations: relations.map(apiRelation),
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
return handleToolError(error);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
server.tool("preview_canonical_identity_backfill", "Preview the tenant-scoped canonical identity backfill for one LeadGroup. It reads only the listed leads and their configured Company parent, returns an exact plan digest, and creates no identity, relationship, outreach, or activation.", backfillScope, async ({ organization_id, lead_group_id, lead_ids }) => {
|
|
49
|
+
try {
|
|
50
|
+
return toolResult(await client.post("/api/canonical-identity/backfill", {
|
|
51
|
+
organizationId: organization_id, leadGroupId: lead_group_id, leadIds: lead_ids,
|
|
52
|
+
projectionTarget: "lead", dryRun: true,
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
return handleToolError(error);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
server.tool("apply_canonical_identity_backfill", "Apply exactly a reviewed canonical identity backfill plan. The organization and LeadGroup stay explicit, and the backend rejects a changed digest, cross-tenant lead, missing parent, or missing canonical Company account. It never sends outreach or activates campaigns.", { ...backfillScope, expected_plan_digest: z.string().regex(/^[a-f0-9]{64}$/) }, async ({ organization_id, lead_group_id, lead_ids, expected_plan_digest }) => {
|
|
60
|
+
try {
|
|
61
|
+
return toolResult(await client.post("/api/canonical-identity/backfill", {
|
|
62
|
+
organizationId: organization_id, leadGroupId: lead_group_id, leadIds: lead_ids,
|
|
63
|
+
projectionTarget: "lead", dryRun: false, expectedPlanDigest: expected_plan_digest,
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
return handleToolError(error);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
@@ -161,6 +161,13 @@ export declare const verticalContextContentSchema: z.ZodEffects<z.ZodObject<{
|
|
|
161
161
|
implication?: string | undefined;
|
|
162
162
|
}>, "many">>;
|
|
163
163
|
}, "strict", z.ZodTypeAny, {
|
|
164
|
+
painPoints?: {
|
|
165
|
+
id: string;
|
|
166
|
+
title: string;
|
|
167
|
+
description?: string | undefined;
|
|
168
|
+
customerCaseIds?: string[] | undefined;
|
|
169
|
+
useCaseIds?: string[] | undefined;
|
|
170
|
+
}[] | undefined;
|
|
164
171
|
allowedVocabulary?: string[] | undefined;
|
|
165
172
|
prohibitedVocabulary?: string[] | undefined;
|
|
166
173
|
legalConstraints?: {
|
|
@@ -191,13 +198,6 @@ export declare const verticalContextContentSchema: z.ZodEffects<z.ZodObject<{
|
|
|
191
198
|
description?: string | undefined;
|
|
192
199
|
customerCaseIds?: string[] | undefined;
|
|
193
200
|
}[] | undefined;
|
|
194
|
-
painPoints?: {
|
|
195
|
-
id: string;
|
|
196
|
-
title: string;
|
|
197
|
-
description?: string | undefined;
|
|
198
|
-
customerCaseIds?: string[] | undefined;
|
|
199
|
-
useCaseIds?: string[] | undefined;
|
|
200
|
-
}[] | undefined;
|
|
201
201
|
qualificationSignals?: {
|
|
202
202
|
id: string;
|
|
203
203
|
title: string;
|
|
@@ -226,6 +226,13 @@ export declare const verticalContextContentSchema: z.ZodEffects<z.ZodObject<{
|
|
|
226
226
|
implication?: string | undefined;
|
|
227
227
|
}[] | undefined;
|
|
228
228
|
}, {
|
|
229
|
+
painPoints?: {
|
|
230
|
+
id: string;
|
|
231
|
+
title: string;
|
|
232
|
+
description?: string | undefined;
|
|
233
|
+
customerCaseIds?: string[] | undefined;
|
|
234
|
+
useCaseIds?: string[] | undefined;
|
|
235
|
+
}[] | undefined;
|
|
229
236
|
allowedVocabulary?: string[] | undefined;
|
|
230
237
|
prohibitedVocabulary?: string[] | undefined;
|
|
231
238
|
legalConstraints?: {
|
|
@@ -256,13 +263,6 @@ export declare const verticalContextContentSchema: z.ZodEffects<z.ZodObject<{
|
|
|
256
263
|
description?: string | undefined;
|
|
257
264
|
customerCaseIds?: string[] | undefined;
|
|
258
265
|
}[] | undefined;
|
|
259
|
-
painPoints?: {
|
|
260
|
-
id: string;
|
|
261
|
-
title: string;
|
|
262
|
-
description?: string | undefined;
|
|
263
|
-
customerCaseIds?: string[] | undefined;
|
|
264
|
-
useCaseIds?: string[] | undefined;
|
|
265
|
-
}[] | undefined;
|
|
266
266
|
qualificationSignals?: {
|
|
267
267
|
id: string;
|
|
268
268
|
title: string;
|
|
@@ -291,6 +291,13 @@ export declare const verticalContextContentSchema: z.ZodEffects<z.ZodObject<{
|
|
|
291
291
|
implication?: string | undefined;
|
|
292
292
|
}[] | undefined;
|
|
293
293
|
}>, {
|
|
294
|
+
painPoints?: {
|
|
295
|
+
id: string;
|
|
296
|
+
title: string;
|
|
297
|
+
description?: string | undefined;
|
|
298
|
+
customerCaseIds?: string[] | undefined;
|
|
299
|
+
useCaseIds?: string[] | undefined;
|
|
300
|
+
}[] | undefined;
|
|
294
301
|
allowedVocabulary?: string[] | undefined;
|
|
295
302
|
prohibitedVocabulary?: string[] | undefined;
|
|
296
303
|
legalConstraints?: {
|
|
@@ -321,13 +328,6 @@ export declare const verticalContextContentSchema: z.ZodEffects<z.ZodObject<{
|
|
|
321
328
|
description?: string | undefined;
|
|
322
329
|
customerCaseIds?: string[] | undefined;
|
|
323
330
|
}[] | undefined;
|
|
324
|
-
painPoints?: {
|
|
325
|
-
id: string;
|
|
326
|
-
title: string;
|
|
327
|
-
description?: string | undefined;
|
|
328
|
-
customerCaseIds?: string[] | undefined;
|
|
329
|
-
useCaseIds?: string[] | undefined;
|
|
330
|
-
}[] | undefined;
|
|
331
331
|
qualificationSignals?: {
|
|
332
332
|
id: string;
|
|
333
333
|
title: string;
|
|
@@ -356,6 +356,13 @@ export declare const verticalContextContentSchema: z.ZodEffects<z.ZodObject<{
|
|
|
356
356
|
implication?: string | undefined;
|
|
357
357
|
}[] | undefined;
|
|
358
358
|
}, {
|
|
359
|
+
painPoints?: {
|
|
360
|
+
id: string;
|
|
361
|
+
title: string;
|
|
362
|
+
description?: string | undefined;
|
|
363
|
+
customerCaseIds?: string[] | undefined;
|
|
364
|
+
useCaseIds?: string[] | undefined;
|
|
365
|
+
}[] | undefined;
|
|
359
366
|
allowedVocabulary?: string[] | undefined;
|
|
360
367
|
prohibitedVocabulary?: string[] | undefined;
|
|
361
368
|
legalConstraints?: {
|
|
@@ -386,13 +393,6 @@ export declare const verticalContextContentSchema: z.ZodEffects<z.ZodObject<{
|
|
|
386
393
|
description?: string | undefined;
|
|
387
394
|
customerCaseIds?: string[] | undefined;
|
|
388
395
|
}[] | undefined;
|
|
389
|
-
painPoints?: {
|
|
390
|
-
id: string;
|
|
391
|
-
title: string;
|
|
392
|
-
description?: string | undefined;
|
|
393
|
-
customerCaseIds?: string[] | undefined;
|
|
394
|
-
useCaseIds?: string[] | undefined;
|
|
395
|
-
}[] | undefined;
|
|
396
396
|
qualificationSignals?: {
|
|
397
397
|
id: string;
|
|
398
398
|
title: string;
|
package/dist/tools/personas.js
CHANGED
|
@@ -6,9 +6,68 @@ import { LeadifyApiError, handleToolError, toolResult } from "../types.js";
|
|
|
6
6
|
* versioned `personaContract`. These tools deliberately do not expose any
|
|
7
7
|
* historical Persona field or field-specific patch operation.
|
|
8
8
|
*/
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
.
|
|
9
|
+
const tierSchema = z.object({
|
|
10
|
+
rule: z.string(),
|
|
11
|
+
expectedEvidence: z.string(),
|
|
12
|
+
examples: z.array(z.string()).max(20),
|
|
13
|
+
}).strict();
|
|
14
|
+
const commonContractSchema = z.object({
|
|
15
|
+
schemaVersion: z.literal(2),
|
|
16
|
+
kind: z.enum(["PERSON", "COMPANY"]),
|
|
17
|
+
targeting: z.object({
|
|
18
|
+
targetProfile: z.unknown().nullable(),
|
|
19
|
+
disqualificationCriteria: z.unknown().nullable(),
|
|
20
|
+
schemaPacks: z.array(z.string()).max(2),
|
|
21
|
+
agentDomain: z.string().nullable(),
|
|
22
|
+
outputLanguage: z.string().nullable(),
|
|
23
|
+
}).strict(),
|
|
24
|
+
qualification: z.object({
|
|
25
|
+
tiers: z.object({
|
|
26
|
+
hot: tierSchema,
|
|
27
|
+
warm: tierSchema,
|
|
28
|
+
cold: tierSchema,
|
|
29
|
+
disqualified: tierSchema,
|
|
30
|
+
}).strict(),
|
|
31
|
+
signalExamples: z.array(z.object({
|
|
32
|
+
id: z.string().min(1),
|
|
33
|
+
signal: z.string().min(1),
|
|
34
|
+
level: z.enum(["GOLDEN", "CRITICAL", "STRONG", "INFO"]),
|
|
35
|
+
justification: z.string().min(1),
|
|
36
|
+
}).strict()).max(100),
|
|
37
|
+
signalTierRules: z.unknown().nullable(),
|
|
38
|
+
enableSignals: z.boolean(),
|
|
39
|
+
}).strict(),
|
|
40
|
+
intelligence: z.object({
|
|
41
|
+
activeTools: z.array(z.string()),
|
|
42
|
+
painPoints: z.unknown().nullable(),
|
|
43
|
+
icpStrategy: z.unknown().nullable(),
|
|
44
|
+
cardAnalysisSections: z.unknown().nullable(),
|
|
45
|
+
}).strict(),
|
|
46
|
+
outreach: z.object({
|
|
47
|
+
outreachSignalRouting: z.unknown().nullable(),
|
|
48
|
+
outreachTemplates: z.unknown().nullable(),
|
|
49
|
+
toneInstructions: z.string().nullable(),
|
|
50
|
+
outreachFields: z.unknown().nullable(),
|
|
51
|
+
}).strict(),
|
|
52
|
+
}).strict();
|
|
53
|
+
const personExtensionSchema = z.object({
|
|
54
|
+
assessmentAxes: z.object({
|
|
55
|
+
identityAndEmployment: z.object({ question: z.string(), expectedEvidence: z.string() }).strict(),
|
|
56
|
+
commercialLink: z.object({ question: z.string(), expectedEvidence: z.string() }).strict(),
|
|
57
|
+
actionPower: z.object({ question: z.string(), expectedEvidence: z.string() }).strict(),
|
|
58
|
+
individualMoment: z.object({ question: z.string(), expectedEvidence: z.string() }).strict(),
|
|
59
|
+
}).strict(),
|
|
60
|
+
roleArchetypes: z.array(z.object({
|
|
61
|
+
name: z.string().min(1),
|
|
62
|
+
relevanceRule: z.string(),
|
|
63
|
+
expectedEvidence: z.string(),
|
|
64
|
+
examples: z.array(z.string()).max(20),
|
|
65
|
+
}).strict()).max(50),
|
|
66
|
+
}).strict();
|
|
67
|
+
const contractSchema = z.discriminatedUnion("kind", [
|
|
68
|
+
commonContractSchema.extend({ kind: z.literal("COMPANY"), person: z.null() }).strict(),
|
|
69
|
+
commonContractSchema.extend({ kind: z.literal("PERSON"), person: personExtensionSchema }).strict(),
|
|
70
|
+
]).describe("Complete strict Persona contract, schemaVersion 2.");
|
|
12
71
|
const tenantScope = {
|
|
13
72
|
organization_id: z
|
|
14
73
|
.string()
|
|
@@ -27,6 +86,7 @@ function canonicalPersona(persona) {
|
|
|
27
86
|
if (!persona.personaContract || typeof persona.personaContract !== "object") {
|
|
28
87
|
throw new Error("PERSONA_CONTRACT_REQUIRED: run the audited Persona migration before using this MCP.");
|
|
29
88
|
}
|
|
89
|
+
const contract = contractSchema.parse(persona.personaContract);
|
|
30
90
|
return {
|
|
31
91
|
id: persona.id,
|
|
32
92
|
name: persona.name,
|
|
@@ -34,7 +94,7 @@ function canonicalPersona(persona) {
|
|
|
34
94
|
updatedAt: persona.updatedAt,
|
|
35
95
|
revision: persona.revision ?? 0,
|
|
36
96
|
status: persona.status,
|
|
37
|
-
contract
|
|
97
|
+
contract,
|
|
38
98
|
};
|
|
39
99
|
}
|
|
40
100
|
async function fetchPersona(id, organizationId, client) {
|
|
@@ -155,7 +215,7 @@ export function registerPersonaTools(server, injectedClient) {
|
|
|
155
215
|
organizationId: organization_id,
|
|
156
216
|
id,
|
|
157
217
|
expectedUpdatedAt: expected_updated_at,
|
|
158
|
-
contract: setContractPath(contract, path, value),
|
|
218
|
+
contract: contractSchema.parse(setContractPath(contract, path, value)),
|
|
159
219
|
client,
|
|
160
220
|
}));
|
|
161
221
|
}
|