@sellable/mcp 0.1.80 → 0.1.82

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.
Files changed (36) hide show
  1. package/agents/post-find-leads-filter-scout.md +19 -8
  2. package/agents/post-find-leads-message-scout.md +21 -6
  3. package/agents/registry.json +33 -18
  4. package/agents/source-scout-linkedin-engagement.md +10 -2
  5. package/agents/source-scout-prospeo-contact.md +9 -2
  6. package/agents/source-scout-sales-nav.md +10 -2
  7. package/dist/server.js +7 -1
  8. package/dist/tools/bootstrap.js +2 -2
  9. package/dist/tools/campaigns.d.ts +12 -0
  10. package/dist/tools/campaigns.js +40 -5
  11. package/dist/tools/context.d.ts +10 -4
  12. package/dist/tools/context.js +8 -4
  13. package/dist/tools/leads.d.ts +6 -3
  14. package/dist/tools/leads.js +39 -43
  15. package/dist/tools/navigation.d.ts +28 -1
  16. package/dist/tools/navigation.js +220 -10
  17. package/dist/tools/prompts.js +1 -1
  18. package/dist/tools/provider-preflight.js +2 -3
  19. package/dist/tools/readiness.d.ts +31 -6
  20. package/dist/tools/readiness.js +6 -1
  21. package/dist/tools/rubrics.d.ts +2 -0
  22. package/dist/tools/rubrics.js +2 -0
  23. package/package.json +1 -1
  24. package/skills/create-campaign/SKILL.md +24 -12
  25. package/skills/create-campaign-v2/SKILL.md +166 -114
  26. package/skills/create-campaign-v2/SOUL.md +19 -11
  27. package/skills/create-campaign-v2/core/auto-execute.yaml +14 -13
  28. package/skills/create-campaign-v2/core/flow.v2.json +964 -310
  29. package/skills/create-campaign-v2/references/approval-gate-framing.md +64 -32
  30. package/skills/create-campaign-v2/references/filter-leads.md +8 -0
  31. package/skills/create-campaign-v2/references/final-handoff-contract.md +55 -20
  32. package/skills/create-campaign-v2/references/lead-validation-preview.md +30 -17
  33. package/skills/create-campaign-v2/references/step-13-import-leads.md +62 -17
  34. package/skills/create-campaign-v2/references/validation-criteria.md +10 -5
  35. package/skills/create-campaign-v2/references/watch-link-handoff.md +72 -72
  36. package/skills/create-campaign-v2-tail/SKILL.md +123 -92
@@ -1,5 +1,6 @@
1
1
  type WaitForCampaignTableReadyInput = {
2
2
  campaignId: string;
3
+ flowVersion?: "v1" | "v2";
3
4
  timeoutMs?: number;
4
5
  intervalMs?: number;
5
6
  requireRows?: boolean;
@@ -43,6 +44,11 @@ export declare const readinessToolDefinitions: ({
43
44
  type: string;
44
45
  description: string;
45
46
  };
47
+ flowVersion: {
48
+ type: string;
49
+ enum: string[];
50
+ description: string;
51
+ };
46
52
  leadListId?: undefined;
47
53
  campaignOfferId?: undefined;
48
54
  provider?: undefined;
@@ -96,6 +102,7 @@ export declare const readinessToolDefinitions: ({
96
102
  description: string;
97
103
  };
98
104
  campaignId?: undefined;
105
+ flowVersion?: undefined;
99
106
  };
100
107
  required: never[];
101
108
  additionalProperties: boolean;
@@ -108,8 +115,8 @@ export declare function waitForCampaignTableReady(input: WaitForCampaignTableRea
108
115
  elapsedMs: number;
109
116
  navigation: {
110
117
  campaignId: string;
111
- computedStep: "campaign-created" | "pick-provider" | "provider-search" | "confirm-lead-list";
112
- blockedAt: ("campaign-created" | "pick-provider" | "provider-search" | "confirm-lead-list") | null;
118
+ computedStep: "running" | "messages" | "settings" | "sequence" | "send" | "campaign-created" | "pick-provider" | "provider-search" | "confirm-lead-list" | "filter-rules";
119
+ blockedAt: ("running" | "messages" | "settings" | "sequence" | "send" | "campaign-created" | "pick-provider" | "provider-search" | "confirm-lead-list" | "filter-rules") | null;
113
120
  missing: string[];
114
121
  expectedHeadlessStep: string | null;
115
122
  headlessCurrentStep: string | null;
@@ -125,6 +132,12 @@ export declare function waitForCampaignTableReady(input: WaitForCampaignTableRea
125
132
  leadSourceProvider: string | null;
126
133
  selectedLeadListId: string | null;
127
134
  providerCurrentStep: string | null;
135
+ enableICPFilters: boolean | null;
136
+ activeRubricCount: number;
137
+ hasApprovedMessageTemplate: boolean;
138
+ senderCount: number;
139
+ hasSequenceTemplate: boolean;
140
+ campaignStatus: string | null;
128
141
  };
129
142
  warnings: string[];
130
143
  };
@@ -135,8 +148,8 @@ export declare function waitForCampaignTableReady(input: WaitForCampaignTableRea
135
148
  elapsedMs: number;
136
149
  navigation: {
137
150
  campaignId: string;
138
- computedStep: "campaign-created" | "pick-provider" | "provider-search" | "confirm-lead-list";
139
- blockedAt: ("campaign-created" | "pick-provider" | "provider-search" | "confirm-lead-list") | null;
151
+ computedStep: "running" | "messages" | "settings" | "sequence" | "send" | "campaign-created" | "pick-provider" | "provider-search" | "confirm-lead-list" | "filter-rules";
152
+ blockedAt: ("running" | "messages" | "settings" | "sequence" | "send" | "campaign-created" | "pick-provider" | "provider-search" | "confirm-lead-list" | "filter-rules") | null;
140
153
  missing: string[];
141
154
  expectedHeadlessStep: string | null;
142
155
  headlessCurrentStep: string | null;
@@ -152,6 +165,12 @@ export declare function waitForCampaignTableReady(input: WaitForCampaignTableRea
152
165
  leadSourceProvider: string | null;
153
166
  selectedLeadListId: string | null;
154
167
  providerCurrentStep: string | null;
168
+ enableICPFilters: boolean | null;
169
+ activeRubricCount: number;
170
+ hasApprovedMessageTemplate: boolean;
171
+ senderCount: number;
172
+ hasSequenceTemplate: boolean;
173
+ campaignStatus: string | null;
155
174
  };
156
175
  warnings: string[];
157
176
  };
@@ -164,8 +183,8 @@ export declare function waitForCampaignTableReady(input: WaitForCampaignTableRea
164
183
  elapsedMs: number;
165
184
  navigation: {
166
185
  campaignId: string;
167
- computedStep: "campaign-created" | "pick-provider" | "provider-search" | "confirm-lead-list";
168
- blockedAt: ("campaign-created" | "pick-provider" | "provider-search" | "confirm-lead-list") | null;
186
+ computedStep: "running" | "messages" | "settings" | "sequence" | "send" | "campaign-created" | "pick-provider" | "provider-search" | "confirm-lead-list" | "filter-rules";
187
+ blockedAt: ("running" | "messages" | "settings" | "sequence" | "send" | "campaign-created" | "pick-provider" | "provider-search" | "confirm-lead-list" | "filter-rules") | null;
169
188
  missing: string[];
170
189
  expectedHeadlessStep: string | null;
171
190
  headlessCurrentStep: string | null;
@@ -181,6 +200,12 @@ export declare function waitForCampaignTableReady(input: WaitForCampaignTableRea
181
200
  leadSourceProvider: string | null;
182
201
  selectedLeadListId: string | null;
183
202
  providerCurrentStep: string | null;
203
+ enableICPFilters: boolean | null;
204
+ activeRubricCount: number;
205
+ hasApprovedMessageTemplate: boolean;
206
+ senderCount: number;
207
+ hasSequenceTemplate: boolean;
208
+ campaignStatus: string | null;
184
209
  };
185
210
  warnings: string[];
186
211
  } | null;
@@ -67,6 +67,11 @@ export const readinessToolDefinitions = [
67
67
  type: "boolean",
68
68
  description: "When true (default), wait for at least one row to appear.",
69
69
  },
70
+ flowVersion: {
71
+ type: "string",
72
+ enum: ["v1", "v2"],
73
+ description: "Framework flow version used when hydrating campaign context (default: v1).",
74
+ },
70
75
  },
71
76
  required: ["campaignId"],
72
77
  additionalProperties: false,
@@ -148,7 +153,7 @@ export async function waitForCampaignTableReady(input) {
148
153
  const rowsSatisfied = requireRows ? hasRows : hasTable;
149
154
  const missingTableBits = navState.missing.filter((m) => m === "workflowTableId" || m === "workflowTableRows");
150
155
  if (hasTable && rowsSatisfied && missingTableBits.length === 0) {
151
- const entry = hydrateCampaignContextFromNavigation(navState, "wait_for_campaign_table_ready");
156
+ const entry = hydrateCampaignContextFromNavigation(navState, "wait_for_campaign_table_ready", input.flowVersion ?? "v1");
152
157
  return {
153
158
  ready: true,
154
159
  attempts,
@@ -457,6 +457,8 @@ export declare function saveRubrics(input: SaveRubricsInput): Promise<{
457
457
  criteriaCount: number;
458
458
  deletedCount: number;
459
459
  enableICPFiltersSet: boolean;
460
+ rubrics: RubricItem[];
461
+ activeRubrics: RubricItem[];
460
462
  }>;
461
463
  export declare function checkRubric(input: CheckRubricInput): Promise<{
462
464
  success: boolean;
@@ -545,6 +545,8 @@ export async function saveRubrics(input) {
545
545
  criteriaCount: normalizedDraft.length,
546
546
  deletedCount: deletedRubricIds.length,
547
547
  enableICPFiltersSet,
548
+ rubrics: result?.rubrics ?? normalizedDraft,
549
+ activeRubrics: result?.rubrics ?? normalizedDraft,
548
550
  };
549
551
  }
550
552
  export async function checkRubric(input) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.80",
3
+ "version": "0.1.82",
4
4
  "type": "module",
5
5
  "description": "Sellable MCP server for Claude Code and Codex campaign workflows",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: create-campaign
3
- description: Create a Sellable campaign through the approval-gated workflow.
3
+ description: Create a Sellable campaign through the shell-first CampaignOffer workflow.
4
4
  visibility: public
5
5
  allowed-tools:
6
6
  - mcp__sellable__get_auth_status
@@ -66,6 +66,14 @@ allowed-tools:
66
66
 
67
67
  Use this as the customer-facing entrypoint for Sellable campaign creation.
68
68
 
69
+ CampaignOffer state is canonical; disk artifacts are a debug trail. The
70
+ internal create-campaign-v2 flow still writes the diagnostics, and all 14 disk
71
+ artifacts remain as debug outputs, but resume, gating, and handoff read campaign
72
+ state first. The
73
+ watchable campaign exists after the short brief; lead import is bounded to the
74
+ first review batch, and enrichment/message generation waits until rubrics and
75
+ the approved message template are saved on the campaign.
76
+
69
77
  ## Opening Turn Contract
70
78
 
71
79
  On the first visible response after this skill is invoked, do not narrate
@@ -75,7 +83,7 @@ or tool discovery. Start in product language:
75
83
  ```text
76
84
  I’ll help you launch this as a Sellable campaign. First I’ll confirm who we’re
77
85
  sending from and which company this is for, then I’ll turn that into a campaign
78
- brief before anything is created.
86
+ brief before any leads are imported or anything can send.
79
87
  ```
80
88
 
81
89
  If a linked/local skill file is stale or missing, silently use the installed
@@ -91,7 +99,8 @@ clear business decisions, tradeoffs, and approval gates. Use product language:
91
99
  - "a couple setup choices", not `request_user_input`
92
100
  - "campaign brief", not prompt artifact
93
101
  - "lead source", not provider internals unless comparing source options
94
- - "nothing is created until you approve", not mutation jargon
102
+ - "I can create a draft shell for you to watch, but no leads import and nothing
103
+ sends until you approve", not mutation jargon
95
104
 
96
105
  When explaining lead-source decisions, show the concrete counts behind the
97
106
  logic: lanes searched, timeframe, raw result counts, finalist posts or preview
@@ -130,7 +139,7 @@ Every approval gate must include artifact access after the readable inline
130
139
  content. Show a short `Open artifact:` line with the one key clickable markdown
131
140
  link for that stage. Do not show raw filesystem paths unless links cannot be
132
141
  created or the user asks. Do this for brief approval, lead-source
133
- approval/review, lead-filter review, message review, and final approval packet.
142
+ approval/review, lead-filter review, and message review.
134
143
  The link is for deeper inspection; never use it as a substitute for showing the
135
144
  content in chat.
136
145
 
@@ -340,7 +349,7 @@ I can’t confirm it, I’ll ask for your LinkedIn URL or company website and us
340
349
  that to understand the company before we choose the target, offer, proof, and
341
350
  lead source.
342
351
 
343
- Then I’ll turn that into a campaign brief for you to approve before anything is created.
352
+ Then I’ll turn that into a campaign brief for you to approve before any leads are imported or anything can send.
344
353
  ```
345
354
 
346
355
  Do not silently ask Codex intake or approval questions as plain chat when
@@ -374,7 +383,7 @@ No problem. You can still continue by switching Codex to Plan mode and running:
374
383
 
375
384
  $sellable:create-campaign
376
385
 
377
- I won’t create or change anything in Sellable until you approve the final campaign.
386
+ I won’t import leads, attach a sequence, or start anything until the brief, source, filters, and message are set.
378
387
  ```
379
388
 
380
389
  Plain chat questions are only acceptable in non-interactive `codex exec`
@@ -520,12 +529,15 @@ updates.
520
529
  `mcp__sellable__get_subskill_prompt({ subskillName: "generate-messages", offset, limit })`
521
530
  calls until `hasMore` is false. Do not synthesize
522
531
  `message-validation.md` from the brief, lead review, or general knowledge.
523
- 5. Treat message quality as the gate before minting. Do not create a campaign,
524
- show a commit gate, or mint anything until `message-validation.md` proves
525
- the full generate-messages workflow ran and `message-review.md` recommends
526
- `approve-message` against the gold-standard rules.
527
- 6. Do not create or mutate the live campaign until the approval gate returns
528
- `approve`.
532
+ 5. Create the campaign shell early with the v1 brief so the user can open the
533
+ watch link and see useful setup state immediately. Import only the first
534
+ bounded review batch after the source is attached to the campaign; do not
535
+ queue workflow cells, attach a sequence, or start until
536
+ `message-validation.md` proves the full generate-messages workflow ran,
537
+ `message-review.md` approves the template, rubrics are saved, and the
538
+ approved message set is synced into the campaign brief.
539
+ 6. Keep `selectedLeadListId` as the source list and `workflowTableId` as the
540
+ campaign table. Do not use disk files as the post-mint source of truth.
529
541
  7. Do not ask the user to run another command.
530
542
 
531
543
  ## Fallback