@sendinel/mcp-server 1.0.40 → 1.0.42
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/action-approvals.js +1 -1
- package/build/tools/contacts.js +35 -12
- package/package.json +1 -1
|
@@ -277,7 +277,7 @@ export async function requestApproval(action, params, apiKeyId, channelContext,
|
|
|
277
277
|
action,
|
|
278
278
|
summary,
|
|
279
279
|
expires_at: expiresAt,
|
|
280
|
-
approve_via: 'Open approve_url (works on a phone)
|
|
280
|
+
approve_via: 'Open approve_url (works on a phone) or Dashboard → Settings → Pending Approvals',
|
|
281
281
|
approve_url: approvalPageUrl(data.id),
|
|
282
282
|
message: `This action requires human approval. A notification has been sent to your dashboard. Approval ID: ${data.id}. Check status with: poll this approval_id, or wait for the webhook callback (event: approval.decided). Token expires in 30 minutes.`,
|
|
283
283
|
};
|
package/build/tools/contacts.js
CHANGED
|
@@ -2115,16 +2115,10 @@ Requirements: urgency without desperation, acknowledge the gap, one clear CTA, v
|
|
|
2115
2115
|
const projectId = getProjectId();
|
|
2116
2116
|
const maxGroups = Math.min(limit, 200);
|
|
2117
2117
|
const CONTACT_SCAN_LIMIT = 2000;
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
.eq('global_unsubscribed', false)
|
|
2123
|
-
.order('created_at', { ascending: true })
|
|
2124
|
-
.limit(CONTACT_SCAN_LIMIT);
|
|
2125
|
-
// #3604: hide seed/fixture rows like every other default contact view.
|
|
2126
|
-
if (!include_test)
|
|
2127
|
-
q = q.not('is_test', 'is', true);
|
|
2118
|
+
// #3604: PostgREST returns at most 1,000 rows per request, so a single
|
|
2119
|
+
// .limit(2000) query only ever read 1,000. Read in pages up to the limit.
|
|
2120
|
+
const SCAN_PAGE = 1000;
|
|
2121
|
+
let siteIds = null;
|
|
2128
2122
|
if (site_id) {
|
|
2129
2123
|
const { data: subs } = await db()
|
|
2130
2124
|
.from('site_subscriptions')
|
|
@@ -2134,9 +2128,38 @@ Requirements: urgency without desperation, acknowledge the gap, one clear CTA, v
|
|
|
2134
2128
|
const ids = (subs ?? []).map((s) => s.contact_id);
|
|
2135
2129
|
if (!ids.length)
|
|
2136
2130
|
return j({ duplicate_groups: [], total_groups: 0, coverage: { contacts_scanned: 0, contacts_matching: 0, contact_limit: CONTACT_SCAN_LIMIT, complete: true } });
|
|
2137
|
-
|
|
2131
|
+
siteIds = ids;
|
|
2132
|
+
}
|
|
2133
|
+
const pageQuery = (from) => {
|
|
2134
|
+
let q = db()
|
|
2135
|
+
.from('subscribers')
|
|
2136
|
+
.select('id, email, first_name, last_name, engagement_score, lifecycle_stage, created_at, source', { count: 'exact' })
|
|
2137
|
+
.eq('project_id', projectId)
|
|
2138
|
+
.eq('global_unsubscribed', false);
|
|
2139
|
+
// #3604: hide seed/fixture rows like every other default contact view.
|
|
2140
|
+
if (!include_test)
|
|
2141
|
+
q = q.not('is_test', 'is', true);
|
|
2142
|
+
if (siteIds)
|
|
2143
|
+
q = q.in('id', siteIds);
|
|
2144
|
+
return q.order('created_at', { ascending: true }).order('id', { ascending: true })
|
|
2145
|
+
.range(from, Math.min(from + SCAN_PAGE, CONTACT_SCAN_LIMIT) - 1);
|
|
2146
|
+
};
|
|
2147
|
+
const contacts = [];
|
|
2148
|
+
let count = null;
|
|
2149
|
+
let error = null;
|
|
2150
|
+
for (let from = 0; from < CONTACT_SCAN_LIMIT; from += SCAN_PAGE) {
|
|
2151
|
+
const res = await pageQuery(from);
|
|
2152
|
+
if (res.error) {
|
|
2153
|
+
error = res.error;
|
|
2154
|
+
break;
|
|
2155
|
+
}
|
|
2156
|
+
if (from === 0)
|
|
2157
|
+
count = typeof res.count === 'number' ? res.count : null;
|
|
2158
|
+
const rows = res.data ?? [];
|
|
2159
|
+
contacts.push(...rows);
|
|
2160
|
+
if (rows.length < SCAN_PAGE)
|
|
2161
|
+
break;
|
|
2138
2162
|
}
|
|
2139
|
-
const { data: contacts, error, count } = await q;
|
|
2140
2163
|
if (error)
|
|
2141
2164
|
return txt(`Error: ${error.message}`);
|
|
2142
2165
|
// #3604: say when the scan stopped at the limit instead of presenting a partial scan as complete.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sendinel/mcp-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.42",
|
|
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",
|