@sendinel/mcp-server 1.0.19 → 1.0.20
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/contacts.js +28 -11
- package/package.json +1 -1
package/build/tools/contacts.js
CHANGED
|
@@ -2241,16 +2241,30 @@ Requirements: urgency without desperation, acknowledge the gap, one clear CTA, v
|
|
|
2241
2241
|
});
|
|
2242
2242
|
if (error) {
|
|
2243
2243
|
// Fallback: inline query if RPC not yet available
|
|
2244
|
-
const
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2244
|
+
const SCHEMA_SAMPLE_LIMIT = 500;
|
|
2245
|
+
async function sampleSubscriberProperties(scopeToSite) {
|
|
2246
|
+
let query = db()
|
|
2247
|
+
.from('subscribers')
|
|
2248
|
+
.select('custom_properties')
|
|
2249
|
+
.eq('project_id', projectId)
|
|
2250
|
+
.not('custom_properties', 'is', null)
|
|
2251
|
+
.order('created_at', { ascending: false });
|
|
2252
|
+
if (scopeToSite)
|
|
2253
|
+
query = query.eq('source_site', site_id);
|
|
2254
|
+
return query.limit(SCHEMA_SAMPLE_LIMIT);
|
|
2255
|
+
}
|
|
2256
|
+
const siteSample = await sampleSubscriberProperties(true);
|
|
2257
|
+
if (siteSample.error)
|
|
2258
|
+
return txt(`Error: ${siteSample.error.message}`);
|
|
2259
|
+
let rows = siteSample.data ?? [];
|
|
2260
|
+
let scope = 'site';
|
|
2261
|
+
if (rows.length === 0) {
|
|
2262
|
+
const projectSample = await sampleSubscriberProperties(false);
|
|
2263
|
+
if (projectSample.error)
|
|
2264
|
+
return txt(`Error: ${projectSample.error.message}`);
|
|
2265
|
+
rows = projectSample.data ?? [];
|
|
2266
|
+
scope = 'project';
|
|
2267
|
+
}
|
|
2254
2268
|
const keyMap = new Map();
|
|
2255
2269
|
for (const row of rows ?? []) {
|
|
2256
2270
|
const props = row.custom_properties;
|
|
@@ -2277,9 +2291,12 @@ Requirements: urgency without desperation, acknowledge the gap, one clear CTA, v
|
|
|
2277
2291
|
}));
|
|
2278
2292
|
return j({
|
|
2279
2293
|
site_id,
|
|
2294
|
+
scope,
|
|
2280
2295
|
total_keys: schema.length,
|
|
2281
2296
|
schema,
|
|
2282
|
-
note:
|
|
2297
|
+
note: scope === 'project'
|
|
2298
|
+
? `No contacts are tagged to site ${site_id} via source_site — sampled custom_properties across the whole project instead. Use merge_tag syntax in email body/subject. For sensitive data, add a fallback: {{custom.plan|subscriber}}. ⚠️ custom_properties data passes through the Anthropic API — avoid storing sensitive PII (SSNs, passwords, financial account numbers).`
|
|
2299
|
+
: 'Use merge_tag syntax in email body/subject. For sensitive data, add a fallback: {{custom.plan|subscriber}}. ⚠️ custom_properties data passes through the Anthropic API — avoid storing sensitive PII (SSNs, passwords, financial account numbers).',
|
|
2283
2300
|
});
|
|
2284
2301
|
}
|
|
2285
2302
|
return j({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sendinel/mcp-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.20",
|
|
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",
|