@agifyai/leadify-mcp 8.6.1 → 8.6.3
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 +7 -0
- package/dist/tools/events.js +10 -8
- package/dist/tools/leads.js +1 -3
- package/dist/tools/personas.js +17 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +5 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -210,6 +210,13 @@ des sélecteurs courants sans effacer son historique. Les champs legacy
|
|
|
210
210
|
restent disponibles pour compatibilité/export, mais ne sont jamais synchronisés
|
|
211
211
|
depuis ce modèle.
|
|
212
212
|
|
|
213
|
+
Il n’existe plus de score de confiance événementiel : le statut et ses preuves
|
|
214
|
+
portent seuls la validation utile. `Event.description` explique l’audience et
|
|
215
|
+
l’utilité de l’événement ; `activity_summary` explique ce que l’entreprise y
|
|
216
|
+
fait, présente ou cible. `proof_excerpt` reste l’extrait exact destiné aux
|
|
217
|
+
agents et à l’audit. `record_event_participations` sert aussi bien à créer une
|
|
218
|
+
participation qu’à ajouter une nouvelle preuve ou à corriger le snapshot.
|
|
219
|
+
|
|
213
220
|
Pour `add_leads` et `update_lead`, `location` utilise l’objet canonique
|
|
214
221
|
`{ city, region?, postalCode?, countryCode, street? }`. `city` et le code pays
|
|
215
222
|
ISO-2 `countryCode` sont obligatoires. La projection `geo` est calculée par
|
package/dist/tools/events.js
CHANGED
|
@@ -19,13 +19,14 @@ const role = z.enum([
|
|
|
19
19
|
"OTHER",
|
|
20
20
|
]);
|
|
21
21
|
const status = z.enum(["UNVERIFIED", "VERIFIED", "DISPUTED", "REFUTED"]);
|
|
22
|
-
const confidence = z.enum(["LOW", "MEDIUM", "HIGH"]);
|
|
23
22
|
const nullableLabel = z.string().trim().min(1).max(500).nullable().optional();
|
|
23
|
+
const nullableNarrative = z.string().trim().min(1).max(5_000).nullable().optional();
|
|
24
24
|
const nullableUrl = z.string().trim().url().max(2048).nullable().optional();
|
|
25
25
|
const idempotencyKey = z.string().trim().min(1).max(255);
|
|
26
26
|
const eventFields = {
|
|
27
27
|
name: z.string().trim().min(1).max(300),
|
|
28
28
|
edition: z.string().trim().min(1).max(200),
|
|
29
|
+
description: nullableNarrative.describe("Readable description of the event, its audience, purpose and importance."),
|
|
29
30
|
starts_on: dateOnly,
|
|
30
31
|
ends_on: dateOnly,
|
|
31
32
|
city: nullableLabel,
|
|
@@ -50,6 +51,7 @@ const updateEventShape = {
|
|
|
50
51
|
event_id: z.string().trim().min(1),
|
|
51
52
|
name: eventFields.name.optional(),
|
|
52
53
|
edition: eventFields.edition.optional(),
|
|
54
|
+
description: eventFields.description,
|
|
53
55
|
starts_on: eventFields.starts_on.optional(),
|
|
54
56
|
ends_on: eventFields.ends_on.optional(),
|
|
55
57
|
city: eventFields.city,
|
|
@@ -62,7 +64,7 @@ const updateEventShape = {
|
|
|
62
64
|
idempotency_key: idempotencyKey,
|
|
63
65
|
};
|
|
64
66
|
const updateEventInput = z.object(updateEventShape).strict().superRefine((value, context) => {
|
|
65
|
-
const mutable = ["name", "edition", "starts_on", "ends_on", "city", "country_code", "venue", "official_url", "last_verified_on"];
|
|
67
|
+
const mutable = ["name", "edition", "description", "starts_on", "ends_on", "city", "country_code", "venue", "official_url", "last_verified_on"];
|
|
66
68
|
const supplied = mutable.filter((key) => value[key] !== undefined);
|
|
67
69
|
if (value.archive && supplied.length > 0) {
|
|
68
70
|
context.addIssue({ code: z.ZodIssueCode.custom, path: ["archive"], message: "Archive and field updates must be separate idempotent operations." });
|
|
@@ -83,10 +85,10 @@ const participationItem = z.object({
|
|
|
83
85
|
stands: z.array(z.string().trim().min(1).max(200)).max(50).optional().default([]),
|
|
84
86
|
source_urls: z.array(z.string().trim().url().max(2048)).max(50).optional().default([]),
|
|
85
87
|
source_provider: nullableLabel,
|
|
88
|
+
activity_summary: nullableNarrative.describe("Readable summary of what the company does, presents or targets at this event."),
|
|
86
89
|
proof_excerpt: z.string().trim().min(1).max(20_000),
|
|
87
90
|
observed_on: dateOnly,
|
|
88
91
|
verified_on: dateOnly.nullable().optional(),
|
|
89
|
-
confidence,
|
|
90
92
|
status,
|
|
91
93
|
correction_reason: z.string().trim().min(1).max(5_000).optional(),
|
|
92
94
|
idempotency_key: idempotencyKey,
|
|
@@ -121,10 +123,10 @@ function participationPayload(item) {
|
|
|
121
123
|
stands: item.stands,
|
|
122
124
|
sourceUrls: item.source_urls,
|
|
123
125
|
sourceProvider: item.source_provider,
|
|
126
|
+
activitySummary: item.activity_summary,
|
|
124
127
|
proofExcerpt: item.proof_excerpt,
|
|
125
128
|
observedOn: item.observed_on,
|
|
126
129
|
verifiedOn: item.verified_on,
|
|
127
|
-
confidence: item.confidence,
|
|
128
130
|
status: item.status,
|
|
129
131
|
correctionReason: item.correction_reason,
|
|
130
132
|
idempotencyKey: item.idempotency_key,
|
|
@@ -208,6 +210,7 @@ export function registerEventTools(server, client = getClient()) {
|
|
|
208
210
|
slug: input.slug,
|
|
209
211
|
name: input.name,
|
|
210
212
|
edition: input.edition,
|
|
213
|
+
description: input.description,
|
|
211
214
|
startsOn: input.starts_on,
|
|
212
215
|
endsOn: input.ends_on,
|
|
213
216
|
city: input.city,
|
|
@@ -236,6 +239,7 @@ export function registerEventTools(server, client = getClient()) {
|
|
|
236
239
|
organizationId: input.organization_id,
|
|
237
240
|
name: input.name,
|
|
238
241
|
edition: input.edition,
|
|
242
|
+
description: input.description,
|
|
239
243
|
startsOn: input.starts_on,
|
|
240
244
|
endsOn: input.ends_on,
|
|
241
245
|
city: input.city,
|
|
@@ -260,13 +264,12 @@ export function registerEventTools(server, client = getClient()) {
|
|
|
260
264
|
editions: z.array(z.string().trim().min(1).max(200)).max(100).optional(),
|
|
261
265
|
roles: z.array(role).max(20).optional(),
|
|
262
266
|
statuses: z.array(status).min(1).max(10).optional().default(["VERIFIED"]),
|
|
263
|
-
confidences: z.array(confidence).max(10).optional(),
|
|
264
267
|
starts_on_from: dateOnly.optional(),
|
|
265
268
|
starts_on_to: dateOnly.optional(),
|
|
266
269
|
include_facts: z.boolean().optional().default(false),
|
|
267
270
|
limit: z.number().int().min(1).max(100).optional().default(50),
|
|
268
271
|
cursor: z.string().trim().min(1).optional(),
|
|
269
|
-
}, async ({ organization_id, event_ids, account_ids, lead_id, editions, roles, statuses,
|
|
272
|
+
}, async ({ organization_id, event_ids, account_ids, lead_id, editions, roles, statuses, starts_on_from, starts_on_to, include_facts, limit, cursor }) => {
|
|
270
273
|
try {
|
|
271
274
|
const params = new URLSearchParams({
|
|
272
275
|
organizationId: organization_id,
|
|
@@ -280,7 +283,6 @@ export function registerEventTools(server, client = getClient()) {
|
|
|
280
283
|
params.set("leadId", lead_id);
|
|
281
284
|
setCsv(params, "editions", editions);
|
|
282
285
|
setCsv(params, "roles", roles);
|
|
283
|
-
setCsv(params, "confidences", confidences);
|
|
284
286
|
if (starts_on_from)
|
|
285
287
|
params.set("startsOnFrom", starts_on_from);
|
|
286
288
|
if (starts_on_to)
|
|
@@ -318,7 +320,7 @@ export function registerEventTools(server, client = getClient()) {
|
|
|
318
320
|
return handleToolError(error);
|
|
319
321
|
}
|
|
320
322
|
});
|
|
321
|
-
server.tool("record_event_participations", "
|
|
323
|
+
server.tool("record_event_participations", "Create participation evidence, add a corroborating source, or correct 1-100 company-event observations. Set validate_only=true for a no-write dry-run. activity_summary is the readable account of what the company does at the event; proof_excerpt remains the exact agent/audit evidence. Each item targets exactly one account_id or resolvable lead_id and has its own idempotency key. Corrections append an immutable fact and require correction_reason; there is no delete operation. VERIFIED requires a source URL, proof excerpt and verification date. Uncertain or absent data cannot be cited as attendance.", {
|
|
322
324
|
organization_id: z.string().trim().min(1),
|
|
323
325
|
batch_id: z.string().trim().min(1).max(255),
|
|
324
326
|
validate_only: z.boolean().optional().default(false),
|
package/dist/tools/leads.js
CHANGED
|
@@ -10,7 +10,6 @@ const eventFilterSchema = z.object({
|
|
|
10
10
|
"CONTRIBUTOR", "PARTICIPANT", "UNKNOWN", "OTHER",
|
|
11
11
|
])).max(20).optional(),
|
|
12
12
|
statuses: z.array(z.enum(["UNVERIFIED", "VERIFIED", "DISPUTED", "REFUTED"])).min(1).max(10).optional(),
|
|
13
|
-
confidences: z.array(z.enum(["LOW", "MEDIUM", "HIGH"])).max(10).optional(),
|
|
14
13
|
starts_on_from: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
|
|
15
14
|
starts_on_to: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
|
|
16
15
|
}).strict().superRefine((value, context) => {
|
|
@@ -193,7 +192,7 @@ export function registerLeadTools(server, client = getClient()) {
|
|
|
193
192
|
"operator to value. Operators: equals, not_equals, contains, not_contains, " +
|
|
194
193
|
"gte, lte, is_true, is_false, is_null, is_not_null. " +
|
|
195
194
|
'Example: {"industry": {"contains": "tech"}, "company": {"is_not_null": "true"}}'),
|
|
196
|
-
event_filter: eventFilterSchema.optional().describe("Structured company-event participation filter. Values within one list use OR; event, edition, role, status
|
|
195
|
+
event_filter: eventFilterSchema.optional().describe("Structured company-event participation filter. Values within one list use OR; event, edition, role, status and date dimensions use AND against the same participation. statuses defaults to [VERIFIED]. Pass uncertain statuses explicitly for review. There is no confidence score, negative operator or absence filter."),
|
|
197
196
|
}, async ({ group_id, view_id, page, limit, search, fields, include_schema, filters, event_filter }) => {
|
|
198
197
|
try {
|
|
199
198
|
const params = new URLSearchParams();
|
|
@@ -220,7 +219,6 @@ export function registerLeadTools(server, client = getClient()) {
|
|
|
220
219
|
...(checked.editions ? { editions: checked.editions } : {}),
|
|
221
220
|
...(checked.roles ? { roles: checked.roles } : {}),
|
|
222
221
|
statuses: checked.statuses ?? ["VERIFIED"],
|
|
223
|
-
...(checked.confidences ? { confidences: checked.confidences } : {}),
|
|
224
222
|
...(checked.starts_on_from ? { startsOnFrom: checked.starts_on_from } : {}),
|
|
225
223
|
...(checked.starts_on_to ? { startsOnTo: checked.starts_on_to } : {}),
|
|
226
224
|
}));
|
package/dist/tools/personas.js
CHANGED
|
@@ -40,6 +40,16 @@ const signalTierRule = z.object({
|
|
|
40
40
|
signal_id: z.string().optional(),
|
|
41
41
|
tier: z.enum(["hot", "warm", "cold"]).optional(),
|
|
42
42
|
});
|
|
43
|
+
// Persona v2 owns entity-specific qualification contracts. Keep their nested
|
|
44
|
+
// shape forward-compatible here: the Leadify API remains the authority that
|
|
45
|
+
// validates the versioned Company/Person contracts, while the MCP must never
|
|
46
|
+
// silently strip them before forwarding the wholesale upsert.
|
|
47
|
+
const companyQualification = z
|
|
48
|
+
.record(z.unknown())
|
|
49
|
+
.describe("Versioned Company Persona qualification contract forwarded unchanged to Leadify.");
|
|
50
|
+
const personQualification = z
|
|
51
|
+
.record(z.unknown())
|
|
52
|
+
.describe("Versioned Person Persona qualification contract forwarded unchanged to Leadify.");
|
|
43
53
|
const extraPromptPhase = z.object({
|
|
44
54
|
scope: z.enum(["qualify", "outreach"]).optional(),
|
|
45
55
|
insertion_point: z
|
|
@@ -319,6 +329,9 @@ export function registerPersonaTools(server, client) {
|
|
|
319
329
|
.min(1)
|
|
320
330
|
.describe("Required Vertical ID in the same organization."),
|
|
321
331
|
description: z.string().optional().describe("Detailed persona description."),
|
|
332
|
+
// Persona v2 qualification contracts
|
|
333
|
+
company_qualification: companyQualification.optional(),
|
|
334
|
+
person_qualification: personQualification.optional(),
|
|
322
335
|
// targeting
|
|
323
336
|
target_profile: z
|
|
324
337
|
.record(z.unknown())
|
|
@@ -449,6 +462,10 @@ export function registerPersonaTools(server, client) {
|
|
|
449
462
|
body.expectedUpdatedAt = params.expected_updated_at;
|
|
450
463
|
if (params.description !== undefined)
|
|
451
464
|
body.description = params.description;
|
|
465
|
+
if (params.company_qualification !== undefined)
|
|
466
|
+
body.companyQualification = params.company_qualification;
|
|
467
|
+
if (params.person_qualification !== undefined)
|
|
468
|
+
body.personQualification = params.person_qualification;
|
|
452
469
|
if (params.target_profile !== undefined)
|
|
453
470
|
body.targetProfile = params.target_profile;
|
|
454
471
|
if (params.disqualification_criteria !== undefined)
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import packageJson from "../package.json" with { type: "json" };
|
|
1
2
|
export const MCP_PACKAGE_NAME = "@agifyai/leadify-mcp";
|
|
2
3
|
export const MCP_SERVER_NAME = "leadify";
|
|
3
|
-
|
|
4
|
+
// publish.yml may select the next patch release immediately before building.
|
|
5
|
+
// Read the package manifest so the MCP handshake always reports that same
|
|
6
|
+
// published artifact version rather than a stale source constant.
|
|
7
|
+
export const MCP_VERSION = packageJson.version;
|