@sellable/mcp 0.1.328 → 0.1.329

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/server.js CHANGED
@@ -6,6 +6,7 @@ import { getAuthStatus } from "./tools/auth.js";
6
6
  import { handleAddColumn, handleCommitBlueprint, } from "./tools/blueprint-commit.js";
7
7
  import { bootstrapCreateCampaign } from "./tools/bootstrap.js";
8
8
  import { prepareCampaignAbTest } from "./tools/campaign-ab-test.js";
9
+ import { fillCampaignHorizon } from "./tools/campaign-horizon-fill.js";
9
10
  import { cancelPrepareCampaignMessages, getPrepareCampaignMessagesStatus, startPrepareCampaignMessages, } from "./tools/campaign-message-preparation.js";
10
11
  import { getCampaignTableSchema, queueCampaignCells, reviseMessageTemplateAndRerun, selectCampaignCells, waitForCampaignProcessing, } from "./tools/campaign-processing.js";
11
12
  import { createCampaign, duplicateCampaign, getCampaign, getCampaignMessagesPreview, getCampaigns, pauseCampaign, startCampaign, updateCampaign, updateCampaignBrief, } from "./tools/campaigns.js";
@@ -178,6 +179,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
178
179
  case "get_campaign_messages_preview":
179
180
  result = await getCampaignMessagesPreview(args);
180
181
  break;
182
+ case "fill_campaign_horizon":
183
+ result = await fillCampaignHorizon(args);
184
+ if (args?.campaignId) {
185
+ markCampaignContextDirty(args.campaignId, "fill_campaign_horizon");
186
+ }
187
+ break;
181
188
  case "start_campaign_message_preparation":
182
189
  case "start_prepare_campaign_messages":
183
190
  result = await startPrepareCampaignMessages(args);
@@ -0,0 +1,93 @@
1
+ type FillCampaignHorizonInput = {
2
+ action: "audit" | "apply";
3
+ campaignId: string;
4
+ tableId?: string;
5
+ stateRevision?: string;
6
+ excludedPostIds?: string[];
7
+ excludedPostUrls?: string[];
8
+ excludedAuthorProfileUrls?: string[];
9
+ excludedAuthorNames?: string[];
10
+ targetPreparedMessages?: number;
11
+ maxRowsToCheck?: number;
12
+ batchSize?: number;
13
+ };
14
+ export declare const campaignHorizonFillToolDefinitions: {
15
+ name: string;
16
+ description: string;
17
+ inputSchema: {
18
+ type: string;
19
+ properties: {
20
+ action: {
21
+ type: string;
22
+ enum: string[];
23
+ description: string;
24
+ };
25
+ campaignId: {
26
+ type: string;
27
+ description: string;
28
+ };
29
+ tableId: {
30
+ type: string;
31
+ description: string;
32
+ };
33
+ stateRevision: {
34
+ type: string;
35
+ description: string;
36
+ };
37
+ excludedPostIds: {
38
+ type: string;
39
+ items: {
40
+ type: string;
41
+ };
42
+ maxItems: number;
43
+ description: string;
44
+ };
45
+ excludedPostUrls: {
46
+ type: string;
47
+ items: {
48
+ type: string;
49
+ };
50
+ maxItems: number;
51
+ description: string;
52
+ };
53
+ excludedAuthorProfileUrls: {
54
+ type: string;
55
+ items: {
56
+ type: string;
57
+ };
58
+ maxItems: number;
59
+ description: string;
60
+ };
61
+ excludedAuthorNames: {
62
+ type: string;
63
+ items: {
64
+ type: string;
65
+ };
66
+ maxItems: number;
67
+ description: string;
68
+ };
69
+ targetPreparedMessages: {
70
+ type: string;
71
+ minimum: number;
72
+ maximum: number;
73
+ description: string;
74
+ };
75
+ maxRowsToCheck: {
76
+ type: string;
77
+ minimum: number;
78
+ maximum: number;
79
+ description: string;
80
+ };
81
+ batchSize: {
82
+ type: string;
83
+ minimum: number;
84
+ maximum: number;
85
+ description: string;
86
+ };
87
+ };
88
+ required: string[];
89
+ additionalProperties: boolean;
90
+ };
91
+ }[];
92
+ export declare function fillCampaignHorizon(input: FillCampaignHorizonInput): Promise<unknown>;
93
+ export {};
@@ -0,0 +1,92 @@
1
+ import { getApi } from "../api.js";
2
+ async function postHorizonFill(body) {
3
+ const api = getApi();
4
+ return api.post("/api/v3/mcp/campaign-horizon-fill", body);
5
+ }
6
+ export const campaignHorizonFillToolDefinitions = [
7
+ {
8
+ name: "fill_campaign_horizon",
9
+ description: "Audit or apply a bounded CampaignOffer horizon fill from Signal Discovery/source lead-list rows. Use audit first to get stateRevision, then apply with that stateRevision. Apply imports at most 300 eligible non-excluded source rows, starts bounded message preparation in approval mode, skips rows from excluded posts/authors, and does not start or launch the campaign.",
10
+ inputSchema: {
11
+ type: "object",
12
+ properties: {
13
+ action: {
14
+ type: "string",
15
+ enum: ["audit", "apply"],
16
+ description: 'Use "audit" to inspect counts/receipt without writes. Use "apply" with the audit stateRevision to import/prep.',
17
+ },
18
+ campaignId: {
19
+ type: "string",
20
+ description: "CampaignOffer.id for the campaign to fill.",
21
+ },
22
+ tableId: {
23
+ type: "string",
24
+ description: "Optional workflow table id. Must match the campaign workflowTableId when provided.",
25
+ },
26
+ stateRevision: {
27
+ type: "string",
28
+ description: "Required for apply. Copy from the immediately preceding audit receipt.",
29
+ },
30
+ excludedPostIds: {
31
+ type: "array",
32
+ items: { type: "string" },
33
+ maxItems: 100,
34
+ description: "Exact SignalSearchPost ids to exclude from import/preparation.",
35
+ },
36
+ excludedPostUrls: {
37
+ type: "array",
38
+ items: { type: "string" },
39
+ maxItems: 100,
40
+ description: "Exact LinkedIn post URLs to exclude from import/preparation.",
41
+ },
42
+ excludedAuthorProfileUrls: {
43
+ type: "array",
44
+ items: { type: "string" },
45
+ maxItems: 100,
46
+ description: "Exact LinkedIn author profile URLs whose source rows should be excluded.",
47
+ },
48
+ excludedAuthorNames: {
49
+ type: "array",
50
+ items: { type: "string" },
51
+ maxItems: 25,
52
+ description: "Exact author names to exclude only when they resolve unambiguously inside campaign Signal Discovery posts.",
53
+ },
54
+ targetPreparedMessages: {
55
+ type: "number",
56
+ minimum: 1,
57
+ maximum: 300,
58
+ description: "Prepared/approved message target for the first pass. Backend caps this at 300.",
59
+ },
60
+ maxRowsToCheck: {
61
+ type: "number",
62
+ minimum: 1,
63
+ maximum: 300,
64
+ description: "Hard first-pass row cap. Backend caps import and prep at 300 rows.",
65
+ },
66
+ batchSize: {
67
+ type: "number",
68
+ minimum: 1,
69
+ maximum: 100,
70
+ description: "Preparation batch size. Backend caps newly checked rows at 100 per batch.",
71
+ },
72
+ },
73
+ required: ["action", "campaignId"],
74
+ additionalProperties: false,
75
+ },
76
+ },
77
+ ];
78
+ export function fillCampaignHorizon(input) {
79
+ return postHorizonFill({
80
+ action: input.action,
81
+ campaignId: input.campaignId,
82
+ tableId: input.tableId,
83
+ stateRevision: input.stateRevision,
84
+ excludedPostIds: input.excludedPostIds,
85
+ excludedPostUrls: input.excludedPostUrls,
86
+ excludedAuthorProfileUrls: input.excludedAuthorProfileUrls,
87
+ excludedAuthorNames: input.excludedAuthorNames,
88
+ targetPreparedMessages: input.targetPreparedMessages,
89
+ maxRowsToCheck: input.maxRowsToCheck,
90
+ batchSize: input.batchSize,
91
+ });
92
+ }
@@ -474,6 +474,83 @@ export declare const allTools: ({
474
474
  required: string[];
475
475
  additionalProperties: boolean;
476
476
  };
477
+ } | {
478
+ name: string;
479
+ description: string;
480
+ inputSchema: {
481
+ type: string;
482
+ properties: {
483
+ action: {
484
+ type: string;
485
+ enum: string[];
486
+ description: string;
487
+ };
488
+ campaignId: {
489
+ type: string;
490
+ description: string;
491
+ };
492
+ tableId: {
493
+ type: string;
494
+ description: string;
495
+ };
496
+ stateRevision: {
497
+ type: string;
498
+ description: string;
499
+ };
500
+ excludedPostIds: {
501
+ type: string;
502
+ items: {
503
+ type: string;
504
+ };
505
+ maxItems: number;
506
+ description: string;
507
+ };
508
+ excludedPostUrls: {
509
+ type: string;
510
+ items: {
511
+ type: string;
512
+ };
513
+ maxItems: number;
514
+ description: string;
515
+ };
516
+ excludedAuthorProfileUrls: {
517
+ type: string;
518
+ items: {
519
+ type: string;
520
+ };
521
+ maxItems: number;
522
+ description: string;
523
+ };
524
+ excludedAuthorNames: {
525
+ type: string;
526
+ items: {
527
+ type: string;
528
+ };
529
+ maxItems: number;
530
+ description: string;
531
+ };
532
+ targetPreparedMessages: {
533
+ type: string;
534
+ minimum: number;
535
+ maximum: number;
536
+ description: string;
537
+ };
538
+ maxRowsToCheck: {
539
+ type: string;
540
+ minimum: number;
541
+ maximum: number;
542
+ description: string;
543
+ };
544
+ batchSize: {
545
+ type: string;
546
+ minimum: number;
547
+ maximum: number;
548
+ description: string;
549
+ };
550
+ };
551
+ required: string[];
552
+ additionalProperties: boolean;
553
+ };
477
554
  } | {
478
555
  name: string;
479
556
  description: string;
@@ -2,6 +2,7 @@ import { authToolDefinitions } from "./auth.js";
2
2
  import { blueprintCommitToolDefinitions } from "./blueprint-commit.js";
3
3
  import { bootstrapToolDefinitions } from "./bootstrap.js";
4
4
  import { campaignAbTestToolDefinitions } from "./campaign-ab-test.js";
5
+ import { campaignHorizonFillToolDefinitions } from "./campaign-horizon-fill.js";
5
6
  import { campaignMessagePreparationToolDefinitions } from "./campaign-message-preparation.js";
6
7
  import { campaignProcessingToolDefinitions } from "./campaign-processing.js";
7
8
  import { campaignToolDefinitions } from "./campaigns.js";
@@ -42,6 +43,7 @@ import { workspaceToolDefinitions } from "./workspaces.js";
42
43
  export const allTools = [
43
44
  ...campaignToolDefinitions,
44
45
  ...campaignAbTestToolDefinitions,
46
+ ...campaignHorizonFillToolDefinitions,
45
47
  ...campaignMessagePreparationToolDefinitions,
46
48
  ...campaignProcessingToolDefinitions,
47
49
  ...authToolDefinitions,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.328",
3
+ "version": "0.1.329",
4
4
  "type": "module",
5
5
  "description": "Sellable MCP server for Claude Code and Codex campaign workflows",
6
6
  "main": "dist/index.js",
@@ -46,6 +46,7 @@ allowed-tools:
46
46
  - mcp__sellable__select_campaign_cells
47
47
  - mcp__sellable__queue_campaign_cells
48
48
  - mcp__sellable__wait_for_campaign_processing
49
+ - mcp__sellable__fill_campaign_horizon
49
50
  - mcp__sellable__start_campaign_message_preparation
50
51
  - mcp__sellable__get_campaign_message_preparation_status
51
52
  - mcp__sellable__cancel_campaign_message_preparation
@@ -107,6 +108,13 @@ the template is approved.
107
108
  The default path stays the existing first campaign-table execution slice:
108
109
  review the normal `reviewBatchLimit:15`, approve reviewed draft rows, then move
109
110
  to Settings/sequence/final greenlight. Only call
111
+ `fill_campaign_horizon` for explicit source-cleanup horizon-fill requests, such
112
+ as "fill sends from Signal Discovery but not John Cutler posts." Run
113
+ `fill_campaign_horizon({ action:"audit", ... })` first, then apply with the
114
+ returned `stateRevision`. It imports/prepares at most 300 eligible non-excluded
115
+ source rows in the first pass, caps prep batches at 100, skips existing rows
116
+ from excluded post/author sources, and does not launch the campaign. If the
117
+ user only asks for generic extra sends with no source cleanup, use
110
118
  `start_campaign_message_preparation` when the user explicitly asks for more
111
119
  prepared messages, a send count, or language like "fill up/load sends for these
112
120
  senders." Treat those requests as capacity-fill preparation: calculate the