@sellable/mcp 0.1.544 → 0.1.546

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.
@@ -184,6 +184,7 @@ export type ConfirmLeadListInput = {
184
184
  reviewBatchLimit?: number;
185
185
  includeRawImportResult?: boolean;
186
186
  allowPartialSourceList?: boolean;
187
+ allowDifferentSourceLeadList?: boolean;
187
188
  sourceRowIds?: string[];
188
189
  sourceRowLimit?: number;
189
190
  /**
@@ -305,6 +306,7 @@ export declare const leadToolDefinitions: ({
305
306
  sourceRowIds?: undefined;
306
307
  sourceRowLimit?: undefined;
307
308
  allowPartialSourceList?: undefined;
309
+ allowDifferentSourceLeadList?: undefined;
308
310
  includeRawImportResult?: undefined;
309
311
  selections?: undefined;
310
312
  selectionMode?: undefined;
@@ -502,6 +504,7 @@ export declare const leadToolDefinitions: ({
502
504
  sourceRowIds?: undefined;
503
505
  sourceRowLimit?: undefined;
504
506
  allowPartialSourceList?: undefined;
507
+ allowDifferentSourceLeadList?: undefined;
505
508
  includeRawImportResult?: undefined;
506
509
  selections?: undefined;
507
510
  selectionMode?: undefined;
@@ -598,6 +601,7 @@ export declare const leadToolDefinitions: ({
598
601
  sourceRowIds?: undefined;
599
602
  sourceRowLimit?: undefined;
600
603
  allowPartialSourceList?: undefined;
604
+ allowDifferentSourceLeadList?: undefined;
601
605
  includeRawImportResult?: undefined;
602
606
  selections?: undefined;
603
607
  selectionMode?: undefined;
@@ -766,6 +770,7 @@ export declare const leadToolDefinitions: ({
766
770
  sourceRowIds?: undefined;
767
771
  sourceRowLimit?: undefined;
768
772
  allowPartialSourceList?: undefined;
773
+ allowDifferentSourceLeadList?: undefined;
769
774
  includeRawImportResult?: undefined;
770
775
  selections?: undefined;
771
776
  selectionMode?: undefined;
@@ -876,6 +881,7 @@ export declare const leadToolDefinitions: ({
876
881
  sourceRowIds?: undefined;
877
882
  sourceRowLimit?: undefined;
878
883
  allowPartialSourceList?: undefined;
884
+ allowDifferentSourceLeadList?: undefined;
879
885
  includeRawImportResult?: undefined;
880
886
  selections?: undefined;
881
887
  selectionMode?: undefined;
@@ -995,6 +1001,7 @@ export declare const leadToolDefinitions: ({
995
1001
  sourceRowIds?: undefined;
996
1002
  sourceRowLimit?: undefined;
997
1003
  allowPartialSourceList?: undefined;
1004
+ allowDifferentSourceLeadList?: undefined;
998
1005
  includeRawImportResult?: undefined;
999
1006
  selections?: undefined;
1000
1007
  selectionMode?: undefined;
@@ -1103,6 +1110,7 @@ export declare const leadToolDefinitions: ({
1103
1110
  sourceRowIds?: undefined;
1104
1111
  sourceRowLimit?: undefined;
1105
1112
  allowPartialSourceList?: undefined;
1113
+ allowDifferentSourceLeadList?: undefined;
1106
1114
  includeRawImportResult?: undefined;
1107
1115
  selections?: undefined;
1108
1116
  selectionMode?: undefined;
@@ -1216,6 +1224,7 @@ export declare const leadToolDefinitions: ({
1216
1224
  sourceRowIds?: undefined;
1217
1225
  sourceRowLimit?: undefined;
1218
1226
  allowPartialSourceList?: undefined;
1227
+ allowDifferentSourceLeadList?: undefined;
1219
1228
  includeRawImportResult?: undefined;
1220
1229
  selections?: undefined;
1221
1230
  selectionMode?: undefined;
@@ -1317,6 +1326,7 @@ export declare const leadToolDefinitions: ({
1317
1326
  sourceRowIds?: undefined;
1318
1327
  sourceRowLimit?: undefined;
1319
1328
  allowPartialSourceList?: undefined;
1329
+ allowDifferentSourceLeadList?: undefined;
1320
1330
  includeRawImportResult?: undefined;
1321
1331
  selections?: undefined;
1322
1332
  selectionMode?: undefined;
@@ -2210,6 +2220,7 @@ export declare const leadToolDefinitions: ({
2210
2220
  sourceRowIds?: undefined;
2211
2221
  sourceRowLimit?: undefined;
2212
2222
  allowPartialSourceList?: undefined;
2223
+ allowDifferentSourceLeadList?: undefined;
2213
2224
  includeRawImportResult?: undefined;
2214
2225
  selections?: undefined;
2215
2226
  selectionMode?: undefined;
@@ -2320,6 +2331,7 @@ export declare const leadToolDefinitions: ({
2320
2331
  sourceRowIds?: undefined;
2321
2332
  sourceRowLimit?: undefined;
2322
2333
  allowPartialSourceList?: undefined;
2334
+ allowDifferentSourceLeadList?: undefined;
2323
2335
  includeRawImportResult?: undefined;
2324
2336
  selections?: undefined;
2325
2337
  selectionMode?: undefined;
@@ -3371,6 +3383,7 @@ export declare const leadToolDefinitions: ({
3371
3383
  sourceRowIds?: undefined;
3372
3384
  sourceRowLimit?: undefined;
3373
3385
  allowPartialSourceList?: undefined;
3386
+ allowDifferentSourceLeadList?: undefined;
3374
3387
  includeRawImportResult?: undefined;
3375
3388
  selections?: undefined;
3376
3389
  selectionMode?: undefined;
@@ -3528,6 +3541,7 @@ export declare const leadToolDefinitions: ({
3528
3541
  sourceRowIds?: undefined;
3529
3542
  sourceRowLimit?: undefined;
3530
3543
  allowPartialSourceList?: undefined;
3544
+ allowDifferentSourceLeadList?: undefined;
3531
3545
  includeRawImportResult?: undefined;
3532
3546
  selections?: undefined;
3533
3547
  selectionMode?: undefined;
@@ -3675,6 +3689,7 @@ export declare const leadToolDefinitions: ({
3675
3689
  sourceRowIds?: undefined;
3676
3690
  sourceRowLimit?: undefined;
3677
3691
  allowPartialSourceList?: undefined;
3692
+ allowDifferentSourceLeadList?: undefined;
3678
3693
  includeRawImportResult?: undefined;
3679
3694
  selections?: undefined;
3680
3695
  selectionMode?: undefined;
@@ -3777,6 +3792,7 @@ export declare const leadToolDefinitions: ({
3777
3792
  sourceRowIds?: undefined;
3778
3793
  sourceRowLimit?: undefined;
3779
3794
  allowPartialSourceList?: undefined;
3795
+ allowDifferentSourceLeadList?: undefined;
3780
3796
  includeRawImportResult?: undefined;
3781
3797
  selections?: undefined;
3782
3798
  selectionMode?: undefined;
@@ -3841,6 +3857,10 @@ export declare const leadToolDefinitions: ({
3841
3857
  type: string;
3842
3858
  description: string;
3843
3859
  };
3860
+ allowDifferentSourceLeadList: {
3861
+ type: string;
3862
+ description: string;
3863
+ };
3844
3864
  confirmed: {
3845
3865
  type: string;
3846
3866
  description: string;
@@ -4050,6 +4070,7 @@ export declare const leadToolDefinitions: ({
4050
4070
  sourceRowIds?: undefined;
4051
4071
  sourceRowLimit?: undefined;
4052
4072
  allowPartialSourceList?: undefined;
4073
+ allowDifferentSourceLeadList?: undefined;
4053
4074
  includeRawImportResult?: undefined;
4054
4075
  };
4055
4076
  required: string[];
@@ -4150,6 +4171,7 @@ export declare const leadToolDefinitions: ({
4150
4171
  sourceRowIds?: undefined;
4151
4172
  sourceRowLimit?: undefined;
4152
4173
  allowPartialSourceList?: undefined;
4174
+ allowDifferentSourceLeadList?: undefined;
4153
4175
  includeRawImportResult?: undefined;
4154
4176
  selections?: undefined;
4155
4177
  selectionMode?: undefined;
@@ -2239,6 +2239,10 @@ export const leadToolDefinitions = [
2239
2239
  type: "boolean",
2240
2240
  description: "Explicit override for user-approved early continuation. Default false. When true, confirm_lead_list may copy the currently materialized rows from a still-running source import; use only after the user explicitly asks to keep going with the partial list.",
2241
2241
  },
2242
+ allowDifferentSourceLeadList: {
2243
+ type: "boolean",
2244
+ description: "Explicit override for bounded recovery/refill copies from a source list different from the campaign.selectedLeadListId. Use only when the operator intentionally approved that exact alternate source list.",
2245
+ },
2242
2246
  confirmed: {
2243
2247
  type: "boolean",
2244
2248
  description: "Set true after user approval when interaction mode requires confirmation for confirm/import.",
@@ -4202,7 +4206,7 @@ export async function confirmLeadList(input) {
4202
4206
  const api = getApi();
4203
4207
  const workspaceId = normalizeExplicitWorkspaceId(input.workspaceId);
4204
4208
  const requestOptions = workspaceRequestOptions(workspaceId);
4205
- const { campaignOfferId, currentStep, confirmed, sourceLeadListId, campaignName, keepInSync, jobId, reviewBatchLimit, includeRawImportResult, allowPartialSourceList, targetLeadCount, sourceRowIds, sourceRowLimit, } = input;
4209
+ const { campaignOfferId, currentStep, confirmed, sourceLeadListId, campaignName, keepInSync, jobId, reviewBatchLimit, includeRawImportResult, allowPartialSourceList, allowDifferentSourceLeadList, targetLeadCount, sourceRowIds, sourceRowLimit, } = input;
4206
4210
  assertInteractionApproval({
4207
4211
  campaignId: campaignOfferId,
4208
4212
  action: "confirm-lead-list",
@@ -4414,6 +4418,7 @@ export async function confirmLeadList(input) {
4414
4418
  currentStep: null,
4415
4419
  sourceRowIds,
4416
4420
  sourceRowLimit,
4421
+ allowDifferentSourceLeadList,
4417
4422
  ...(workspaceId ? { workspaceId } : {}),
4418
4423
  };
4419
4424
  const importResult = await (requestOptions
@@ -3234,6 +3234,7 @@ export declare const allTools: ({
3234
3234
  sourceRowIds?: undefined;
3235
3235
  sourceRowLimit?: undefined;
3236
3236
  allowPartialSourceList?: undefined;
3237
+ allowDifferentSourceLeadList?: undefined;
3237
3238
  includeRawImportResult?: undefined;
3238
3239
  selections?: undefined;
3239
3240
  selectionMode?: undefined;
@@ -3431,6 +3432,7 @@ export declare const allTools: ({
3431
3432
  sourceRowIds?: undefined;
3432
3433
  sourceRowLimit?: undefined;
3433
3434
  allowPartialSourceList?: undefined;
3435
+ allowDifferentSourceLeadList?: undefined;
3434
3436
  includeRawImportResult?: undefined;
3435
3437
  selections?: undefined;
3436
3438
  selectionMode?: undefined;
@@ -3527,6 +3529,7 @@ export declare const allTools: ({
3527
3529
  sourceRowIds?: undefined;
3528
3530
  sourceRowLimit?: undefined;
3529
3531
  allowPartialSourceList?: undefined;
3532
+ allowDifferentSourceLeadList?: undefined;
3530
3533
  includeRawImportResult?: undefined;
3531
3534
  selections?: undefined;
3532
3535
  selectionMode?: undefined;
@@ -3695,6 +3698,7 @@ export declare const allTools: ({
3695
3698
  sourceRowIds?: undefined;
3696
3699
  sourceRowLimit?: undefined;
3697
3700
  allowPartialSourceList?: undefined;
3701
+ allowDifferentSourceLeadList?: undefined;
3698
3702
  includeRawImportResult?: undefined;
3699
3703
  selections?: undefined;
3700
3704
  selectionMode?: undefined;
@@ -3805,6 +3809,7 @@ export declare const allTools: ({
3805
3809
  sourceRowIds?: undefined;
3806
3810
  sourceRowLimit?: undefined;
3807
3811
  allowPartialSourceList?: undefined;
3812
+ allowDifferentSourceLeadList?: undefined;
3808
3813
  includeRawImportResult?: undefined;
3809
3814
  selections?: undefined;
3810
3815
  selectionMode?: undefined;
@@ -3924,6 +3929,7 @@ export declare const allTools: ({
3924
3929
  sourceRowIds?: undefined;
3925
3930
  sourceRowLimit?: undefined;
3926
3931
  allowPartialSourceList?: undefined;
3932
+ allowDifferentSourceLeadList?: undefined;
3927
3933
  includeRawImportResult?: undefined;
3928
3934
  selections?: undefined;
3929
3935
  selectionMode?: undefined;
@@ -4032,6 +4038,7 @@ export declare const allTools: ({
4032
4038
  sourceRowIds?: undefined;
4033
4039
  sourceRowLimit?: undefined;
4034
4040
  allowPartialSourceList?: undefined;
4041
+ allowDifferentSourceLeadList?: undefined;
4035
4042
  includeRawImportResult?: undefined;
4036
4043
  selections?: undefined;
4037
4044
  selectionMode?: undefined;
@@ -4145,6 +4152,7 @@ export declare const allTools: ({
4145
4152
  sourceRowIds?: undefined;
4146
4153
  sourceRowLimit?: undefined;
4147
4154
  allowPartialSourceList?: undefined;
4155
+ allowDifferentSourceLeadList?: undefined;
4148
4156
  includeRawImportResult?: undefined;
4149
4157
  selections?: undefined;
4150
4158
  selectionMode?: undefined;
@@ -4246,6 +4254,7 @@ export declare const allTools: ({
4246
4254
  sourceRowIds?: undefined;
4247
4255
  sourceRowLimit?: undefined;
4248
4256
  allowPartialSourceList?: undefined;
4257
+ allowDifferentSourceLeadList?: undefined;
4249
4258
  includeRawImportResult?: undefined;
4250
4259
  selections?: undefined;
4251
4260
  selectionMode?: undefined;
@@ -5139,6 +5148,7 @@ export declare const allTools: ({
5139
5148
  sourceRowIds?: undefined;
5140
5149
  sourceRowLimit?: undefined;
5141
5150
  allowPartialSourceList?: undefined;
5151
+ allowDifferentSourceLeadList?: undefined;
5142
5152
  includeRawImportResult?: undefined;
5143
5153
  selections?: undefined;
5144
5154
  selectionMode?: undefined;
@@ -5249,6 +5259,7 @@ export declare const allTools: ({
5249
5259
  sourceRowIds?: undefined;
5250
5260
  sourceRowLimit?: undefined;
5251
5261
  allowPartialSourceList?: undefined;
5262
+ allowDifferentSourceLeadList?: undefined;
5252
5263
  includeRawImportResult?: undefined;
5253
5264
  selections?: undefined;
5254
5265
  selectionMode?: undefined;
@@ -6300,6 +6311,7 @@ export declare const allTools: ({
6300
6311
  sourceRowIds?: undefined;
6301
6312
  sourceRowLimit?: undefined;
6302
6313
  allowPartialSourceList?: undefined;
6314
+ allowDifferentSourceLeadList?: undefined;
6303
6315
  includeRawImportResult?: undefined;
6304
6316
  selections?: undefined;
6305
6317
  selectionMode?: undefined;
@@ -6457,6 +6469,7 @@ export declare const allTools: ({
6457
6469
  sourceRowIds?: undefined;
6458
6470
  sourceRowLimit?: undefined;
6459
6471
  allowPartialSourceList?: undefined;
6472
+ allowDifferentSourceLeadList?: undefined;
6460
6473
  includeRawImportResult?: undefined;
6461
6474
  selections?: undefined;
6462
6475
  selectionMode?: undefined;
@@ -6604,6 +6617,7 @@ export declare const allTools: ({
6604
6617
  sourceRowIds?: undefined;
6605
6618
  sourceRowLimit?: undefined;
6606
6619
  allowPartialSourceList?: undefined;
6620
+ allowDifferentSourceLeadList?: undefined;
6607
6621
  includeRawImportResult?: undefined;
6608
6622
  selections?: undefined;
6609
6623
  selectionMode?: undefined;
@@ -6706,6 +6720,7 @@ export declare const allTools: ({
6706
6720
  sourceRowIds?: undefined;
6707
6721
  sourceRowLimit?: undefined;
6708
6722
  allowPartialSourceList?: undefined;
6723
+ allowDifferentSourceLeadList?: undefined;
6709
6724
  includeRawImportResult?: undefined;
6710
6725
  selections?: undefined;
6711
6726
  selectionMode?: undefined;
@@ -6770,6 +6785,10 @@ export declare const allTools: ({
6770
6785
  type: string;
6771
6786
  description: string;
6772
6787
  };
6788
+ allowDifferentSourceLeadList: {
6789
+ type: string;
6790
+ description: string;
6791
+ };
6773
6792
  confirmed: {
6774
6793
  type: string;
6775
6794
  description: string;
@@ -6979,6 +6998,7 @@ export declare const allTools: ({
6979
6998
  sourceRowIds?: undefined;
6980
6999
  sourceRowLimit?: undefined;
6981
7000
  allowPartialSourceList?: undefined;
7001
+ allowDifferentSourceLeadList?: undefined;
6982
7002
  includeRawImportResult?: undefined;
6983
7003
  };
6984
7004
  required: string[];
@@ -7079,6 +7099,7 @@ export declare const allTools: ({
7079
7099
  sourceRowIds?: undefined;
7080
7100
  sourceRowLimit?: undefined;
7081
7101
  allowPartialSourceList?: undefined;
7102
+ allowDifferentSourceLeadList?: undefined;
7082
7103
  includeRawImportResult?: undefined;
7083
7104
  selections?: undefined;
7084
7105
  selectionMode?: undefined;
@@ -7998,6 +8019,7 @@ export declare const allTools: ({
7998
8019
  };
7999
8020
  tableId?: undefined;
8000
8021
  template?: undefined;
8022
+ templateRef?: undefined;
8001
8023
  confirmed?: undefined;
8002
8024
  campaignId?: undefined;
8003
8025
  currentStep?: undefined;
@@ -8018,6 +8040,11 @@ export declare const allTools: ({
8018
8040
  type: string;
8019
8041
  description: string;
8020
8042
  };
8043
+ templateRef: {
8044
+ type: string;
8045
+ enum: string[];
8046
+ description: string;
8047
+ };
8021
8048
  confirmed: {
8022
8049
  type: string;
8023
8050
  description: string;
@@ -8057,6 +8084,7 @@ export declare const allTools: ({
8057
8084
  sequenceActions?: undefined;
8058
8085
  tableId?: undefined;
8059
8086
  template?: undefined;
8087
+ templateRef?: undefined;
8060
8088
  };
8061
8089
  required: string[];
8062
8090
  };
@@ -19,7 +19,8 @@ export type CreateWorkflowTableResponse = {
19
19
  };
20
20
  export type AttachSequenceInput = {
21
21
  tableId: string;
22
- template: Record<string, unknown>;
22
+ template?: Record<string, unknown>;
23
+ templateRef?: "connection_only";
23
24
  confirmed?: boolean;
24
25
  };
25
26
  export type AttachSequenceResponse = {
@@ -74,6 +75,7 @@ export declare const sequencerToolDefinitions: ({
74
75
  };
75
76
  tableId?: undefined;
76
77
  template?: undefined;
78
+ templateRef?: undefined;
77
79
  confirmed?: undefined;
78
80
  campaignId?: undefined;
79
81
  currentStep?: undefined;
@@ -94,6 +96,11 @@ export declare const sequencerToolDefinitions: ({
94
96
  type: string;
95
97
  description: string;
96
98
  };
99
+ templateRef: {
100
+ type: string;
101
+ enum: string[];
102
+ description: string;
103
+ };
97
104
  confirmed: {
98
105
  type: string;
99
106
  description: string;
@@ -133,6 +140,7 @@ export declare const sequencerToolDefinitions: ({
133
140
  sequenceActions?: undefined;
134
141
  tableId?: undefined;
135
142
  template?: undefined;
143
+ templateRef?: undefined;
136
144
  };
137
145
  required: string[];
138
146
  };
@@ -53,12 +53,17 @@ export const sequencerToolDefinitions = [
53
53
  type: "object",
54
54
  description: "Sequence template object with version, entryNodeId, nodes, and branches",
55
55
  },
56
+ templateRef: {
57
+ type: "string",
58
+ enum: ["connection_only"],
59
+ description: "Optional backend-owned known template reference. Use connection_only for invite-only evergreen setup without duplicating app template JSON in MCP.",
60
+ },
56
61
  confirmed: {
57
62
  type: "boolean",
58
63
  description: "Set true to overwrite existing sequence columns if the table already has them",
59
64
  },
60
65
  },
61
- required: ["tableId", "template"],
66
+ required: ["tableId"],
62
67
  },
63
68
  },
64
69
  {
@@ -107,31 +112,39 @@ export async function attachSequence(input) {
107
112
  const api = getApi();
108
113
  const template = input.template;
109
114
  const preValidationErrors = [];
110
- if (!Array.isArray(template.nodes) || template.nodes.length === 0) {
111
- preValidationErrors.push("Template must have a non-empty 'nodes' array.");
112
- }
113
- if (typeof template.entryNodeId !== "string" ||
114
- template.entryNodeId.trim().length === 0) {
115
- preValidationErrors.push("Template must have an 'entryNodeId' string.");
115
+ if (input.template && input.templateRef) {
116
+ throw new Error("INVALID_TEMPLATE: Pass either template or templateRef, not both.");
116
117
  }
117
- if (template.version !== 2) {
118
- preValidationErrors.push("Template version must be 2.");
118
+ if (!input.template && !input.templateRef) {
119
+ throw new Error("INVALID_TEMPLATE: Pass template or templateRef.");
119
120
  }
120
- if (Array.isArray(template.nodes) &&
121
- typeof template.entryNodeId === "string") {
122
- const nodeIds = new Set(template.nodes
123
- .map((node) => node && typeof node === "object"
124
- ? node.id
125
- : null)
126
- .filter((nodeId) => typeof nodeId === "string"));
127
- if (template.entryNodeId && !nodeIds.has(template.entryNodeId)) {
128
- preValidationErrors.push(`entryNodeId "${template.entryNodeId}" does not match any node id. Available node ids: ${Array.from(nodeIds).join(", ")}`);
121
+ if (input.template) {
122
+ if (!Array.isArray(template.nodes) || template.nodes.length === 0) {
123
+ preValidationErrors.push("Template must have a non-empty 'nodes' array.");
124
+ }
125
+ if (typeof template.entryNodeId !== "string" ||
126
+ template.entryNodeId.trim().length === 0) {
127
+ preValidationErrors.push("Template must have an 'entryNodeId' string.");
128
+ }
129
+ if (template.version !== 2) {
130
+ preValidationErrors.push("Template version must be 2.");
131
+ }
132
+ if (Array.isArray(template.nodes) &&
133
+ typeof template.entryNodeId === "string") {
134
+ const nodeIds = new Set(template.nodes
135
+ .map((node) => node && typeof node === "object"
136
+ ? node.id
137
+ : null)
138
+ .filter((nodeId) => typeof nodeId === "string"));
139
+ if (template.entryNodeId && !nodeIds.has(template.entryNodeId)) {
140
+ preValidationErrors.push(`entryNodeId "${template.entryNodeId}" does not match any node id. Available node ids: ${Array.from(nodeIds).join(", ")}`);
141
+ }
142
+ }
143
+ if (preValidationErrors.length > 0) {
144
+ throw new Error("INVALID_TEMPLATE: Template has structural issues:\n" +
145
+ preValidationErrors.map((issue) => ` - ${issue}`).join("\n") +
146
+ "\n\nFix these issues and retry.");
129
147
  }
130
- }
131
- if (preValidationErrors.length > 0) {
132
- throw new Error("INVALID_TEMPLATE: Template has structural issues:\n" +
133
- preValidationErrors.map((issue) => ` - ${issue}`).join("\n") +
134
- "\n\nFix these issues and retry.");
135
148
  }
136
149
  // Campaign-backed tables route to the campaigns endpoint so the MCP
137
150
  // tool persists the sequence to the same place the UI does
@@ -155,7 +168,8 @@ export async function attachSequence(input) {
155
168
  : `/api/v3/workflow-tables/${input.tableId}/sequence`;
156
169
  try {
157
170
  return await api.put(endpoint, {
158
- template: input.template,
171
+ ...(input.template ? { template: input.template } : {}),
172
+ ...(input.templateRef ? { templateRef: input.templateRef } : {}),
159
173
  confirmed: input.confirmed,
160
174
  });
161
175
  }
@@ -1,4 +1,5 @@
1
1
  type SetupEvergreenCampaignsInput = {
2
+ workspaceId?: string;
2
3
  mode?: "plan" | "verify";
3
4
  depth?: "structure_only" | "customer_visible";
4
5
  handoffMode?: "create_campaign_goals";
@@ -15,6 +16,9 @@ type SetupEvergreenCampaignsInput = {
15
16
  planRevision?: string;
16
17
  selectedActionIds?: string[];
17
18
  receipts?: Array<Record<string, unknown>>;
19
+ campaignSequenceOptions?: {
20
+ mode: "connection_only";
21
+ };
18
22
  };
19
23
  export declare const setupEvergreenCampaignsToolDefinitions: {
20
24
  name: string;
@@ -27,6 +31,23 @@ export declare const setupEvergreenCampaignsToolDefinitions: {
27
31
  enum: string[];
28
32
  description: string;
29
33
  };
34
+ workspaceId: {
35
+ type: string;
36
+ description: string;
37
+ };
38
+ campaignSequenceOptions: {
39
+ type: string;
40
+ properties: {
41
+ mode: {
42
+ type: string;
43
+ enum: string[];
44
+ description: string;
45
+ };
46
+ };
47
+ required: string[];
48
+ additionalProperties: boolean;
49
+ description: string;
50
+ };
30
51
  depth: {
31
52
  type: string;
32
53
  enum: string[];
@@ -1,7 +1,7 @@
1
1
  import { getApi } from "../api.js";
2
- async function postSetupEvergreenCampaigns(body) {
2
+ async function postSetupEvergreenCampaigns(body, workspaceId) {
3
3
  const api = getApi();
4
- return api.post("/api/v3/mcp/setup-evergreen-campaigns", body);
4
+ return api.post("/api/v3/mcp/setup-evergreen-campaigns", body, workspaceId ? { workspaceId } : undefined);
5
5
  }
6
6
  export const setupEvergreenCampaignsToolDefinitions = [
7
7
  {
@@ -15,6 +15,23 @@ export const setupEvergreenCampaignsToolDefinitions = [
15
15
  enum: ["plan", "verify"],
16
16
  description: 'Defaults to "plan". Verify only validates worker receipts.',
17
17
  },
18
+ workspaceId: {
19
+ type: "string",
20
+ description: "Optional explicit workspace id. Required for connection-only evergreen setup; it is also sent as the request workspace so concurrent threads cannot drift to another active workspace.",
21
+ },
22
+ campaignSequenceOptions: {
23
+ type: "object",
24
+ properties: {
25
+ mode: {
26
+ type: "string",
27
+ enum: ["connection_only"],
28
+ description: "Optional non-default sequence policy. connection_only means attach the canonical invite-only template and verify exactly send_invite, with no DM, InMail, View Profile, follow-up, launch, or send side effects.",
29
+ },
30
+ },
31
+ required: ["mode"],
32
+ additionalProperties: false,
33
+ description: "Optional non-default evergreen sequence policy. Omit to keep the standard tier-recommended Premium/Sales Nav behavior.",
34
+ },
18
35
  depth: {
19
36
  type: "string",
20
37
  enum: ["structure_only", "customer_visible"],
@@ -90,10 +107,12 @@ export const setupEvergreenCampaignsToolDefinitions = [
90
107
  ];
91
108
  export function setupEvergreenCampaigns(input) {
92
109
  return postSetupEvergreenCampaigns({
110
+ workspaceId: input.workspaceId,
93
111
  mode: input.mode,
94
112
  yolo: input.mode === "verify" ? undefined : input.yolo,
95
113
  depth: input.depth,
96
114
  handoffMode: input.mode === "verify" ? undefined : input.handoffMode,
115
+ campaignSequenceOptions: input.campaignSequenceOptions,
97
116
  allConnectedSenders: input.allConnectedSenders,
98
117
  selectedSenderIds: input.selectedSenderIds,
99
118
  postEngagerSenderIds: input.postEngagerSenderIds,
@@ -102,5 +121,5 @@ export function setupEvergreenCampaigns(input) {
102
121
  planRevision: input.planRevision,
103
122
  selectedActionIds: input.selectedActionIds,
104
123
  receipts: input.receipts,
105
- });
124
+ }, input.workspaceId);
106
125
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.544",
3
+ "version": "0.1.546",
4
4
  "type": "module",
5
5
  "description": "Sellable MCP server for Claude Code, Codex, and Hermes campaign workflows",
6
6
  "main": "dist/index.js",
@@ -59,6 +59,11 @@ The tail MUST verify:
59
59
 
60
60
  - `attach_recommended_sequence` is the only way to pick a template in
61
61
  the autonomous tail. Do NOT hand-wire a sequence at Step 16.
62
+ - Exception: when the parent `$sellable:create-evergreen-campaigns` plan
63
+ explicitly carries `campaignSequenceOptions:{ mode:"connection_only" }`,
64
+ do not call `attach_recommended_sequence`. Use the backend-owned
65
+ `attach_sequence({ tableId, templateRef:"connection_only" })` path and prove
66
+ `sequenceReceipt.actionTypes:["send_invite"]`.
62
67
  - Tier mismatch at attach time is an escalation, NOT a silent fallback.
63
68
  - A Standard sender MUST NOT be attached to an INMAIL_OPEN template.
64
69
  This would produce sends that fail at Unipile with `not_authorized`.
@@ -134,6 +134,18 @@ run without user input, or similar, run in **automation mode**:
134
134
  exactly one quality-valid route-proof row when needed, and attach the
135
135
  recommended sequence, but it still must not launch campaigns, schedule
136
136
  sends, send messages, or spend paid InMail.
137
+ - **Connection-only evergreen completion is optional and non-default.** Use it
138
+ only when the prompt explicitly says connection-only, invite-only,
139
+ connection request only, no DMs, or no follow-ups. Pass the typed option
140
+ `campaignSequenceOptions:{ mode:"connection_only" }` plus an explicit
141
+ `workspaceId` to `setup_evergreen_campaigns`. Omit
142
+ `campaignSequenceOptions` for the standard tier-recommended Premium,
143
+ Sales Nav, Recruiter, and paid InMail behavior.
144
+ Connection-only completion still creates/reuses the same evergreen lanes,
145
+ source rows, and paused/unlaunched review state, but it attaches only the
146
+ canonical invite template. It does not require Message Drafting, generated
147
+ messages, route-proof approval, first DM, InMail, View Profile fallback,
148
+ follow-up branch, `currentStep:"send"`, launch, scheduling, or sends.
137
149
 
138
150
  If the invoking prompt explicitly asks for interactive message polish or sample
139
151
  proof, run in **interactive polish mode** and use the confirmation/sample steps
@@ -720,6 +732,9 @@ not a parent-thread summary. The receipt must include:
720
732
  creation, preserve that original packet only in a separate `parentLanePacket`
721
733
  object; do not leave `setupPlanCall.campaignId:null` or
722
734
  `setupPlanCall.tableId:null`.
735
+ If the parent plan used connection-only, the receipt must also include
736
+ `setupPlanCall.campaignSequenceOptions:{ "mode":"connection_only" }` or
737
+ `setupPlanCall.sequencePolicy.mode:"connection_only"`.
723
738
  Short form: For create lanes, `setupPlanCall.campaignId` and `setupPlanCall.tableId` must be the actual created campaign/table ids.
724
739
  Short form: Do not leave `setupPlanCall.campaignId:null` or `setupPlanCall.tableId:null`.
725
740
  - `createCampaignWorkflowReceipt`: proof the worker loaded the actual installed
@@ -810,21 +825,39 @@ not a parent-thread summary. The receipt must include:
810
825
  them into canonical `promptLoadedToHasMoreFalse`, `requiredAssetsLoaded`,
811
826
  `validationLoaded`, `reviewBatchRowHash`, and
812
827
  `messageDraftRecommendation`.
828
+ Connection-only lanes are the exception: do not include
829
+ `messageDraftingReceipt` or run generated-message prep unless the operator
830
+ separately asked for message copy. The parent verifier expects no message
831
+ proof for connection-only lanes.
813
832
  - `reviewBatchReceipt`: review-batch row ids/hash, generated row count,
814
833
  quality-valid route-proof row id when approved, and proof that no broad
815
834
  approve-all occurred.
835
+ Connection-only lanes are the exception: do not approve a route-proof row and
836
+ do not include a required review-batch receipt.
816
837
  - `sequenceReceipt`: exact current workflowTableId, recommended non-paid
817
838
  sequence attach/precheck result, and readback showing `hasSequence:true` when
818
839
  completion is claimed. If the tool output uses
819
840
  `attachRecommendedSequenceResult.actionTypes` or
820
841
  `nonPaidRecommendedSequence`, copy them to canonical `actionTypes` and
821
842
  `nonPaid`.
843
+ For connection-only lanes, do not call `attach_recommended_sequence`. Attach
844
+ with `attach_sequence({ tableId, templateRef:"connection_only" })`, then
845
+ include exact current-template proof:
846
+ `sequenceReceipt.hasSequence:true`,
847
+ `sequenceReceipt.actionTypes:["send_invite"]`, and
848
+ `sequenceReceipt.nonPaid:true`. Receipts that only say
849
+ `tool:"attach_recommended_sequence"` or include `send_dm`,
850
+ `send_inmail_open`, `send_inmail_closed`, or `view_profile` are failing
851
+ connection-only receipts.
822
852
  - final paused-send proof: if the current campaign table is `DRAFT` after the
823
853
  sequence is attached, call the product `pause_campaign({ campaignId })`
824
854
  endpoint/tool to put the unlaunched campaign into `PAUSED` review state, then
825
855
  reread the campaign/table. Do not raw-write `campaignStatus`, do not start or
826
856
  launch, and do not schedule/send. Completion requires reread proof of
827
- `currentStep:"send"` and `campaignStatus:"PAUSED"`. If the raw output nests
857
+ `currentStep:"send"` and `campaignStatus:"PAUSED"` for standard
858
+ customer-visible lanes. Connection-only lanes may finish at a paused
859
+ unlaunched review step such as `currentStep:"review"` as long as the exact
860
+ invite-only sequence proof and source-row proof pass. If the raw output nests
828
861
  this in `finalCampaignRead` or `finalTableRead`, copy it to canonical
829
862
  `finalPausedSendProof.currentStep` and
830
863
  `finalPausedSendProof.campaignStatus`.
@@ -1088,9 +1121,14 @@ plain row generation. The lane worker must inline the same
1088
1121
  approvedGeneratedMessageCount exactly 1. Do not report completion with 2+
1089
1122
  approved rows.
1090
1123
  Approval shorthand: Do not report completion with 2+ approved rows.
1091
- 8. Continue to `attach_recommended_sequence({ campaignId, currentStep:"send" })`
1092
- and, if the campaign is still `DRAFT`, `pause_campaign({ campaignId })`.
1093
- Reread the campaign/table before claiming completion.
1124
+ 8. Standard mode: continue to
1125
+ `attach_recommended_sequence({ campaignId, currentStep:"send" })` and, if
1126
+ the campaign is still `DRAFT`, `pause_campaign({ campaignId })`. Reread the
1127
+ campaign/table before claiming completion.
1128
+ Connection-only mode: skip Message Drafting and route-proof approval, call
1129
+ `attach_sequence({ tableId, templateRef:"connection_only" })`, prove
1130
+ `sequenceReceipt.actionTypes:["send_invite"]`, and pause/reread without
1131
+ launching or sending.
1094
1132
 
1095
1133
  That packaged worker path must return `messageDraftingReceipt.statusSource:
1096
1134
  "packaged-generate-messages-worker"`. It is accepted only when the receipt
@@ -1515,11 +1553,14 @@ Message, and verify current-revision sample messages before final completion.
1515
1553
  - DM lanes: add a `Delivery format:` line — either `multiline (each paragraph sends as its own DM message)` or `single message`. When multiline, the template's blank-line paragraphs ARE the message boundaries — write each one as a standalone typed message.
1516
1554
  - **InMail lanes can never be multiline**: an InMail is one message and the recipient must reply before anything else can be sent. InMail-bound templates must read as one cohesive message — declare `Delivery format: single message (InMail — no follow-up until reply)` and never structure the copy to depend on multi-message pacing.
1517
1555
 
1518
- - The sequence is auto-selected by sender tier; do not hand-author sequence
1556
+ - In standard mode, the sequence is auto-selected by sender tier; do not hand-author sequence
1519
1557
  templates here. Sales Nav/Recruiter senders may receive the unified Sales
1520
1558
  Nav cascade through `attach_recommended_sequence`; attaching it does not
1521
1559
  spend paid InMail credits by itself. Do not substitute the manual Paid
1522
1560
  InMail Campaign template.
1561
+ For explicit connection-only evergreen lanes only, use the backend-owned
1562
+ `attach_sequence({ tableId, templateRef:"connection_only" })` path and do
1563
+ not call `attach_recommended_sequence`.
1523
1564
  3. **Customer-Visible Completion Contract**: a named evergreen lane that appears
1524
1565
  as a campaign card or campaign-backed table is not done when the shell exists.
1525
1566
  It is done only when the customer can open the campaign and land on final
@@ -1543,7 +1584,7 @@ Message, and verify current-revision sample messages before final completion.
1543
1584
  evergreen setup. Do not leave customer-visible campaigns at
1544
1585
  `filter-choice`, `filter-rules`, or `apply-icp-rubric` and report success.
1545
1586
  Do not proceed to Message Drafting until saved filters are applied.
1546
- - Message Drafting has run from the current campaign/table basis, using the
1587
+ - In standard mode, Message Drafting has run from the current campaign/table basis, using the
1547
1588
  create-campaign message prompt/assets and validation gate. Updating
1548
1589
  `currentStep:"messages"` is not proof. Parent-thread handwritten copy is
1549
1590
  not a substitute. The proof receipt must show
@@ -1584,6 +1625,9 @@ Message, and verify current-revision sample messages before final completion.
1584
1625
  Fallback samples must still reject source/conversation hedges such as
1585
1626
  `"hope this is relevant"`, `"might be interested"`, or `"saw you in a few
1586
1627
  conversations"`.
1628
+ For explicit connection-only lanes, this whole Message Drafting and sample
1629
+ proof block is not required and must not be faked with parent-written
1630
+ messages.
1587
1631
  - The first review batch exists and at least 3 review rows have generated
1588
1632
  messages from the approved brief. If fewer than 3 usable rows exist, report
1589
1633
  the actual count and why.
@@ -1596,7 +1640,7 @@ Message, and verify current-revision sample messages before final completion.
1596
1640
  completion, approve exactly one quality-valid generated row. If one or more
1597
1641
  rows are already approved, do not add more approvals during evergreen
1598
1642
  completion. Never broad approve all rows.
1599
- - The recommended tier-aware sequence is attached to the current campaign
1643
+ - In standard mode, the recommended tier-aware sequence is attached to the current campaign
1600
1644
  table, and the watched campaign is on Send. Use
1601
1645
  `attach_recommended_sequence({ campaignId, currentStep:"send" })` when a
1602
1646
  safe attach is needed. After `confirm_lead_list` or any source-list copy,
@@ -1611,6 +1655,10 @@ Message, and verify current-revision sample messages before final completion.
1611
1655
  manual Paid InMail Campaign, and never attach/replace sequence outside the
1612
1656
  current table unless the current lane packet explicitly allowed sequence
1613
1657
  repair.
1658
+ For explicit connection-only lanes, the current campaign table must have
1659
+ exactly the canonical invite-only sequence:
1660
+ `sequenceReceipt.actionTypes:["send_invite"]`. Any DM, InMail, or View
1661
+ Profile action means the lane is not complete.
1614
1662
  - If the current campaign table is still `DRAFT` after sequence/readiness
1615
1663
  proof, call `pause_campaign({ campaignId })` and reread. `pause_campaign`
1616
1664
  is the product-native review-state transition; it is not a launch and does
@@ -196,6 +196,11 @@ rather than asking which campaign class to fill. If a stale target plan selects
196
196
  planner before mutation.
197
197
  Short form: trust the target plan's inferred lane when it is a connection invite,
198
198
  paid-InMail refill lane, or unified Sales Nav cascade.
199
+ Connection-only evergreen campaigns with exact `["send_invite"]` sequence proof
200
+ are plain invite capacity: treat them as `selectedLane:"send_invite"` only. Do
201
+ not infer DM, InMail, Sales Nav cascade, paid-credit refresh, message
202
+ generation, follow-up, sequence mutation, launch/start, scheduling override, or
203
+ direct-send work from a connection-only lane.
199
204
 
200
205
  Structured planner packet:
201
206
 
@@ -62,6 +62,11 @@ for lease expiry; never guess a fence.
62
62
  The default `intent:"auto"` inspects `managed_waterfall`,
63
63
  `dashboard_evergreen`, and `active_campaign` lane sources. Report the lane
64
64
  source and lane chain as proof for every selected sender.
65
+ Connection-only evergreen lanes are invite-only refill targets. When the packet
66
+ or campaign proof shows exactly `["send_invite"]`, report and execute only
67
+ `selectedLane:"send_invite"` work; do not infer DM, InMail, Sales Nav cascade,
68
+ paid-credit refresh, message generation, follow-up, sequence mutation,
69
+ launch/start beyond packet authority, scheduler writes, or direct sends.
65
70
 
66
71
  If membership blocks a workspace read, report the structured
67
72
  `workspace_access` blocker instead of retrying auth or switching workspaces.
@@ -61,6 +61,13 @@ the repair rung, such as re-run errored enrichment/message cells
61
61
  (`start_campaign`). The loop bounds and refuses repair loops; it never invents
62
62
  a fix list.
63
63
 
64
+ Connection-only evergreen packets are invite-only. If the selected lane or
65
+ campaign proof is exactly `["send_invite"]`, the workflow may refill only
66
+ `selectedLane:"send_invite"` capacity. Do not treat that lane as a DM, InMail,
67
+ Sales Nav cascade, paid-credit refresh, generated-message requirement,
68
+ follow-up branch, sequence-repair task, scheduler write, launch/send, or
69
+ provider-family continuation.
70
+
64
71
  Use plain-language labels first and tokens second, for example "copy leads
65
72
  already found into the campaign table (`reconcile_source_copy`)".
66
73
 
@@ -52,6 +52,7 @@
52
52
  "awaiting scheduler is not an end state; window-closed reports name remaining-ready, expected pickup time, and resume handle",
53
53
  "honest-rubric-fail means a human updates the rubric or changes lead source",
54
54
  "source replenishment beyond same-source-automatic is a scoped create-campaign handoff, never refill-owned provider search",
55
+ "connection-only evergreen lanes with exact [\"send_invite\"] proof are invite-only refill capacity; never infer DM, InMail, Sales Nav cascade, paid-credit refresh, message generation, follow-up, sequence mutation, scheduler writes, launch, or send work from them",
55
56
  "no campaign creation, provider-family switch, threshold lowering, scheduler writes, sends, archives, deletes, or brief/filter/message/sequence/sender mutation without a separate approval packet"
56
57
  ],
57
58
  "requiredBootstrap": [
@@ -0,0 +1,9 @@
1
+ {
2
+ "parallelMode": "wide",
3
+ "agentCount": 6,
4
+ "maxToolCallsPerAgent": 2,
5
+ "senderMaxAgents": 2,
6
+ "senderMaxToolCallsPerAgent": 3,
7
+ "progressMode": true,
8
+ "debugMode": true
9
+ }