shipmail-mcp 0.8.8 → 0.9.0
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/.claude-plugin/plugin.json +3 -3
- package/.codex-plugin/plugin.json +9 -8
- package/.plugin/plugin.json +3 -3
- package/README.md +17 -24
- package/assets/shipmail-logo.png +0 -0
- package/assets/shipmail-logo.svg +1 -7
- package/assets/shipmail-mark-400.png +0 -0
- package/assets/shipmail-mark.png +0 -0
- package/assets/shipmail-mark.svg +1 -6
- package/dist/capabilities.d.ts +2 -8
- package/dist/capabilities.js +5 -65
- package/dist/index.js +89 -427
- package/dist/server.d.ts +1 -2
- package/dist/server.js +88 -422
- package/distribution/shipmail/.claude-plugin/plugin.json +3 -3
- package/distribution/shipmail/.codex-plugin/plugin.json +9 -8
- package/distribution/shipmail/.plugin/plugin.json +3 -3
- package/distribution/shipmail/assets/shipmail-logo.png +0 -0
- package/distribution/shipmail/assets/shipmail-logo.svg +1 -7
- package/distribution/shipmail/assets/shipmail-mark-400.png +0 -0
- package/distribution/shipmail/assets/shipmail-mark.png +0 -0
- package/distribution/shipmail/assets/shipmail-mark.svg +1 -6
- package/distribution/shipmail/skills/shipmail/SKILL.md +2 -2
- package/package.json +2 -2
- package/server.json +2 -2
- package/skills/shipmail/SKILL.md +2 -2
- package/smithery.yaml +1 -1
package/dist/index.js
CHANGED
|
@@ -19,8 +19,6 @@ Environment:
|
|
|
19
19
|
SHIPMAIL_API_KEY when set; reduces env-trace leak surface for hosts that
|
|
20
20
|
log environment variables.
|
|
21
21
|
SHIPMAIL_BASE_URL Optional API base URL. Must be https. Defaults to ${DEFAULT_BASE_URL}.
|
|
22
|
-
SHIPMAIL_ORGANIZATION_ID
|
|
23
|
-
Optional delegated child organization ID for infrastructure tools.
|
|
24
22
|
SHIPMAIL_ALLOW_INSECURE_BASE_URL=1
|
|
25
23
|
Permit non-https or non-shipmail.to base URL (development only).
|
|
26
24
|
|
|
@@ -89,8 +87,7 @@ function readConfig(argv = process.argv.slice(2)) {
|
|
|
89
87
|
const baseUrl = rawBaseUrl !== void 0 && rawBaseUrl.length > 0 ? validateBaseUrl(rawBaseUrl, allowInsecure) : void 0;
|
|
90
88
|
return {
|
|
91
89
|
apiKey: readApiKey(),
|
|
92
|
-
baseUrl
|
|
93
|
-
organizationId: env["SHIPMAIL_ORGANIZATION_ID"] || void 0
|
|
90
|
+
baseUrl
|
|
94
91
|
};
|
|
95
92
|
}
|
|
96
93
|
|
|
@@ -266,19 +263,6 @@ var MCP_PERMISSION_GROUPS = [
|
|
|
266
263
|
description: "Read and remove suppressed recipient addresses.",
|
|
267
264
|
scopes: ["suppressions:read", "suppressions:write"],
|
|
268
265
|
persistent: false
|
|
269
|
-
},
|
|
270
|
-
{
|
|
271
|
-
name: "partner_admin",
|
|
272
|
-
label: "Partner administration",
|
|
273
|
-
description: "Manage delegated partner organizations, credential grants, and usage.",
|
|
274
|
-
scopes: [
|
|
275
|
-
"partner:organizations:read",
|
|
276
|
-
"partner:organizations:write",
|
|
277
|
-
"partner:organizations:access",
|
|
278
|
-
"partner:mailbox_credentials:issue",
|
|
279
|
-
"partner:usage:read"
|
|
280
|
-
],
|
|
281
|
-
persistent: true
|
|
282
266
|
}
|
|
283
267
|
];
|
|
284
268
|
var CAPABILITY_ROWS = [
|
|
@@ -435,50 +419,7 @@ var CAPABILITY_ROWS = [
|
|
|
435
419
|
["shipmail_create_booking_page", "createBookingPage", "booking_pages:write"],
|
|
436
420
|
["shipmail_get_booking_page", "getBookingPage", "booking_pages:read"],
|
|
437
421
|
["shipmail_update_booking_page", "updateBookingPage", "booking_pages:write"],
|
|
438
|
-
["shipmail_delete_booking_page", "deleteBookingPage", "booking_pages:write"]
|
|
439
|
-
["shipmail_list_partner_organizations", "listPartnerOrganizations", "partner:organizations:read"],
|
|
440
|
-
[
|
|
441
|
-
"shipmail_create_partner_organization",
|
|
442
|
-
"createPartnerOrganization",
|
|
443
|
-
"partner:organizations:write"
|
|
444
|
-
],
|
|
445
|
-
["shipmail_get_partner_organization", "getPartnerOrganization", "partner:organizations:read"],
|
|
446
|
-
[
|
|
447
|
-
"shipmail_update_partner_organization",
|
|
448
|
-
"updatePartnerOrganization",
|
|
449
|
-
"partner:organizations:write"
|
|
450
|
-
],
|
|
451
|
-
[
|
|
452
|
-
"shipmail_resend_partner_ownership_invitation",
|
|
453
|
-
"resendPartnerOwnershipInvitation",
|
|
454
|
-
"partner:organizations:write"
|
|
455
|
-
],
|
|
456
|
-
[
|
|
457
|
-
"shipmail_suspend_partner_organization",
|
|
458
|
-
"suspendPartnerOrganization",
|
|
459
|
-
"partner:organizations:write"
|
|
460
|
-
],
|
|
461
|
-
[
|
|
462
|
-
"shipmail_resume_partner_organization",
|
|
463
|
-
"resumePartnerOrganization",
|
|
464
|
-
"partner:organizations:write"
|
|
465
|
-
],
|
|
466
|
-
[
|
|
467
|
-
"shipmail_offboard_partner_organization",
|
|
468
|
-
"offboardPartnerOrganization",
|
|
469
|
-
"partner:organizations:write"
|
|
470
|
-
],
|
|
471
|
-
[
|
|
472
|
-
"shipmail_list_partner_mailbox_credential_grants",
|
|
473
|
-
"listPartnerMailboxCredentialGrants",
|
|
474
|
-
"partner:mailbox_credentials:issue"
|
|
475
|
-
],
|
|
476
|
-
[
|
|
477
|
-
"shipmail_consume_partner_mailbox_credential_grant",
|
|
478
|
-
"consumePartnerMailboxCredentialGrant",
|
|
479
|
-
"partner:mailbox_credentials:issue"
|
|
480
|
-
],
|
|
481
|
-
["shipmail_get_partner_usage", "getPartnerUsage", "partner:usage:read"]
|
|
422
|
+
["shipmail_delete_booking_page", "deleteBookingPage", "booking_pages:write"]
|
|
482
423
|
];
|
|
483
424
|
var MEMBER_GROUPS = new Set(
|
|
484
425
|
MCP_MEMBER_PERMISSION_GROUP_NAMES
|
|
@@ -487,14 +428,12 @@ var DESTRUCTIVE_PREFIXES = [
|
|
|
487
428
|
"shipmail_delete_",
|
|
488
429
|
"shipmail_remove_",
|
|
489
430
|
"shipmail_revoke_",
|
|
490
|
-
"shipmail_offboard_",
|
|
491
431
|
"shipmail_cancel_"
|
|
492
432
|
];
|
|
493
433
|
var DESTRUCTIVE_TOOLS = /* @__PURE__ */ new Set([
|
|
494
434
|
"shipmail_create_mailbox_app_password",
|
|
495
435
|
"shipmail_create_mailbox_export",
|
|
496
436
|
"shipmail_rotate_webhook_secret",
|
|
497
|
-
"shipmail_consume_partner_mailbox_credential_grant",
|
|
498
437
|
"shipmail_rotate_audience_feed",
|
|
499
438
|
"shipmail_revoke_audience_feed"
|
|
500
439
|
]);
|
|
@@ -541,7 +480,6 @@ var OPEN_WORLD_READ_SCOPES = /* @__PURE__ */ new Set([
|
|
|
541
480
|
]);
|
|
542
481
|
function permissionGroupFor(toolName, requiredScope) {
|
|
543
482
|
if (requiredScope === "public") return "account_status";
|
|
544
|
-
if (requiredScope.startsWith("partner:")) return "partner_admin";
|
|
545
483
|
if (requiredScope.startsWith("domains:")) return "domain_admin";
|
|
546
484
|
if (requiredScope.startsWith("mailbox_credentials:")) return "credentials";
|
|
547
485
|
if (requiredScope.startsWith("mailbox_forwarding:")) return "forwarding";
|
|
@@ -582,7 +520,7 @@ function recipientControlFor(toolName) {
|
|
|
582
520
|
}
|
|
583
521
|
function durationFor(toolName) {
|
|
584
522
|
if (toolName === "shipmail_run_automation") return "one_shot";
|
|
585
|
-
if (toolName.includes("app_password") || toolName
|
|
523
|
+
if (toolName.includes("app_password") || toolName === "shipmail_rotate_webhook_secret") {
|
|
586
524
|
return "credential";
|
|
587
525
|
}
|
|
588
526
|
if (toolName.includes("forwarding") || toolName.includes("mailbox_rule") || toolName.includes("webhook") || toolName.includes("booking_page") || toolName.includes("automation")) {
|
|
@@ -595,7 +533,7 @@ function durationFor(toolName) {
|
|
|
595
533
|
}
|
|
596
534
|
function idempotencyFor(toolName, effect) {
|
|
597
535
|
if (effect === "read") return "none";
|
|
598
|
-
if (toolName === "shipmail_create_mailbox_app_password" || toolName === "
|
|
536
|
+
if (toolName === "shipmail_create_mailbox_app_password" || toolName === "shipmail_prepare_newsletter_asset_upload" || toolName === "shipmail_prepare_staged_attachment_upload") {
|
|
599
537
|
return "forbidden";
|
|
600
538
|
}
|
|
601
539
|
if (DESTRUCTIVE_PREFIXES.some((prefix) => toolName.startsWith(prefix)) || toolName.startsWith("shipmail_suspend_") || toolName.startsWith("shipmail_resume_")) {
|
|
@@ -626,7 +564,7 @@ function defineCapability(row) {
|
|
|
626
564
|
},
|
|
627
565
|
auditAction: effect === "read" ? null : "api.mutation",
|
|
628
566
|
transports: {
|
|
629
|
-
hostedOAuth:
|
|
567
|
+
hostedOAuth: true,
|
|
630
568
|
directApiKeyHttp: true,
|
|
631
569
|
stdio: toolName !== "shipmail_compose_message_with_file" && toolName !== "shipmail_upload_newsletter_asset_with_file"
|
|
632
570
|
}
|
|
@@ -740,7 +678,7 @@ var MAX_STRING_LENGTH = 16384;
|
|
|
740
678
|
var TRUNCATION_MARKER = "\n\u2026[truncated]";
|
|
741
679
|
var DANGEROUS_CHARS_REGEX = (
|
|
742
680
|
// eslint-disable-next-line no-control-regex
|
|
743
|
-
/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F
|
|
681
|
+
/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F\u061C\u200B\u200E\u200F\u202A-\u202E\u2060\u2066-\u2069\uFEFF\u{E0000}-\u{E007F}]/gu
|
|
744
682
|
);
|
|
745
683
|
function sanitizeString(value, maxLength = MAX_STRING_LENGTH) {
|
|
746
684
|
const stripped = value.replace(DANGEROUS_CHARS_REGEX, "");
|
|
@@ -751,26 +689,25 @@ function sanitizeString(value, maxLength = MAX_STRING_LENGTH) {
|
|
|
751
689
|
function isPlainObject(value) {
|
|
752
690
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
753
691
|
}
|
|
754
|
-
function
|
|
692
|
+
function childField(field, key) {
|
|
693
|
+
return field !== void 0 && field.path[0] === key ? { path: field.path.slice(1), maxLength: field.maxLength } : void 0;
|
|
694
|
+
}
|
|
695
|
+
function sanitizeValue(value, longField) {
|
|
755
696
|
if (typeof value === "string") {
|
|
756
|
-
return sanitizeString(value,
|
|
697
|
+
return sanitizeString(value, longField?.path.length === 0 ? longField.maxLength : void 0);
|
|
757
698
|
}
|
|
758
699
|
if (Array.isArray(value)) {
|
|
759
|
-
return value.map((item) => sanitizeValue(item
|
|
700
|
+
return value.map((item) => sanitizeValue(item));
|
|
760
701
|
}
|
|
761
702
|
if (isPlainObject(value)) {
|
|
762
|
-
|
|
763
|
-
for (const [key, item] of Object.entries(value)) {
|
|
764
|
-
out[key] = sanitizeValue(item, maxStringLength);
|
|
765
|
-
}
|
|
766
|
-
return out;
|
|
703
|
+
return sanitizeRecord(value, longField);
|
|
767
704
|
}
|
|
768
705
|
return value;
|
|
769
706
|
}
|
|
770
|
-
function sanitizeRecord(value,
|
|
707
|
+
function sanitizeRecord(value, longField) {
|
|
771
708
|
const out = {};
|
|
772
709
|
for (const [key, item] of Object.entries(value)) {
|
|
773
|
-
out[key] = sanitizeValue(item,
|
|
710
|
+
out[key] = sanitizeValue(item, childField(longField, key));
|
|
774
711
|
}
|
|
775
712
|
return out;
|
|
776
713
|
}
|
|
@@ -791,8 +728,8 @@ var GENERIC_INTERNAL_MESSAGE = "Internal MCP error. The original message is logg
|
|
|
791
728
|
var MCP_RATE_LIMIT_MARKER = "[mcp.rate_limit]";
|
|
792
729
|
var MCP_SCHEMA_VIOLATION_MARKER = "[mcp.schema_violation]";
|
|
793
730
|
var SAFE_MARKERS = [MCP_RATE_LIMIT_MARKER, MCP_SCHEMA_VIOLATION_MARKER];
|
|
794
|
-
function jsonResult(structuredContent) {
|
|
795
|
-
const sanitized = sanitizeRecord(structuredContent);
|
|
731
|
+
function jsonResult(structuredContent, longField) {
|
|
732
|
+
const sanitized = sanitizeRecord(structuredContent, longField);
|
|
796
733
|
return {
|
|
797
734
|
content: [
|
|
798
735
|
{
|
|
@@ -998,6 +935,7 @@ function isPublicHttpsUrl(rawUrl) {
|
|
|
998
935
|
if (host.startsWith("[") && host.endsWith("]")) {
|
|
999
936
|
host = host.slice(1, -1);
|
|
1000
937
|
}
|
|
938
|
+
host = host.replace(/\.$/, "");
|
|
1001
939
|
if (host.length === 0) return false;
|
|
1002
940
|
for (const pattern of PRIVATE_HOST_NAME_PATTERNS) {
|
|
1003
941
|
if (pattern.test(host)) return false;
|
|
@@ -1183,7 +1121,7 @@ var mailboxSchema = z.object({
|
|
|
1183
1121
|
address: z.string(),
|
|
1184
1122
|
display_name: z.string().nullable(),
|
|
1185
1123
|
suspended_at: z.string().nullable(),
|
|
1186
|
-
suspension_reasons: z.array(z.enum(["billing", "manual", "security"])),
|
|
1124
|
+
suspension_reasons: z.array(z.enum(["billing", "manual", "security", "abuse"])),
|
|
1187
1125
|
auto_reply: autoReplySchema,
|
|
1188
1126
|
created_at: z.string(),
|
|
1189
1127
|
updated_at: z.string()
|
|
@@ -1244,7 +1182,7 @@ var mailboxAppPasswordSchema = z.object({
|
|
|
1244
1182
|
mailbox_id: z.string(),
|
|
1245
1183
|
name: z.string(),
|
|
1246
1184
|
state: z.enum(["pending_create", "active", "pending_revoke", "revoked", "failed"]),
|
|
1247
|
-
purpose: z.enum(["operator_client"
|
|
1185
|
+
purpose: z.enum(["operator_client"]),
|
|
1248
1186
|
expires_at: z.string().nullable(),
|
|
1249
1187
|
allowed_cidrs: z.array(z.string()),
|
|
1250
1188
|
last_used_at: z.string().nullable(),
|
|
@@ -1254,23 +1192,6 @@ var mailboxAppPasswordSchema = z.object({
|
|
|
1254
1192
|
var createdMailboxAppPasswordSchema = mailboxAppPasswordSchema.extend({
|
|
1255
1193
|
secret: z.string()
|
|
1256
1194
|
});
|
|
1257
|
-
var partnerMailboxCredentialSchema = createdMailboxAppPasswordSchema.extend({
|
|
1258
|
-
operator_notified: z.boolean()
|
|
1259
|
-
});
|
|
1260
|
-
var partnerMailboxCredentialGrantSchema = z.object({
|
|
1261
|
-
object: z.literal("partner_mailbox_credential_grant"),
|
|
1262
|
-
id: z.string(),
|
|
1263
|
-
partner_organization_id: z.string(),
|
|
1264
|
-
organization_id: z.string(),
|
|
1265
|
-
organization_name: z.string(),
|
|
1266
|
-
external_reference: z.string(),
|
|
1267
|
-
operator_email: z.string(),
|
|
1268
|
-
mailbox_id: z.string(),
|
|
1269
|
-
mailbox_address: z.string(),
|
|
1270
|
-
disclosure_version: z.string(),
|
|
1271
|
-
expires_at: z.string(),
|
|
1272
|
-
consented_at: z.string()
|
|
1273
|
-
});
|
|
1274
1195
|
var mailboxFolderSchema = z.object({
|
|
1275
1196
|
object: z.literal("mailbox_folder"),
|
|
1276
1197
|
id: z.string(),
|
|
@@ -1447,7 +1368,8 @@ var inboxFullMessageSchema = inboxMessageSchema.omit({ object: true }).extend({
|
|
|
1447
1368
|
var inboxAttachmentContentSchema = inboxAttachmentSchema.omit({ download_path: true }).extend({
|
|
1448
1369
|
object: z.literal("inbox_attachment_content"),
|
|
1449
1370
|
mailbox_id: z.string(),
|
|
1450
|
-
message_id: z.string()
|
|
1371
|
+
message_id: z.string(),
|
|
1372
|
+
text: z.string().optional()
|
|
1451
1373
|
});
|
|
1452
1374
|
var inboxMessagesSchema = z.object({
|
|
1453
1375
|
object: z.literal("inbox_messages"),
|
|
@@ -1740,6 +1662,8 @@ var scheduledMessageSchema = z.object({
|
|
|
1740
1662
|
object: z.literal("scheduled_message"),
|
|
1741
1663
|
id: z.string(),
|
|
1742
1664
|
scheduled_message_id: z.string(),
|
|
1665
|
+
// Optional so this package keeps working against a server that predates the field.
|
|
1666
|
+
status: z.enum(["scheduled", "settling"]).optional(),
|
|
1743
1667
|
kind: z.enum(["scheduled", "undo"]),
|
|
1744
1668
|
mailbox_id: z.string(),
|
|
1745
1669
|
mailbox_address: z.string(),
|
|
@@ -1838,6 +1762,8 @@ var webhookSchema = z.object({
|
|
|
1838
1762
|
events: z.array(z.enum(WEBHOOK_EVENT_TYPES)),
|
|
1839
1763
|
active: z.boolean(),
|
|
1840
1764
|
description: z.string().nullable(),
|
|
1765
|
+
mailbox_ids: z.array(z.string()).nullable(),
|
|
1766
|
+
domain_ids: z.array(z.string()).nullable(),
|
|
1841
1767
|
created_at: z.string(),
|
|
1842
1768
|
updated_at: z.string()
|
|
1843
1769
|
});
|
|
@@ -1905,14 +1831,6 @@ var mailboxAppPasswordsOutputSchema = z.object({
|
|
|
1905
1831
|
data: z.array(mailboxAppPasswordSchema)
|
|
1906
1832
|
})
|
|
1907
1833
|
});
|
|
1908
|
-
var partnerMailboxCredentialOutputSchema = z.object({
|
|
1909
|
-
credential: partnerMailboxCredentialSchema
|
|
1910
|
-
});
|
|
1911
|
-
var partnerMailboxCredentialGrantsOutputSchema = z.object({
|
|
1912
|
-
grants: z.object({
|
|
1913
|
-
data: z.array(partnerMailboxCredentialGrantSchema)
|
|
1914
|
-
})
|
|
1915
|
-
});
|
|
1916
1834
|
var mailboxFolderOutputSchema = z.object({ folder: mailboxFolderSchema });
|
|
1917
1835
|
var mailboxFoldersOutputSchema = z.object({ folders: mailboxFoldersSchema });
|
|
1918
1836
|
var mailboxRulesOutputSchema = z.object({ rules: mailboxRulesSchema });
|
|
@@ -2634,10 +2552,15 @@ var webhookEventSchema = z.enum(WEBHOOK_EVENT_TYPES);
|
|
|
2634
2552
|
var webhookDeliveryStatusSchema = z.enum(WEBHOOK_DELIVERY_STATUSES);
|
|
2635
2553
|
var listWebhooksInputSchema = paginationInputSchema;
|
|
2636
2554
|
var listMembersInputSchema = paginationInputSchema;
|
|
2555
|
+
var webhookScopeIdsInputSchema = z.array(idSchema).max(100).nullable();
|
|
2637
2556
|
var createWebhookInputSchema = z.object({
|
|
2638
2557
|
url: publicHttpsUrlSchema,
|
|
2639
2558
|
events: z.array(webhookEventSchema).min(1).max(WEBHOOK_EVENT_TYPES.length),
|
|
2640
2559
|
description: noControlString(500, "description").optional(),
|
|
2560
|
+
mailbox_ids: webhookScopeIdsInputSchema.optional().describe(
|
|
2561
|
+
"Only deliver events for these mailbox IDs (plus mailboxes of domain_ids). Omit for every mailbox. Organization events are always delivered."
|
|
2562
|
+
),
|
|
2563
|
+
domain_ids: webhookScopeIdsInputSchema.optional().describe("Only deliver events for these domain IDs and their mailboxes."),
|
|
2641
2564
|
idempotency_key: idempotencyKeySchema
|
|
2642
2565
|
});
|
|
2643
2566
|
var updateWebhookInputSchema = z.object({
|
|
@@ -2646,9 +2569,11 @@ var updateWebhookInputSchema = z.object({
|
|
|
2646
2569
|
events: z.array(webhookEventSchema).min(1).max(WEBHOOK_EVENT_TYPES.length).optional(),
|
|
2647
2570
|
description: noControlString(500, "description").nullable().optional(),
|
|
2648
2571
|
active: z.boolean().optional(),
|
|
2572
|
+
mailbox_ids: webhookScopeIdsInputSchema.optional().describe("Replace the mailbox filter. Null or [] clears it."),
|
|
2573
|
+
domain_ids: webhookScopeIdsInputSchema.optional().describe("Replace the domain filter. Null or [] clears it."),
|
|
2649
2574
|
idempotency_key: idempotencyKeySchema
|
|
2650
2575
|
}).refine(
|
|
2651
|
-
(value) => value.url !== void 0 || value.events !== void 0 || value.description !== void 0 || value.active !== void 0,
|
|
2576
|
+
(value) => value.url !== void 0 || value.events !== void 0 || value.description !== void 0 || value.active !== void 0 || value.mailbox_ids !== void 0 || value.domain_ids !== void 0,
|
|
2652
2577
|
{
|
|
2653
2578
|
message: "Provide at least one webhook field to update."
|
|
2654
2579
|
}
|
|
@@ -3765,95 +3690,6 @@ var updateBookingPageInputSchema = z.object({
|
|
|
3765
3690
|
active: z.boolean().optional(),
|
|
3766
3691
|
idempotency_key: idempotencyKeySchema
|
|
3767
3692
|
});
|
|
3768
|
-
var partnerOrganizationSchema = z.object({
|
|
3769
|
-
object: z.literal("partner_organization"),
|
|
3770
|
-
id: z.string(),
|
|
3771
|
-
organization_id: z.string(),
|
|
3772
|
-
name: z.string(),
|
|
3773
|
-
external_reference: z.string(),
|
|
3774
|
-
owner_email: z.string(),
|
|
3775
|
-
owner_user_id: z.string().nullable(),
|
|
3776
|
-
status: z.enum(["pending_owner", "active", "suspended", "offboarding", "disconnected"]),
|
|
3777
|
-
data_classification: z.enum(["internal_test", "customer"]),
|
|
3778
|
-
mailbox_limit: z.number().int(),
|
|
3779
|
-
delegated_permissions: z.array(z.string()),
|
|
3780
|
-
owner_accepted_at: z.string().nullable(),
|
|
3781
|
-
activated_at: z.string().nullable(),
|
|
3782
|
-
suspended_at: z.string().nullable(),
|
|
3783
|
-
disconnected_at: z.string().nullable(),
|
|
3784
|
-
created_at: z.string(),
|
|
3785
|
-
updated_at: z.string()
|
|
3786
|
-
});
|
|
3787
|
-
var partnerOrganizationOutputSchema = z.object({
|
|
3788
|
-
organization: partnerOrganizationSchema
|
|
3789
|
-
});
|
|
3790
|
-
var createdPartnerOrganizationSchema = partnerOrganizationSchema.extend({
|
|
3791
|
-
ownership_invitation: z.object({
|
|
3792
|
-
object: z.literal("partner_ownership_invitation"),
|
|
3793
|
-
owner_email: z.string(),
|
|
3794
|
-
email_sent: z.boolean(),
|
|
3795
|
-
expires_at: z.string()
|
|
3796
|
-
}).nullable()
|
|
3797
|
-
});
|
|
3798
|
-
var createdPartnerOrganizationOutputSchema = z.object({
|
|
3799
|
-
organization: createdPartnerOrganizationSchema
|
|
3800
|
-
});
|
|
3801
|
-
var partnerOrganizationsOutputSchema = z.object({
|
|
3802
|
-
data: z.array(partnerOrganizationSchema)
|
|
3803
|
-
});
|
|
3804
|
-
var partnerInvitationOutputSchema = z.object({
|
|
3805
|
-
invitation: z.object({
|
|
3806
|
-
object: z.literal("partner_ownership_invitation"),
|
|
3807
|
-
owner_email: z.string(),
|
|
3808
|
-
email_sent: z.boolean(),
|
|
3809
|
-
expires_at: z.string()
|
|
3810
|
-
})
|
|
3811
|
-
});
|
|
3812
|
-
var partnerUsageOutputSchema = z.object({
|
|
3813
|
-
usage: z.object({
|
|
3814
|
-
object: z.literal("partner_usage"),
|
|
3815
|
-
period_start: z.string(),
|
|
3816
|
-
period_end: z.string(),
|
|
3817
|
-
closed_through: z.string().nullable(),
|
|
3818
|
-
active_children: z.number().int(),
|
|
3819
|
-
active_mailboxes: z.number().int(),
|
|
3820
|
-
child_active_seconds: z.number().int(),
|
|
3821
|
-
mailbox_active_seconds: z.number().int(),
|
|
3822
|
-
child_subtotal: z.number().int(),
|
|
3823
|
-
mailbox_subtotal: z.number().int(),
|
|
3824
|
-
minimum_shortfall: z.number().int(),
|
|
3825
|
-
projected_total: z.number().int(),
|
|
3826
|
-
currency: z.string()
|
|
3827
|
-
})
|
|
3828
|
-
});
|
|
3829
|
-
var createPartnerOrganizationInputSchema = z.object({
|
|
3830
|
-
name: noControlString(120, "name").min(1),
|
|
3831
|
-
external_reference: noControlString(200, "external reference").min(1),
|
|
3832
|
-
owner_email: emailSchema,
|
|
3833
|
-
mailbox_limit: z.number().int().min(1).max(50).default(3),
|
|
3834
|
-
data_classification: z.enum(["internal_test", "customer"]).default("customer"),
|
|
3835
|
-
idempotency_key: idempotencyKeySchema
|
|
3836
|
-
});
|
|
3837
|
-
var partnerOrganizationByIdInputSchema = z.object({
|
|
3838
|
-
id: idSchema.describe("Partner organization relationship ID.")
|
|
3839
|
-
});
|
|
3840
|
-
var updatePartnerOrganizationInputSchema = partnerOrganizationByIdInputSchema.extend({
|
|
3841
|
-
name: noControlString(120, "name").min(1).optional(),
|
|
3842
|
-
mailbox_limit: z.number().int().min(1).max(50).optional(),
|
|
3843
|
-
idempotency_key: idempotencyKeySchema
|
|
3844
|
-
}).refine((value) => value.name !== void 0 || value.mailbox_limit !== void 0, {
|
|
3845
|
-
message: "Provide name or mailbox_limit."
|
|
3846
|
-
});
|
|
3847
|
-
var resendPartnerInvitationInputSchema = partnerOrganizationByIdInputSchema.extend({
|
|
3848
|
-
owner_email: emailSchema.optional(),
|
|
3849
|
-
idempotency_key: idempotencyKeySchema
|
|
3850
|
-
});
|
|
3851
|
-
var consumePartnerMailboxCredentialGrantInputSchema = z.object({
|
|
3852
|
-
grant_id: idSchema.describe("Single-use mailbox credential grant ID."),
|
|
3853
|
-
name: noControlString(100, "name").trim().min(1).optional(),
|
|
3854
|
-
expires_at: z.iso.datetime().optional(),
|
|
3855
|
-
allowed_cidrs: z.array(appPasswordCidrInputSchema).max(20).optional()
|
|
3856
|
-
});
|
|
3857
3693
|
|
|
3858
3694
|
// src/cross-organization-tools.ts
|
|
3859
3695
|
var MAX_CONCURRENT_ORGANIZATIONS = 4;
|
|
@@ -5266,14 +5102,7 @@ var SESSION_LIMITS = {
|
|
|
5266
5102
|
shipmail_delete_booking_page: 10,
|
|
5267
5103
|
shipmail_create_automation: 20,
|
|
5268
5104
|
shipmail_update_automation: 20,
|
|
5269
|
-
shipmail_run_automation: 20
|
|
5270
|
-
shipmail_create_partner_organization: 20,
|
|
5271
|
-
shipmail_update_partner_organization: 50,
|
|
5272
|
-
shipmail_resend_partner_ownership_invitation: 20,
|
|
5273
|
-
shipmail_suspend_partner_organization: 20,
|
|
5274
|
-
shipmail_resume_partner_organization: 20,
|
|
5275
|
-
shipmail_offboard_partner_organization: 10,
|
|
5276
|
-
shipmail_consume_partner_mailbox_credential_grant: 20
|
|
5105
|
+
shipmail_run_automation: 20
|
|
5277
5106
|
};
|
|
5278
5107
|
var SESSION_TOTAL_LIMIT = 500;
|
|
5279
5108
|
var DEBUG_ENABLED = process.env["SHIPMAIL_MCP_DEBUG"] === "1";
|
|
@@ -5299,11 +5128,25 @@ var OutputSchemaViolation = class extends Error {
|
|
|
5299
5128
|
issues;
|
|
5300
5129
|
};
|
|
5301
5130
|
var MEDIA_TYPE_PATTERN = /^[a-z0-9][a-z0-9!#$&^_.+-]{0,126}\/[a-z0-9][a-z0-9!#$&^_.+-]{0,126}$/i;
|
|
5131
|
+
var CHARSET_PARAMETER_PATTERN = /(?:^|;)\s*charset\s*=\s*(?:"([a-z0-9][a-z0-9._-]{0,39})"|([a-z0-9][a-z0-9._-]{0,39}))(?:\s*;|$)/i;
|
|
5302
5132
|
var MAX_MCP_ATTACHMENT_BYTES = 3 * 1024 * 1024;
|
|
5133
|
+
var MAX_MCP_ATTACHMENT_RESPONSE_BYTES = Math.ceil(MAX_MCP_ATTACHMENT_BYTES * 4 / 3) + 64 * 1024;
|
|
5303
5134
|
function normalizeAttachmentContentType(contentType) {
|
|
5304
5135
|
const mediaType = contentType.split(";", 1)[0]?.trim().toLowerCase();
|
|
5305
5136
|
return mediaType && MEDIA_TYPE_PATTERN.test(mediaType) ? mediaType : "application/octet-stream";
|
|
5306
5137
|
}
|
|
5138
|
+
function isTextAttachment(contentType) {
|
|
5139
|
+
return normalizeAttachmentContentType(contentType).startsWith("text/");
|
|
5140
|
+
}
|
|
5141
|
+
function decodeTextAttachment(bytes, contentType) {
|
|
5142
|
+
if (!isTextAttachment(contentType)) return null;
|
|
5143
|
+
const charset = contentType.match(CHARSET_PARAMETER_PATTERN)?.slice(1).find(Boolean) ?? "utf-8";
|
|
5144
|
+
try {
|
|
5145
|
+
return new TextDecoder(charset, { fatal: true }).decode(bytes);
|
|
5146
|
+
} catch {
|
|
5147
|
+
return null;
|
|
5148
|
+
}
|
|
5149
|
+
}
|
|
5307
5150
|
function attachmentResourceUri(mailboxId, messageId, partId) {
|
|
5308
5151
|
return `shipmail://mailboxes/${encodeURIComponent(mailboxId)}/inbox/messages/${encodeURIComponent(messageId)}/attachments/${encodeURIComponent(partId)}`;
|
|
5309
5152
|
}
|
|
@@ -5397,7 +5240,7 @@ function registerTools(rawServer, client, allowedTools, grantedOrganizations = [
|
|
|
5397
5240
|
}
|
|
5398
5241
|
callCounts.set(name, used + 1);
|
|
5399
5242
|
}
|
|
5400
|
-
async function runTool(name, outputSchema, body) {
|
|
5243
|
+
async function runTool(name, outputSchema, body, longField) {
|
|
5401
5244
|
const start = performance2.now();
|
|
5402
5245
|
try {
|
|
5403
5246
|
checkRateLimit(name);
|
|
@@ -5410,7 +5253,7 @@ function registerTools(rawServer, client, allowedTools, grantedOrganizations = [
|
|
|
5410
5253
|
throw new OutputSchemaViolation(name, issues);
|
|
5411
5254
|
}
|
|
5412
5255
|
logToolCall(name, performance2.now() - start);
|
|
5413
|
-
return jsonResult(parsed.data);
|
|
5256
|
+
return jsonResult(parsed.data, longField);
|
|
5414
5257
|
} catch (error) {
|
|
5415
5258
|
if (error instanceof OutputSchemaViolation) {
|
|
5416
5259
|
process.stderr.write(
|
|
@@ -6328,13 +6171,14 @@ function registerTools(rawServer, client, allowedTools, grantedOrganizations = [
|
|
|
6328
6171
|
"shipmail_read_mailbox_inbox_attachment",
|
|
6329
6172
|
{
|
|
6330
6173
|
title: "Read Mailbox Inbox Attachment",
|
|
6331
|
-
description: "Fetch one attachment from an exact JMAP inbox message
|
|
6174
|
+
description: "Fetch one attachment from an exact JMAP inbox message. Decodable text attachments are returned in attachment.text; other attachments are embedded resources. The input uses the attachment part ID.",
|
|
6332
6175
|
inputSchema: readMailboxInboxAttachmentInputSchema,
|
|
6333
6176
|
outputSchema: inboxAttachmentContentOutputSchema,
|
|
6334
6177
|
annotations: { readOnlyHint: true, openWorldHint: true }
|
|
6335
6178
|
},
|
|
6336
6179
|
async ({ id, message_id, part_id }) => {
|
|
6337
6180
|
let resource;
|
|
6181
|
+
let text;
|
|
6338
6182
|
const result = await runTool(
|
|
6339
6183
|
"shipmail_read_mailbox_inbox_attachment",
|
|
6340
6184
|
inboxAttachmentContentOutputSchema,
|
|
@@ -6358,15 +6202,18 @@ function registerTools(rawServer, client, allowedTools, grantedOrganizations = [
|
|
|
6358
6202
|
if (bytes.byteLength > MAX_MCP_ATTACHMENT_BYTES) {
|
|
6359
6203
|
throw new ValidationError3("Attachment exceeds the MCP read limit of 3 MB.");
|
|
6360
6204
|
}
|
|
6361
|
-
|
|
6362
|
-
|
|
6363
|
-
resource
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6205
|
+
text = decodeTextAttachment(bytes, attachment.content_type) ?? void 0;
|
|
6206
|
+
if (text === void 0) {
|
|
6207
|
+
resource = {
|
|
6208
|
+
type: "resource",
|
|
6209
|
+
resource: {
|
|
6210
|
+
uri: attachmentResourceUri(id, message.id, attachment.part_id),
|
|
6211
|
+
mimeType: isTextAttachment(attachment.content_type) ? "application/octet-stream" : normalizeAttachmentContentType(attachment.content_type),
|
|
6212
|
+
blob: Buffer.from(bytes).toString("base64")
|
|
6213
|
+
},
|
|
6214
|
+
annotations: { audience: ["assistant"], priority: 1 }
|
|
6215
|
+
};
|
|
6216
|
+
}
|
|
6370
6217
|
return {
|
|
6371
6218
|
attachment: {
|
|
6372
6219
|
object: "inbox_attachment_content",
|
|
@@ -6376,13 +6223,23 @@ function registerTools(rawServer, client, allowedTools, grantedOrganizations = [
|
|
|
6376
6223
|
blob_id: attachment.blob_id,
|
|
6377
6224
|
name: attachment.name,
|
|
6378
6225
|
content_type: attachment.content_type,
|
|
6379
|
-
size: bytes.byteLength
|
|
6226
|
+
size: bytes.byteLength,
|
|
6227
|
+
...text !== void 0 ? { text } : {}
|
|
6380
6228
|
}
|
|
6381
6229
|
};
|
|
6382
|
-
}
|
|
6230
|
+
},
|
|
6231
|
+
{ path: ["attachment", "text"], maxLength: MAX_MCP_ATTACHMENT_BYTES }
|
|
6383
6232
|
);
|
|
6384
|
-
if (result.isError
|
|
6385
|
-
return { ...result, content: [...result.content, resource] };
|
|
6233
|
+
if (result.isError) return result;
|
|
6234
|
+
if (resource !== void 0) return { ...result, content: [...result.content, resource] };
|
|
6235
|
+
if (text !== void 0 && Buffer.byteLength(JSON.stringify(result), "utf8") > MAX_MCP_ATTACHMENT_RESPONSE_BYTES) {
|
|
6236
|
+
return errorResult(
|
|
6237
|
+
new ValidationError3(
|
|
6238
|
+
"Text attachment exceeds the MCP response budget after JSON encoding."
|
|
6239
|
+
)
|
|
6240
|
+
);
|
|
6241
|
+
}
|
|
6242
|
+
return result;
|
|
6386
6243
|
}
|
|
6387
6244
|
);
|
|
6388
6245
|
});
|
|
@@ -6917,11 +6774,14 @@ function registerTools(rawServer, client, allowedTools, grantedOrganizations = [
|
|
|
6917
6774
|
client_reference: args.client_reference,
|
|
6918
6775
|
cursor: args.cursor,
|
|
6919
6776
|
limit: args.limit
|
|
6920
|
-
} : {
|
|
6777
|
+
} : args.client_reference ? {
|
|
6921
6778
|
client_reference: args.client_reference,
|
|
6922
6779
|
cursor: args.cursor,
|
|
6923
6780
|
limit: args.limit
|
|
6924
|
-
};
|
|
6781
|
+
} : void 0;
|
|
6782
|
+
if (!params) {
|
|
6783
|
+
throw new Error("Provide mailbox_id or client_reference.");
|
|
6784
|
+
}
|
|
6925
6785
|
return client.messages.list(params);
|
|
6926
6786
|
})
|
|
6927
6787
|
);
|
|
@@ -7305,7 +7165,7 @@ function registerTools(rawServer, client, allowedTools, grantedOrganizations = [
|
|
|
7305
7165
|
"shipmail_update_webhook",
|
|
7306
7166
|
{
|
|
7307
7167
|
title: "Update Webhook",
|
|
7308
|
-
description: "Update webhook URL, subscribed events, description, or
|
|
7168
|
+
description: "Update webhook URL, subscribed events, description, active state, or mailbox and domain filter. A URL change redirects future deliveries.",
|
|
7309
7169
|
inputSchema: updateWebhookInputSchema,
|
|
7310
7170
|
outputSchema: webhookOutputSchema,
|
|
7311
7171
|
annotations: {
|
|
@@ -7321,6 +7181,8 @@ function registerTools(rawServer, client, allowedTools, grantedOrganizations = [
|
|
|
7321
7181
|
if (args.events !== void 0) update.events = args.events;
|
|
7322
7182
|
if (args.description !== void 0) update.description = args.description;
|
|
7323
7183
|
if (args.active !== void 0) update.active = args.active;
|
|
7184
|
+
if (args.mailbox_ids !== void 0) update.mailbox_ids = args.mailbox_ids;
|
|
7185
|
+
if (args.domain_ids !== void 0) update.domain_ids = args.domain_ids;
|
|
7324
7186
|
return {
|
|
7325
7187
|
webhook: await client.webhooks.update(args.id, update, mutationOptions(args))
|
|
7326
7188
|
};
|
|
@@ -8596,204 +8458,6 @@ function registerTools(rawServer, client, allowedTools, grantedOrganizations = [
|
|
|
8596
8458
|
})
|
|
8597
8459
|
);
|
|
8598
8460
|
});
|
|
8599
|
-
registerIfAllowed("shipmail_list_partner_organizations", () => {
|
|
8600
|
-
server.registerTool(
|
|
8601
|
-
"shipmail_list_partner_organizations",
|
|
8602
|
-
{
|
|
8603
|
-
title: "List Partner Organizations",
|
|
8604
|
-
description: "List operator-owned organizations connected to the partner account.",
|
|
8605
|
-
outputSchema: partnerOrganizationsOutputSchema,
|
|
8606
|
-
annotations: { readOnlyHint: true, openWorldHint: false }
|
|
8607
|
-
},
|
|
8608
|
-
async () => runTool(
|
|
8609
|
-
"shipmail_list_partner_organizations",
|
|
8610
|
-
partnerOrganizationsOutputSchema,
|
|
8611
|
-
() => client.partner.listOrganizations()
|
|
8612
|
-
)
|
|
8613
|
-
);
|
|
8614
|
-
});
|
|
8615
|
-
registerIfAllowed("shipmail_create_partner_organization", () => {
|
|
8616
|
-
server.registerTool(
|
|
8617
|
-
"shipmail_create_partner_organization",
|
|
8618
|
-
{
|
|
8619
|
-
title: "Create Partner Organization",
|
|
8620
|
-
description: "Create an operator organization and email its ownership invitation. No domain or mailbox is created.",
|
|
8621
|
-
inputSchema: createPartnerOrganizationInputSchema,
|
|
8622
|
-
outputSchema: createdPartnerOrganizationOutputSchema,
|
|
8623
|
-
annotations: {
|
|
8624
|
-
readOnlyHint: false,
|
|
8625
|
-
destructiveHint: false,
|
|
8626
|
-
idempotentHint: true,
|
|
8627
|
-
openWorldHint: false
|
|
8628
|
-
}
|
|
8629
|
-
},
|
|
8630
|
-
async (args) => runTool(
|
|
8631
|
-
"shipmail_create_partner_organization",
|
|
8632
|
-
createdPartnerOrganizationOutputSchema,
|
|
8633
|
-
async () => ({
|
|
8634
|
-
organization: await client.partner.createOrganization(
|
|
8635
|
-
stripIdempotencyKey(args),
|
|
8636
|
-
mutationOptions(args)
|
|
8637
|
-
)
|
|
8638
|
-
})
|
|
8639
|
-
)
|
|
8640
|
-
);
|
|
8641
|
-
});
|
|
8642
|
-
registerIfAllowed("shipmail_get_partner_organization", () => {
|
|
8643
|
-
server.registerTool(
|
|
8644
|
-
"shipmail_get_partner_organization",
|
|
8645
|
-
{
|
|
8646
|
-
title: "Get Partner Organization",
|
|
8647
|
-
description: "Get one partner child relationship and its ownership state.",
|
|
8648
|
-
inputSchema: partnerOrganizationByIdInputSchema,
|
|
8649
|
-
outputSchema: partnerOrganizationOutputSchema,
|
|
8650
|
-
annotations: { readOnlyHint: true, openWorldHint: false }
|
|
8651
|
-
},
|
|
8652
|
-
async ({ id }) => runTool("shipmail_get_partner_organization", partnerOrganizationOutputSchema, async () => ({
|
|
8653
|
-
organization: await client.partner.getOrganization(id)
|
|
8654
|
-
}))
|
|
8655
|
-
);
|
|
8656
|
-
});
|
|
8657
|
-
registerIfAllowed("shipmail_update_partner_organization", () => {
|
|
8658
|
-
server.registerTool(
|
|
8659
|
-
"shipmail_update_partner_organization",
|
|
8660
|
-
{
|
|
8661
|
-
title: "Update Partner Organization",
|
|
8662
|
-
description: "Update an operator organization name or mailbox allocation.",
|
|
8663
|
-
inputSchema: updatePartnerOrganizationInputSchema,
|
|
8664
|
-
outputSchema: partnerOrganizationOutputSchema,
|
|
8665
|
-
annotations: {
|
|
8666
|
-
readOnlyHint: false,
|
|
8667
|
-
destructiveHint: false,
|
|
8668
|
-
idempotentHint: true,
|
|
8669
|
-
openWorldHint: false
|
|
8670
|
-
}
|
|
8671
|
-
},
|
|
8672
|
-
async (args) => runTool(
|
|
8673
|
-
"shipmail_update_partner_organization",
|
|
8674
|
-
partnerOrganizationOutputSchema,
|
|
8675
|
-
async () => {
|
|
8676
|
-
const { id, idempotency_key: _key, ...params } = args;
|
|
8677
|
-
return {
|
|
8678
|
-
organization: await client.partner.updateOrganization(
|
|
8679
|
-
id,
|
|
8680
|
-
params,
|
|
8681
|
-
mutationOptions(args)
|
|
8682
|
-
)
|
|
8683
|
-
};
|
|
8684
|
-
}
|
|
8685
|
-
)
|
|
8686
|
-
);
|
|
8687
|
-
});
|
|
8688
|
-
registerIfAllowed("shipmail_resend_partner_ownership_invitation", () => {
|
|
8689
|
-
server.registerTool(
|
|
8690
|
-
"shipmail_resend_partner_ownership_invitation",
|
|
8691
|
-
{
|
|
8692
|
-
title: "Resend Partner Ownership Invitation",
|
|
8693
|
-
description: "Revoke the pending ownership link and email a new single-use link.",
|
|
8694
|
-
inputSchema: resendPartnerInvitationInputSchema,
|
|
8695
|
-
outputSchema: partnerInvitationOutputSchema,
|
|
8696
|
-
annotations: {
|
|
8697
|
-
readOnlyHint: false,
|
|
8698
|
-
destructiveHint: false,
|
|
8699
|
-
idempotentHint: true,
|
|
8700
|
-
openWorldHint: true
|
|
8701
|
-
}
|
|
8702
|
-
},
|
|
8703
|
-
async (args) => runTool(
|
|
8704
|
-
"shipmail_resend_partner_ownership_invitation",
|
|
8705
|
-
partnerInvitationOutputSchema,
|
|
8706
|
-
async () => ({
|
|
8707
|
-
invitation: await client.partner.resendOwnershipInvitation(
|
|
8708
|
-
args.id,
|
|
8709
|
-
{ owner_email: args.owner_email },
|
|
8710
|
-
mutationOptions(args)
|
|
8711
|
-
)
|
|
8712
|
-
})
|
|
8713
|
-
)
|
|
8714
|
-
);
|
|
8715
|
-
});
|
|
8716
|
-
for (const transition of ["suspend", "resume", "offboard"]) {
|
|
8717
|
-
const toolName = `shipmail_${transition}_partner_organization`;
|
|
8718
|
-
registerIfAllowed(toolName, () => {
|
|
8719
|
-
server.registerTool(
|
|
8720
|
-
toolName,
|
|
8721
|
-
{
|
|
8722
|
-
title: `${transition[0]?.toUpperCase() ?? ""}${transition.slice(1)} Partner Organization`,
|
|
8723
|
-
description: transition === "suspend" ? "Suspend outbound sending for one operator organization. Inbound mail and storage continue." : transition === "resume" ? "Resume partner-managed outbound sending for one operator organization." : "Start non-destructive offboarding and immediately remove delegated access.",
|
|
8724
|
-
inputSchema: partnerOrganizationByIdInputSchema,
|
|
8725
|
-
outputSchema: partnerOrganizationOutputSchema,
|
|
8726
|
-
annotations: {
|
|
8727
|
-
readOnlyHint: false,
|
|
8728
|
-
destructiveHint: transition !== "resume",
|
|
8729
|
-
idempotentHint: true,
|
|
8730
|
-
openWorldHint: false
|
|
8731
|
-
}
|
|
8732
|
-
},
|
|
8733
|
-
async ({ id }) => runTool(toolName, partnerOrganizationOutputSchema, async () => ({
|
|
8734
|
-
organization: transition === "suspend" ? await client.partner.suspendOrganization(id) : transition === "resume" ? await client.partner.resumeOrganization(id) : await client.partner.offboardOrganization(id)
|
|
8735
|
-
}))
|
|
8736
|
-
);
|
|
8737
|
-
});
|
|
8738
|
-
}
|
|
8739
|
-
registerIfAllowed("shipmail_consume_partner_mailbox_credential_grant", () => {
|
|
8740
|
-
server.registerTool(
|
|
8741
|
-
"shipmail_consume_partner_mailbox_credential_grant",
|
|
8742
|
-
{
|
|
8743
|
-
title: "Consume Partner Mailbox Credential Grant",
|
|
8744
|
-
description: "Consume a single-use grant and issue an embedded-webmail credential. The secret appears once and the operator receives a notification.",
|
|
8745
|
-
inputSchema: consumePartnerMailboxCredentialGrantInputSchema,
|
|
8746
|
-
outputSchema: partnerMailboxCredentialOutputSchema,
|
|
8747
|
-
annotations: {
|
|
8748
|
-
readOnlyHint: false,
|
|
8749
|
-
destructiveHint: true,
|
|
8750
|
-
idempotentHint: false,
|
|
8751
|
-
openWorldHint: true
|
|
8752
|
-
}
|
|
8753
|
-
},
|
|
8754
|
-
async (args) => runTool(
|
|
8755
|
-
"shipmail_consume_partner_mailbox_credential_grant",
|
|
8756
|
-
partnerMailboxCredentialOutputSchema,
|
|
8757
|
-
async () => ({
|
|
8758
|
-
credential: await client.partner.consumeMailboxCredentialGrant(args.grant_id, {
|
|
8759
|
-
...args.name ? { name: args.name } : {},
|
|
8760
|
-
...args.expires_at ? { expires_at: args.expires_at } : {},
|
|
8761
|
-
...args.allowed_cidrs ? { allowed_cidrs: args.allowed_cidrs } : {}
|
|
8762
|
-
})
|
|
8763
|
-
})
|
|
8764
|
-
)
|
|
8765
|
-
);
|
|
8766
|
-
});
|
|
8767
|
-
registerIfAllowed("shipmail_list_partner_mailbox_credential_grants", () => {
|
|
8768
|
-
server.registerTool(
|
|
8769
|
-
"shipmail_list_partner_mailbox_credential_grants",
|
|
8770
|
-
{
|
|
8771
|
-
title: "List Partner Mailbox Credential Grants",
|
|
8772
|
-
description: "List active ten-minute mailbox approvals created by operator owners. Grant metadata contains no app-password secret.",
|
|
8773
|
-
outputSchema: partnerMailboxCredentialGrantsOutputSchema,
|
|
8774
|
-
annotations: { readOnlyHint: true, openWorldHint: false }
|
|
8775
|
-
},
|
|
8776
|
-
async () => runTool(
|
|
8777
|
-
"shipmail_list_partner_mailbox_credential_grants",
|
|
8778
|
-
partnerMailboxCredentialGrantsOutputSchema,
|
|
8779
|
-
async () => ({ grants: await client.partner.listMailboxCredentialGrants() })
|
|
8780
|
-
)
|
|
8781
|
-
);
|
|
8782
|
-
});
|
|
8783
|
-
registerIfAllowed("shipmail_get_partner_usage", () => {
|
|
8784
|
-
server.registerTool(
|
|
8785
|
-
"shipmail_get_partner_usage",
|
|
8786
|
-
{
|
|
8787
|
-
title: "Get Partner Usage",
|
|
8788
|
-
description: "Get consolidated child and mailbox usage for the current UTC month.",
|
|
8789
|
-
outputSchema: partnerUsageOutputSchema,
|
|
8790
|
-
annotations: { readOnlyHint: true, openWorldHint: false }
|
|
8791
|
-
},
|
|
8792
|
-
async () => runTool("shipmail_get_partner_usage", partnerUsageOutputSchema, async () => ({
|
|
8793
|
-
usage: await client.partner.usage()
|
|
8794
|
-
}))
|
|
8795
|
-
);
|
|
8796
|
-
});
|
|
8797
8461
|
if (allowedTools) {
|
|
8798
8462
|
const unknown = [...allowedTools].filter((name) => !knownTools.includes(name));
|
|
8799
8463
|
if (unknown.length > 0) {
|
|
@@ -8804,7 +8468,7 @@ function registerTools(rawServer, client, allowedTools, grantedOrganizations = [
|
|
|
8804
8468
|
}
|
|
8805
8469
|
|
|
8806
8470
|
// src/version.ts
|
|
8807
|
-
var VERSION = "0.
|
|
8471
|
+
var VERSION = "0.9.0";
|
|
8808
8472
|
|
|
8809
8473
|
// src/server.ts
|
|
8810
8474
|
var SHIPMAIL_MCP_INSTRUCTIONS = `Shipmail MCP exposes the business email and calendar tools authorized by the connection's current Shipmail permissions.
|
|
@@ -8818,7 +8482,7 @@ Operational instructions:
|
|
|
8818
8482
|
- Do not create or change mailbox rules without explicit user intent. List rules and folders before rule changes; custom folder IDs must belong to the target mailbox. Read the latest rule before updating or deleting it, and retain expected_position to detect concurrent reordering.
|
|
8819
8483
|
- Do not create or delete a custom mailbox folder without explicit user intent. List folders before creating or deleting one. Deleting a custom folder moves its remaining messages to Trash and conflicts while an inbox rule or automation references it. For inbox messages, use the exact inbox ID, list folders before a custom-folder move, and move a message to Trash before permanent deletion.
|
|
8820
8484
|
- Do not change a domain catch-all or enable an auto-reply without explicit user intent. A catch-all retargets unmatched-recipient mail, and an enabled auto-reply can send replies.
|
|
8821
|
-
- Do not reset a mailbox password unless the operator supplied the replacement password. Do not create an app password without explicit operator approval; store its one-time secret securely.
|
|
8485
|
+
- Do not reset a mailbox password unless the operator supplied the replacement password. Do not create an app password without explicit operator approval; store its one-time secret securely.
|
|
8822
8486
|
- Webhook signing secrets appear once in the conversation log. Treat that log as sensitive and store each secret in the user's chosen secret manager.
|
|
8823
8487
|
- Confirm that a recipient should receive mail again before removing a suppression. Use the subscriber state tools for subscription changes rather than a profile update. Prefer unsubscribing to removing a subscriber when opt-out history must be preserved.
|
|
8824
8488
|
- Do not create, send, schedule, resume, or otherwise mutate a newsletter without the user's explicit approval. A test send requires approval of the exact draft and test recipient. Scheduling requires approval of the content, audience, and scheduled time. Resume requires confirmation that delivery should continue. Run newsletter preflight before test sending or scheduling, and obtain sender identities and existing asset IDs from their list tools.
|
|
@@ -8846,7 +8510,6 @@ function createShipmailMcpServer(config, allowedTools, organizationGrants = [])
|
|
|
8846
8510
|
const client = new ShipmailClient({
|
|
8847
8511
|
apiKey: config.apiKey,
|
|
8848
8512
|
...config.baseUrl ? { baseUrl: config.baseUrl } : {},
|
|
8849
|
-
...config.organizationId ? { organizationId: config.organizationId } : {},
|
|
8850
8513
|
defaultHeaders
|
|
8851
8514
|
});
|
|
8852
8515
|
const server = new McpServer5(
|
|
@@ -8953,7 +8616,6 @@ async function main() {
|
|
|
8953
8616
|
const client = new ShipmailClient2({
|
|
8954
8617
|
apiKey: config.apiKey,
|
|
8955
8618
|
...config.baseUrl ? { baseUrl: config.baseUrl } : {},
|
|
8956
|
-
...config.organizationId ? { organizationId: config.organizationId } : {},
|
|
8957
8619
|
defaultHeaders: {
|
|
8958
8620
|
"User-Agent": `shipmail-mcp/${VERSION}`,
|
|
8959
8621
|
"X-Shipmail-Client": "mcp",
|