@sellable/mcp 0.1.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/.claude-plugin/plugin.json +12 -0
- package/.mcp.json +9 -0
- package/README.md +355 -0
- package/dist/api.d.ts +21 -0
- package/dist/api.js +73 -0
- package/dist/auth.d.ts +60 -0
- package/dist/auth.js +246 -0
- package/dist/engage-memory.d.ts +63 -0
- package/dist/engage-memory.js +354 -0
- package/dist/index-dev.d.ts +2 -0
- package/dist/index-dev.js +17 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +8 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +499 -0
- package/dist/skills.d.ts +11 -0
- package/dist/skills.js +97 -0
- package/dist/tools/auth.d.ts +30 -0
- package/dist/tools/auth.js +124 -0
- package/dist/tools/blueprint-commit.d.ts +174 -0
- package/dist/tools/blueprint-commit.js +286 -0
- package/dist/tools/bootstrap.d.ts +64 -0
- package/dist/tools/bootstrap.js +246 -0
- package/dist/tools/campaigns.d.ts +589 -0
- package/dist/tools/campaigns.js +892 -0
- package/dist/tools/cells.d.ts +58 -0
- package/dist/tools/cells.js +48 -0
- package/dist/tools/context.d.ts +88 -0
- package/dist/tools/context.js +271 -0
- package/dist/tools/csv-domains.d.ts +73 -0
- package/dist/tools/csv-domains.js +464 -0
- package/dist/tools/csv-linkedin.d.ts +102 -0
- package/dist/tools/csv-linkedin.js +712 -0
- package/dist/tools/direct-campaigns.d.ts +240 -0
- package/dist/tools/direct-campaigns.js +250 -0
- package/dist/tools/engage-bootstrap.d.ts +94 -0
- package/dist/tools/engage-bootstrap.js +205 -0
- package/dist/tools/engage-discovery.d.ts +78 -0
- package/dist/tools/engage-discovery.js +150 -0
- package/dist/tools/engage-memory.d.ts +181 -0
- package/dist/tools/engage-memory.js +143 -0
- package/dist/tools/engage-state.d.ts +72 -0
- package/dist/tools/engage-state.js +62 -0
- package/dist/tools/enrichment.d.ts +167 -0
- package/dist/tools/enrichment.js +174 -0
- package/dist/tools/flow-preflight.d.ts +68 -0
- package/dist/tools/flow-preflight.js +138 -0
- package/dist/tools/framework.d.ts +44 -0
- package/dist/tools/framework.js +153 -0
- package/dist/tools/interaction-mode.d.ts +27 -0
- package/dist/tools/interaction-mode.js +102 -0
- package/dist/tools/leads.d.ts +2417 -0
- package/dist/tools/leads.js +2307 -0
- package/dist/tools/linkedin.d.ts +210 -0
- package/dist/tools/linkedin.js +229 -0
- package/dist/tools/navigation.d.ts +91 -0
- package/dist/tools/navigation.js +381 -0
- package/dist/tools/one-off.d.ts +229 -0
- package/dist/tools/one-off.js +273 -0
- package/dist/tools/processing.d.ts +70 -0
- package/dist/tools/processing.js +56 -0
- package/dist/tools/prompts.d.ts +211 -0
- package/dist/tools/prompts.js +210 -0
- package/dist/tools/provider-preflight.d.ts +21 -0
- package/dist/tools/provider-preflight.js +59 -0
- package/dist/tools/readiness.d.ts +261 -0
- package/dist/tools/readiness.js +510 -0
- package/dist/tools/rows.d.ts +126 -0
- package/dist/tools/rows.js +105 -0
- package/dist/tools/rubrics.d.ts +497 -0
- package/dist/tools/rubrics.js +681 -0
- package/dist/tools/senders.d.ts +44 -0
- package/dist/tools/senders.js +69 -0
- package/dist/tools/sequencer.d.ts +127 -0
- package/dist/tools/sequencer.js +194 -0
- package/dist/tools/tables.d.ts +35 -0
- package/dist/tools/tables.js +36 -0
- package/dist/tools/verify-row.d.ts +36 -0
- package/dist/tools/verify-row.js +38 -0
- package/dist/tools/workspaces.d.ts +140 -0
- package/dist/tools/workspaces.js +139 -0
- package/dist/utils/workspace-root.d.ts +1 -0
- package/dist/utils/workspace-root.js +39 -0
- package/package.json +46 -0
- package/skills/building-gtm-tables/SKILL.md +216 -0
- package/skills/building-gtm-tables/core/auto-execute.yaml +19 -0
- package/skills/building-gtm-tables/core/blueprint-schema.json +72 -0
- package/skills/building-gtm-tables/references/brief-to-blueprint.md +334 -0
- package/skills/building-gtm-tables/references/column-type-catalog.md +318 -0
- package/skills/building-gtm-tables/references/common-blueprints.fixtures.ts +199 -0
- package/skills/building-gtm-tables/references/common-blueprints.md +44 -0
- package/skills/building-gtm-tables/references/failure-taxonomy.md +197 -0
- package/skills/building-gtm-tables/references/uat-seed-prompts.md +37 -0
- package/skills/building-gtm-tables/references/verify-loop.md +74 -0
- package/skills/campaign-messages/SKILL.md +173 -0
- package/skills/campaign-messages/flow.v1.json +75 -0
- package/skills/craft-message/SKILL.md +401 -0
- package/skills/create-campaign/ARCHITECTURE.md +232 -0
- package/skills/create-campaign/DISCUSS.md +296 -0
- package/skills/create-campaign/FLOW_ASCII.md +240 -0
- package/skills/create-campaign/HOST-PARITY-CHECKLIST.md +49 -0
- package/skills/create-campaign/README.md +142 -0
- package/skills/create-campaign/SKILL.md +286 -0
- package/skills/create-campaign/context/README.md +67 -0
- package/skills/create-campaign/context/_TEMPLATE.md +12 -0
- package/skills/create-campaign/context/context.md +35 -0
- package/skills/create-campaign/context/learnings.md +16 -0
- package/skills/create-campaign/context/registry.json +19 -0
- package/skills/create-campaign/core/flow.v1.json +217 -0
- package/skills/create-campaign/core/policy.md +191 -0
- package/skills/create-campaign/core/providers/apollo.json +35 -0
- package/skills/create-campaign/core/providers/prospeo.json +34 -0
- package/skills/create-campaign/core/providers/registry.json +31 -0
- package/skills/create-campaign/core/providers/sales-nav.json +37 -0
- package/skills/create-campaign/core/providers/signal-discovery.json +42 -0
- package/skills/create-campaign/references/brief-template.md +64 -0
- package/skills/create-campaign/references/campaign-quality.md +84 -0
- package/skills/create-campaign/references/copy-calibration-examples.md +120 -0
- package/skills/create-campaign/references/offer-patterns.md +108 -0
- package/skills/create-campaign/references/provider-selection-strategy.md +212 -0
- package/skills/create-campaign/references/question-examples.md +167 -0
- package/skills/create-campaign/references/token-fill-examples.md +81 -0
- package/skills/create-campaign-brief/ARCHITECTURE.md +72 -0
- package/skills/create-campaign-brief/DISCUSS.md +64 -0
- package/skills/create-campaign-brief/README.md +176 -0
- package/skills/create-campaign-brief/SKILL.md +537 -0
- package/skills/create-campaign-brief/references/brief-synthesis-rules.md +100 -0
- package/skills/create-campaign-brief/references/brief-template.md +220 -0
- package/skills/create-campaign-brief/references/campaign-idea-options.md +30 -0
- package/skills/create-campaign-brief/references/copy-appendix-template.md +62 -0
- package/skills/create-campaign-brief/references/draft-lifecycle.md +23 -0
- package/skills/create-campaign-brief/references/examples/MANIFEST.json +89 -0
- package/skills/create-campaign-brief/references/examples/briefs/clover.md +223 -0
- package/skills/create-campaign-brief/references/examples/briefs/galley.md +222 -0
- package/skills/create-campaign-brief/references/examples/briefs/gelee.md +220 -0
- package/skills/create-campaign-brief/references/examples/briefs/hey-digital.md +234 -0
- package/skills/create-campaign-brief/references/examples/briefs/persona.md +231 -0
- package/skills/create-campaign-brief/references/examples/briefs/revvix.md +220 -0
- package/skills/create-campaign-brief/references/examples/briefs/sellable-dev.md +220 -0
- package/skills/create-campaign-brief/references/examples/briefs/superposition.md +233 -0
- package/skills/create-campaign-brief/references/examples/briefs/superpower.md +219 -0
- package/skills/create-campaign-brief/references/examples/briefs/westpark-villas.md +220 -0
- package/skills/create-campaign-brief/references/icp-lock-question-bank.md +43 -0
- package/skills/create-campaign-brief/references/messaging-inputs.md +58 -0
- package/skills/create-campaign-brief/references/output-acceptance-rubric.md +62 -0
- package/skills/create-campaign-brief/references/phase75-active-runtime-message-pack.md +248 -0
- package/skills/create-campaign-brief/references/phase75-canonical-brief-template.md +319 -0
- package/skills/create-campaign-brief/references/phase75-good-brief-and-messaging-examples.md +445 -0
- package/skills/create-campaign-brief/references/quick-research-protocol.md +39 -0
- package/skills/create-campaign-brief/references/reference-sheet-protocol.md +60 -0
- package/skills/create-campaign-brief/references/zero-shot-iteration-rules.md +66 -0
- package/skills/create-campaign-v2/SKILL.md +1619 -0
- package/skills/create-campaign-v2/core/auto-execute.README.md +219 -0
- package/skills/create-campaign-v2/core/auto-execute.yaml +121 -0
- package/skills/create-campaign-v2/core/flow.v2.json +1643 -0
- package/skills/create-campaign-v2/core/policy.md +82 -0
- package/skills/create-campaign-v2/references/ai-tells.md +253 -0
- package/skills/create-campaign-v2/references/approval-gate-framing.md +346 -0
- package/skills/create-campaign-v2/references/draft-lifecycle.md +110 -0
- package/skills/create-campaign-v2/references/escalation-ladder.md +119 -0
- package/skills/create-campaign-v2/references/filter-leads.md +495 -0
- package/skills/create-campaign-v2/references/final-handoff-contract.md +176 -0
- package/skills/create-campaign-v2/references/gold-standard-message-examples.md +394 -0
- package/skills/create-campaign-v2/references/gold-standard-message-patterns.md +314 -0
- package/skills/create-campaign-v2/references/gold-standard-message-validation-example.md +212 -0
- package/skills/create-campaign-v2/references/lead-validation-preview.md +172 -0
- package/skills/create-campaign-v2/references/parallel-critique-protocol.md +368 -0
- package/skills/create-campaign-v2/references/sample-validation-loop.md +289 -0
- package/skills/create-campaign-v2/references/step-13-import-leads.md +151 -0
- package/skills/create-campaign-v2/references/step-15-re-cascade.md +90 -0
- package/skills/create-campaign-v2/references/thomas-revision-filters.md +521 -0
- package/skills/create-campaign-v2/references/thomas-variant-selection.md +202 -0
- package/skills/create-campaign-v2/references/tier-routing-matrix.md +66 -0
- package/skills/create-campaign-v2/references/validation-criteria.md +367 -0
- package/skills/create-campaign-v2/references/watch-link-handoff.md +106 -0
- package/skills/create-campaign-v2-validation/SKILL.md +296 -0
- package/skills/create-post/SKILL.md +1308 -0
- package/skills/create-rubric/SKILL.md +251 -0
- package/skills/engage/SKILL.md +549 -0
- package/skills/engage/core/README.md +23 -0
- package/skills/engage/core/proven-searches.json +11 -0
- package/skills/engage/core/style-guide.template.md +47 -0
- package/skills/engage/core/tracked-people.json +10 -0
- package/skills/enrich-prospects/SKILL.md +97 -0
- package/skills/find-leads/SKILL.md +467 -0
- package/skills/generate-messages/SKILL.md +2361 -0
- package/skills/interview/SKILL.md +132 -0
- package/skills/interview/core/ENGAGE_STYLE_GUIDE.template.md +54 -0
- package/skills/interview/core/ICP.template.md +54 -0
- package/skills/interview/core/VOICE_PROFILE.template.md +101 -0
- package/skills/providers/apollo.md +520 -0
- package/skills/providers/prospeo.md +398 -0
- package/skills/providers/sales-nav.md +372 -0
- package/skills/providers/signal-discovery.md +495 -0
- package/skills/research/SKILL.md +258 -0
- package/skills/research/config.json +9 -0
- package/skills/research/override.md +13 -0
- package/skills/research-prospect/SKILL.md +99 -0
- package/skills/research-sender/SKILL.md +158 -0
- package/skills/workflow-sequences/SKILL.md +85 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export type SenderListItem = {
|
|
2
|
+
id: string;
|
|
3
|
+
unipileAccountId: string;
|
|
4
|
+
timeZone: string;
|
|
5
|
+
displayName: string;
|
|
6
|
+
linkedinProfileUrl: string | null;
|
|
7
|
+
};
|
|
8
|
+
export type ListSendersResponse = {
|
|
9
|
+
senders: SenderListItem[];
|
|
10
|
+
};
|
|
11
|
+
export type GetSenderInput = {
|
|
12
|
+
senderId: string;
|
|
13
|
+
};
|
|
14
|
+
export type SenderDetailResponse = {
|
|
15
|
+
sender: any;
|
|
16
|
+
};
|
|
17
|
+
export declare const senderToolDefinitions: ({
|
|
18
|
+
name: string;
|
|
19
|
+
description: string;
|
|
20
|
+
inputSchema: {
|
|
21
|
+
type: string;
|
|
22
|
+
properties: {
|
|
23
|
+
senderId?: undefined;
|
|
24
|
+
};
|
|
25
|
+
required: never[];
|
|
26
|
+
additionalProperties: boolean;
|
|
27
|
+
};
|
|
28
|
+
} | {
|
|
29
|
+
name: string;
|
|
30
|
+
description: string;
|
|
31
|
+
inputSchema: {
|
|
32
|
+
type: string;
|
|
33
|
+
properties: {
|
|
34
|
+
senderId: {
|
|
35
|
+
type: string;
|
|
36
|
+
description: string;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
required: string[];
|
|
40
|
+
additionalProperties: boolean;
|
|
41
|
+
};
|
|
42
|
+
})[];
|
|
43
|
+
export declare function listSenders(): Promise<ListSendersResponse>;
|
|
44
|
+
export declare function getSender(input: GetSenderInput): Promise<SenderDetailResponse>;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { getApi } from "../api.js";
|
|
2
|
+
function pickString(...values) {
|
|
3
|
+
for (const value of values) {
|
|
4
|
+
if (typeof value !== "string")
|
|
5
|
+
continue;
|
|
6
|
+
const trimmed = value.trim();
|
|
7
|
+
if (trimmed)
|
|
8
|
+
return trimmed;
|
|
9
|
+
}
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
function computeDisplayName(sender) {
|
|
13
|
+
const profile = sender?.unipileAccount?.profileData;
|
|
14
|
+
const name = pickString(profile?.name);
|
|
15
|
+
if (name)
|
|
16
|
+
return name;
|
|
17
|
+
const first = pickString(profile?.first_name, profile?.firstName);
|
|
18
|
+
const last = pickString(profile?.last_name, profile?.lastName);
|
|
19
|
+
const full = [first, last].filter(Boolean).join(" ").trim();
|
|
20
|
+
if (full)
|
|
21
|
+
return full;
|
|
22
|
+
return `Sender ${String(sender?.id ?? "").slice(0, 8) || "unknown"}`;
|
|
23
|
+
}
|
|
24
|
+
function computeLinkedinProfileUrl(sender) {
|
|
25
|
+
const profile = sender?.unipileAccount?.profileData;
|
|
26
|
+
return (pickString(profile?.linkedinProfileUrl, profile?.linkedin_url, profile?.publicProfileUrl) || null);
|
|
27
|
+
}
|
|
28
|
+
export const senderToolDefinitions = [
|
|
29
|
+
{
|
|
30
|
+
name: "list_senders",
|
|
31
|
+
description: "List outbound sender identities available in the active workspace. Use this instead of asking for a LinkedIn URL.",
|
|
32
|
+
inputSchema: {
|
|
33
|
+
type: "object",
|
|
34
|
+
properties: {},
|
|
35
|
+
required: [],
|
|
36
|
+
additionalProperties: false,
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: "get_sender",
|
|
41
|
+
description: "Get a specific outbound sender identity by senderId (workspace-scoped).",
|
|
42
|
+
inputSchema: {
|
|
43
|
+
type: "object",
|
|
44
|
+
properties: {
|
|
45
|
+
senderId: { type: "string", description: "Outbound sender ID" },
|
|
46
|
+
},
|
|
47
|
+
required: ["senderId"],
|
|
48
|
+
additionalProperties: false,
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
];
|
|
52
|
+
export async function listSenders() {
|
|
53
|
+
const api = getApi();
|
|
54
|
+
const senders = await api.get("/api/v1/outbound-sender-identities");
|
|
55
|
+
return {
|
|
56
|
+
senders: (senders || []).map((s) => ({
|
|
57
|
+
id: String(s?.id || ""),
|
|
58
|
+
unipileAccountId: String(s?.unipileAccountId || ""),
|
|
59
|
+
timeZone: String(s?.timeZone || ""),
|
|
60
|
+
displayName: computeDisplayName(s),
|
|
61
|
+
linkedinProfileUrl: computeLinkedinProfileUrl(s),
|
|
62
|
+
})),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export async function getSender(input) {
|
|
66
|
+
const api = getApi();
|
|
67
|
+
const sender = await api.get(`/api/v1/outbound-sender-identities/${encodeURIComponent(input.senderId)}`);
|
|
68
|
+
return { sender };
|
|
69
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
export type CreateWorkflowTableInput = {
|
|
2
|
+
name: string;
|
|
3
|
+
senderId: string;
|
|
4
|
+
clientProspectId?: string;
|
|
5
|
+
sequenceActions?: string[];
|
|
6
|
+
};
|
|
7
|
+
export type CreateWorkflowTableResponse = {
|
|
8
|
+
tableId: string;
|
|
9
|
+
campaignOfferId: string;
|
|
10
|
+
tableName: string;
|
|
11
|
+
columns: Array<{
|
|
12
|
+
key: string;
|
|
13
|
+
name: string;
|
|
14
|
+
columnType: string;
|
|
15
|
+
}>;
|
|
16
|
+
requirements: Record<string, unknown>;
|
|
17
|
+
created: boolean;
|
|
18
|
+
};
|
|
19
|
+
export type AttachSequenceInput = {
|
|
20
|
+
tableId: string;
|
|
21
|
+
template: Record<string, unknown>;
|
|
22
|
+
confirmed?: boolean;
|
|
23
|
+
};
|
|
24
|
+
export type AttachSequenceResponse = {
|
|
25
|
+
success: boolean;
|
|
26
|
+
version: number;
|
|
27
|
+
_perf?: Record<string, number>;
|
|
28
|
+
};
|
|
29
|
+
export type AttachRecommendedSequenceInput = {
|
|
30
|
+
campaignId: string;
|
|
31
|
+
confirmed?: boolean;
|
|
32
|
+
};
|
|
33
|
+
export type AttachRecommendedSequenceResponse = {
|
|
34
|
+
success: boolean;
|
|
35
|
+
version: number;
|
|
36
|
+
template?: {
|
|
37
|
+
name?: string;
|
|
38
|
+
entryNodeId?: string;
|
|
39
|
+
nodes?: Array<Record<string, unknown>>;
|
|
40
|
+
};
|
|
41
|
+
_perf?: Record<string, number>;
|
|
42
|
+
};
|
|
43
|
+
export declare const sequencerToolDefinitions: ({
|
|
44
|
+
name: string;
|
|
45
|
+
description: string;
|
|
46
|
+
inputSchema: {
|
|
47
|
+
type: string;
|
|
48
|
+
properties: {
|
|
49
|
+
name: {
|
|
50
|
+
type: string;
|
|
51
|
+
description: string;
|
|
52
|
+
};
|
|
53
|
+
senderId: {
|
|
54
|
+
type: string;
|
|
55
|
+
description: string;
|
|
56
|
+
};
|
|
57
|
+
clientProspectId: {
|
|
58
|
+
type: string;
|
|
59
|
+
description: string;
|
|
60
|
+
};
|
|
61
|
+
sequenceActions: {
|
|
62
|
+
type: string;
|
|
63
|
+
items: {
|
|
64
|
+
type: string;
|
|
65
|
+
};
|
|
66
|
+
description: string;
|
|
67
|
+
};
|
|
68
|
+
tableId?: undefined;
|
|
69
|
+
template?: undefined;
|
|
70
|
+
confirmed?: undefined;
|
|
71
|
+
campaignId?: undefined;
|
|
72
|
+
};
|
|
73
|
+
required: string[];
|
|
74
|
+
};
|
|
75
|
+
} | {
|
|
76
|
+
name: string;
|
|
77
|
+
description: string;
|
|
78
|
+
inputSchema: {
|
|
79
|
+
type: string;
|
|
80
|
+
properties: {
|
|
81
|
+
tableId: {
|
|
82
|
+
type: string;
|
|
83
|
+
description: string;
|
|
84
|
+
};
|
|
85
|
+
template: {
|
|
86
|
+
type: string;
|
|
87
|
+
description: string;
|
|
88
|
+
};
|
|
89
|
+
confirmed: {
|
|
90
|
+
type: string;
|
|
91
|
+
description: string;
|
|
92
|
+
};
|
|
93
|
+
name?: undefined;
|
|
94
|
+
senderId?: undefined;
|
|
95
|
+
clientProspectId?: undefined;
|
|
96
|
+
sequenceActions?: undefined;
|
|
97
|
+
campaignId?: undefined;
|
|
98
|
+
};
|
|
99
|
+
required: string[];
|
|
100
|
+
};
|
|
101
|
+
} | {
|
|
102
|
+
name: string;
|
|
103
|
+
description: string;
|
|
104
|
+
inputSchema: {
|
|
105
|
+
type: string;
|
|
106
|
+
properties: {
|
|
107
|
+
campaignId: {
|
|
108
|
+
type: string;
|
|
109
|
+
description: string;
|
|
110
|
+
};
|
|
111
|
+
confirmed: {
|
|
112
|
+
type: string;
|
|
113
|
+
description: string;
|
|
114
|
+
};
|
|
115
|
+
name?: undefined;
|
|
116
|
+
senderId?: undefined;
|
|
117
|
+
clientProspectId?: undefined;
|
|
118
|
+
sequenceActions?: undefined;
|
|
119
|
+
tableId?: undefined;
|
|
120
|
+
template?: undefined;
|
|
121
|
+
};
|
|
122
|
+
required: string[];
|
|
123
|
+
};
|
|
124
|
+
})[];
|
|
125
|
+
export declare function createWorkflowTable(input: CreateWorkflowTableInput): Promise<CreateWorkflowTableResponse>;
|
|
126
|
+
export declare function attachSequence(input: AttachSequenceInput): Promise<AttachSequenceResponse>;
|
|
127
|
+
export declare function attachRecommendedSequence(input: AttachRecommendedSequenceInput): Promise<AttachRecommendedSequenceResponse>;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { getApi, SellableApiError } from "../api.js";
|
|
2
|
+
export const sequencerToolDefinitions = [
|
|
3
|
+
{
|
|
4
|
+
name: "create_workflow_table",
|
|
5
|
+
description: "Create a campaign-backed workflow table with a lightweight CampaignOffer shell and minimal config columns optionally derived from sequence action types. " +
|
|
6
|
+
"Returns tableId, campaignOfferId, column list, and derived requirements.\n\n" +
|
|
7
|
+
"All tables include LinkedIn URL, Name, and Approved. " +
|
|
8
|
+
"Additional columns depend on the planned actions: INVITE/DM -> Message, " +
|
|
9
|
+
"INMAIL_* -> Subject + Message, COMMENT -> Post URL + Comment + Reaction Type. " +
|
|
10
|
+
"Campaign brief, rubrics, positioning, and prospect linkage remain optional follow-on metadata.",
|
|
11
|
+
inputSchema: {
|
|
12
|
+
type: "object",
|
|
13
|
+
properties: {
|
|
14
|
+
name: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "Campaign or table name (1-200 chars)",
|
|
17
|
+
},
|
|
18
|
+
senderId: {
|
|
19
|
+
type: "string",
|
|
20
|
+
description: "Outbound sender ID (from list_senders)",
|
|
21
|
+
},
|
|
22
|
+
clientProspectId: {
|
|
23
|
+
type: "string",
|
|
24
|
+
description: "Optional client prospect ID (from enrich_sender)",
|
|
25
|
+
},
|
|
26
|
+
sequenceActions: {
|
|
27
|
+
type: "array",
|
|
28
|
+
items: { type: "string" },
|
|
29
|
+
description: "Optional action types: INVITE, DM, INMAIL_OPEN, INMAIL_CLOSED, VIEW_PROFILE, COMMENT",
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
required: ["name", "senderId"],
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: "attach_sequence",
|
|
37
|
+
description: "Attach a sequence template to an existing workflow table. " +
|
|
38
|
+
"This works for direct campaign tables and for type-agnostic tables created with create_workflow_table. " +
|
|
39
|
+
"The tool pre-validates template structure and surfaces 409 conflicts clearly when sequence columns already exist.",
|
|
40
|
+
inputSchema: {
|
|
41
|
+
type: "object",
|
|
42
|
+
properties: {
|
|
43
|
+
tableId: {
|
|
44
|
+
type: "string",
|
|
45
|
+
description: "Workflow table ID from create_workflow_table or list_tables",
|
|
46
|
+
},
|
|
47
|
+
template: {
|
|
48
|
+
type: "object",
|
|
49
|
+
description: "Sequence template object with version, entryNodeId, nodes, and branches",
|
|
50
|
+
},
|
|
51
|
+
confirmed: {
|
|
52
|
+
type: "boolean",
|
|
53
|
+
description: "Set true to overwrite existing sequence columns if the table already has them",
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
required: ["tableId", "template"],
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: "attach_recommended_sequence",
|
|
61
|
+
description: "Attach the tier-recommended sequence template to a campaign. " +
|
|
62
|
+
"Delegates template selection to the backend's existing tier-aware selector " +
|
|
63
|
+
"(selectTemplateForTiers), which picks `If Open Profile -> INMAIL_OPEN, else INVITE` " +
|
|
64
|
+
"for premium/Sales Nav senders and `INVITE -> accepted -> DM` otherwise. " +
|
|
65
|
+
"Prefer this over attach_sequence during the create-campaign-v2 autonomous tail — " +
|
|
66
|
+
"it removes the risk of hand-authoring an invalid template mid-long-context. " +
|
|
67
|
+
"Use attach_sequence directly only when the caller needs a custom non-recommended cadence.",
|
|
68
|
+
inputSchema: {
|
|
69
|
+
type: "object",
|
|
70
|
+
properties: {
|
|
71
|
+
campaignId: {
|
|
72
|
+
type: "string",
|
|
73
|
+
description: "CampaignOffer ID from create_campaign",
|
|
74
|
+
},
|
|
75
|
+
confirmed: {
|
|
76
|
+
type: "boolean",
|
|
77
|
+
description: "Set true to overwrite existing sequence columns if the campaign already has a sequence attached",
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
required: ["campaignId"],
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
export async function createWorkflowTable(input) {
|
|
85
|
+
const api = getApi();
|
|
86
|
+
return api.post("/api/v3/sequencer-tables", {
|
|
87
|
+
name: input.name,
|
|
88
|
+
senderId: input.senderId,
|
|
89
|
+
clientProspectId: input.clientProspectId,
|
|
90
|
+
...(input.sequenceActions
|
|
91
|
+
? { sequenceActions: input.sequenceActions }
|
|
92
|
+
: {}),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
export async function attachSequence(input) {
|
|
96
|
+
const api = getApi();
|
|
97
|
+
const template = input.template;
|
|
98
|
+
const preValidationErrors = [];
|
|
99
|
+
if (!Array.isArray(template.nodes) || template.nodes.length === 0) {
|
|
100
|
+
preValidationErrors.push("Template must have a non-empty 'nodes' array.");
|
|
101
|
+
}
|
|
102
|
+
if (typeof template.entryNodeId !== "string" ||
|
|
103
|
+
template.entryNodeId.trim().length === 0) {
|
|
104
|
+
preValidationErrors.push("Template must have an 'entryNodeId' string.");
|
|
105
|
+
}
|
|
106
|
+
if (template.version !== 2) {
|
|
107
|
+
preValidationErrors.push("Template version must be 2.");
|
|
108
|
+
}
|
|
109
|
+
if (Array.isArray(template.nodes) &&
|
|
110
|
+
typeof template.entryNodeId === "string") {
|
|
111
|
+
const nodeIds = new Set(template.nodes
|
|
112
|
+
.map((node) => node && typeof node === "object"
|
|
113
|
+
? node.id
|
|
114
|
+
: null)
|
|
115
|
+
.filter((nodeId) => typeof nodeId === "string"));
|
|
116
|
+
if (template.entryNodeId && !nodeIds.has(template.entryNodeId)) {
|
|
117
|
+
preValidationErrors.push(`entryNodeId "${template.entryNodeId}" does not match any node id. Available node ids: ${Array.from(nodeIds).join(", ")}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (preValidationErrors.length > 0) {
|
|
121
|
+
throw new Error("INVALID_TEMPLATE: Template has structural issues:\n" +
|
|
122
|
+
preValidationErrors.map((issue) => ` - ${issue}`).join("\n") +
|
|
123
|
+
"\n\nFix these issues and retry.");
|
|
124
|
+
}
|
|
125
|
+
// Campaign-backed tables route to the campaigns endpoint so the MCP
|
|
126
|
+
// tool persists the sequence to the same place the UI does
|
|
127
|
+
// (`CampaignOffer.sequenceTemplate`). The workflow-tables endpoint
|
|
128
|
+
// writes to `WorkflowTable.config.sequenceTemplate`, which the UI
|
|
129
|
+
// doesn't read — hitting it on a campaign table is silently wrong.
|
|
130
|
+
let campaignOfferId = null;
|
|
131
|
+
try {
|
|
132
|
+
const tableMeta = await api.get(`/api/v3/workflow-tables/${input.tableId}?mode=meta`);
|
|
133
|
+
const rawCampaignId = tableMeta?.table?.config?.campaignOfferId;
|
|
134
|
+
if (typeof rawCampaignId === "string" && rawCampaignId.length > 0) {
|
|
135
|
+
campaignOfferId = rawCampaignId;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// Fall back to workflow-tables path on meta-fetch failure —
|
|
140
|
+
// non-campaign tables won't have the field set anyway.
|
|
141
|
+
}
|
|
142
|
+
const endpoint = campaignOfferId
|
|
143
|
+
? `/api/v3/campaigns/${campaignOfferId}/sequence`
|
|
144
|
+
: `/api/v3/workflow-tables/${input.tableId}/sequence`;
|
|
145
|
+
try {
|
|
146
|
+
return await api.put(endpoint, {
|
|
147
|
+
template: input.template,
|
|
148
|
+
confirmed: input.confirmed,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
if (error instanceof SellableApiError && error.status === 409) {
|
|
153
|
+
let columnInfo = "";
|
|
154
|
+
try {
|
|
155
|
+
const responseBody = JSON.parse(error.body);
|
|
156
|
+
if (typeof responseBody?.details?.columnCount === "number") {
|
|
157
|
+
columnInfo = ` (${responseBody.details.columnCount} existing columns)`;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
// Best effort only.
|
|
162
|
+
}
|
|
163
|
+
throw new Error(`SEQUENCE_EXISTS: This table already has sequence columns${columnInfo}. ` +
|
|
164
|
+
"Call attach_sequence again with confirmed: true to replace the existing sequence, or use a different table.");
|
|
165
|
+
}
|
|
166
|
+
throw error;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
export async function attachRecommendedSequence(input) {
|
|
170
|
+
const api = getApi();
|
|
171
|
+
try {
|
|
172
|
+
return await api.put(`/api/v3/campaigns/${input.campaignId}/sequence`, {
|
|
173
|
+
autoSelectFromSenders: true,
|
|
174
|
+
confirmed: input.confirmed,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
if (error instanceof SellableApiError && error.status === 409) {
|
|
179
|
+
let columnInfo = "";
|
|
180
|
+
try {
|
|
181
|
+
const responseBody = JSON.parse(error.body);
|
|
182
|
+
if (typeof responseBody?.details?.columnCount === "number") {
|
|
183
|
+
columnInfo = ` (${responseBody.details.columnCount} existing columns)`;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
// Best effort only.
|
|
188
|
+
}
|
|
189
|
+
throw new Error(`SEQUENCE_EXISTS: This campaign already has a sequence attached${columnInfo}. ` +
|
|
190
|
+
"Call attach_recommended_sequence again with confirmed: true to replace, or inspect the existing sequence via get_campaign.");
|
|
191
|
+
}
|
|
192
|
+
throw error;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface WorkflowTableListItem {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
type: string | null;
|
|
5
|
+
campaignOfferId: string | null;
|
|
6
|
+
campaignBacked: boolean;
|
|
7
|
+
hasSequence: boolean;
|
|
8
|
+
columns: number;
|
|
9
|
+
rows: number;
|
|
10
|
+
createdAt: string;
|
|
11
|
+
updatedAt: string;
|
|
12
|
+
}
|
|
13
|
+
export interface ListTablesInput {
|
|
14
|
+
limit?: number;
|
|
15
|
+
hasSequence?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare const tableToolDefinitions: {
|
|
18
|
+
name: string;
|
|
19
|
+
description: string;
|
|
20
|
+
inputSchema: {
|
|
21
|
+
type: string;
|
|
22
|
+
properties: {
|
|
23
|
+
limit: {
|
|
24
|
+
type: string;
|
|
25
|
+
description: string;
|
|
26
|
+
};
|
|
27
|
+
hasSequence: {
|
|
28
|
+
type: string;
|
|
29
|
+
description: string;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
required: never[];
|
|
33
|
+
};
|
|
34
|
+
}[];
|
|
35
|
+
export declare function listTables(input: ListTablesInput): Promise<WorkflowTableListItem[]>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { getApi } from "../api.js";
|
|
2
|
+
export const tableToolDefinitions = [
|
|
3
|
+
{
|
|
4
|
+
name: "list_tables",
|
|
5
|
+
description: "List all workflow tables in the active workspace. Returns metadata including whether each table is campaign-backed and whether it has a sequence attached.\n\n" +
|
|
6
|
+
"Unlike get_campaigns, this lists every WorkflowTable regardless of how it was created, including create_workflow_table, create_on_demand_table, and UI-created tables.",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
limit: {
|
|
11
|
+
type: "number",
|
|
12
|
+
description: "Number of tables to return (default 50, max 200)",
|
|
13
|
+
},
|
|
14
|
+
hasSequence: {
|
|
15
|
+
type: "boolean",
|
|
16
|
+
description: "Optional filter: true for sequence tables only, false for tables without sequences",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
required: [],
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
];
|
|
23
|
+
export async function listTables(input) {
|
|
24
|
+
const api = getApi();
|
|
25
|
+
const params = new URLSearchParams();
|
|
26
|
+
if (input.limit) {
|
|
27
|
+
params.set("limit", String(input.limit));
|
|
28
|
+
}
|
|
29
|
+
if (input.hasSequence !== undefined) {
|
|
30
|
+
params.set("hasSequence", String(input.hasSequence));
|
|
31
|
+
}
|
|
32
|
+
const queryString = params.toString();
|
|
33
|
+
const path = `/api/v3/mcp/tables${queryString ? `?${queryString}` : ""}`;
|
|
34
|
+
const result = await api.get(path);
|
|
35
|
+
return result.tables;
|
|
36
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export type VerifyTableRowInput = {
|
|
2
|
+
tableId: string;
|
|
3
|
+
rowId: string;
|
|
4
|
+
skipColumnIds?: string[];
|
|
5
|
+
forceRerun?: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare const verifyRowToolDefinitions: {
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: string;
|
|
12
|
+
properties: {
|
|
13
|
+
tableId: {
|
|
14
|
+
type: string;
|
|
15
|
+
description: string;
|
|
16
|
+
};
|
|
17
|
+
rowId: {
|
|
18
|
+
type: string;
|
|
19
|
+
description: string;
|
|
20
|
+
};
|
|
21
|
+
skipColumnIds: {
|
|
22
|
+
type: string;
|
|
23
|
+
items: {
|
|
24
|
+
type: string;
|
|
25
|
+
};
|
|
26
|
+
description: string;
|
|
27
|
+
};
|
|
28
|
+
forceRerun: {
|
|
29
|
+
type: string;
|
|
30
|
+
description: string;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
required: string[];
|
|
34
|
+
};
|
|
35
|
+
}[];
|
|
36
|
+
export declare function handleVerifyTableRow(input: VerifyTableRowInput): Promise<any>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { getApi } from "../api.js";
|
|
2
|
+
export const verifyRowToolDefinitions = [
|
|
3
|
+
{
|
|
4
|
+
name: "verify_table_row",
|
|
5
|
+
description: "Run one workflow-table row through orchestrator-path columns and report per-column status. Sweeper-path sequence columns are reported as deferred_to_sweeper and are never executed by this tool.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: "object",
|
|
8
|
+
properties: {
|
|
9
|
+
tableId: {
|
|
10
|
+
type: "string",
|
|
11
|
+
description: "Workflow table ID",
|
|
12
|
+
},
|
|
13
|
+
rowId: {
|
|
14
|
+
type: "string",
|
|
15
|
+
description: "Workflow table row ID to verify",
|
|
16
|
+
},
|
|
17
|
+
skipColumnIds: {
|
|
18
|
+
type: "array",
|
|
19
|
+
items: { type: "string" },
|
|
20
|
+
description: "Column IDs the caller intentionally wants to skip. No implicit skip heuristics are applied.",
|
|
21
|
+
},
|
|
22
|
+
forceRerun: {
|
|
23
|
+
type: "boolean",
|
|
24
|
+
description: "Defaults true. Bypasses cached/completed cells so verification actually re-executes.",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
required: ["tableId", "rowId"],
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
export async function handleVerifyTableRow(input) {
|
|
32
|
+
const api = getApi();
|
|
33
|
+
return api.post(`/api/v3/workflow-tables/${input.tableId}/verify-row`, {
|
|
34
|
+
rowId: input.rowId,
|
|
35
|
+
skipColumnIds: input.skipColumnIds || [],
|
|
36
|
+
forceRerun: input.forceRerun ?? true,
|
|
37
|
+
});
|
|
38
|
+
}
|