@agifyai/leadify-mcp 8.1.0 → 8.2.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/README.md
CHANGED
|
@@ -179,6 +179,8 @@ Conséquences pratiques :
|
|
|
179
179
|
| Tool | Description |
|
|
180
180
|
|------|-------------|
|
|
181
181
|
| `test_api_key` | Vérifier que la clé API configurée est valide (health check). |
|
|
182
|
+
| `list_lead_groups` | Lister les groupes accessibles d'une organisation explicitement sélectionnée, en vue compacte. |
|
|
183
|
+
| `get_lead_group` | Consulter les métadonnées compactes d'un groupe accessible par son ID. |
|
|
182
184
|
| `add_leads` | Ajouter un ou plusieurs leads à un groupe. |
|
|
183
185
|
| `get_leads` | Rechercher et lister des leads avec filtres, recherche et pagination. |
|
|
184
186
|
| `get_lead` | Récupérer les détails complets d'un lead par son ID. |
|
|
@@ -201,6 +203,7 @@ Conséquences pratiques :
|
|
|
201
203
|
| `signal_disable` | Désactiver un signal (faux positif / écarté manuellement). Flip de `state` uniquement. |
|
|
202
204
|
| `signal_delete` | Supprimer définitivement un signal (cas rare : donnée erronée, doublon). |
|
|
203
205
|
| `add_activity` | Journaliser une interaction prospect (LinkedIn, email, call) dans le feed du lead. |
|
|
206
|
+
| `compile_context_pack` | Compiler en lecture seule un Context Pack canonique depuis une cible explicite (`organization`, `lead_group`, `campaign`, `account`, `person`) ou un couple lead + campagne pour `WRITE_OUTREACH`. Retourne publications courantes, sources, freshness, contradictions et provenance. N’utilise jamais la Data Room legacy ni ne choisit de cible implicite. |
|
|
204
207
|
| `get_context_workspace` | Lire le Context Workspace canonique versionné (`company_brain` ou `gtm_playbook`) d'une organisation explicitement sélectionnée. Retourne le brouillon et la dernière version publiée. |
|
|
205
208
|
| `update_company_brain_sections` | Modifier uniquement les sections indiquées du Company Brain : le MCP relit le brouillon ou la dernière publication, fusionne les sections ciblées, puis sauvegarde avec révision attendue et clé d'idempotence. |
|
|
206
209
|
| `update_gtm_playbook_sections` | Modifier uniquement les sections indiquées du GTM Playbook, avec la même lecture-fusion-révision atomiquement contrôlée. |
|
package/dist/server.js
CHANGED
|
@@ -16,7 +16,7 @@ import { registerContextWorkspaceTools } from "./tools/context_workspace.js";
|
|
|
16
16
|
export function createServer() {
|
|
17
17
|
const server = new McpServer({
|
|
18
18
|
name: "leadify",
|
|
19
|
-
version: "8.
|
|
19
|
+
version: "8.2.0",
|
|
20
20
|
});
|
|
21
21
|
registerAuthTools(server);
|
|
22
22
|
registerOrganizationTools(server);
|
|
@@ -4,6 +4,9 @@ export interface ContextWorkspaceClient {
|
|
|
4
4
|
put(path: string, body: unknown): Promise<unknown>;
|
|
5
5
|
post(path: string, body: unknown): Promise<unknown>;
|
|
6
6
|
}
|
|
7
|
+
export interface ContextPackClient {
|
|
8
|
+
post(path: string, body: unknown): Promise<unknown>;
|
|
9
|
+
}
|
|
7
10
|
/** Bounded projection for agents: the active draft and latest published version only. */
|
|
8
11
|
export declare function projectContextWorkspaceRead(data: unknown): Record<string, unknown>;
|
|
9
12
|
export declare function registerContextWorkspaceTools(server: McpServer, client?: ContextWorkspaceClient): void;
|
|
@@ -102,6 +102,37 @@ async function updateSections(client, input) {
|
|
|
102
102
|
});
|
|
103
103
|
}
|
|
104
104
|
export function registerContextWorkspaceTools(server, client = getClient()) {
|
|
105
|
+
server.registerTool("compile_context_pack", {
|
|
106
|
+
title: "Compile the canonical Context Pack",
|
|
107
|
+
description: "Compile the canonical, tenant-scoped Context Pack for one explicitly selected target. Use `target_kind` + `target_id` for organization, " +
|
|
108
|
+
"lead group, campaign, account, or person; use lead + campaign only for the WRITE_OUTREACH pack. This is read-only and never uses Data Room.",
|
|
109
|
+
inputSchema: {
|
|
110
|
+
organization_id: z.string().trim().min(1).describe("Organization explicitly selected through discover_leadify_context."),
|
|
111
|
+
target_kind: z.enum(["organization", "lead_group", "campaign", "account", "person"]).optional().describe("Direct canonical target; never causes an implicit lead/campaign selection."),
|
|
112
|
+
target_id: z.string().trim().min(1).optional().describe("Required for every target except organization."),
|
|
113
|
+
lead_id: z.string().trim().min(1).optional().describe("Lead targeted by a WRITE_OUTREACH pack; requires campaign_id."),
|
|
114
|
+
campaign_id: z.string().trim().min(1).optional().describe("Campaign targeted by a WRITE_OUTREACH pack; requires lead_id."),
|
|
115
|
+
max_evidence_age_ms: z.number().int().positive().max(90 * 24 * 60 * 60 * 1000).optional().describe("Optional freshness limit; defaults to 30 days and never exceeds 90 days."),
|
|
116
|
+
},
|
|
117
|
+
annotations: { readOnlyHint: true },
|
|
118
|
+
}, async ({ organization_id, target_kind, target_id, lead_id, campaign_id, max_evidence_age_ms }) => {
|
|
119
|
+
try {
|
|
120
|
+
if (target_kind) {
|
|
121
|
+
if (target_kind !== "organization" && !target_id)
|
|
122
|
+
return toolResult({ error: "target_id is required for this target_kind" });
|
|
123
|
+
return toolResult(await client.post("/api/context-pack/target", { organizationId: organization_id, target: { kind: target_kind, ...(target_id ? { id: target_id } : {}) } }));
|
|
124
|
+
}
|
|
125
|
+
if (!lead_id || !campaign_id)
|
|
126
|
+
return toolResult({ error: "Provide target_kind (and target_id when needed), or both lead_id and campaign_id." });
|
|
127
|
+
const body = { organizationId: organization_id, leadId: lead_id, campaignId: campaign_id };
|
|
128
|
+
if (max_evidence_age_ms !== undefined)
|
|
129
|
+
body.maxEvidenceAgeMs = max_evidence_age_ms;
|
|
130
|
+
return toolResult(await client.post("/api/context-pack/compile", body));
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
return handleToolError(error);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
105
136
|
server.registerTool("get_context_workspace", {
|
|
106
137
|
title: "Read canonical versioned Context Workspace",
|
|
107
138
|
description: "Read the canonical Leadify Context Workspace for one explicitly selected organization and kind. " +
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
export declare function assertLeadGroupsBelongToOrganization(data: unknown, organizationId: string): Array<Record<string, unknown>>;
|
|
3
|
+
/** Keep group reads navigable: never return schema, profiles, or lead data. */
|
|
4
|
+
export declare function compactLeadGroup(group: unknown): Record<string, unknown>;
|
|
3
5
|
export declare function registerOrganizationTools(server: McpServer): void;
|
|
@@ -22,6 +22,28 @@ export function assertLeadGroupsBelongToOrganization(data, organizationId) {
|
|
|
22
22
|
}
|
|
23
23
|
return leadGroups;
|
|
24
24
|
}
|
|
25
|
+
/** Keep group reads navigable: never return schema, profiles, or lead data. */
|
|
26
|
+
export function compactLeadGroup(group) {
|
|
27
|
+
const source = group && typeof group === "object" ? group : {};
|
|
28
|
+
const count = source._count && typeof source._count === "object"
|
|
29
|
+
? source._count
|
|
30
|
+
: {};
|
|
31
|
+
return {
|
|
32
|
+
id: source.id,
|
|
33
|
+
name: source.name,
|
|
34
|
+
description: source.description ?? null,
|
|
35
|
+
organizationId: source.organizationId,
|
|
36
|
+
entityKind: source.entityKind ?? "GENERIC",
|
|
37
|
+
personaTypes: Array.isArray(source.personaTypes) ? source.personaTypes : [],
|
|
38
|
+
hasPersona: Boolean(source.personaId),
|
|
39
|
+
disabledTools: Array.isArray(source.disabledTools) ? source.disabledTools : [],
|
|
40
|
+
leadCount: typeof count.leads === "number" ? count.leads : 0,
|
|
41
|
+
published: source.published ?? false,
|
|
42
|
+
refreshEnabled: source.refreshEnabled ?? false,
|
|
43
|
+
refreshFrequencyDays: source.refreshFrequencyDays ?? null,
|
|
44
|
+
createdAt: source.createdAt ?? null,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
25
47
|
export function registerOrganizationTools(server) {
|
|
26
48
|
// ── list_organizations ─────────────────────────────────────────────────
|
|
27
49
|
server.tool("list_organizations", "List every organization accessible to the caller, returning each with id, name, and " +
|
|
@@ -64,6 +86,21 @@ export function registerOrganizationTools(server) {
|
|
|
64
86
|
return handleToolError(error);
|
|
65
87
|
}
|
|
66
88
|
});
|
|
89
|
+
server.tool("get_lead_group", "Read the compact metadata of one accessible lead group by ID. Use this after list_lead_groups " +
|
|
90
|
+
"or discover_leadify_context to confirm its type and operational state. Returns only navigation " +
|
|
91
|
+
"metadata (no lead records, schema, company profile, or persona payload) and reports inaccessible " +
|
|
92
|
+
"groups as not found, without revealing their organization.", {
|
|
93
|
+
lead_group_id: z.string().describe("Lead group ID returned by Leadify discovery or another authorized Leadify response."),
|
|
94
|
+
}, async ({ lead_group_id }) => {
|
|
95
|
+
try {
|
|
96
|
+
const data = await getClient().get(`/api/lead-group/${encodeURIComponent(lead_group_id)}`);
|
|
97
|
+
const source = data && typeof data === "object" ? data : {};
|
|
98
|
+
return toolResult({ leadGroup: compactLeadGroup(source.leadGroup) });
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
return handleToolError(error);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
67
104
|
server.tool("discover_leadify_context", "Safe zero-ID entry point for Leadify. With no organization_id, lists accessible organizations " +
|
|
68
105
|
"and never chooses one when several are available. With an explicit organization_id, returns " +
|
|
69
106
|
"a compact list of its lead groups. Use the returned lead_group_id with lead, campaign, persona " +
|