@sellable/mcp 0.1.28 → 0.1.30

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.30",
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,106 @@
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
36
 
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.
37
+ ## Setup: Pre-Load Deferred Tools (One-Time, Before The Parallel Batch)
46
38
 
47
- ### `deep-proof` (2-3 agents in parallel, max 5 tool calls total, ~30 seconds)
39
+ Some hosts (Claude Code with deferred-tool fetch) require `WebSearch` and
40
+ some MCP tools to be loaded via `ToolSearch` before they can be invoked. If
41
+ they are not already directly callable, issue this once as the first tool
42
+ call, on its own:
48
43
 
49
- **Condition:** `proofDigest.caseStudyCount === 0` OR `proofDigest.reviewHighlight` is null
44
+ `ToolSearch({ query: "select:WebSearch,mcp__sellable__enrich_sender,mcp__sellable__complete_sender_research", max_results: 5 })`
50
45
 
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.
46
+ Skip this turn entirely if the tools are already directly callable.
55
47
 
56
- ## Positioning Context (Conditional — from companySnapshot.description)
48
+ ## The One Round (Parallel Batch)
57
49
 
58
- If `companySnapshot.description` is null/undefined or shorter than ~120 characters, run the **Company Positioning** agent (1 WebSearch, no WebFetch).
50
+ **HARD RULE:** the four tool calls below MUST be emitted as **four `tool_use`
51
+ content blocks inside a single assistant message** (one turn, parallel
52
+ execution). Do NOT split them across multiple assistant messages.
59
53
 
60
- ## Execution Backend Routing
54
+ Concretely, your next assistant message must contain exactly these four
55
+ `tool_use` blocks, in any order, with no leading or trailing prose:
61
56
 
62
- Choose backend once:
57
+ 1. `enrich_sender({ linkedinUrl, companyDomain })` — baseline + `clientProspectId`.
58
+ 2. `WebSearch({ query: 'site:{companyDomain} ("case study" OR "customer story" OR testimonial OR "success story") "{companyName}"' })` — proof.
59
+ 3. `WebSearch({ query: '"{companyName}" {companyDomain} {currentYear} (funding OR raised OR seed OR series OR hiring OR launch OR "press release")' })` — growth/credibility.
60
+ 4. `WebSearch({ query: '"{companyName}" about product site:{companyDomain}' })` — positioning.
63
61
 
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.
62
+ **Self-check before you reply:** if your reply contains fewer than four
63
+ `tool_use` blocks (after the optional `ToolSearch` setup turn), you are
64
+ violating the protocol. Stop, rewrite the reply with all four.
67
65
 
68
- Never claim Task subagents were used when they were not.
66
+ **Known limitation (`claude -p` headless mode):** Claude often serializes
67
+ these calls one-per-turn even with explicit instructions. That's fine — the
68
+ skill still produces the same output, just with sequential tool execution
69
+ (~30–40s total wall time vs. ~10–15s if truly parallelized). If you can
70
+ batch, do; if not, proceed sequentially without retrying or re-prompting.
69
71
 
70
- ## Agent Prompts (when needed)
72
+ No subagent fan-out. No second round of enrichment polling.
71
73
 
72
- ### Agent 1: Case Studies + Proof (max 3 tool calls)
74
+ ## Synthesis (Single Pass After Batch Returns)
73
75
 
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
- ```
82
-
83
- ### Agent 2: Growth/Credibility Signals (max 1 tool call)
76
+ Merge the four results. Treat `enrich_sender` as the authoritative baseline
77
+ for company/sender facts; treat WebSearch as proof and signals.
84
78
 
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)
79
+ ```markdown
80
+ ## {Company} - Sender Research
95
81
 
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
- }
82
+ **Company Context:** [companySnapshot.description OR positioning WebSearch top result]
83
+ **Industry / Size:** [companySnapshot.industry + employeeRange]
84
+ **Positioning Notes:** [proofDigest.positioningOneLiner + keyDifferentiators]
85
+ **Proof Options:** [proofDigest.caseStudySummary + case-study WebSearch hits — pick 1-3 with named customers / metrics]
86
+ **Credibility Signals:** [proofDigest.reviewHighlight + growth WebSearch hits (funding, hiring, press)]
87
+ **Gaps:** [what's still missing usually fine to ship with this]
103
88
  ```
104
89
 
105
- ## Synthesis (Orchestrator No Agents)
90
+ If `enrich_sender` returns `enrichmentStatus: "partial"`, that's expected and
91
+ fine — `companySnapshot` and `senderBackground` are populated immediately.
92
+ `proofDigest` may be null on partial; in that case rely on WebSearch results
93
+ for proof and credibility, not on a second enrichment poll.
106
94
 
107
- After agents return (or immediately for minimal-verification), merge enrichment baseline + agent findings:
95
+ ## Optional Deepen (Only If Synthesis Reveals A Hard Gap)
108
96
 
109
- ```markdown
110
- ## {Company} - Sender Research
97
+ If after synthesis you genuinely have zero proof and zero credibility
98
+ signals, AND the campaign fixture/operator told you proof is required, you
99
+ MAY issue ONE additional WebFetch on the most promising case-study URL from
100
+ batch step 2. Cap at one WebFetch. No subagents, no second WebSearch round.
111
101
 
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
- ```
102
+ If that still yields nothing, set `proofItemsFound: 0` in
103
+ `complete_sender_research` and proceed; the brief can ship without proof.
118
104
 
119
105
  ## Completion Marker (Required)
120
106
 
@@ -124,7 +110,7 @@ After synthesis, call:
124
110
 
125
111
  Count rules:
126
112
 
127
- - `depth`: "minimal-verification" or "deep-proof"
113
+ - `depth`: always `"parallel-batch"` for this protocol.
128
114
  - `proofItemsFound`: number of concrete proof items you would confidently use.
129
115
  - `caseStudyItemsFound`: number of usable case-study examples.
130
116
  - `credibilitySignalsFound`: number of trust signals (reviews/ratings/funding/hiring/press).
@@ -133,26 +119,21 @@ If no reliable evidence is found, set counts to 0 and include that in `notes`.
133
119
 
134
120
  ## Progress UX
135
121
 
136
- If launching deep-proof agents:
137
-
138
- ```
139
- Running a quick research pass for case studies and growth signals (~30s)...
140
- ```
141
-
142
- If also launching the Company Positioning agent:
122
+ Before issuing the parallel batch:
143
123
 
144
124
  ```
145
- Running a quick research pass for case studies, growth signals, and positioning (~30s)...
125
+ Pulling sender enrichment + case studies + growth signals + positioning in parallel (~10s)...
146
126
  ```
147
127
 
148
- If only launching the Company Positioning agent:
128
+ After synthesis:
149
129
 
150
130
  ```
151
- Pulling a quick positioning summary from search snippets (~10s)...
131
+ Sender research ready {proofItemsFound} proof items, {credibilitySignalsFound} credibility signals.
152
132
  ```
153
133
 
154
- If skipping agents (minimal-verification):
134
+ ## What Changed From The Previous Protocol
155
135
 
156
- ```
157
- Enrichment already has strong proofsynthesizing directly from baseline data.
158
- ```
136
+ - No "minimal-verification vs deep-proof" branch. Always run the same parallel batch.
137
+ - No spawn of `general-purpose` subagents for research WebSearch from the orchestrator turn is faster and cheaper.
138
+ - No waiting on `enrich_sender` before issuing WebSearch.
139
+ - One round, one synthesis, one `complete_sender_research` call.