@sendinel/mcp-server 1.0.148 → 1.0.150
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/lib/db-error.js +5 -0
- package/build/tools/campaigns.js +1 -1
- package/build/tools/delivery-ops.js +3 -3
- package/build/tools/gdpr.js +1 -1
- package/build/tools/newsletters.js +3 -3
- package/build/tools/short-links.js +5 -3
- package/build/tools/surveys.js +2 -2
- package/build/tools/templates.js +1 -1
- package/package.json +1 -1
package/build/lib/db-error.js
CHANGED
|
@@ -92,6 +92,8 @@ export const API_USAGE_ERROR_CODE_MAP = {
|
|
|
92
92
|
'unprocessable_entity': 'validation_failed',
|
|
93
93
|
'validation': 'validation_failed',
|
|
94
94
|
'validation_failed': 'validation_failed',
|
|
95
|
+
'approval_not_cancellable': 'conflict',
|
|
96
|
+
'approval_not_pending': 'conflict',
|
|
95
97
|
'23505': 'conflict',
|
|
96
98
|
'conflict': 'conflict',
|
|
97
99
|
'content_changed_since_approval': 'conflict',
|
|
@@ -131,7 +133,10 @@ export const API_USAGE_ERROR_CODE_MAP = {
|
|
|
131
133
|
'activation_failed': 'internal_error',
|
|
132
134
|
'ai_not_configured': 'internal_error',
|
|
133
135
|
'ai_unavailable': 'internal_error',
|
|
136
|
+
'approval_audit_failed': 'internal_error',
|
|
137
|
+
'approval_failed': 'internal_error',
|
|
134
138
|
'approval_lookup_failed': 'internal_error',
|
|
139
|
+
'approval_update_failed': 'internal_error',
|
|
135
140
|
'audience_lookup_failed': 'internal_error',
|
|
136
141
|
'campaign_create_failed': 'internal_error',
|
|
137
142
|
'campaign_lookup_failed': 'internal_error',
|
package/build/tools/campaigns.js
CHANGED
|
@@ -2936,7 +2936,7 @@ Do not include body_html in your response; Sendinel renders body_html from block
|
|
|
2936
2936
|
: row.status === 'expired' ? 'no_reply_by_deadline'
|
|
2937
2937
|
: 'unknown',
|
|
2938
2938
|
}));
|
|
2939
|
-
return j({ items, count: items.length });
|
|
2939
|
+
return j({ items, count: items.length, truncated: items.length === limit });
|
|
2940
2940
|
});
|
|
2941
2941
|
server.registerTool('validate_template', {
|
|
2942
2942
|
title: 'Validate Template',
|
|
@@ -341,7 +341,7 @@ export function registerDeliveryOpsTools(server) {
|
|
|
341
341
|
if (error)
|
|
342
342
|
return j(dbToolError(error));
|
|
343
343
|
const failed = (data ?? []).filter((row) => row.status === 'failed');
|
|
344
|
-
return j({ runs: data ?? [], recent_failures: failed.length, total: data?.length ?? 0 });
|
|
344
|
+
return j({ runs: data ?? [], recent_failures: failed.length, total: data?.length ?? 0, truncated: (data?.length ?? 0) === limit });
|
|
345
345
|
});
|
|
346
346
|
server.registerTool('get_queue_status', {
|
|
347
347
|
title: 'Get Queue Status',
|
|
@@ -406,7 +406,7 @@ export function registerDeliveryOpsTools(server) {
|
|
|
406
406
|
const { data, error } = await query;
|
|
407
407
|
if (error)
|
|
408
408
|
return j(dbToolError(error));
|
|
409
|
-
return j({ dlq: data ?? [], count: data?.length ?? 0 });
|
|
409
|
+
return j({ dlq: data ?? [], count: data?.length ?? 0, truncated: (data?.length ?? 0) === limit });
|
|
410
410
|
});
|
|
411
411
|
server.registerTool('get_enrollment_dlq', {
|
|
412
412
|
title: 'Get Enrollment DLQ',
|
|
@@ -436,7 +436,7 @@ export function registerDeliveryOpsTools(server) {
|
|
|
436
436
|
const { data, error } = await query;
|
|
437
437
|
if (error)
|
|
438
438
|
return j(dbToolError(error));
|
|
439
|
-
return j({ dlq: data ?? [], count: data?.length ?? 0 });
|
|
439
|
+
return j({ dlq: data ?? [], count: data?.length ?? 0, truncated: (data?.length ?? 0) === limit });
|
|
440
440
|
});
|
|
441
441
|
server.registerTool('get_send_queue_rows', {
|
|
442
442
|
title: 'Get Send Queue Rows',
|
package/build/tools/gdpr.js
CHANGED
|
@@ -110,7 +110,7 @@ export function registerGdprTools(server) {
|
|
|
110
110
|
.limit(limit ?? 50);
|
|
111
111
|
if (error)
|
|
112
112
|
return txt(`Error: ${dbToolError(error).error}`);
|
|
113
|
-
return j({ requests: data ?? [], count: data?.length ?? 0 });
|
|
113
|
+
return j({ requests: data ?? [], count: data?.length ?? 0, truncated: (data?.length ?? 0) === (limit ?? 50) });
|
|
114
114
|
});
|
|
115
115
|
server.registerTool('action_ccpa_request', {
|
|
116
116
|
title: 'Action CCPA Request',
|
|
@@ -183,7 +183,7 @@ export function registerNewsletterTools(server) {
|
|
|
183
183
|
const { data, error } = await query;
|
|
184
184
|
if (error)
|
|
185
185
|
return j(dbToolError(error));
|
|
186
|
-
return j({ newsletters: data ?? [], count: data?.length ?? 0 });
|
|
186
|
+
return j({ newsletters: data ?? [], count: data?.length ?? 0, truncated: (data?.length ?? 0) === limit });
|
|
187
187
|
});
|
|
188
188
|
server.registerTool('get_newsletter', {
|
|
189
189
|
title: 'Get Newsletter',
|
|
@@ -376,7 +376,7 @@ export function registerNewsletterTools(server) {
|
|
|
376
376
|
const { data, error } = await query;
|
|
377
377
|
if (error)
|
|
378
378
|
return j(dbToolError(error));
|
|
379
|
-
return j({ issues: data ?? [], count: data?.length ?? 0 });
|
|
379
|
+
return j({ issues: data ?? [], count: data?.length ?? 0, truncated: (data?.length ?? 0) === limit });
|
|
380
380
|
});
|
|
381
381
|
server.registerTool('schedule_newsletter_issue', {
|
|
382
382
|
title: 'Schedule Newsletter Issue',
|
|
@@ -587,7 +587,7 @@ export function registerNewsletterTools(server) {
|
|
|
587
587
|
const { data, error } = await query;
|
|
588
588
|
if (error)
|
|
589
589
|
return j(dbToolError(error));
|
|
590
|
-
return j({ subscribers: data ?? [], count: data?.length ?? 0 });
|
|
590
|
+
return j({ subscribers: data ?? [], count: data?.length ?? 0, truncated: (data?.length ?? 0) === limit });
|
|
591
591
|
});
|
|
592
592
|
server.registerTool('get_newsletter_stats', {
|
|
593
593
|
title: 'Get Newsletter Stats',
|
|
@@ -107,9 +107,9 @@ export function registerShortLinkTools(server) {
|
|
|
107
107
|
return j(dbToolError(linkError));
|
|
108
108
|
if (!link)
|
|
109
109
|
return j({ error: 'Short link not found', code: 'not_found' });
|
|
110
|
-
const { data: clicks, error: clickError } = await db()
|
|
110
|
+
const { data: clicks, error: clickError, count: total } = await db()
|
|
111
111
|
.from('short_link_clicks')
|
|
112
|
-
.select('clicked_at, ip_hash, referer')
|
|
112
|
+
.select('clicked_at, ip_hash, referer', { count: 'exact' })
|
|
113
113
|
.eq('short_link_id', short_link_id)
|
|
114
114
|
.order('clicked_at', { ascending: false })
|
|
115
115
|
.limit(500);
|
|
@@ -118,7 +118,9 @@ export function registerShortLinkTools(server) {
|
|
|
118
118
|
const uniqueClicks = new Set((clicks ?? []).map((click) => click.ip_hash).filter(Boolean)).size;
|
|
119
119
|
return j({
|
|
120
120
|
short_link: link,
|
|
121
|
-
total_clicks: link.click_count ?? clicks?.length ?? 0,
|
|
121
|
+
total_clicks: link.click_count ?? total ?? clicks?.length ?? 0,
|
|
122
|
+
...(total != null ? { total } : {}),
|
|
123
|
+
truncated: (clicks?.length ?? 0) === 500,
|
|
122
124
|
unique_clicks: uniqueClicks,
|
|
123
125
|
recent_clicks: clicks ?? [],
|
|
124
126
|
});
|
package/build/tools/surveys.js
CHANGED
|
@@ -140,7 +140,7 @@ export function registerSurveyTools(server) {
|
|
|
140
140
|
status: z.enum(['draft', 'active', 'closed']).optional(),
|
|
141
141
|
limit: z.number().int().min(1).max(200).optional().default(50),
|
|
142
142
|
},
|
|
143
|
-
}, async ({ status, limit }) => {
|
|
143
|
+
}, async ({ status, limit = 50 }) => {
|
|
144
144
|
const projectId = getProjectId();
|
|
145
145
|
let query = db().from('surveys').select('id, title, status, short_link_id, created_at, updated_at').eq('project_id', projectId).order('created_at', { ascending: false }).limit(limit);
|
|
146
146
|
if (status)
|
|
@@ -148,7 +148,7 @@ export function registerSurveyTools(server) {
|
|
|
148
148
|
const { data, error } = await query;
|
|
149
149
|
if (error)
|
|
150
150
|
return j(dbToolError(error));
|
|
151
|
-
return j({ surveys: data ?? [], count: data?.length ?? 0 });
|
|
151
|
+
return j({ surveys: data ?? [], count: data?.length ?? 0, truncated: (data?.length ?? 0) === limit });
|
|
152
152
|
});
|
|
153
153
|
server.registerTool('get_survey', {
|
|
154
154
|
title: 'Get Survey',
|
package/build/tools/templates.js
CHANGED
|
@@ -93,7 +93,7 @@ export function registerTemplateTools(server) {
|
|
|
93
93
|
const { data, error } = await query;
|
|
94
94
|
if (error)
|
|
95
95
|
return j(dbToolError(error));
|
|
96
|
-
return j({ templates: data ?? [], count: data?.length ?? 0 });
|
|
96
|
+
return j({ templates: data ?? [], count: data?.length ?? 0, truncated: (data?.length ?? 0) === limit });
|
|
97
97
|
});
|
|
98
98
|
server.registerTool('translate_template', {
|
|
99
99
|
title: 'Translate Template',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sendinel/mcp-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.150",
|
|
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",
|