@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.
Files changed (200) hide show
  1. package/.claude-plugin/plugin.json +12 -0
  2. package/.mcp.json +9 -0
  3. package/README.md +355 -0
  4. package/dist/api.d.ts +21 -0
  5. package/dist/api.js +73 -0
  6. package/dist/auth.d.ts +60 -0
  7. package/dist/auth.js +246 -0
  8. package/dist/engage-memory.d.ts +63 -0
  9. package/dist/engage-memory.js +354 -0
  10. package/dist/index-dev.d.ts +2 -0
  11. package/dist/index-dev.js +17 -0
  12. package/dist/index.d.ts +7 -0
  13. package/dist/index.js +8 -0
  14. package/dist/server.d.ts +1 -0
  15. package/dist/server.js +499 -0
  16. package/dist/skills.d.ts +11 -0
  17. package/dist/skills.js +97 -0
  18. package/dist/tools/auth.d.ts +30 -0
  19. package/dist/tools/auth.js +124 -0
  20. package/dist/tools/blueprint-commit.d.ts +174 -0
  21. package/dist/tools/blueprint-commit.js +286 -0
  22. package/dist/tools/bootstrap.d.ts +64 -0
  23. package/dist/tools/bootstrap.js +246 -0
  24. package/dist/tools/campaigns.d.ts +589 -0
  25. package/dist/tools/campaigns.js +892 -0
  26. package/dist/tools/cells.d.ts +58 -0
  27. package/dist/tools/cells.js +48 -0
  28. package/dist/tools/context.d.ts +88 -0
  29. package/dist/tools/context.js +271 -0
  30. package/dist/tools/csv-domains.d.ts +73 -0
  31. package/dist/tools/csv-domains.js +464 -0
  32. package/dist/tools/csv-linkedin.d.ts +102 -0
  33. package/dist/tools/csv-linkedin.js +712 -0
  34. package/dist/tools/direct-campaigns.d.ts +240 -0
  35. package/dist/tools/direct-campaigns.js +250 -0
  36. package/dist/tools/engage-bootstrap.d.ts +94 -0
  37. package/dist/tools/engage-bootstrap.js +205 -0
  38. package/dist/tools/engage-discovery.d.ts +78 -0
  39. package/dist/tools/engage-discovery.js +150 -0
  40. package/dist/tools/engage-memory.d.ts +181 -0
  41. package/dist/tools/engage-memory.js +143 -0
  42. package/dist/tools/engage-state.d.ts +72 -0
  43. package/dist/tools/engage-state.js +62 -0
  44. package/dist/tools/enrichment.d.ts +167 -0
  45. package/dist/tools/enrichment.js +174 -0
  46. package/dist/tools/flow-preflight.d.ts +68 -0
  47. package/dist/tools/flow-preflight.js +138 -0
  48. package/dist/tools/framework.d.ts +44 -0
  49. package/dist/tools/framework.js +153 -0
  50. package/dist/tools/interaction-mode.d.ts +27 -0
  51. package/dist/tools/interaction-mode.js +102 -0
  52. package/dist/tools/leads.d.ts +2417 -0
  53. package/dist/tools/leads.js +2307 -0
  54. package/dist/tools/linkedin.d.ts +210 -0
  55. package/dist/tools/linkedin.js +229 -0
  56. package/dist/tools/navigation.d.ts +91 -0
  57. package/dist/tools/navigation.js +381 -0
  58. package/dist/tools/one-off.d.ts +229 -0
  59. package/dist/tools/one-off.js +273 -0
  60. package/dist/tools/processing.d.ts +70 -0
  61. package/dist/tools/processing.js +56 -0
  62. package/dist/tools/prompts.d.ts +211 -0
  63. package/dist/tools/prompts.js +210 -0
  64. package/dist/tools/provider-preflight.d.ts +21 -0
  65. package/dist/tools/provider-preflight.js +59 -0
  66. package/dist/tools/readiness.d.ts +261 -0
  67. package/dist/tools/readiness.js +510 -0
  68. package/dist/tools/rows.d.ts +126 -0
  69. package/dist/tools/rows.js +105 -0
  70. package/dist/tools/rubrics.d.ts +497 -0
  71. package/dist/tools/rubrics.js +681 -0
  72. package/dist/tools/senders.d.ts +44 -0
  73. package/dist/tools/senders.js +69 -0
  74. package/dist/tools/sequencer.d.ts +127 -0
  75. package/dist/tools/sequencer.js +194 -0
  76. package/dist/tools/tables.d.ts +35 -0
  77. package/dist/tools/tables.js +36 -0
  78. package/dist/tools/verify-row.d.ts +36 -0
  79. package/dist/tools/verify-row.js +38 -0
  80. package/dist/tools/workspaces.d.ts +140 -0
  81. package/dist/tools/workspaces.js +139 -0
  82. package/dist/utils/workspace-root.d.ts +1 -0
  83. package/dist/utils/workspace-root.js +39 -0
  84. package/package.json +46 -0
  85. package/skills/building-gtm-tables/SKILL.md +216 -0
  86. package/skills/building-gtm-tables/core/auto-execute.yaml +19 -0
  87. package/skills/building-gtm-tables/core/blueprint-schema.json +72 -0
  88. package/skills/building-gtm-tables/references/brief-to-blueprint.md +334 -0
  89. package/skills/building-gtm-tables/references/column-type-catalog.md +318 -0
  90. package/skills/building-gtm-tables/references/common-blueprints.fixtures.ts +199 -0
  91. package/skills/building-gtm-tables/references/common-blueprints.md +44 -0
  92. package/skills/building-gtm-tables/references/failure-taxonomy.md +197 -0
  93. package/skills/building-gtm-tables/references/uat-seed-prompts.md +37 -0
  94. package/skills/building-gtm-tables/references/verify-loop.md +74 -0
  95. package/skills/campaign-messages/SKILL.md +173 -0
  96. package/skills/campaign-messages/flow.v1.json +75 -0
  97. package/skills/craft-message/SKILL.md +401 -0
  98. package/skills/create-campaign/ARCHITECTURE.md +232 -0
  99. package/skills/create-campaign/DISCUSS.md +296 -0
  100. package/skills/create-campaign/FLOW_ASCII.md +240 -0
  101. package/skills/create-campaign/HOST-PARITY-CHECKLIST.md +49 -0
  102. package/skills/create-campaign/README.md +142 -0
  103. package/skills/create-campaign/SKILL.md +286 -0
  104. package/skills/create-campaign/context/README.md +67 -0
  105. package/skills/create-campaign/context/_TEMPLATE.md +12 -0
  106. package/skills/create-campaign/context/context.md +35 -0
  107. package/skills/create-campaign/context/learnings.md +16 -0
  108. package/skills/create-campaign/context/registry.json +19 -0
  109. package/skills/create-campaign/core/flow.v1.json +217 -0
  110. package/skills/create-campaign/core/policy.md +191 -0
  111. package/skills/create-campaign/core/providers/apollo.json +35 -0
  112. package/skills/create-campaign/core/providers/prospeo.json +34 -0
  113. package/skills/create-campaign/core/providers/registry.json +31 -0
  114. package/skills/create-campaign/core/providers/sales-nav.json +37 -0
  115. package/skills/create-campaign/core/providers/signal-discovery.json +42 -0
  116. package/skills/create-campaign/references/brief-template.md +64 -0
  117. package/skills/create-campaign/references/campaign-quality.md +84 -0
  118. package/skills/create-campaign/references/copy-calibration-examples.md +120 -0
  119. package/skills/create-campaign/references/offer-patterns.md +108 -0
  120. package/skills/create-campaign/references/provider-selection-strategy.md +212 -0
  121. package/skills/create-campaign/references/question-examples.md +167 -0
  122. package/skills/create-campaign/references/token-fill-examples.md +81 -0
  123. package/skills/create-campaign-brief/ARCHITECTURE.md +72 -0
  124. package/skills/create-campaign-brief/DISCUSS.md +64 -0
  125. package/skills/create-campaign-brief/README.md +176 -0
  126. package/skills/create-campaign-brief/SKILL.md +537 -0
  127. package/skills/create-campaign-brief/references/brief-synthesis-rules.md +100 -0
  128. package/skills/create-campaign-brief/references/brief-template.md +220 -0
  129. package/skills/create-campaign-brief/references/campaign-idea-options.md +30 -0
  130. package/skills/create-campaign-brief/references/copy-appendix-template.md +62 -0
  131. package/skills/create-campaign-brief/references/draft-lifecycle.md +23 -0
  132. package/skills/create-campaign-brief/references/examples/MANIFEST.json +89 -0
  133. package/skills/create-campaign-brief/references/examples/briefs/clover.md +223 -0
  134. package/skills/create-campaign-brief/references/examples/briefs/galley.md +222 -0
  135. package/skills/create-campaign-brief/references/examples/briefs/gelee.md +220 -0
  136. package/skills/create-campaign-brief/references/examples/briefs/hey-digital.md +234 -0
  137. package/skills/create-campaign-brief/references/examples/briefs/persona.md +231 -0
  138. package/skills/create-campaign-brief/references/examples/briefs/revvix.md +220 -0
  139. package/skills/create-campaign-brief/references/examples/briefs/sellable-dev.md +220 -0
  140. package/skills/create-campaign-brief/references/examples/briefs/superposition.md +233 -0
  141. package/skills/create-campaign-brief/references/examples/briefs/superpower.md +219 -0
  142. package/skills/create-campaign-brief/references/examples/briefs/westpark-villas.md +220 -0
  143. package/skills/create-campaign-brief/references/icp-lock-question-bank.md +43 -0
  144. package/skills/create-campaign-brief/references/messaging-inputs.md +58 -0
  145. package/skills/create-campaign-brief/references/output-acceptance-rubric.md +62 -0
  146. package/skills/create-campaign-brief/references/phase75-active-runtime-message-pack.md +248 -0
  147. package/skills/create-campaign-brief/references/phase75-canonical-brief-template.md +319 -0
  148. package/skills/create-campaign-brief/references/phase75-good-brief-and-messaging-examples.md +445 -0
  149. package/skills/create-campaign-brief/references/quick-research-protocol.md +39 -0
  150. package/skills/create-campaign-brief/references/reference-sheet-protocol.md +60 -0
  151. package/skills/create-campaign-brief/references/zero-shot-iteration-rules.md +66 -0
  152. package/skills/create-campaign-v2/SKILL.md +1619 -0
  153. package/skills/create-campaign-v2/core/auto-execute.README.md +219 -0
  154. package/skills/create-campaign-v2/core/auto-execute.yaml +121 -0
  155. package/skills/create-campaign-v2/core/flow.v2.json +1643 -0
  156. package/skills/create-campaign-v2/core/policy.md +82 -0
  157. package/skills/create-campaign-v2/references/ai-tells.md +253 -0
  158. package/skills/create-campaign-v2/references/approval-gate-framing.md +346 -0
  159. package/skills/create-campaign-v2/references/draft-lifecycle.md +110 -0
  160. package/skills/create-campaign-v2/references/escalation-ladder.md +119 -0
  161. package/skills/create-campaign-v2/references/filter-leads.md +495 -0
  162. package/skills/create-campaign-v2/references/final-handoff-contract.md +176 -0
  163. package/skills/create-campaign-v2/references/gold-standard-message-examples.md +394 -0
  164. package/skills/create-campaign-v2/references/gold-standard-message-patterns.md +314 -0
  165. package/skills/create-campaign-v2/references/gold-standard-message-validation-example.md +212 -0
  166. package/skills/create-campaign-v2/references/lead-validation-preview.md +172 -0
  167. package/skills/create-campaign-v2/references/parallel-critique-protocol.md +368 -0
  168. package/skills/create-campaign-v2/references/sample-validation-loop.md +289 -0
  169. package/skills/create-campaign-v2/references/step-13-import-leads.md +151 -0
  170. package/skills/create-campaign-v2/references/step-15-re-cascade.md +90 -0
  171. package/skills/create-campaign-v2/references/thomas-revision-filters.md +521 -0
  172. package/skills/create-campaign-v2/references/thomas-variant-selection.md +202 -0
  173. package/skills/create-campaign-v2/references/tier-routing-matrix.md +66 -0
  174. package/skills/create-campaign-v2/references/validation-criteria.md +367 -0
  175. package/skills/create-campaign-v2/references/watch-link-handoff.md +106 -0
  176. package/skills/create-campaign-v2-validation/SKILL.md +296 -0
  177. package/skills/create-post/SKILL.md +1308 -0
  178. package/skills/create-rubric/SKILL.md +251 -0
  179. package/skills/engage/SKILL.md +549 -0
  180. package/skills/engage/core/README.md +23 -0
  181. package/skills/engage/core/proven-searches.json +11 -0
  182. package/skills/engage/core/style-guide.template.md +47 -0
  183. package/skills/engage/core/tracked-people.json +10 -0
  184. package/skills/enrich-prospects/SKILL.md +97 -0
  185. package/skills/find-leads/SKILL.md +467 -0
  186. package/skills/generate-messages/SKILL.md +2361 -0
  187. package/skills/interview/SKILL.md +132 -0
  188. package/skills/interview/core/ENGAGE_STYLE_GUIDE.template.md +54 -0
  189. package/skills/interview/core/ICP.template.md +54 -0
  190. package/skills/interview/core/VOICE_PROFILE.template.md +101 -0
  191. package/skills/providers/apollo.md +520 -0
  192. package/skills/providers/prospeo.md +398 -0
  193. package/skills/providers/sales-nav.md +372 -0
  194. package/skills/providers/signal-discovery.md +495 -0
  195. package/skills/research/SKILL.md +258 -0
  196. package/skills/research/config.json +9 -0
  197. package/skills/research/override.md +13 -0
  198. package/skills/research-prospect/SKILL.md +99 -0
  199. package/skills/research-sender/SKILL.md +158 -0
  200. package/skills/workflow-sequences/SKILL.md +85 -0
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Sellable MCP Server - Production
4
+ *
5
+ * Uses ~/.claude/sellable.json config (default prod URL: https://app.sellable.dev)
6
+ */
7
+ // Uses default config (sellable.json), just import and run
8
+ import "./server.js";
@@ -0,0 +1 @@
1
+ export {};
package/dist/server.js ADDED
@@ -0,0 +1,499 @@
1
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { CallToolRequestSchema, GetPromptRequestSchema, ListPromptsRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
4
+ import { getSkillByName, listSkills, stripFrontmatter } from "./skills.js";
5
+ import { authToolDefinitions, getAuthStatus } from "./tools/auth.js";
6
+ import { blueprintCommitToolDefinitions, handleAddColumn, handleCommitBlueprint, } from "./tools/blueprint-commit.js";
7
+ import { bootstrapCreateCampaign, bootstrapToolDefinitions, } from "./tools/bootstrap.js";
8
+ import { campaignToolDefinitions, createCampaign, enrichSender, getCampaign, getCampaignMessagesPreview, getCampaigns, pauseCampaign, startCampaign, updateCampaign, updateCampaignBrief, } from "./tools/campaigns.js";
9
+ import { cellToolDefinitions, queueCells, updateCell } from "./tools/cells.js";
10
+ import { contextToolDefinitions, getCampaignContext, hydrateCampaignContextFromCampaign, markCampaignContextDirty, } from "./tools/context.js";
11
+ import { addToCommentCampaign, addToConnectionCampaign, addToInmailCampaign, directCampaignToolDefinitions, getEngagedPosts, getOrCreateDirectCampaignTable, pauseDirectCampaign, startDirectCampaign, } from "./tools/direct-campaigns.js";
12
+ import { bootstrapEngage, bootstrapEngageMulti, engageBootstrapToolDefinitions, } from "./tools/engage-bootstrap.js";
13
+ import { engageDiscoveryToolDefinitions, searchEngagementPosts, } from "./tools/engage-discovery.js";
14
+ import { copySenderConfigTool, engageMemoryToolDefinitions, getEngageMemoryTool, migrateFlatConfigsTool, recordEngageProvenSearchTool, setEngageStyleGuideTool, upsertEngageTrackedPersonTool, } from "./tools/engage-memory.js";
15
+ import { engageStateToolDefinitions, getEngageStateTool, setEngageStateTool, } from "./tools/engage-state.js";
16
+ import { bulkEnrichWithProspeo, enrichmentToolDefinitions, enrichWithProspeo, getProspeoCredits, } from "./tools/enrichment.js";
17
+ import { frameworkToolDefinitions, getCampaignFramework, } from "./tools/framework.js";
18
+ import { cancelLeadImport, confirmLeadList, getProviderPrompt, importLeads, leadToolDefinitions, loadCsvDomains, loadCsvLinkedinLeads, lookupSalesNavFilter, saveDomainFilters, searchApollo, searchProspeo, searchSalesNav, searchSignals, selectPromisingPosts, setHeadlineICPCriteria, } from "./tools/leads.js";
19
+ import { fetchCompany, fetchCompanyPosts, fetchLinkedInPosts, fetchLinkedInProfile, fetchPostEngagers, getLinkedInProfile, getUserPosts, linkedinToolDefinitions, } from "./tools/linkedin.js";
20
+ import { getCampaignNavigationState, navigationToolDefinitions, } from "./tools/navigation.js";
21
+ import { addOnDemandLeads, createOnDemandCampaign, createOnDemandTable, initOnDemandSequence, onDemandToolDefinitions, pauseOnDemandCampaign, startOnDemandCampaign, } from "./tools/one-off.js";
22
+ import { processingToolDefinitions, upsertRubric } from "./tools/processing.js";
23
+ import { completeSenderResearch, getMessagePrompt, getSubskillPrompt, listSubskillPrompts, promptToolDefinitions, searchSubskillPrompts, } from "./tools/prompts.js";
24
+ import { readinessToolDefinitions, waitForCampaignTableReady, waitForLeadListReady, } from "./tools/readiness.js";
25
+ import { getRows, getTableRows, getTableRowsMinimal, rowToolDefinitions, } from "./tools/rows.js";
26
+ import { addRubricItem, checkRubric, deleteRubricItem, draftRubrics, rubricToolDefinitions, saveRubrics, selectNecessaryRubrics, updateRubricItem, waitForRubricResults, } from "./tools/rubrics.js";
27
+ import { getSender, listSenders, senderToolDefinitions, } from "./tools/senders.js";
28
+ import { attachRecommendedSequence, attachSequence, createWorkflowTable, sequencerToolDefinitions, } from "./tools/sequencer.js";
29
+ import { listTables, tableToolDefinitions } from "./tools/tables.js";
30
+ import { handleVerifyTableRow, verifyRowToolDefinitions, } from "./tools/verify-row.js";
31
+ import { addTeammate, createWorkspace, getActiveWorkspace, listWorkspaces, setActiveWorkspace, workspaceToolDefinitions, } from "./tools/workspaces.js";
32
+ const server = new Server({
33
+ name: "sellable-mcp",
34
+ version: "1.0.0",
35
+ }, {
36
+ capabilities: {
37
+ tools: {},
38
+ prompts: {},
39
+ },
40
+ });
41
+ const allTools = [
42
+ ...campaignToolDefinitions,
43
+ ...authToolDefinitions,
44
+ ...bootstrapToolDefinitions,
45
+ ...engageBootstrapToolDefinitions,
46
+ ...engageDiscoveryToolDefinitions,
47
+ ...workspaceToolDefinitions,
48
+ ...frameworkToolDefinitions,
49
+ ...contextToolDefinitions,
50
+ ...navigationToolDefinitions,
51
+ ...leadToolDefinitions,
52
+ ...enrichmentToolDefinitions,
53
+ ...processingToolDefinitions,
54
+ ...rubricToolDefinitions,
55
+ ...readinessToolDefinitions,
56
+ ...rowToolDefinitions,
57
+ ...cellToolDefinitions,
58
+ ...promptToolDefinitions,
59
+ ...linkedinToolDefinitions,
60
+ ...onDemandToolDefinitions,
61
+ ...directCampaignToolDefinitions,
62
+ ...senderToolDefinitions,
63
+ ...engageStateToolDefinitions,
64
+ ...engageMemoryToolDefinitions,
65
+ ...sequencerToolDefinitions,
66
+ ...tableToolDefinitions,
67
+ ...blueprintCommitToolDefinitions,
68
+ ...verifyRowToolDefinitions,
69
+ ];
70
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
71
+ tools: allTools,
72
+ }));
73
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
74
+ const { name, arguments: args } = request.params;
75
+ try {
76
+ let result;
77
+ switch (name) {
78
+ case "get_auth_status":
79
+ result = await getAuthStatus();
80
+ break;
81
+ case "bootstrap_engage":
82
+ result = await bootstrapEngage(args);
83
+ break;
84
+ case "bootstrap_engage_multi":
85
+ result = await bootstrapEngageMulti(args);
86
+ break;
87
+ case "search_engagement_posts":
88
+ result = await searchEngagementPosts(args);
89
+ break;
90
+ case "get_engage_state":
91
+ result = getEngageStateTool();
92
+ break;
93
+ case "set_engage_state":
94
+ result = setEngageStateTool(args);
95
+ break;
96
+ case "get_engage_memory":
97
+ result = getEngageMemoryTool(args);
98
+ break;
99
+ case "set_engage_style_guide":
100
+ result = setEngageStyleGuideTool(args);
101
+ break;
102
+ case "record_engage_proven_search":
103
+ result = recordEngageProvenSearchTool(args);
104
+ break;
105
+ case "upsert_engage_tracked_person":
106
+ result = upsertEngageTrackedPersonTool(args);
107
+ break;
108
+ case "copy_sender_config":
109
+ result = copySenderConfigTool(args);
110
+ break;
111
+ case "migrate_flat_configs":
112
+ result = migrateFlatConfigsTool(args);
113
+ break;
114
+ case "list_workspaces":
115
+ result = await listWorkspaces();
116
+ break;
117
+ case "get_active_workspace":
118
+ result = getActiveWorkspace();
119
+ break;
120
+ case "set_active_workspace":
121
+ result = await setActiveWorkspace(args?.workspaceId, args?.userConfirmed);
122
+ break;
123
+ case "create_workspace":
124
+ result = await createWorkspace(args?.name);
125
+ break;
126
+ case "create_workflow_table":
127
+ result = await createWorkflowTable(args);
128
+ break;
129
+ case "attach_sequence":
130
+ result = await attachSequence(args);
131
+ break;
132
+ case "attach_recommended_sequence":
133
+ result = await attachRecommendedSequence(args);
134
+ break;
135
+ case "bootstrap_create_campaign":
136
+ result = await bootstrapCreateCampaign(args);
137
+ break;
138
+ case "add_teammate":
139
+ result = await addTeammate(args);
140
+ break;
141
+ case "enrich_sender":
142
+ result = await enrichSender(args?.linkedinUrl, args?.companyDomain, args?.forceRefresh);
143
+ break;
144
+ case "get_campaigns":
145
+ result = await getCampaigns(args?.limit);
146
+ break;
147
+ case "get_campaign":
148
+ result = await getCampaign(args?.campaignId);
149
+ break;
150
+ case "get_campaign_messages_preview":
151
+ result = await getCampaignMessagesPreview(args);
152
+ break;
153
+ case "create_campaign":
154
+ result = await createCampaign(args);
155
+ if (result?.id)
156
+ markCampaignContextDirty(result.id, "create_campaign");
157
+ break;
158
+ case "update_campaign":
159
+ result = await updateCampaign(args?.campaignId, args);
160
+ if (result?._campaign?.id) {
161
+ const entry = hydrateCampaignContextFromCampaign(result._campaign, "update_campaign");
162
+ result.navigation = entry.navState;
163
+ delete result._campaign;
164
+ }
165
+ else if (args?.campaignId) {
166
+ markCampaignContextDirty(args.campaignId, "update_campaign");
167
+ }
168
+ break;
169
+ case "start_campaign":
170
+ result = await startCampaign(args?.campaignId);
171
+ break;
172
+ case "pause_campaign":
173
+ result = await pauseCampaign(args?.campaignId);
174
+ break;
175
+ case "update_campaign_brief":
176
+ result = await updateCampaignBrief(args?.campaignId, args?.campaignBrief);
177
+ if (args?.campaignId) {
178
+ markCampaignContextDirty(args.campaignId, "update_campaign_brief");
179
+ }
180
+ break;
181
+ case "get_campaign_framework":
182
+ result = getCampaignFramework(args);
183
+ break;
184
+ case "get_campaign_context":
185
+ result = await getCampaignContext(args);
186
+ break;
187
+ case "get_campaign_navigation_state":
188
+ result = await getCampaignNavigationState(args);
189
+ break;
190
+ case "get_table_rows":
191
+ result = await getTableRows(args?.tableId, {
192
+ limit: args?.limit,
193
+ page: args?.page,
194
+ });
195
+ break;
196
+ case "get_rows_minimal":
197
+ result = await getTableRowsMinimal(args?.tableId, {
198
+ limit: args?.limit,
199
+ page: args?.page,
200
+ });
201
+ break;
202
+ case "list_tables":
203
+ result = await listTables(args);
204
+ break;
205
+ case "commit_blueprint":
206
+ result = await handleCommitBlueprint(args);
207
+ break;
208
+ case "add_column":
209
+ result = await handleAddColumn(args);
210
+ break;
211
+ case "verify_table_row":
212
+ result = await handleVerifyTableRow(args);
213
+ break;
214
+ case "get_rows":
215
+ result = await getRows(args?.tableId, args?.rowIds);
216
+ break;
217
+ case "create_on_demand_table":
218
+ case "create_one_off_table":
219
+ result = await createOnDemandTable(args);
220
+ break;
221
+ case "create_on_demand_campaign":
222
+ result = await createOnDemandCampaign(args);
223
+ break;
224
+ case "add_on_demand_leads":
225
+ case "add_one_off_leads":
226
+ result = await addOnDemandLeads(args);
227
+ break;
228
+ case "start_on_demand_campaign":
229
+ case "start_one_off_campaign":
230
+ result = await startOnDemandCampaign(args);
231
+ break;
232
+ case "pause_on_demand_campaign":
233
+ case "pause_one_off_campaign":
234
+ result = await pauseOnDemandCampaign(args);
235
+ break;
236
+ case "init_on_demand_sequence":
237
+ case "init_one_off_sequence":
238
+ result = await initOnDemandSequence(args);
239
+ break;
240
+ case "add_to_inmail_campaign":
241
+ result = await addToInmailCampaign(args);
242
+ break;
243
+ case "add_to_connection_campaign":
244
+ result = await addToConnectionCampaign(args);
245
+ break;
246
+ case "add_to_comment_campaign":
247
+ result = await addToCommentCampaign(args);
248
+ break;
249
+ case "start_direct_campaign":
250
+ result = await startDirectCampaign(args);
251
+ break;
252
+ case "pause_direct_campaign":
253
+ result = await pauseDirectCampaign(args);
254
+ break;
255
+ case "get_or_create_direct_campaign_table":
256
+ result = await getOrCreateDirectCampaignTable(args);
257
+ break;
258
+ case "get_engaged_posts":
259
+ result = await getEngagedPosts(args);
260
+ break;
261
+ case "list_senders":
262
+ result = await listSenders();
263
+ break;
264
+ case "get_sender":
265
+ result = await getSender(args);
266
+ break;
267
+ case "search_apollo":
268
+ result = await searchApollo(args);
269
+ break;
270
+ case "lookup_sales_nav_filter":
271
+ result = await lookupSalesNavFilter(args);
272
+ break;
273
+ case "search_sales_nav":
274
+ result = await searchSalesNav(args);
275
+ break;
276
+ case "search_prospeo":
277
+ result = await searchProspeo(args);
278
+ break;
279
+ case "load_csv_domains":
280
+ result = await loadCsvDomains(args);
281
+ break;
282
+ case "load_csv_linkedin_leads":
283
+ result = await loadCsvLinkedinLeads(args);
284
+ break;
285
+ case "save_domain_filters":
286
+ result = await saveDomainFilters(args);
287
+ break;
288
+ case "search_signals":
289
+ result = await searchSignals(args);
290
+ break;
291
+ case "import_leads":
292
+ result = await importLeads(args);
293
+ if (args?.campaignOfferId) {
294
+ markCampaignContextDirty(args.campaignOfferId, "import_leads");
295
+ }
296
+ break;
297
+ case "cancel_lead_import":
298
+ result = await cancelLeadImport(args);
299
+ if (args?.campaignOfferId) {
300
+ markCampaignContextDirty(args.campaignOfferId, "cancel_lead_import");
301
+ }
302
+ break;
303
+ case "confirm_lead_list":
304
+ result = await confirmLeadList(args);
305
+ if (args?.campaignOfferId) {
306
+ markCampaignContextDirty(args.campaignOfferId, "confirm_lead_list");
307
+ }
308
+ break;
309
+ case "wait_for_campaign_table_ready":
310
+ result = await waitForCampaignTableReady(args);
311
+ break;
312
+ case "wait_for_lead_list_ready":
313
+ result = await waitForLeadListReady(args);
314
+ break;
315
+ case "upsert_rubric":
316
+ result = await upsertRubric(args);
317
+ if (args?.campaignOfferId) {
318
+ markCampaignContextDirty(args.campaignOfferId, "upsert_rubric");
319
+ }
320
+ break;
321
+ case "draft_rubrics":
322
+ result = await draftRubrics(args);
323
+ break;
324
+ case "select_necessary_rubrics":
325
+ result = await selectNecessaryRubrics(args);
326
+ break;
327
+ case "save_rubrics":
328
+ result = await saveRubrics(args);
329
+ if (args?.campaignOfferId) {
330
+ markCampaignContextDirty(args.campaignOfferId, "save_rubrics");
331
+ }
332
+ break;
333
+ case "add_rubric_item":
334
+ result = await addRubricItem(args);
335
+ break;
336
+ case "update_rubric_item":
337
+ result = await updateRubricItem(args);
338
+ if (args?.campaignOfferId) {
339
+ markCampaignContextDirty(args.campaignOfferId, "update_rubric_item");
340
+ }
341
+ break;
342
+ case "delete_rubric_item":
343
+ result = await deleteRubricItem(args);
344
+ if (args?.campaignOfferId) {
345
+ markCampaignContextDirty(args.campaignOfferId, "delete_rubric_item");
346
+ }
347
+ break;
348
+ case "check_rubric":
349
+ result = await checkRubric(args);
350
+ break;
351
+ case "wait_for_rubric_results":
352
+ result = await waitForRubricResults(args);
353
+ break;
354
+ case "update_cell":
355
+ result = await updateCell(args?.cellId, args?.value);
356
+ break;
357
+ case "queue_cells":
358
+ result = await queueCells(args?.tableId, args?.cellIds);
359
+ break;
360
+ case "get_message_prompt":
361
+ result = await getMessagePrompt();
362
+ break;
363
+ case "get_subskill_prompt":
364
+ result = getSubskillPrompt(args?.subskillName, args?.offset, args?.limit);
365
+ break;
366
+ case "list_subskill_prompts":
367
+ result = listSubskillPrompts(args?.limit, args?.includePublic, args?.includeInternal);
368
+ break;
369
+ case "search_subskill_prompts":
370
+ result = searchSubskillPrompts(args?.query, args?.limit, args?.includePublic, args?.includeInternal);
371
+ break;
372
+ case "complete_sender_research":
373
+ result = completeSenderResearch(args);
374
+ break;
375
+ case "fetch_linkedin_posts":
376
+ result = await fetchLinkedInPosts(args?.linkedinUrl, args?.limit);
377
+ break;
378
+ case "fetch_linkedin_profile":
379
+ result = await fetchLinkedInProfile(args?.linkedinUrl);
380
+ break;
381
+ case "fetch_company":
382
+ result = await fetchCompany(args?.companyUrl);
383
+ break;
384
+ case "fetch_company_posts":
385
+ result = await fetchCompanyPosts(args?.companyUrl, args?.limit, args?.sortBy || "recent");
386
+ break;
387
+ case "get_user_posts":
388
+ result = await getUserPosts(args?.linkedin_url, args?.max_posts);
389
+ break;
390
+ case "get_linkedin_profile":
391
+ result = await getLinkedInProfile(args?.linkedin_url);
392
+ break;
393
+ case "fetch_post_engagers":
394
+ result = await fetchPostEngagers(args?.postUrl, args?.sources || "both", args?.limit);
395
+ break;
396
+ case "get_provider_prompt":
397
+ result = getProviderPrompt(args);
398
+ break;
399
+ case "select_promising_posts":
400
+ result = await selectPromisingPosts(args);
401
+ if (args?.campaignOfferId) {
402
+ markCampaignContextDirty(args.campaignOfferId, "select_promising_posts");
403
+ }
404
+ break;
405
+ case "set_headline_icp_criteria":
406
+ result = await setHeadlineICPCriteria(args);
407
+ if (args?.campaignOfferId) {
408
+ markCampaignContextDirty(args.campaignOfferId, "set_headline_icp_criteria");
409
+ }
410
+ break;
411
+ case "enrich_with_prospeo":
412
+ result = await enrichWithProspeo(args);
413
+ break;
414
+ case "bulk_enrich_with_prospeo":
415
+ result = await bulkEnrichWithProspeo(args);
416
+ break;
417
+ case "get_prospeo_credits":
418
+ result = await getProspeoCredits();
419
+ break;
420
+ default:
421
+ throw new Error(`Unknown tool: ${name}`);
422
+ }
423
+ return {
424
+ content: [
425
+ {
426
+ type: "text",
427
+ text: JSON.stringify(result),
428
+ },
429
+ ],
430
+ };
431
+ }
432
+ catch (error) {
433
+ const message = error instanceof Error ? error.message : "Unknown error";
434
+ return {
435
+ content: [
436
+ {
437
+ type: "text",
438
+ text: `Error: ${message}`,
439
+ },
440
+ ],
441
+ isError: true,
442
+ };
443
+ }
444
+ });
445
+ // List available prompts (skills)
446
+ server.setRequestHandler(ListPromptsRequestSchema, async () => ({
447
+ prompts: listSkills("public").map((skill) => ({
448
+ name: skill.name,
449
+ description: skill.description,
450
+ })),
451
+ }));
452
+ // Get prompt content
453
+ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
454
+ const { name } = request.params;
455
+ const skill = getSkillByName(name);
456
+ if (!skill) {
457
+ throw new Error(`Unknown prompt: ${name}`);
458
+ }
459
+ const content = stripFrontmatter(skill.content);
460
+ return {
461
+ description: skill.description,
462
+ messages: [
463
+ {
464
+ role: "user",
465
+ content: {
466
+ type: "text",
467
+ text: content,
468
+ },
469
+ },
470
+ ],
471
+ };
472
+ });
473
+ async function main() {
474
+ const startTime = Date.now();
475
+ console.error(`[sellable-mcp] pid=${process.pid} starting...`);
476
+ const transport = new StdioServerTransport();
477
+ // Exit cleanly when parent disconnects stdin (Claude Code closed/reconnected)
478
+ process.stdin.on("end", () => {
479
+ console.error(`[sellable-mcp] pid=${process.pid} stdin closed, exiting`);
480
+ process.exit(0);
481
+ });
482
+ process.stdin.on("error", () => {
483
+ process.exit(0);
484
+ });
485
+ // Handle termination signals
486
+ const shutdown = (signal) => {
487
+ console.error(`[sellable-mcp] pid=${process.pid} received ${signal}, exiting`);
488
+ process.exit(0);
489
+ };
490
+ process.on("SIGTERM", () => shutdown("SIGTERM"));
491
+ process.on("SIGINT", () => shutdown("SIGINT"));
492
+ await server.connect(transport);
493
+ const elapsed = Date.now() - startTime;
494
+ console.error(`[sellable-mcp] pid=${process.pid} ready in ${elapsed}ms (tools=${allTools.length})`);
495
+ }
496
+ main().catch((error) => {
497
+ console.error(`[sellable-mcp] pid=${process.pid} failed to start:`, error);
498
+ process.exit(1);
499
+ });
@@ -0,0 +1,11 @@
1
+ export type SkillVisibility = "public" | "internal";
2
+ export interface SkillDefinition {
3
+ name: string;
4
+ description: string;
5
+ content: string;
6
+ visibility: SkillVisibility;
7
+ }
8
+ export declare function loadSkills(force?: boolean): SkillDefinition[];
9
+ export declare function listSkills(visibility?: SkillVisibility): SkillDefinition[];
10
+ export declare function getSkillByName(name: string): SkillDefinition | undefined;
11
+ export declare function stripFrontmatter(content: string): string;
package/dist/skills.js ADDED
@@ -0,0 +1,97 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ function resolveSkillsDir() {
4
+ const candidates = [];
5
+ if (process.env.SELLABLE_SKILLS_DIR) {
6
+ candidates.push(path.resolve(process.env.SELLABLE_SKILLS_DIR));
7
+ }
8
+ if (process.argv[1]) {
9
+ // When running as CLI, argv[1] is typically ".../dist/index.js".
10
+ candidates.push(path.resolve(path.dirname(process.argv[1]), "../skills"));
11
+ }
12
+ // Local repo execution and test contexts.
13
+ candidates.push(path.resolve(process.cwd(), "mcp/sellable/skills"));
14
+ candidates.push(path.resolve(process.cwd(), "skills"));
15
+ for (const candidate of candidates) {
16
+ if (fs.existsSync(candidate)) {
17
+ return candidate;
18
+ }
19
+ }
20
+ // Keep a deterministic fallback for callers that want a path even if missing.
21
+ return candidates[0] ?? path.resolve(process.cwd(), "mcp/sellable/skills");
22
+ }
23
+ let _skillsDir = null;
24
+ function getSkillsDir() {
25
+ if (!_skillsDir)
26
+ _skillsDir = resolveSkillsDir();
27
+ return _skillsDir;
28
+ }
29
+ let cachedSkills = null;
30
+ function parseFrontmatter(content) {
31
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
32
+ if (!frontmatterMatch) {
33
+ return {
34
+ name: "",
35
+ description: "",
36
+ visibility: "public",
37
+ };
38
+ }
39
+ const frontmatter = frontmatterMatch[1];
40
+ const nameMatch = frontmatter.match(/^name:\s*(.+)$/m);
41
+ const descriptionMatch = frontmatter.match(/^description:\s*(.+)$/m);
42
+ const visibilityMatch = frontmatter.match(/^visibility:\s*(.+)$/m);
43
+ let visibility = "public";
44
+ if (visibilityMatch) {
45
+ const parsedVisibility = visibilityMatch[1].trim().toLowerCase();
46
+ if (parsedVisibility === "internal") {
47
+ visibility = "internal";
48
+ }
49
+ }
50
+ return {
51
+ name: nameMatch ? nameMatch[1].trim() : "",
52
+ description: descriptionMatch ? descriptionMatch[1].trim() : "",
53
+ visibility,
54
+ };
55
+ }
56
+ export function loadSkills(force = false) {
57
+ if (!force && cachedSkills) {
58
+ return cachedSkills;
59
+ }
60
+ const skills = [];
61
+ const dir_ = getSkillsDir();
62
+ if (!fs.existsSync(dir_)) {
63
+ cachedSkills = skills;
64
+ return skills;
65
+ }
66
+ const dirs = fs.readdirSync(dir_, { withFileTypes: true });
67
+ for (const dir of dirs) {
68
+ if (!dir.isDirectory())
69
+ continue;
70
+ const skillPath = path.join(dir_, dir.name, "SKILL.md");
71
+ if (!fs.existsSync(skillPath))
72
+ continue;
73
+ const content = fs.readFileSync(skillPath, "utf-8");
74
+ const frontmatter = parseFrontmatter(content);
75
+ skills.push({
76
+ name: frontmatter.name || dir.name,
77
+ description: frontmatter.description || "",
78
+ content,
79
+ visibility: frontmatter.visibility,
80
+ });
81
+ }
82
+ cachedSkills = skills;
83
+ return skills;
84
+ }
85
+ export function listSkills(visibility) {
86
+ const skills = loadSkills();
87
+ if (!visibility)
88
+ return skills;
89
+ return skills.filter((skill) => skill.visibility === visibility);
90
+ }
91
+ export function getSkillByName(name) {
92
+ const skills = loadSkills();
93
+ return skills.find((skill) => skill.name === name);
94
+ }
95
+ export function stripFrontmatter(content) {
96
+ return content.replace(/^---\n[\s\S]*?\n---\n*/, "");
97
+ }
@@ -0,0 +1,30 @@
1
+ export type AuthStatus = {
2
+ ok: boolean;
3
+ configPath: string;
4
+ activeEnvName: string | null;
5
+ apiUrl: string | null;
6
+ activeWorkspaceId: string | null;
7
+ activeWorkspaceName: string | null;
8
+ tokenPrefix: string | null;
9
+ workspacesCount: number | null;
10
+ checkedAt: string;
11
+ /** Short message the LLM MUST show the user after auth succeeds. */
12
+ _userNotice: string | null;
13
+ error: null | {
14
+ type: "config" | "auth" | "workspace" | "api";
15
+ status?: number;
16
+ message: string;
17
+ guidance: string;
18
+ };
19
+ };
20
+ export declare const authToolDefinitions: {
21
+ name: string;
22
+ description: string;
23
+ inputSchema: {
24
+ type: string;
25
+ properties: {};
26
+ required: never[];
27
+ additionalProperties: boolean;
28
+ };
29
+ }[];
30
+ export declare function getAuthStatus(): Promise<AuthStatus>;