@agifyai/leadify-mcp 8.7.2 → 8.7.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 CHANGED
@@ -278,6 +278,9 @@ Leadify et ne doit jamais être envoyée par un agent MCP.
278
278
  | `leadify_read_activity_feed` | Lire l'audit borné d'un lead ; le feed ne constitue jamais une preuve de réponse. |
279
279
  | `get_commercial_truth` | Réconcilier CRM, email, LinkedIn, Unipile et activité avec un statut, une fraîcheur et une action recommandée ; aucune écriture ni envoi. |
280
280
  | `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, sans choisir de cible implicite. |
281
+ | `get_claim_contradiction` | Lire une contradiction canonique tenant-scopée avec ses deux claims immuables, leurs preuves, sa version et son éventuelle résolution auditée. |
282
+ | `resolve_claim_contradiction` | Arbitrer explicitement une contradiction relue par sélection d’un claim ou coexistence, avec justification, version, état attendu et clé d’idempotence ; aucun effet commercial. |
283
+ | `resolve_claim_contradictions_batch` | Soumettre jusqu’à 100 arbitrages explicites et relire chaque résultat ordonné, sans choix automatique ni résolution implicite. |
281
284
  | `get_context_workspace` | Lire le seul Context Workspace encore exposé et versionné : le `company_brain` d'une organisation explicitement sélectionnée. Retourne le brouillon et la dernière version publiée ; l'historique GTM reste stocké mais n'est plus exposé. |
282
285
  | `list_verticals` / `get_vertical` | Lister ou lire les Verticales JSON simples d’une organisation explicitement sélectionnée, avec leurs Personas et Offres liées. |
283
286
  | `create_vertical` | Créer une Verticale tenant-scoped en `DRAFT`, sans activation ni sélection implicite. Son schéma JSON fermé porte les règles sectorielles et `commercialExperience` ; les métadonnées de preuve/source/provenance et les champs propres à l’Offre sont refusés. |
package/dist/server.js CHANGED
@@ -20,6 +20,7 @@ import { registerCommercialTruthTools } from "./tools/commercial_truth.js";
20
20
  import { registerEventTools } from "./tools/events.js";
21
21
  import { registerContextEntityTools } from "./tools/context_entities.js";
22
22
  import { registerPersonEmploymentTools } from "./tools/person_employment.js";
23
+ import { registerClaimContradictionTools } from "./tools/claim_contradictions.js";
23
24
  import { MCP_SERVER_NAME, MCP_VERSION } from "./version.js";
24
25
  export function createServer() {
25
26
  const server = new McpServer({
@@ -33,6 +34,7 @@ export function createServer() {
33
34
  registerLeadTools(server);
34
35
  registerRelationshipTools(server);
35
36
  registerCanonicalBackfillTools(server);
37
+ registerClaimContradictionTools(server);
36
38
  registerPersonEmploymentTools(server);
37
39
  registerEventTools(server);
38
40
  registerCommercialTruthTools(server);
@@ -0,0 +1,5 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { type LeadifyClient } from "../client.js";
3
+ type ClaimContradictionClient = Pick<LeadifyClient, "get" | "post">;
4
+ export declare function registerClaimContradictionTools(server: McpServer, client?: ClaimContradictionClient): void;
5
+ export {};
@@ -0,0 +1,85 @@
1
+ import { z } from "zod";
2
+ import { getClient } from "../client.js";
3
+ import { handleToolError, toolResult } from "../types.js";
4
+ const id = z.string().trim().min(1).max(200);
5
+ const decision = z.discriminatedUnion("type", [
6
+ z.object({ type: z.literal("SELECT_CLAIM"), retained_claim_id: id }).strict(),
7
+ z.object({ type: z.literal("COEXIST") }).strict(),
8
+ ]);
9
+ const resolutionFields = {
10
+ decision,
11
+ justification: z.string().trim().min(8).max(2_000),
12
+ expected_version: z.number().int().min(1),
13
+ expected_status: z.literal("OPEN"),
14
+ idempotency_key: z.string().trim().min(8).max(220),
15
+ };
16
+ const resolution = z.object(resolutionFields).strict();
17
+ const resolutionItem = resolution.extend({ contradiction_id: id }).strict();
18
+ function apiResolution(input) {
19
+ return {
20
+ decision: input.decision.type === "SELECT_CLAIM"
21
+ ? { type: input.decision.type, retainedClaimId: input.decision.retained_claim_id }
22
+ : { type: input.decision.type },
23
+ justification: input.justification,
24
+ expectedVersion: input.expected_version,
25
+ expectedStatus: input.expected_status,
26
+ idempotencyKey: input.idempotency_key,
27
+ };
28
+ }
29
+ export function registerClaimContradictionTools(server, client = getClient()) {
30
+ server.registerTool("get_claim_contradiction", {
31
+ title: "Read a canonical claim contradiction",
32
+ description: "Read one tenant-scoped ClaimContradiction with both immutable claims, their evidence, provenance, current version and audited resolution. This never resolves the contradiction or changes commercial state.",
33
+ inputSchema: {
34
+ organization_id: id.describe("Organization explicitly selected through discover_leadify_context."),
35
+ contradiction_id: id.describe("ClaimContradiction ID obtained from a fresh Context Pack or prior read."),
36
+ },
37
+ annotations: { readOnlyHint: true },
38
+ }, async ({ organization_id, contradiction_id }) => {
39
+ try {
40
+ return toolResult(await client.get(`/api/claim-contradictions/${encodeURIComponent(contradiction_id)}`, new URLSearchParams({ organizationId: organization_id })));
41
+ }
42
+ catch (error) {
43
+ return handleToolError(error);
44
+ }
45
+ });
46
+ server.registerTool("resolve_claim_contradiction", {
47
+ title: "Resolve a canonical claim contradiction",
48
+ description: "Persist one explicit, audited decision after reading the contradiction. SELECT_CLAIM must name one member claim; COEXIST keeps both. The server rejects stale versions, changed state, cross-tenant access and divergent idempotent replays. This never qualifies leads, creates messages, changes campaigns or sends outreach.",
49
+ inputSchema: {
50
+ organization_id: id.describe("Explicit organization; an admin write key is required."),
51
+ contradiction_id: id.describe("ClaimContradiction ID read immediately before this decision."),
52
+ ...resolutionFields,
53
+ },
54
+ annotations: { destructiveHint: false, idempotentHint: true },
55
+ }, async ({ organization_id, contradiction_id, ...input }) => {
56
+ try {
57
+ return toolResult(await client.post(`/api/claim-contradictions/${encodeURIComponent(contradiction_id)}/resolve`, { organizationId: organization_id, ...apiResolution(input) }));
58
+ }
59
+ catch (error) {
60
+ return handleToolError(error);
61
+ }
62
+ });
63
+ server.registerTool("resolve_claim_contradictions_batch", {
64
+ title: "Resolve explicit claim contradictions in a batch",
65
+ description: "Submit up to 100 independent, explicit ClaimContradiction decisions. The API reports each item in order as resolved, replayed or error; there is no automatic choice, latest-wins rule or commercial side effect.",
66
+ inputSchema: {
67
+ organization_id: id.describe("Explicit organization shared by every decision; an admin write key is required."),
68
+ decisions: z.array(resolutionItem).min(1).max(100),
69
+ },
70
+ annotations: { destructiveHint: false, idempotentHint: true },
71
+ }, async ({ organization_id, decisions }) => {
72
+ try {
73
+ return toolResult(await client.post("/api/claim-contradictions/resolve-batch", {
74
+ organizationId: organization_id,
75
+ decisions: decisions.map(({ contradiction_id, ...input }) => ({
76
+ contradictionId: contradiction_id,
77
+ ...apiResolution(input),
78
+ })),
79
+ }));
80
+ }
81
+ catch (error) {
82
+ return handleToolError(error);
83
+ }
84
+ });
85
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agifyai/leadify-mcp",
3
- "version": "8.7.2",
3
+ "version": "8.7.3",
4
4
  "description": "MCP server for Leadify lead management API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",