@sendinel/mcp-server 1.0.30 → 1.0.31
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/build/tools/campaigns.js +8 -3
- package/package.json +1 -1
package/build/tools/campaigns.js
CHANGED
|
@@ -458,8 +458,9 @@ export function registerCampaignTools(server) {
|
|
|
458
458
|
trigger_config: z.record(z.string(), z.unknown()).nullable().optional().describe('For trigger_type=date_field: { field, days_before?, recurring? }. Otherwise: { events?: string[], tags?: string[] }.'),
|
|
459
459
|
segment_id: z.string().uuid().nullable().optional().describe('Segment UUID for ongoing audience targeting; membership is re-evaluated on sends'),
|
|
460
460
|
send_at: z.string().datetime().nullable().optional().describe('For type=broadcast only: ISO 8601 instant to schedule the send. Must be in the future. Set null for no schedule. The campaign must still be activated via update_campaign_status.'),
|
|
461
|
+
send_class: z.enum(['broadcast', 'product']).optional().describe("Who may receive it when the project's consent gate is on: 'broadcast' (default) = only contacts who opted in to marketing; 'product' = also the customer's signed-up users (onboarding, trial, account mail)."),
|
|
461
462
|
},
|
|
462
|
-
}, async ({ site_id, name, type, description, sends_per_hour, requires_approval, trigger_event_name, trigger_tag, trigger_type, trigger_config, segment_id, send_at }) => {
|
|
463
|
+
}, async ({ site_id, name, type, description, sends_per_hour, requires_approval, trigger_event_name, trigger_tag, trigger_type, trigger_config, segment_id, send_at, send_class }) => {
|
|
463
464
|
const limit = await checkPlanLimit('active_campaigns');
|
|
464
465
|
if (!limit.allowed) {
|
|
465
466
|
return { content: [{ type: 'text', text: `Active campaign limit reached (${limit.current}/${limit.limit}). Upgrade to Pro for unlimited campaigns.` }] };
|
|
@@ -473,6 +474,7 @@ export function registerCampaignTools(server) {
|
|
|
473
474
|
description,
|
|
474
475
|
sends_per_hour: sends_per_hour ?? null,
|
|
475
476
|
requires_approval,
|
|
477
|
+
...(send_class ? { send_class } : {}),
|
|
476
478
|
};
|
|
477
479
|
const scheduleError = applyCampaignSendAtField(insertPayload, send_at, type);
|
|
478
480
|
if (scheduleError)
|
|
@@ -2691,7 +2693,7 @@ Return ONLY valid JSON with this exact shape:
|
|
|
2691
2693
|
idempotentHint: true,
|
|
2692
2694
|
openWorldHint: false,
|
|
2693
2695
|
},
|
|
2694
|
-
description: 'Update a campaign name, site, segment, send time, topic, or
|
|
2696
|
+
description: 'Update a campaign name, site, segment, send time, topic, trigger settings, or send class (broadcast vs product). send_at schedules a broadcast send (type=broadcast only) and must be a future ISO 8601 instant; set null to clear a pending schedule. Only provided fields are updated.',
|
|
2695
2697
|
inputSchema: {
|
|
2696
2698
|
campaign_id: z.string().uuid(),
|
|
2697
2699
|
name: z.string().min(1).max(200).optional(),
|
|
@@ -2705,8 +2707,9 @@ Return ONLY valid JSON with this exact shape:
|
|
|
2705
2707
|
trigger_config: z.record(z.string(), z.unknown()).nullable().optional(),
|
|
2706
2708
|
sends_per_hour: z.number().int().min(1).nullable().optional().describe('Optional hourly send cap for wave sending. Set null to clear.'),
|
|
2707
2709
|
send_in_contact_timezone: z.boolean().optional(),
|
|
2710
|
+
send_class: z.enum(['broadcast', 'product']).optional().describe("Who may receive it when the project's consent gate is on: 'broadcast' (default) = only contacts who opted in to marketing; 'product' = also the customer's signed-up users (onboarding, trial, account mail)."),
|
|
2708
2711
|
},
|
|
2709
|
-
}, async ({ campaign_id, name, site_id, segment_id, send_at, topic, trigger_event_name, trigger_tag, trigger_type, trigger_config, sends_per_hour, send_in_contact_timezone }) => {
|
|
2712
|
+
}, async ({ campaign_id, name, site_id, segment_id, send_at, topic, trigger_event_name, trigger_tag, trigger_type, trigger_config, sends_per_hour, send_in_contact_timezone, send_class }) => {
|
|
2710
2713
|
const projectId = getProjectId();
|
|
2711
2714
|
let campaignType;
|
|
2712
2715
|
if (send_at !== undefined && send_at !== null) {
|
|
@@ -2736,6 +2739,8 @@ Return ONLY valid JSON with this exact shape:
|
|
|
2736
2739
|
updates.sends_per_hour = sends_per_hour;
|
|
2737
2740
|
if (send_in_contact_timezone !== undefined)
|
|
2738
2741
|
updates.send_in_contact_timezone = send_in_contact_timezone;
|
|
2742
|
+
if (send_class !== undefined)
|
|
2743
|
+
updates.send_class = send_class;
|
|
2739
2744
|
const targetingError = await applyCampaignTargetingFields(updates, { trigger_event_name, trigger_tag, trigger_type, trigger_config, segment_id }, projectId);
|
|
2740
2745
|
if (targetingError)
|
|
2741
2746
|
return j({ error: targetingError, code: targetingError === 'Segment not found' ? 'NOT_FOUND' : 'INVALID_FIELD' });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sendinel/mcp-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.31",
|
|
4
4
|
"description": "AI-controlled email operations control plane for campaigns, contacts, segments, analytics, and multi-provider sending via MCP.",
|
|
5
5
|
"mcpName": "ai.sendinel/mcp-server",
|
|
6
6
|
"type": "module",
|