@sellable/mcp 0.1.342 → 0.1.343
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
|
@@ -43,6 +43,7 @@ import { addRubricItem, checkRubric, deleteRubricItem, draftRubrics, saveRubrics
|
|
|
43
43
|
import { getSenderRoutingTool, setSenderRoutingTool, } from "./tools/sender-routing.js";
|
|
44
44
|
import { getSender, listSenders } from "./tools/senders.js";
|
|
45
45
|
import { attachRecommendedSequence, attachSequence, createWorkflowTable, } from "./tools/sequencer.js";
|
|
46
|
+
import { setupEvergreenCampaigns } from "./tools/setup-evergreen-campaigns.js";
|
|
46
47
|
import { exportTableCsv, listTables } from "./tools/tables.js";
|
|
47
48
|
import { handleVerifyTableRow } from "./tools/verify-row.js";
|
|
48
49
|
import { sanitizeWatchUrlsForMcpResult } from "./tools/watch-url-security.js";
|
|
@@ -68,6 +69,32 @@ function parseOptionalNumber(value) {
|
|
|
68
69
|
}
|
|
69
70
|
return undefined;
|
|
70
71
|
}
|
|
72
|
+
function markEvergreenSetupCampaignsDirty(args) {
|
|
73
|
+
if (!args || args.mode !== "verify")
|
|
74
|
+
return;
|
|
75
|
+
const campaignIds = new Set();
|
|
76
|
+
const bindings = Array.isArray(args.bindings) ? args.bindings : [];
|
|
77
|
+
for (const binding of bindings) {
|
|
78
|
+
if (!binding || typeof binding !== "object" || Array.isArray(binding))
|
|
79
|
+
continue;
|
|
80
|
+
const campaignId = binding.campaignId;
|
|
81
|
+
if (typeof campaignId === "string" && campaignId.trim()) {
|
|
82
|
+
campaignIds.add(campaignId.trim());
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const receipts = Array.isArray(args.receipts) ? args.receipts : [];
|
|
86
|
+
for (const receipt of receipts) {
|
|
87
|
+
if (!receipt || typeof receipt !== "object" || Array.isArray(receipt))
|
|
88
|
+
continue;
|
|
89
|
+
const campaignId = receipt.campaignId;
|
|
90
|
+
if (typeof campaignId === "string" && campaignId.trim()) {
|
|
91
|
+
campaignIds.add(campaignId.trim());
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
for (const campaignId of campaignIds) {
|
|
95
|
+
markCampaignContextDirty(campaignId, "setup_evergreen_campaigns");
|
|
96
|
+
}
|
|
97
|
+
}
|
|
71
98
|
function formatSubskillPromptText(result) {
|
|
72
99
|
const header = result.chunkCount && result.chunkCount > 1
|
|
73
100
|
? [
|
|
@@ -187,6 +214,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
187
214
|
case "get_campaign_refill_state":
|
|
188
215
|
result = await getCampaignRefillState(args);
|
|
189
216
|
break;
|
|
217
|
+
case "setup_evergreen_campaigns":
|
|
218
|
+
result = await setupEvergreenCampaigns(args);
|
|
219
|
+
markEvergreenSetupCampaignsDirty(args);
|
|
220
|
+
break;
|
|
190
221
|
case "fill_campaign_horizon":
|
|
191
222
|
result = await fillCampaignHorizon(args);
|
|
192
223
|
if (args?.campaignId) {
|
package/dist/tools/registry.js
CHANGED
|
@@ -38,6 +38,7 @@ import { rubricToolDefinitions } from "./rubrics.js";
|
|
|
38
38
|
import { senderRoutingToolDefinitions } from "./sender-routing.js";
|
|
39
39
|
import { senderToolDefinitions } from "./senders.js";
|
|
40
40
|
import { sequencerToolDefinitions } from "./sequencer.js";
|
|
41
|
+
import { setupEvergreenCampaignsToolDefinitions } from "./setup-evergreen-campaigns.js";
|
|
41
42
|
import { tableToolDefinitions } from "./tables.js";
|
|
42
43
|
import { verifyRowToolDefinitions } from "./verify-row.js";
|
|
43
44
|
import { waterfallToolDefinitions } from "./waterfalls.js";
|
|
@@ -47,6 +48,7 @@ export const allTools = [
|
|
|
47
48
|
...campaignAbTestToolDefinitions,
|
|
48
49
|
...campaignFillRoutingToolDefinitions,
|
|
49
50
|
...campaignRefillStateToolDefinitions,
|
|
51
|
+
...setupEvergreenCampaignsToolDefinitions,
|
|
50
52
|
...campaignHorizonFillToolDefinitions,
|
|
51
53
|
...campaignMessagePreparationToolDefinitions,
|
|
52
54
|
...campaignProcessingToolDefinitions,
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
type SetupEvergreenCampaignsInput = {
|
|
2
|
+
mode?: "plan" | "verify";
|
|
3
|
+
depth?: "structure_only" | "customer_visible";
|
|
4
|
+
yolo?: boolean;
|
|
5
|
+
allConnectedSenders?: boolean;
|
|
6
|
+
selectedSenderIds?: string[];
|
|
7
|
+
bindings?: Array<{
|
|
8
|
+
laneKey: string;
|
|
9
|
+
campaignId: string;
|
|
10
|
+
tableId: string;
|
|
11
|
+
}>;
|
|
12
|
+
planRevision?: string;
|
|
13
|
+
selectedActionIds?: string[];
|
|
14
|
+
receipts?: unknown[];
|
|
15
|
+
};
|
|
16
|
+
export declare const setupEvergreenCampaignsToolDefinitions: {
|
|
17
|
+
name: string;
|
|
18
|
+
description: string;
|
|
19
|
+
inputSchema: {
|
|
20
|
+
type: string;
|
|
21
|
+
properties: {
|
|
22
|
+
mode: {
|
|
23
|
+
type: string;
|
|
24
|
+
enum: string[];
|
|
25
|
+
description: string;
|
|
26
|
+
};
|
|
27
|
+
depth: {
|
|
28
|
+
type: string;
|
|
29
|
+
enum: string[];
|
|
30
|
+
description: string;
|
|
31
|
+
};
|
|
32
|
+
yolo: {
|
|
33
|
+
type: string;
|
|
34
|
+
description: string;
|
|
35
|
+
};
|
|
36
|
+
allConnectedSenders: {
|
|
37
|
+
type: string;
|
|
38
|
+
description: string;
|
|
39
|
+
};
|
|
40
|
+
selectedSenderIds: {
|
|
41
|
+
type: string;
|
|
42
|
+
items: {
|
|
43
|
+
type: string;
|
|
44
|
+
};
|
|
45
|
+
maxItems: number;
|
|
46
|
+
description: string;
|
|
47
|
+
};
|
|
48
|
+
bindings: {
|
|
49
|
+
type: string;
|
|
50
|
+
maxItems: number;
|
|
51
|
+
items: {
|
|
52
|
+
type: string;
|
|
53
|
+
properties: {
|
|
54
|
+
laneKey: {
|
|
55
|
+
type: string;
|
|
56
|
+
};
|
|
57
|
+
campaignId: {
|
|
58
|
+
type: string;
|
|
59
|
+
};
|
|
60
|
+
tableId: {
|
|
61
|
+
type: string;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
required: string[];
|
|
65
|
+
additionalProperties: boolean;
|
|
66
|
+
};
|
|
67
|
+
description: string;
|
|
68
|
+
};
|
|
69
|
+
planRevision: {
|
|
70
|
+
type: string;
|
|
71
|
+
description: string;
|
|
72
|
+
};
|
|
73
|
+
selectedActionIds: {
|
|
74
|
+
type: string;
|
|
75
|
+
items: {
|
|
76
|
+
type: string;
|
|
77
|
+
};
|
|
78
|
+
maxItems: number;
|
|
79
|
+
description: string;
|
|
80
|
+
};
|
|
81
|
+
receipts: {
|
|
82
|
+
type: string;
|
|
83
|
+
maxItems: number;
|
|
84
|
+
items: {
|
|
85
|
+
type: string;
|
|
86
|
+
};
|
|
87
|
+
description: string;
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
required: never[];
|
|
91
|
+
additionalProperties: boolean;
|
|
92
|
+
};
|
|
93
|
+
}[];
|
|
94
|
+
export declare function setupEvergreenCampaigns(input: SetupEvergreenCampaignsInput): Promise<unknown>;
|
|
95
|
+
export {};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { getApi } from "../api.js";
|
|
2
|
+
async function postSetupEvergreenCampaigns(body) {
|
|
3
|
+
const api = getApi();
|
|
4
|
+
return api.post("/api/v3/mcp/setup-evergreen-campaigns", body);
|
|
5
|
+
}
|
|
6
|
+
export const setupEvergreenCampaignsToolDefinitions = [
|
|
7
|
+
{
|
|
8
|
+
name: "setup_evergreen_campaigns",
|
|
9
|
+
description: "Evergreen campaign setup plan/verify command. Use plan mode first to inspect exact workspace/sender/campaign/table/source state and receive immutable lane packets for one Post Engagers lane per selected sender plus shared Signal Discovery and Shared Cold Fallback lanes. yolo is only a parent-skill auto-execution hint for safe lane packets; this backend command remains read-only in plan mode and verifies receipts in verify mode. Lane workers must execute creation, source import, create-campaign workflow steps, generate-messages, sequence attachment, and review readiness through existing create-campaign workflow/subskills, then return receipts here for verification. This command does not launch campaigns, does not schedule sends, does not assign scheduler-owned send fields, does not archive/delete cleanup targets, and does not spend paid credits.",
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: "object",
|
|
12
|
+
properties: {
|
|
13
|
+
mode: {
|
|
14
|
+
type: "string",
|
|
15
|
+
enum: ["plan", "verify"],
|
|
16
|
+
description: 'Defaults to "plan". Verify only validates worker receipts.',
|
|
17
|
+
},
|
|
18
|
+
depth: {
|
|
19
|
+
type: "string",
|
|
20
|
+
enum: ["structure_only", "customer_visible"],
|
|
21
|
+
description: 'Use "customer_visible" for full setup proof or "structure_only" when only ensuring lane shells/config.',
|
|
22
|
+
},
|
|
23
|
+
yolo: {
|
|
24
|
+
type: "boolean",
|
|
25
|
+
description: "plan mode only. Requests auto-executable lane packets when state is safe; never authorizes cleanup, launch, scheduling, sending, or ambiguous target choice.",
|
|
26
|
+
},
|
|
27
|
+
allConnectedSenders: {
|
|
28
|
+
type: "boolean",
|
|
29
|
+
description: "Plan sender-owned Post Engagers lanes for all eligible connected senders in the active workspace.",
|
|
30
|
+
},
|
|
31
|
+
selectedSenderIds: {
|
|
32
|
+
type: "array",
|
|
33
|
+
items: { type: "string" },
|
|
34
|
+
maxItems: 25,
|
|
35
|
+
description: "Exact OutboundSenderIdentity ids for sender-owned Post Engagers lanes and shared-lane sender set.",
|
|
36
|
+
},
|
|
37
|
+
bindings: {
|
|
38
|
+
type: "array",
|
|
39
|
+
maxItems: 20,
|
|
40
|
+
items: {
|
|
41
|
+
type: "object",
|
|
42
|
+
properties: {
|
|
43
|
+
laneKey: { type: "string" },
|
|
44
|
+
campaignId: { type: "string" },
|
|
45
|
+
tableId: { type: "string" },
|
|
46
|
+
},
|
|
47
|
+
required: ["laneKey", "campaignId", "tableId"],
|
|
48
|
+
additionalProperties: false,
|
|
49
|
+
},
|
|
50
|
+
description: "Exact existing campaign/table bindings to reuse for lane keys. Do not pass names.",
|
|
51
|
+
},
|
|
52
|
+
planRevision: {
|
|
53
|
+
type: "string",
|
|
54
|
+
description: "Required for verify. Copy from the immediately preceding plan.",
|
|
55
|
+
},
|
|
56
|
+
selectedActionIds: {
|
|
57
|
+
type: "array",
|
|
58
|
+
items: { type: "string" },
|
|
59
|
+
maxItems: 20,
|
|
60
|
+
description: "Required for verify. Immutable action ids selected from the current plan.",
|
|
61
|
+
},
|
|
62
|
+
receipts: {
|
|
63
|
+
type: "array",
|
|
64
|
+
maxItems: 20,
|
|
65
|
+
items: { type: "object" },
|
|
66
|
+
description: "Required for verify. Structured lane worker receipts from create-campaign/source/message/sequence execution.",
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
required: [],
|
|
70
|
+
additionalProperties: false,
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
];
|
|
74
|
+
export function setupEvergreenCampaigns(input) {
|
|
75
|
+
return postSetupEvergreenCampaigns({
|
|
76
|
+
mode: input.mode,
|
|
77
|
+
yolo: input.yolo,
|
|
78
|
+
depth: input.depth,
|
|
79
|
+
allConnectedSenders: input.allConnectedSenders,
|
|
80
|
+
selectedSenderIds: input.selectedSenderIds,
|
|
81
|
+
bindings: input.bindings,
|
|
82
|
+
planRevision: input.planRevision,
|
|
83
|
+
selectedActionIds: input.selectedActionIds,
|
|
84
|
+
receipts: input.receipts,
|
|
85
|
+
});
|
|
86
|
+
}
|
package/package.json
CHANGED
|
@@ -51,6 +51,58 @@ Default evergreen plan per workspace (override only if the prompt specifies diff
|
|
|
51
51
|
3. **`<Workspace/Team> - Shared Cold Fallback`** — one shared cold/fallback campaign lane across senders
|
|
52
52
|
</inputs>
|
|
53
53
|
|
|
54
|
+
<command_backed_workflow>
|
|
55
|
+
For full/customer-visible setup, the first operational command is always
|
|
56
|
+
`setup_evergreen_campaigns({ mode:"plan", yolo })`. Inventory can happen first
|
|
57
|
+
for operator understanding, but do not create/reuse/repair campaign shells,
|
|
58
|
+
source rows, messages, sequence, approvals, or cleanup before the command-backed
|
|
59
|
+
plan returns lane packets.
|
|
60
|
+
|
|
61
|
+
Plan shape:
|
|
62
|
+
|
|
63
|
+
- one Post Engagers lane per selected sender;
|
|
64
|
+
- one shared Signal Discovery lane;
|
|
65
|
+
- one shared Cold Fallback lane;
|
|
66
|
+
- explicit existing campaign/table bindings when the user points at a canonical
|
|
67
|
+
lane. Pass those exact ids to the plan and reuse/verify them instead of
|
|
68
|
+
creating duplicates.
|
|
69
|
+
- If a user supplies canonical ids, reuse/verify them instead of creating duplicates.
|
|
70
|
+
|
|
71
|
+
When senders are ambiguous, ask which sender ids need Post Engagers lanes before
|
|
72
|
+
planning. If the operator says all connected senders, pass `allConnectedSenders`
|
|
73
|
+
and let the command return exact selected sender ids or blockers.
|
|
74
|
+
|
|
75
|
+
`--yolo` is supported, but it is a safety-scoped execution mode, not a cleanup
|
|
76
|
+
or launch permission. With `--yolo`, pass `yolo:true` to
|
|
77
|
+
`setup_evergreen_campaigns({ mode:"plan", yolo })` and proceed without
|
|
78
|
+
intermediate approval only when every selected lane packet returns
|
|
79
|
+
`autoExecutable:true`. `--yolo` does not authorize archive/delete cleanup,
|
|
80
|
+
launch/start, schedule/send, broad approve-all, wrong workspace work, stale
|
|
81
|
+
plan execution, paid InMail spend, or ambiguous target choice. Stop on wrong
|
|
82
|
+
workspace, cleanup/archive/delete need, stale plan, disconnected sender,
|
|
83
|
+
duplicate candidate, unsafe side effect, missing source proof, or missing
|
|
84
|
+
message proof.
|
|
85
|
+
|
|
86
|
+
After approval or safe `--yolo`, fan out lane worker tasks only from the current
|
|
87
|
+
plan. Each worker receives the complete lane packet: workspace id, sender ids,
|
|
88
|
+
lane key/type, existing campaign/table binding or create intent, source hints,
|
|
89
|
+
caps, planRevision, actionId, allowed side effects, and postconditions. Workers
|
|
90
|
+
must use the create-campaign workflow and create-campaign workflow/subskills for
|
|
91
|
+
campaign creation/setup, source/import, filter choice, Message Drafting,
|
|
92
|
+
packaged `generate-messages`, sequence attachment, and send-review readiness.
|
|
93
|
+
Do not rebuild those steps ad hoc in the parent thread.
|
|
94
|
+
|
|
95
|
+
Workers return worker receipts. The parent then calls
|
|
96
|
+
`setup_evergreen_campaigns({ mode:"verify", planRevision, selectedActionIds,
|
|
97
|
+
receipts })` and report only verified completion. If verify blocks, report the
|
|
98
|
+
blocker and repair only the missing postconditions from the same current plan.
|
|
99
|
+
|
|
100
|
+
Message proof for every customer-visible lane must come from the current
|
|
101
|
+
campaign/table basis and include at least 3 generated review rows from the
|
|
102
|
+
packaged `generate-messages` path before completion is reported.
|
|
103
|
+
Parent-thread handwritten copy or setting `currentStep` is not proof.
|
|
104
|
+
</command_backed_workflow>
|
|
105
|
+
|
|
54
106
|
<objective>
|
|
55
107
|
1. **Inventory first**: `get_campaigns` + `list_tables` + `get_campaign_waterfall` in the active workspace. Treat `list_tables` and the managed waterfall as authoritative for older managed slots; `get_campaigns` is a recent campaign page and may miss canonical evergreen lanes. Match existing campaigns/tables/waterfall slots to the plan by name (case-insensitive, ignore suffixes like "(Copy)") and stored slot identity. `list_tables.campaignStatus` and `list_tables.dashboardBucket` are part of the identity check: a matching `ARCHIVED` table/campaign is not a plain `REUSE`. If it is the canonical prod slot and the invocation explicitly allows dashboard visibility repair, repair it to `PAUSED`; otherwise mark it `flagged`/`blocked` and do not create a duplicate. A matching non-archived campaign/table/waterfall slot = REUSE; record it and move on. Never create a second campaign for a slot that already has one in any of those inventories.
|
|
56
108
|
2. **Create only the missing slots** with `create_on_demand_campaign({ name, senderIds, campaignBrief })`:
|