@sendinel/mcp-server 1.0.46 → 1.0.48
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/README.md +2 -2
- package/build/tools/contacts.js +27 -9
- package/build/tools/org.js +25 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ AI-controlled email operations control plane for campaigns, contacts, segments,
|
|
|
12
12
|
|
|
13
13
|
## Tool groups
|
|
14
14
|
|
|
15
|
-
Sendinel currently exposes 34 tool groups and
|
|
15
|
+
Sendinel currently exposes 34 tool groups and 321 tools (gateway mode adds 3 meta-tools). These counts are checked against the tool registry in CI, so this table matches what ships.
|
|
16
16
|
|
|
17
17
|
| Group | Count | Purpose |
|
|
18
18
|
|-------|-------|---------|
|
|
@@ -38,7 +38,7 @@ Sendinel currently exposes 34 tool groups and 320 tools (gateway mode adds 3 met
|
|
|
38
38
|
| `landing-pages` | 5 | Landing page CRUD |
|
|
39
39
|
| `lists` | 7 | Static contact lists and membership management |
|
|
40
40
|
| `newsletters` | 12 | Newsletter publications, issues, subscribers, scheduling, sending, stats |
|
|
41
|
-
| `org` |
|
|
41
|
+
| `org` | 22 | Team members, plan usage/limits, audit log, model registry, white-label, support tickets, provider switching |
|
|
42
42
|
| `segments` | 6 | Audience builder: create, edit, natural-language generation, preview |
|
|
43
43
|
| `short-links` | 3 | Short links, click stats, QR codes |
|
|
44
44
|
| `signatures` | 4 | Sending signature blocks |
|
package/build/tools/contacts.js
CHANGED
|
@@ -625,15 +625,33 @@ export function registerContactTools(server) {
|
|
|
625
625
|
}, async () => {
|
|
626
626
|
const projectId = getProjectId();
|
|
627
627
|
const cutoff = daysAgo(90);
|
|
628
|
-
//
|
|
629
|
-
//
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
628
|
+
// Overwrite of existing tags is fixed (#3834). Writes are per-row, so paging this
|
|
629
|
+
// read past 1000 is now safe as a follow-up.
|
|
630
|
+
const { data: contacts, error: readError } = await db().from('subscribers').select('id, email, first_name, last_name, custom_properties, tags, last_engaged_at').eq('project_id', projectId).lt('last_engaged_at', cutoff).limit(1000);
|
|
631
|
+
if (readError)
|
|
632
|
+
return j({ error: readError.message });
|
|
633
|
+
let tagged = 0;
|
|
634
|
+
let skipped = 0;
|
|
635
|
+
let failed = 0;
|
|
636
|
+
let firstError;
|
|
637
|
+
for (const contact of contacts ?? []) {
|
|
638
|
+
const current = contact.tags ?? [];
|
|
639
|
+
if (current.includes('cold')) {
|
|
640
|
+
skipped++;
|
|
641
|
+
continue;
|
|
642
|
+
}
|
|
643
|
+
const merged = [...current, 'cold'];
|
|
644
|
+
const { error } = await db().from('subscribers').update({ tags: merged }).eq('id', contact.id).eq('project_id', projectId);
|
|
645
|
+
if (error) {
|
|
646
|
+
failed++;
|
|
647
|
+
if (!firstError)
|
|
648
|
+
firstError = error.message;
|
|
649
|
+
continue;
|
|
650
|
+
}
|
|
651
|
+
tagged++;
|
|
652
|
+
await writeBackMcpContact(projectId, contact, { tags: merged });
|
|
653
|
+
}
|
|
654
|
+
return j({ tagged, suppressed: 0, skipped, ...(failed ? { failed, error: firstError } : {}) });
|
|
637
655
|
});
|
|
638
656
|
server.registerTool('list_hygiene_audit', {
|
|
639
657
|
title: 'List Hygiene Audit',
|
package/build/tools/org.js
CHANGED
|
@@ -857,6 +857,31 @@ export function registerOrgTools(server) {
|
|
|
857
857
|
});
|
|
858
858
|
return result.ok ? j(result.data) : j({ error: result.error });
|
|
859
859
|
});
|
|
860
|
+
server.registerTool('list_my_support_tickets', {
|
|
861
|
+
title: 'List My Support Tickets',
|
|
862
|
+
annotations: {
|
|
863
|
+
readOnlyHint: true,
|
|
864
|
+
destructiveHint: false,
|
|
865
|
+
idempotentHint: true,
|
|
866
|
+
openWorldHint: false,
|
|
867
|
+
},
|
|
868
|
+
description: 'Check the status of support tickets filed by the caller\'s organization, including plain-language status, assigned owner, next step, and related issue numbers. Optional ticket and status filters.',
|
|
869
|
+
inputSchema: {
|
|
870
|
+
ticket: z.string().optional().describe('Filter by ticket number or reference, e.g. "SND-1015" or "1015"'),
|
|
871
|
+
status: z.string().optional().describe('Filter by status, e.g. "open", "in progress", "resolved", "closed"'),
|
|
872
|
+
},
|
|
873
|
+
}, async ({ ticket, status }) => {
|
|
874
|
+
const query = {};
|
|
875
|
+
if (ticket)
|
|
876
|
+
query.ticket = ticket;
|
|
877
|
+
if (status)
|
|
878
|
+
query.status = status;
|
|
879
|
+
const result = await callSendinelV1('/api/v1/support/tickets', {
|
|
880
|
+
method: 'GET',
|
|
881
|
+
query,
|
|
882
|
+
});
|
|
883
|
+
return result.ok ? j(result.data) : j({ error: result.error });
|
|
884
|
+
});
|
|
860
885
|
server.registerTool('start_provider_switch', {
|
|
861
886
|
title: 'Start Provider Switch',
|
|
862
887
|
annotations: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sendinel/mcp-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.48",
|
|
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",
|