@sellable/mcp 0.1.28 → 0.1.29

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/dist/index-dev.js CHANGED
File without changes
package/dist/index.js CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.28",
3
+ "version": "0.1.29",
4
4
  "type": "module",
5
5
  "description": "Sellable MCP server for Claude Code and Codex campaign workflows",
6
6
  "main": "dist/index.js",
@@ -873,34 +873,40 @@ Orchestration requirements:
873
873
  before category nouns like `platform` or `MCP`.
874
874
  - pass the Thomas revision filters before writing findings
875
875
  - immediately after `message-validation.md` is confirmed and reconciled with
876
- `lead-filter.md`, write `message-review.md` and render it inline starting
877
- with `Status: message-review` as the first visible line. Do not put a
878
- markdown heading, preface, or summary before that status line. This is a
879
- customer checkpoint, not an audit report: show the approved campaign message
880
- template first, then show one filled sample prospect version immediately after
881
- it so the user can judge whether the tokens are being used correctly. Then
882
- show rendered examples that prove the tokens fill well and can be omitted
883
- cleanly when row data is weak. Keep the detailed
884
- gold-standard/rule audit inside `message-validation.md`, not in the
885
- user-facing review. The review must use this exact label shape so the gate can
886
- be parsed: `Subject: ...`, `Tokenized template: ...`, `Sample prospect fill:
887
- ...`, `Rendered examples: ...`, `Good token fill: ...`, `Good omit: ...`,
888
- `Bad token fill: ...`, `Why bad: ...`, `Fallback if missing: ...`,
889
- `Token notes: ...`, `My take: ...`, `Suggested adjustment: ...`,
890
- `Question: approve-message or revise-messaging?`, `Recommendation:
891
- approve-message|revise-messaging`.
892
- - Never ask the message approval question until the full message review is
893
- visible in the chat. A summary like `Message review is ready` or `the draft
894
- avoids a generic pitch` is not enough. The user must see the actual subject,
895
- the actual tokenized message template, one filled sample prospect version, at
896
- least one good filled example, one good omit example, one bad fill example,
897
- why the bad fill is wrong, fallback rules for missing row data, token notes,
898
- your take, and the suggested adjustment before any `approve-message` /
899
- `revise-messaging` question appears. If you catch yourself wanting to offer
900
- `show me message` as a choice, stop: render the message review first, then ask
901
- only `approve-message` or `revise-messaging`.
902
- Include `Open artifacts:` links to `message-review.md` and
903
- `message-validation.md` before the approval question.
876
+ `lead-filter.md`, write `message-review.md` and render the slim chat version
877
+ inline starting with `Status: message-review` as the first visible line. Do
878
+ not put a markdown heading, preface, or summary before that status line.
879
+ This is a customer checkpoint optimized for fast approve / revise judgment.
880
+ - Chat-vs-file split (this is the rule the user pinned):
881
+ - `message-review.md` (the file) keeps the full detail: `Status:
882
+ message-review`, `Subject:`, `Tokenized template:`, `Sample prospect fill:` + `Token fill basis:`, `Rendered examples:`, `Good token fill:`,
883
+ `Good omit:`, `Bad token fill:`, `Why bad:`, `Fallback if missing:`,
884
+ `Token notes:`, `My take:`, `Suggested adjustment:`, `Question:
885
+ approve-message or revise-messaging?`, `Recommendation:
886
+ approve-message|revise-messaging`. The detailed gold-standard/rule audit
887
+ stays in `message-validation.md`. Both files are unchanged in scope and
888
+ are still required.
889
+ - The chat rendering shows ONLY: `Status: message-review`, `Subject:`,
890
+ `Tokenized template:`, `Sample prospect fill:` (with `Token fill basis:`),
891
+ `My take:`, `Suggested adjustment:`, `Question: approve-message or
892
+ revise-messaging?`, `Recommendation:`. Then `Open artifacts:` links to
893
+ `message-review.md` and `message-validation.md` so the user can read the
894
+ full token guidance, good/omit/bad examples, and fallbacks if they want
895
+ to before deciding.
896
+ - Do NOT inline `Rendered examples:`, `Good token fill:`, `Good omit:`,
897
+ `Bad token fill:`, `Why bad:`, `Fallback if missing:`, or `Token notes:`
898
+ in chat. Those exist in the file and are linked. Keeping them out of
899
+ chat is what makes the gate easy to approve or revise on.
900
+ - Never ask the message approval question until the slim chat review is fully
901
+ visible. A summary like `Message review is ready` or `the draft avoids a
902
+ generic pitch` is not enough. The user must see the actual subject, the
903
+ actual tokenized message template, one filled sample prospect version with
904
+ its token fill basis, your take, and the suggested adjustment before any
905
+ `approve-message` / `revise-messaging` question appears. If you catch
906
+ yourself wanting to offer `show me message` as a choice, stop: render the
907
+ slim chat review first, then ask only `approve-message` or
908
+ `revise-messaging`. Include `Open artifacts:` links to `message-review.md`
909
+ and `message-validation.md` before the approval question.
904
910
  - `My take:` and `Suggested adjustment:` are mandatory customer-facing decision
905
911
  fields, not optional summary text. They must appear after `Token notes:` and
906
912
  before the question in every rendered message review. They must each be
@@ -605,25 +605,23 @@
605
605
  "subject",
606
606
  "tokenized template",
607
607
  "sample prospect fill",
608
- "rendered examples",
609
- "bad token examples",
610
- "token notes",
611
608
  "my take",
612
609
  "suggested adjustment",
613
610
  "question",
614
611
  "recommendation"
615
612
  ],
616
613
  "mustRenderInlineBeforeQuestion": true,
617
- "minimumVisibleMessageDetail": "full_message_review_before_question",
614
+ "minimumVisibleMessageDetail": "tokenized_template_plus_sample_fill_only",
618
615
  "requiredArtifactLinks": [
619
616
  "message-review.md",
620
617
  "message-validation.md"
621
618
  ],
622
619
  "artifactLinkTiming": "before_approval_question",
623
- "requiredLabels": [
620
+ "requiredFileLabels": [
624
621
  "Subject:",
625
622
  "Tokenized template:",
626
623
  "Sample prospect fill:",
624
+ "Token fill basis:",
627
625
  "Rendered examples:",
628
626
  "Good token fill:",
629
627
  "Good omit:",
@@ -636,6 +634,18 @@
636
634
  "Question: approve-message or revise-messaging?",
637
635
  "Recommendation:"
638
636
  ],
637
+ "requiredChatLabels": [
638
+ "Status: message-review",
639
+ "Subject:",
640
+ "Tokenized template:",
641
+ "Sample prospect fill:",
642
+ "Token fill basis:",
643
+ "My take:",
644
+ "Suggested adjustment:",
645
+ "Question: approve-message or revise-messaging?",
646
+ "Recommendation:"
647
+ ],
648
+ "chatRenderRule": "Show ONLY the tokenized template and one filled sample prospect version (with Token fill basis), then My take, Suggested adjustment, Question, Recommendation, and Open artifacts links. Do NOT inline Rendered examples, Good token fill, Good omit, Bad token fill, Why bad, Fallback if missing, or Token notes — those live in message-review.md and message-validation.md only.",
639
649
  "allowedRecommendations": ["approve-message", "revise-messaging"],
640
650
  "judgeAgainst": [
641
651
  "generate-messages rules",
@@ -670,13 +680,7 @@
670
680
  "Subject:",
671
681
  "Tokenized template:",
672
682
  "Sample prospect fill:",
673
- "Rendered examples:",
674
- "Good token fill:",
675
- "Good omit:",
676
- "Bad token fill:",
677
- "Why bad:",
678
- "Fallback if missing:",
679
- "Token notes:",
683
+ "Token fill basis:",
680
684
  "My take:",
681
685
  "Suggested adjustment:",
682
686
  "Recommendation:"
@@ -1,120 +1,82 @@
1
1
  ---
2
2
  name: research-sender
3
- description: Enrichment-first sender research protocol. 0-3 agents, 30s target.
3
+ description: Parallel-first sender research protocol. One round of batched tool calls, ~10-15s wall time.
4
4
  visibility: internal
5
5
  ---
6
6
 
7
- # Research Sender (Enrichment-First)
7
+ # Research Sender (Parallel-First)
8
8
 
9
9
  Use this subskill when creating campaigns and you need sender/company research.
10
10
  This protocol is standalone and does not depend on the generic `research` subskill.
11
11
 
12
- ## Core Architecture
12
+ ## Core Idea — Don't Wait, Fan Out
13
13
 
14
- `enrich_sender` compact mode already returns `companySnapshot`, `senderBackground`, and `proofDigest`.
15
- Four of the old five research agents duplicated this data. Only Growth Signals + Case Studies are net-new.
16
- When `companySnapshot.description` is missing/thin, we also run a tiny positioning snippet pass (1 WebSearch) so we don't end up with blank company context.
14
+ Old protocol: call `enrich_sender` wait for partial maybe spawn 2-3 subagents → wait.
15
+ That's 3-4 sequential rounds and ~60s+ wall time.
17
16
 
18
- **This protocol uses enrichment as the baseline and only spawns extra work when proof or positioning context is missing.**
17
+ New protocol: **fire one parallel batch.** `enrich_sender` (5-8s, returns
18
+ `clientProspectId` + baseline) runs alongside 2-3 `WebSearch` calls. They all
19
+ finish in the same ~10s window, then you synthesize.
20
+
21
+ The `enrich_sender` call is still required because downstream tools
22
+ (`create_campaign`, `attach_sequence`, message generation) need the
23
+ `clientProspectId` it produces and the cached `EnrichedProspect` row it writes.
24
+ Don't skip it — just stop waiting for it before doing the rest of the research.
19
25
 
20
26
  ## Inputs
21
27
 
22
28
  Provide as many as available. Use `"Unknown"` for missing values.
23
29
 
30
+ - `linkedinUrl` (REQUIRED)
24
31
  - `name`
25
32
  - `title`
26
33
  - `companyName`
27
- - `companyDomain`
28
- - `companyLinkedinUrl` (optional)
29
- - `linkedinUrl` (optional)
34
+ - `companyDomain` (REQUIRED for WebSearch — derive from email or LinkedIn if absent)
30
35
  - `headline` (optional)
31
- - `enrichSender` response (REQUIRED — must include `companySnapshot`, `senderBackground`, `proofDigest`)
32
-
33
- ## Depth Decision (Deterministic — from proofDigest)
34
-
35
- Check the `proofDigest` from the `enrich_sender` compact response:
36
-
37
- ### `minimal-verification` (0-1 agent, 0-1 web calls, ~2-10 seconds)
38
-
39
- **Condition:** `proofDigest.caseStudyCount > 0` AND `proofDigest.reviewHighlight` exists (not null)
40
-
41
- - Do NOT spawn proof/growth agents (Case Studies, Growth Signals).
42
- - If `companySnapshot.description` is missing/thin, spawn the **Company Positioning** agent (1 WebSearch, no WebFetch).
43
- - Synthesize directly from enrichment data (companySnapshot + senderBackground + proofDigest) plus Agent 3 if used.
44
- - Call `complete_sender_research()` immediately with enrichment counts.
45
- - ~0 additional tokens.
46
-
47
- ### `deep-proof` (2-3 agents in parallel, max 5 tool calls total, ~30 seconds)
48
36
 
49
- **Condition:** `proofDigest.caseStudyCount === 0` OR `proofDigest.reviewHighlight` is null
37
+ ## The One Round (Mandatory Parallel Batch)
50
38
 
51
- - Spawn exactly **2 agents in parallel** (Case Studies + Growth Signals).
52
- - If `companySnapshot.description` is missing/thin, also spawn **1 positioning agent** (Company Positioning) in parallel.
53
- - Homepage, Company LinkedIn, Reviews all covered by enrichment, skip these entirely.
54
- - ~100k tokens total.
39
+ Issue ALL of the following in a single tool-call batch (Task subagents,
40
+ `multi_tool_use.parallel`, or whatever batching primitive your host exposes).
41
+ Do NOT issue any of them sequentially that defeats the protocol.
55
42
 
56
- ## Positioning Context (Conditionalfrom companySnapshot.description)
43
+ 1. `enrich_sender({ linkedinUrl, companyDomain })` baseline + `clientProspectId`.
44
+ 2. `WebSearch`: `site:{companyDomain} ("case study" OR "customer story" OR testimonial OR "success story") "{companyName}"` — proof.
45
+ 3. `WebSearch`: `"{companyName}" {companyDomain} {currentYear} (funding OR raised OR seed OR series OR hiring OR launch OR "press release")` — growth/credibility.
46
+ 4. `WebSearch` (conditional, include unless you have strong positioning context already): `"{companyName}" about product site:{companyDomain}` — positioning.
57
47
 
58
- If `companySnapshot.description` is null/undefined or shorter than ~120 characters, run the **Company Positioning** agent (1 WebSearch, no WebFetch).
48
+ That's it. No subagent fan-out. No second round of enrichment polling.
59
49
 
60
- ## Execution Backend Routing
61
-
62
- Choose backend once:
63
-
64
- 1. If `Task` is available: use Task subagents in parallel (Claude host).
65
- 2. Else if `multi_tool_use.parallel` is available: batch independent tool calls (Codex host).
66
- 3. Else: run units sequentially.
67
-
68
- Never claim Task subagents were used when they were not.
69
-
70
- ## Agent Prompts (when needed)
71
-
72
- ### Agent 1: Case Studies + Proof (max 3 tool calls)
73
-
74
- ```json
75
- {
76
- "subagent_type": "general-purpose",
77
- "model": "haiku",
78
- "description": "Case studies and proof",
79
- "prompt": "Find 1-3 concrete proof items for {companyName} ({companyDomain}).\n\nUse only: WebSearch, WebFetch.\n\nTool budget:\n- 1 WebSearch\n- Up to 2 WebFetch (only if the page looks like a case study/testimonial with named customers or metrics)\n\nWebSearch query (run exactly once):\nsite:{companyDomain} (\"case study\" OR \"customer story\" OR testimonial OR results OR \"success story\") \"{companyName}\"\n\nWebFetch: pick up to 2 results that look most likely to contain named customers or metrics.\nIf a fetched page is JS-heavy/empty, skip it and use snippets.\nDo not do a second search.\n\nReturn EXACTLY:\n---\nPROOF_OPTIONS: [Up to 3 items. Each: customer + outcome/metric + timeframe if present; or 'None found']\nSOURCES: [Short source hints]\n---\nKeep under 120 words. No extra commentary."
80
- }
81
- ```
50
+ ## Synthesis (Single Pass After Batch Returns)
82
51
 
83
- ### Agent 2: Growth/Credibility Signals (max 1 tool call)
52
+ Merge the four results. Treat `enrich_sender` as the authoritative baseline
53
+ for company/sender facts; treat WebSearch as proof and signals.
84
54
 
85
- ```json
86
- {
87
- "subagent_type": "general-purpose",
88
- "model": "haiku",
89
- "description": "Growth and credibility signals",
90
- "prompt": "Find recent growth/credibility signals for {companyName} ({companyDomain}).\n\nUse only: WebSearch.\nTool budget: 1 WebSearch.\n\nWebSearch query (run exactly once):\n\"{companyName}\" {companyDomain} {currentYear} (funding OR raised OR seed OR series OR hiring OR \"we're hiring\" OR launch OR announcement OR \"press release\")\n\nReturn EXACTLY:\n---\nHIRING: [Notable signals or 'None found']\nFUNDING: [Round, amount, date or 'None found']\nPRESS: [Recent announcement or 'None found']\n---\nKeep under 90 words. No extra commentary."
91
- }
92
- ```
93
-
94
- ### Agent 3: Company Positioning (max 1 tool call)
55
+ ```markdown
56
+ ## {Company} - Sender Research
95
57
 
96
- ```json
97
- {
98
- "subagent_type": "general-purpose",
99
- "model": "haiku",
100
- "description": "Company positioning context",
101
- "prompt": "If the enrichment company description is missing/thin, pull a crisp positioning summary for {companyName} ({companyDomain}) using only search snippets.\n\nUse only: WebSearch.\nTool budget: 1 WebSearch.\n\nWebSearch query (run exactly once):\n\"{companyName}\" about product site:{companyDomain}\n\nReturn EXACTLY:\n---\nPOSITIONING: [1-2 sentences]\nICP: [1 short line, or 'Unknown']\nDIFFERENTIATORS: [Up to 3 short bullets, or 'Unknown']\nSOURCES: [Short source hints]\n---\nKeep under 90 words. No extra commentary."
102
- }
58
+ **Company Context:** [companySnapshot.description OR positioning WebSearch top result]
59
+ **Industry / Size:** [companySnapshot.industry + employeeRange]
60
+ **Positioning Notes:** [proofDigest.positioningOneLiner + keyDifferentiators]
61
+ **Proof Options:** [proofDigest.caseStudySummary + case-study WebSearch hits — pick 1-3 with named customers / metrics]
62
+ **Credibility Signals:** [proofDigest.reviewHighlight + growth WebSearch hits (funding, hiring, press)]
63
+ **Gaps:** [what's still missing usually fine to ship with this]
103
64
  ```
104
65
 
105
- ## Synthesis (Orchestrator No Agents)
66
+ If `enrich_sender` returns `enrichmentStatus: "partial"`, that's expected and
67
+ fine — `companySnapshot` and `senderBackground` are populated immediately.
68
+ `proofDigest` may be null on partial; in that case rely on WebSearch results
69
+ for proof and credibility, not on a second enrichment poll.
106
70
 
107
- After agents return (or immediately for minimal-verification), merge enrichment baseline + agent findings:
71
+ ## Optional Deepen (Only If Synthesis Reveals A Hard Gap)
108
72
 
109
- ```markdown
110
- ## {Company} - Sender Research
73
+ If after synthesis you genuinely have zero proof and zero credibility
74
+ signals, AND the campaign fixture/operator told you proof is required, you
75
+ MAY issue ONE additional WebFetch on the most promising case-study URL from
76
+ batch step 2. Cap at one WebFetch. No subagents, no second WebSearch round.
111
77
 
112
- **Company Context:** [companySnapshot.description OR Agent 3 POSITIONING] + [companySnapshot.industry + employeeRange]
113
- **Positioning Notes:** [proofDigest.positioningOneLiner + keyDifferentiators + Agent 3 DIFFERENTIATORS (if present)]
114
- **Proof Options:** [proofDigest.caseStudySummary + agent upgrades if deep-proof]
115
- **Credibility Signals:** [proofDigest.reviewHighlight + agent growth signals if deep-proof]
116
- **Gaps:** [what's missing]
117
- ```
78
+ If that still yields nothing, set `proofItemsFound: 0` in
79
+ `complete_sender_research` and proceed; the brief can ship without proof.
118
80
 
119
81
  ## Completion Marker (Required)
120
82
 
@@ -124,7 +86,7 @@ After synthesis, call:
124
86
 
125
87
  Count rules:
126
88
 
127
- - `depth`: "minimal-verification" or "deep-proof"
89
+ - `depth`: always `"parallel-batch"` for this protocol.
128
90
  - `proofItemsFound`: number of concrete proof items you would confidently use.
129
91
  - `caseStudyItemsFound`: number of usable case-study examples.
130
92
  - `credibilitySignalsFound`: number of trust signals (reviews/ratings/funding/hiring/press).
@@ -133,26 +95,21 @@ If no reliable evidence is found, set counts to 0 and include that in `notes`.
133
95
 
134
96
  ## Progress UX
135
97
 
136
- If launching deep-proof agents:
98
+ Before issuing the parallel batch:
137
99
 
138
100
  ```
139
- Running a quick research pass for case studies and growth signals (~30s)...
101
+ Pulling sender enrichment + case studies + growth signals + positioning in parallel (~10s)...
140
102
  ```
141
103
 
142
- If also launching the Company Positioning agent:
104
+ After synthesis:
143
105
 
144
106
  ```
145
- Running a quick research pass for case studies, growth signals, and positioning (~30s)...
107
+ Sender research ready {proofItemsFound} proof items, {credibilitySignalsFound} credibility signals.
146
108
  ```
147
109
 
148
- If only launching the Company Positioning agent:
110
+ ## What Changed From The Previous Protocol
149
111
 
150
- ```
151
- Pulling a quick positioning summary from search snippets (~10s)...
152
- ```
153
-
154
- If skipping agents (minimal-verification):
155
-
156
- ```
157
- Enrichment already has strong proof — synthesizing directly from baseline data.
158
- ```
112
+ - No "minimal-verification vs deep-proof" branch. Always run the same parallel batch.
113
+ - No spawn of `general-purpose` subagents for research — WebSearch from the orchestrator turn is faster and cheaper.
114
+ - No waiting on `enrich_sender` before issuing WebSearch.
115
+ - One round, one synthesis, one `complete_sender_research` call.