shipmail-mcp 0.2.9 → 0.3.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/README.md +31 -20
- package/dist/index.js +473 -8
- package/package.json +2 -2
- package/server.json +2 -2
- package/smithery.yaml +1 -1
package/README.md
CHANGED
|
@@ -181,17 +181,18 @@ Once connected, ask your agent:
|
|
|
181
181
|
|
|
182
182
|
All tools are namespaced with `shipmail_` to avoid collisions with peer MCP servers.
|
|
183
183
|
|
|
184
|
-
| Group | Tools
|
|
185
|
-
| -------------------- |
|
|
186
|
-
| Status | `shipmail_status`
|
|
187
|
-
| Domains | `shipmail_list_domains`, `shipmail_get_domain`, `shipmail_get_domain_dns_records`, `shipmail_create_domain`, `shipmail_update_domain`, `shipmail_delete_domain`, `shipmail_verify_domain`, `shipmail_search_domains`
|
|
188
|
-
| Mailboxes | `shipmail_list_mailboxes`, `shipmail_get_mailbox`, `shipmail_create_mailbox`, `shipmail_update_mailbox`, `shipmail_delete_mailbox`, `shipmail_suspend_mailbox`, `shipmail_resume_mailbox`, `shipmail_list_mailbox_forwarding`, `shipmail_create_mailbox_forwarding`, `shipmail_delete_mailbox_forwarding`, `shipmail_list_mailbox_folders`, `shipmail_create_mailbox_folder`, `shipmail_update_mailbox_folder`, `shipmail_delete_mailbox_folder`, `shipmail_list_mailbox_identities`, `shipmail_get_mailbox_rules`, `shipmail_set_mailbox_rules`, `shipmail_reset_mailbox_password`, `shipmail_set_auto_reply`, `shipmail_set_spam_filter`, `shipmail_inject_sandbox_inbound` |
|
|
189
|
-
| Mailbox inbox | `shipmail_list_mailbox_inbox_messages`, `shipmail_get_mailbox_inbox_thread`, `shipmail_update_inbox_message`, `shipmail_move_inbox_message`, `shipmail_delete_inbox_message`
|
|
190
|
-
| Messages and threads | `shipmail_list_messages`, `shipmail_get_message`, `shipmail_send_message`, `shipmail_reply_to_message`, `shipmail_list_threads`, `shipmail_get_thread`, `shipmail_reply_to_thread`
|
|
191
|
-
| Webhooks | `shipmail_list_webhooks`, `shipmail_get_webhook`, `shipmail_create_webhook`, `shipmail_update_webhook`, `shipmail_delete_webhook`, `shipmail_rotate_webhook_secret`, `shipmail_test_webhook`, `shipmail_list_webhook_deliveries`, `shipmail_get_webhook_delivery`, `shipmail_replay_webhook_delivery`
|
|
192
|
-
| Suppressions | `shipmail_list_suppressions`, `shipmail_remove_suppression`
|
|
193
|
-
| Audiences | `shipmail_list_audiences`, `shipmail_get_audience`, `shipmail_create_audience`, `shipmail_update_audience`, `shipmail_delete_audience`, `shipmail_list_subscribers`, `shipmail_get_subscriber`, `shipmail_get_subscriber_by_email`, `shipmail_add_subscriber`, `shipmail_add_subscribers_batch`, `shipmail_update_subscriber`, `shipmail_unsubscribe_subscriber`, `shipmail_resubscribe_subscriber`, `shipmail_remove_subscriber`
|
|
194
|
-
| Newsletters | `shipmail_list_newsletter_domains`, `shipmail_list_newsletter_assets`, `shipmail_list_newsletters`, `shipmail_get_newsletter`, `shipmail_preview_newsletter`, `shipmail_create_newsletter`, `shipmail_create_newsletter_from_changelog`, `shipmail_update_newsletter`, `shipmail_run_newsletter_preflight`, `shipmail_send_newsletter_test`, `shipmail_schedule_newsletter`, `shipmail_cancel_newsletter`, `shipmail_resume_newsletter`
|
|
184
|
+
| Group | Tools |
|
|
185
|
+
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
186
|
+
| Status | `shipmail_status` |
|
|
187
|
+
| Domains | `shipmail_list_domains`, `shipmail_get_domain`, `shipmail_get_domain_dns_records`, `shipmail_create_domain`, `shipmail_update_domain`, `shipmail_delete_domain`, `shipmail_verify_domain`, `shipmail_search_domains` |
|
|
188
|
+
| Mailboxes | `shipmail_list_mailboxes`, `shipmail_get_mailbox`, `shipmail_create_mailbox`, `shipmail_update_mailbox`, `shipmail_delete_mailbox`, `shipmail_suspend_mailbox`, `shipmail_resume_mailbox`, `shipmail_list_mailbox_app_passwords`, `shipmail_create_mailbox_app_password`, `shipmail_revoke_mailbox_app_password`, `shipmail_list_mailbox_forwarding`, `shipmail_create_mailbox_forwarding`, `shipmail_delete_mailbox_forwarding`, `shipmail_list_mailbox_folders`, `shipmail_create_mailbox_folder`, `shipmail_update_mailbox_folder`, `shipmail_delete_mailbox_folder`, `shipmail_list_mailbox_identities`, `shipmail_get_mailbox_rules`, `shipmail_set_mailbox_rules`, `shipmail_reset_mailbox_password`, `shipmail_set_auto_reply`, `shipmail_set_spam_filter`, `shipmail_inject_sandbox_inbound` |
|
|
189
|
+
| Mailbox inbox | `shipmail_list_mailbox_inbox_messages`, `shipmail_get_mailbox_inbox_thread`, `shipmail_update_inbox_message`, `shipmail_move_inbox_message`, `shipmail_delete_inbox_message` |
|
|
190
|
+
| Messages and threads | `shipmail_list_messages`, `shipmail_get_message`, `shipmail_send_message`, `shipmail_reply_to_message`, `shipmail_list_threads`, `shipmail_get_thread`, `shipmail_reply_to_thread` |
|
|
191
|
+
| Webhooks | `shipmail_list_webhooks`, `shipmail_get_webhook`, `shipmail_create_webhook`, `shipmail_update_webhook`, `shipmail_delete_webhook`, `shipmail_rotate_webhook_secret`, `shipmail_test_webhook`, `shipmail_list_webhook_deliveries`, `shipmail_get_webhook_delivery`, `shipmail_replay_webhook_delivery` |
|
|
192
|
+
| Suppressions | `shipmail_list_suppressions`, `shipmail_remove_suppression` |
|
|
193
|
+
| Audiences | `shipmail_list_audiences`, `shipmail_get_audience`, `shipmail_create_audience`, `shipmail_update_audience`, `shipmail_delete_audience`, `shipmail_list_subscribers`, `shipmail_get_subscriber`, `shipmail_get_subscriber_by_email`, `shipmail_add_subscriber`, `shipmail_add_subscribers_batch`, `shipmail_update_subscriber`, `shipmail_unsubscribe_subscriber`, `shipmail_resubscribe_subscriber`, `shipmail_remove_subscriber` |
|
|
194
|
+
| Newsletters | `shipmail_list_newsletter_domains`, `shipmail_list_newsletter_assets`, `shipmail_list_newsletters`, `shipmail_get_newsletter`, `shipmail_preview_newsletter`, `shipmail_create_newsletter`, `shipmail_create_newsletter_from_changelog`, `shipmail_update_newsletter`, `shipmail_run_newsletter_preflight`, `shipmail_send_newsletter_test`, `shipmail_schedule_newsletter`, `shipmail_cancel_newsletter`, `shipmail_resume_newsletter` |
|
|
195
|
+
| Partner beta | `shipmail_list_partner_organizations`, `shipmail_create_partner_organization`, `shipmail_get_partner_organization`, `shipmail_update_partner_organization`, `shipmail_resend_partner_ownership_invitation`, `shipmail_suspend_partner_organization`, `shipmail_resume_partner_organization`, `shipmail_offboard_partner_organization`, `shipmail_list_partner_mailbox_credential_grants`, `shipmail_consume_partner_mailbox_credential_grant`, `shipmail_get_partner_usage` |
|
|
195
196
|
|
|
196
197
|
Message send and reply tools accept optional `client_reference`, scalar `metadata`,
|
|
197
198
|
`source_rfc_message_id`, and validated safe `headers`. `shipmail_list_messages` accepts either a
|
|
@@ -199,6 +200,12 @@ Message send and reply tools accept optional `client_reference`, scalar `metadat
|
|
|
199
200
|
|
|
200
201
|
With an `sm_test_...` API key, send and reply tools accept `sandbox_outcome` and the sandbox inbound tool creates fake inbound mail. The API keeps test storage and events isolated and never delivers sandbox mail to real recipients.
|
|
201
202
|
|
|
203
|
+
App-password creation, revocation, and partner grant consumption are destructive/high-risk tools.
|
|
204
|
+
Creation and grant consumption return a live secret once; revocation disconnects that client
|
|
205
|
+
immediately. Partner grant consumption requires the exact `partner:mailbox_credentials:issue`
|
|
206
|
+
scope and an operator-approved one-time grant. App-password creation and grant consumption do not
|
|
207
|
+
accept idempotency keys.
|
|
208
|
+
|
|
202
209
|
To restrict the surface, pass `--tools` (overrides `SHIPMAIL_MCP_TOOLS`):
|
|
203
210
|
|
|
204
211
|
```json
|
|
@@ -240,20 +247,24 @@ Pre-built prompts the agent can use as guided workflows:
|
|
|
240
247
|
|
|
241
248
|
## Configuration
|
|
242
249
|
|
|
243
|
-
| Variable
|
|
244
|
-
|
|
|
245
|
-
| `SHIPMAIL_API_KEY`
|
|
246
|
-
| `SHIPMAIL_API_KEY_FILE`
|
|
247
|
-
| `SHIPMAIL_BASE_URL`
|
|
248
|
-
| `
|
|
249
|
-
|
|
250
|
-
|
|
250
|
+
| Variable | Required | Description |
|
|
251
|
+
| -------------------------- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
252
|
+
| `SHIPMAIL_API_KEY` | Yes (or `SHIPMAIL_API_KEY_FILE`) | Shipmail API key (`sm_live_...`). |
|
|
253
|
+
| `SHIPMAIL_API_KEY_FILE` | No | Path to a file containing the API key. Takes precedence over `SHIPMAIL_API_KEY`. Reduces env-trace leak surface (Docker secrets, systemd `LoadCredential`). |
|
|
254
|
+
| `SHIPMAIL_BASE_URL` | No | Override the API base URL. Must be https on a `shipmail.to` host. Defaults to `https://shipmail.to/api/v1`. |
|
|
255
|
+
| `SHIPMAIL_ORGANIZATION_ID` | No | Delegated child organization for an approved infrastructure-only MCP session. |
|
|
256
|
+
|
|
257
|
+
In a delegated partner session, call `shipmail_create_mailbox` with `generate_password: true`.
|
|
258
|
+
Shipmail generates the primary credential and never returns it to the partner.
|
|
259
|
+
| `SHIPMAIL_MCP_TOOLS` | No | Comma-separated tool allowlist. The `--tools` flag overrides this. |
|
|
260
|
+
| `SHIPMAIL_ALLOW_INSECURE_BASE_URL` | No | Set to `1` to permit a non-https or non-`shipmail.to` base URL. Local development only. |
|
|
261
|
+
| `SHIPMAIL_MCP_DEBUG` | No | Set to `1` to include `request_id` and `status` in stderr tool-call logs. |
|
|
251
262
|
|
|
252
263
|
## Security
|
|
253
264
|
|
|
254
265
|
- **Tool namespacing**: All tools are prefixed with `shipmail_` to avoid collisions with peer MCP servers in the same host.
|
|
255
266
|
- **Structured outputs**: Successful tools return both text fallback content and structured MCP `structuredContent`.
|
|
256
|
-
- **Idempotency**: Mutating tools accept an optional `idempotency_key`. When omitted, the server generates a fresh key per tool call. Supply your own key if a specific request must stay idempotent across MCP retries.
|
|
267
|
+
- **Idempotency**: Mutating tools accept an optional `idempotency_key`. When omitted, the server generates a fresh key per tool call. Supply your own key if a specific request must stay idempotent across MCP retries. Mailbox app-password creation and partner grant consumption are excluded because their one-time plaintext secrets must never be cached.
|
|
257
268
|
- **Input sanitization**: Email content, addresses, and error text are stripped of ASCII control characters, DEL, and Unicode directional or BiDi markers (U+061C, U+200E/F, U+202A-E, U+2066-9). Long strings are truncated.
|
|
258
269
|
- **Error redaction**: 5xx and unexpected Shipmail errors are redacted to a generic message; the original `request_id` is preserved for support. Generic `Error` thrown values (network errors, deserialization) are redacted to "Internal MCP error" before reaching the LLM. Detail lands on stderr.
|
|
259
270
|
- **Circuit breaker**: Each session enforces per-tool rate limits and a hard total-call ceiling as a runaway-agent guard. These are not abuse controls. Real abuse limits live at the API per API key. Restart the server to reset.
|
package/dist/index.js
CHANGED
|
@@ -18,6 +18,8 @@ Environment:
|
|
|
18
18
|
SHIPMAIL_API_KEY when set; reduces env-trace leak surface for hosts that
|
|
19
19
|
log environment variables.
|
|
20
20
|
SHIPMAIL_BASE_URL Optional API base URL. Must be https. Defaults to ${DEFAULT_BASE_URL}.
|
|
21
|
+
SHIPMAIL_ORGANIZATION_ID
|
|
22
|
+
Optional delegated child organization ID for infrastructure tools.
|
|
21
23
|
SHIPMAIL_MCP_TOOLS Optional comma-separated tool allowlist. --tools overrides this.
|
|
22
24
|
SHIPMAIL_ALLOW_INSECURE_BASE_URL=1
|
|
23
25
|
Permit non-https or non-shipmail.to base URL (development only).`;
|
|
@@ -95,6 +97,7 @@ function readConfig(argv = process.argv.slice(2)) {
|
|
|
95
97
|
return {
|
|
96
98
|
apiKey,
|
|
97
99
|
baseUrl,
|
|
100
|
+
organizationId: env["SHIPMAIL_ORGANIZATION_ID"] || void 0,
|
|
98
101
|
selectedTools: parseToolsArg(argv) ?? parseToolsList(env["SHIPMAIL_MCP_TOOLS"])
|
|
99
102
|
};
|
|
100
103
|
}
|
|
@@ -110,6 +113,7 @@ import { z as z2 } from "zod/v4";
|
|
|
110
113
|
|
|
111
114
|
// src/schemas.ts
|
|
112
115
|
import {
|
|
116
|
+
CONFERENCING_PROVIDER_IDS,
|
|
113
117
|
DOMAIN_STATUSES,
|
|
114
118
|
MESSAGE_SOURCES,
|
|
115
119
|
MESSAGE_STATUSES,
|
|
@@ -434,6 +438,39 @@ var mailboxExportSchema = z.object({
|
|
|
434
438
|
started_at: z.string().nullable(),
|
|
435
439
|
completed_at: z.string().nullable()
|
|
436
440
|
});
|
|
441
|
+
var mailboxAppPasswordSchema = z.object({
|
|
442
|
+
object: z.literal("mailbox_app_password"),
|
|
443
|
+
id: z.string(),
|
|
444
|
+
mailbox_id: z.string(),
|
|
445
|
+
name: z.string(),
|
|
446
|
+
state: z.enum(["pending_create", "active", "pending_revoke", "revoked", "failed"]),
|
|
447
|
+
purpose: z.enum(["operator_client", "partner_embedded_webmail"]),
|
|
448
|
+
expires_at: z.string().nullable(),
|
|
449
|
+
allowed_cidrs: z.array(z.string()),
|
|
450
|
+
last_used_at: z.string().nullable(),
|
|
451
|
+
created_at: z.string(),
|
|
452
|
+
revoked_at: z.string().nullable()
|
|
453
|
+
});
|
|
454
|
+
var createdMailboxAppPasswordSchema = mailboxAppPasswordSchema.extend({
|
|
455
|
+
secret: z.string()
|
|
456
|
+
});
|
|
457
|
+
var partnerMailboxCredentialSchema = createdMailboxAppPasswordSchema.extend({
|
|
458
|
+
operator_notified: z.boolean()
|
|
459
|
+
});
|
|
460
|
+
var partnerMailboxCredentialGrantSchema = z.object({
|
|
461
|
+
object: z.literal("partner_mailbox_credential_grant"),
|
|
462
|
+
id: z.string(),
|
|
463
|
+
partner_organization_id: z.string(),
|
|
464
|
+
organization_id: z.string(),
|
|
465
|
+
organization_name: z.string(),
|
|
466
|
+
external_reference: z.string(),
|
|
467
|
+
operator_email: z.string(),
|
|
468
|
+
mailbox_id: z.string(),
|
|
469
|
+
mailbox_address: z.string(),
|
|
470
|
+
disclosure_version: z.string(),
|
|
471
|
+
expires_at: z.string(),
|
|
472
|
+
consented_at: z.string()
|
|
473
|
+
});
|
|
437
474
|
var mailboxFolderSchema = z.object({
|
|
438
475
|
object: z.literal("mailbox_folder"),
|
|
439
476
|
id: z.string(),
|
|
@@ -809,6 +846,26 @@ var domainOutputSchema = z.object({ domain: domainSchema });
|
|
|
809
846
|
var domainDnsRecordsOutputSchema = z.object({ dns_records: domainDnsRecordSetSchema });
|
|
810
847
|
var mailboxOutputSchema = z.object({ mailbox: mailboxSchema });
|
|
811
848
|
var mailboxExportOutputSchema = z.object({ export: mailboxExportSchema });
|
|
849
|
+
var mailboxAppPasswordOutputSchema = z.object({
|
|
850
|
+
app_password: mailboxAppPasswordSchema
|
|
851
|
+
});
|
|
852
|
+
var createdMailboxAppPasswordOutputSchema = z.object({
|
|
853
|
+
app_password: createdMailboxAppPasswordSchema
|
|
854
|
+
});
|
|
855
|
+
var mailboxAppPasswordsOutputSchema = z.object({
|
|
856
|
+
app_passwords: z.object({
|
|
857
|
+
object: z.literal("list"),
|
|
858
|
+
data: z.array(mailboxAppPasswordSchema)
|
|
859
|
+
})
|
|
860
|
+
});
|
|
861
|
+
var partnerMailboxCredentialOutputSchema = z.object({
|
|
862
|
+
credential: partnerMailboxCredentialSchema
|
|
863
|
+
});
|
|
864
|
+
var partnerMailboxCredentialGrantsOutputSchema = z.object({
|
|
865
|
+
grants: z.object({
|
|
866
|
+
data: z.array(partnerMailboxCredentialGrantSchema)
|
|
867
|
+
})
|
|
868
|
+
});
|
|
812
869
|
var mailboxFolderOutputSchema = z.object({ folder: mailboxFolderSchema });
|
|
813
870
|
var mailboxFoldersOutputSchema = z.object({ folders: mailboxFoldersSchema });
|
|
814
871
|
var mailboxIdentitiesOutputSchema = z.object({ identities: mailboxIdentitiesSchema });
|
|
@@ -971,15 +1028,38 @@ var createMailboxInputSchema = z.object({
|
|
|
971
1028
|
password: z.string().min(8).max(128).refine((value) => /[a-z]/.test(value), "Password must include a lowercase letter.").refine((value) => /[A-Z]/.test(value), "Password must include an uppercase letter.").refine((value) => /[0-9]/.test(value), "Password must include a number.").refine(
|
|
972
1029
|
(value) => !COMMON_MAILBOX_PASSWORDS.has(value.toLowerCase()),
|
|
973
1030
|
"This password is too common. Choose something stronger."
|
|
974
|
-
),
|
|
1031
|
+
).optional(),
|
|
1032
|
+
generate_password: z.literal(true).optional(),
|
|
975
1033
|
display_name: recipientNameSchema.max(128).optional(),
|
|
976
1034
|
idempotency_key: idempotencyKeySchema
|
|
1035
|
+
}).superRefine((value, ctx) => {
|
|
1036
|
+
if (Boolean(value.password) === Boolean(value.generate_password)) {
|
|
1037
|
+
ctx.addIssue({
|
|
1038
|
+
code: "custom",
|
|
1039
|
+
path: ["password"],
|
|
1040
|
+
message: "Provide password or set generate_password to true, but not both."
|
|
1041
|
+
});
|
|
1042
|
+
}
|
|
977
1043
|
});
|
|
978
1044
|
var updateMailboxInputSchema = z.object({
|
|
979
1045
|
id: idSchema,
|
|
980
1046
|
display_name: recipientNameSchema.max(200).nullable().describe("New display name, or null to clear."),
|
|
981
1047
|
idempotency_key: idempotencyKeySchema
|
|
982
1048
|
});
|
|
1049
|
+
var appPasswordCidrInputSchema = z.union([
|
|
1050
|
+
z.cidrv4("Must be a valid IPv4 CIDR range."),
|
|
1051
|
+
z.cidrv6("Must be a valid IPv6 CIDR range.")
|
|
1052
|
+
]);
|
|
1053
|
+
var createMailboxAppPasswordInputSchema = z.object({
|
|
1054
|
+
id: idSchema.describe("Mailbox ID."),
|
|
1055
|
+
name: noControlString(100, "name").trim().min(1),
|
|
1056
|
+
expires_at: z.iso.datetime().optional(),
|
|
1057
|
+
allowed_cidrs: z.array(appPasswordCidrInputSchema).max(20).optional()
|
|
1058
|
+
});
|
|
1059
|
+
var revokeMailboxAppPasswordInputSchema = z.object({
|
|
1060
|
+
id: idSchema.describe("Mailbox ID."),
|
|
1061
|
+
app_password_id: idSchema.describe("App password ID.")
|
|
1062
|
+
});
|
|
983
1063
|
var createMailboxFolderInputSchema = z.object({
|
|
984
1064
|
id: idSchema,
|
|
985
1065
|
name: folderNameSchema.describe("Custom folder name to create."),
|
|
@@ -1776,6 +1856,7 @@ var bookingPageSchema = z.object({
|
|
|
1776
1856
|
buffer_minutes: z.number(),
|
|
1777
1857
|
minimum_notice_minutes: z.number(),
|
|
1778
1858
|
max_advance_days: z.number(),
|
|
1859
|
+
conferencing_provider: z.enum(CONFERENCING_PROVIDER_IDS).nullable(),
|
|
1779
1860
|
active: z.boolean(),
|
|
1780
1861
|
created_at: z.string(),
|
|
1781
1862
|
updated_at: z.string()
|
|
@@ -1892,6 +1973,9 @@ var createBookingPageInputSchema = z.object({
|
|
|
1892
1973
|
buffer_minutes: z.number().int().min(0).max(240).optional(),
|
|
1893
1974
|
minimum_notice_minutes: z.number().int().min(0).optional(),
|
|
1894
1975
|
max_advance_days: z.number().int().min(1).max(365).optional(),
|
|
1976
|
+
conferencing_provider: z.enum(CONFERENCING_PROVIDER_IDS).nullish().describe(
|
|
1977
|
+
"Opt-in meeting provider. It must already be connected to the page's mailbox. Null means no meeting link."
|
|
1978
|
+
),
|
|
1895
1979
|
active: z.boolean().optional(),
|
|
1896
1980
|
idempotency_key: idempotencyKeySchema
|
|
1897
1981
|
});
|
|
@@ -1909,9 +1993,101 @@ var updateBookingPageInputSchema = z.object({
|
|
|
1909
1993
|
buffer_minutes: z.number().int().min(0).max(240).optional(),
|
|
1910
1994
|
minimum_notice_minutes: z.number().int().min(0).optional(),
|
|
1911
1995
|
max_advance_days: z.number().int().min(1).max(365).optional(),
|
|
1996
|
+
conferencing_provider: z.enum(CONFERENCING_PROVIDER_IDS).nullish().describe(
|
|
1997
|
+
"Opt-in meeting provider. It must already be connected to the page's mailbox. Set null to stop creating meeting links."
|
|
1998
|
+
),
|
|
1912
1999
|
active: z.boolean().optional(),
|
|
1913
2000
|
idempotency_key: idempotencyKeySchema
|
|
1914
2001
|
});
|
|
2002
|
+
var partnerOrganizationSchema = z.object({
|
|
2003
|
+
object: z.literal("partner_organization"),
|
|
2004
|
+
id: z.string(),
|
|
2005
|
+
organization_id: z.string(),
|
|
2006
|
+
name: z.string(),
|
|
2007
|
+
external_reference: z.string(),
|
|
2008
|
+
owner_email: z.string(),
|
|
2009
|
+
owner_user_id: z.string().nullable(),
|
|
2010
|
+
status: z.enum(["pending_owner", "active", "suspended", "offboarding", "disconnected"]),
|
|
2011
|
+
data_classification: z.enum(["internal_test", "customer"]),
|
|
2012
|
+
mailbox_limit: z.number().int(),
|
|
2013
|
+
delegated_permissions: z.array(z.string()),
|
|
2014
|
+
owner_accepted_at: z.string().nullable(),
|
|
2015
|
+
activated_at: z.string().nullable(),
|
|
2016
|
+
suspended_at: z.string().nullable(),
|
|
2017
|
+
disconnected_at: z.string().nullable(),
|
|
2018
|
+
created_at: z.string(),
|
|
2019
|
+
updated_at: z.string()
|
|
2020
|
+
});
|
|
2021
|
+
var partnerOrganizationOutputSchema = z.object({
|
|
2022
|
+
organization: partnerOrganizationSchema
|
|
2023
|
+
});
|
|
2024
|
+
var createdPartnerOrganizationSchema = partnerOrganizationSchema.extend({
|
|
2025
|
+
ownership_invitation: z.object({
|
|
2026
|
+
object: z.literal("partner_ownership_invitation"),
|
|
2027
|
+
owner_email: z.string(),
|
|
2028
|
+
email_sent: z.boolean(),
|
|
2029
|
+
expires_at: z.string()
|
|
2030
|
+
}).nullable()
|
|
2031
|
+
});
|
|
2032
|
+
var createdPartnerOrganizationOutputSchema = z.object({
|
|
2033
|
+
organization: createdPartnerOrganizationSchema
|
|
2034
|
+
});
|
|
2035
|
+
var partnerOrganizationsOutputSchema = z.object({
|
|
2036
|
+
data: z.array(partnerOrganizationSchema)
|
|
2037
|
+
});
|
|
2038
|
+
var partnerInvitationOutputSchema = z.object({
|
|
2039
|
+
invitation: z.object({
|
|
2040
|
+
object: z.literal("partner_ownership_invitation"),
|
|
2041
|
+
owner_email: z.string(),
|
|
2042
|
+
email_sent: z.boolean(),
|
|
2043
|
+
expires_at: z.string()
|
|
2044
|
+
})
|
|
2045
|
+
});
|
|
2046
|
+
var partnerUsageOutputSchema = z.object({
|
|
2047
|
+
usage: z.object({
|
|
2048
|
+
object: z.literal("partner_usage"),
|
|
2049
|
+
period_start: z.string(),
|
|
2050
|
+
period_end: z.string(),
|
|
2051
|
+
closed_through: z.string().nullable(),
|
|
2052
|
+
active_children: z.number().int(),
|
|
2053
|
+
active_mailboxes: z.number().int(),
|
|
2054
|
+
child_active_seconds: z.number().int(),
|
|
2055
|
+
mailbox_active_seconds: z.number().int(),
|
|
2056
|
+
child_subtotal: z.number().int(),
|
|
2057
|
+
mailbox_subtotal: z.number().int(),
|
|
2058
|
+
minimum_shortfall: z.number().int(),
|
|
2059
|
+
projected_total: z.number().int(),
|
|
2060
|
+
currency: z.string()
|
|
2061
|
+
})
|
|
2062
|
+
});
|
|
2063
|
+
var createPartnerOrganizationInputSchema = z.object({
|
|
2064
|
+
name: noControlString(120, "name").min(1),
|
|
2065
|
+
external_reference: noControlString(200, "external reference").min(1),
|
|
2066
|
+
owner_email: emailSchema,
|
|
2067
|
+
mailbox_limit: z.number().int().min(1).max(50).default(3),
|
|
2068
|
+
data_classification: z.enum(["internal_test", "customer"]).default("customer"),
|
|
2069
|
+
idempotency_key: idempotencyKeySchema
|
|
2070
|
+
});
|
|
2071
|
+
var partnerOrganizationByIdInputSchema = z.object({
|
|
2072
|
+
id: idSchema.describe("Partner organization relationship ID.")
|
|
2073
|
+
});
|
|
2074
|
+
var updatePartnerOrganizationInputSchema = partnerOrganizationByIdInputSchema.extend({
|
|
2075
|
+
name: noControlString(120, "name").min(1).optional(),
|
|
2076
|
+
mailbox_limit: z.number().int().min(1).max(50).optional(),
|
|
2077
|
+
idempotency_key: idempotencyKeySchema
|
|
2078
|
+
}).refine((value) => value.name !== void 0 || value.mailbox_limit !== void 0, {
|
|
2079
|
+
message: "Provide name or mailbox_limit."
|
|
2080
|
+
});
|
|
2081
|
+
var resendPartnerInvitationInputSchema = partnerOrganizationByIdInputSchema.extend({
|
|
2082
|
+
owner_email: emailSchema.optional(),
|
|
2083
|
+
idempotency_key: idempotencyKeySchema
|
|
2084
|
+
});
|
|
2085
|
+
var consumePartnerMailboxCredentialGrantInputSchema = z.object({
|
|
2086
|
+
grant_id: idSchema.describe("Single-use mailbox credential grant ID."),
|
|
2087
|
+
name: noControlString(100, "name").trim().min(1).optional(),
|
|
2088
|
+
expires_at: z.iso.datetime().optional(),
|
|
2089
|
+
allowed_cidrs: z.array(appPasswordCidrInputSchema).max(20).optional()
|
|
2090
|
+
});
|
|
1915
2091
|
|
|
1916
2092
|
// src/prompts.ts
|
|
1917
2093
|
var MAILBOX_LOCAL_REGEX = /^[a-zA-Z0-9]([a-zA-Z0-9._-]{0,62}[a-zA-Z0-9])?$/;
|
|
@@ -2357,6 +2533,8 @@ var SESSION_LIMITS = {
|
|
|
2357
2533
|
shipmail_create_domain: 10,
|
|
2358
2534
|
shipmail_create_mailbox: 20,
|
|
2359
2535
|
shipmail_create_mailbox_export: 5,
|
|
2536
|
+
shipmail_create_mailbox_app_password: 10,
|
|
2537
|
+
shipmail_revoke_mailbox_app_password: 20,
|
|
2360
2538
|
shipmail_create_mailbox_import: 5,
|
|
2361
2539
|
shipmail_cancel_mailbox_import: 10,
|
|
2362
2540
|
shipmail_undo_mailbox_import: 10,
|
|
@@ -2404,7 +2582,14 @@ var SESSION_LIMITS = {
|
|
|
2404
2582
|
shipmail_delete_calendar_event: 50,
|
|
2405
2583
|
shipmail_create_booking_page: 20,
|
|
2406
2584
|
shipmail_update_booking_page: 20,
|
|
2407
|
-
shipmail_delete_booking_page: 10
|
|
2585
|
+
shipmail_delete_booking_page: 10,
|
|
2586
|
+
shipmail_create_partner_organization: 20,
|
|
2587
|
+
shipmail_update_partner_organization: 50,
|
|
2588
|
+
shipmail_resend_partner_ownership_invitation: 20,
|
|
2589
|
+
shipmail_suspend_partner_organization: 20,
|
|
2590
|
+
shipmail_resume_partner_organization: 20,
|
|
2591
|
+
shipmail_offboard_partner_organization: 10,
|
|
2592
|
+
shipmail_consume_partner_mailbox_credential_grant: 20
|
|
2408
2593
|
};
|
|
2409
2594
|
var SESSION_TOTAL_LIMIT = 500;
|
|
2410
2595
|
var DEBUG_ENABLED = process.env["SHIPMAIL_MCP_DEBUG"] === "1";
|
|
@@ -2696,6 +2881,72 @@ function registerTools(server, client, selectedTools) {
|
|
|
2696
2881
|
}))
|
|
2697
2882
|
);
|
|
2698
2883
|
});
|
|
2884
|
+
registerIfAllowed("shipmail_list_mailbox_app_passwords", () => {
|
|
2885
|
+
server.registerTool(
|
|
2886
|
+
"shipmail_list_mailbox_app_passwords",
|
|
2887
|
+
{
|
|
2888
|
+
title: "List Mailbox App Passwords",
|
|
2889
|
+
description: "List app-password metadata for one mailbox. Secret values are never returned by this read operation.",
|
|
2890
|
+
inputSchema: getByIdInputSchema,
|
|
2891
|
+
outputSchema: mailboxAppPasswordsOutputSchema,
|
|
2892
|
+
annotations: { readOnlyHint: true, openWorldHint: false }
|
|
2893
|
+
},
|
|
2894
|
+
async ({ id }) => runTool(
|
|
2895
|
+
"shipmail_list_mailbox_app_passwords",
|
|
2896
|
+
mailboxAppPasswordsOutputSchema,
|
|
2897
|
+
async () => ({ app_passwords: await client.mailboxes.listAppPasswords(id) })
|
|
2898
|
+
)
|
|
2899
|
+
);
|
|
2900
|
+
});
|
|
2901
|
+
registerIfAllowed("shipmail_create_mailbox_app_password", () => {
|
|
2902
|
+
server.registerTool(
|
|
2903
|
+
"shipmail_create_mailbox_app_password",
|
|
2904
|
+
{
|
|
2905
|
+
title: "Create Mailbox App Password",
|
|
2906
|
+
description: "Create a revocable mailbox credential for an email client. The secret is returned exactly once in this tool result, so only call after explicit operator approval and store it securely.",
|
|
2907
|
+
inputSchema: createMailboxAppPasswordInputSchema,
|
|
2908
|
+
outputSchema: createdMailboxAppPasswordOutputSchema,
|
|
2909
|
+
annotations: {
|
|
2910
|
+
readOnlyHint: false,
|
|
2911
|
+
destructiveHint: true,
|
|
2912
|
+
idempotentHint: false,
|
|
2913
|
+
openWorldHint: false
|
|
2914
|
+
}
|
|
2915
|
+
},
|
|
2916
|
+
async (args) => runTool(
|
|
2917
|
+
"shipmail_create_mailbox_app_password",
|
|
2918
|
+
createdMailboxAppPasswordOutputSchema,
|
|
2919
|
+
async () => ({
|
|
2920
|
+
app_password: await client.mailboxes.createAppPassword(args.id, {
|
|
2921
|
+
name: args.name,
|
|
2922
|
+
...args.expires_at ? { expires_at: args.expires_at } : {},
|
|
2923
|
+
...args.allowed_cidrs ? { allowed_cidrs: args.allowed_cidrs } : {}
|
|
2924
|
+
})
|
|
2925
|
+
})
|
|
2926
|
+
)
|
|
2927
|
+
);
|
|
2928
|
+
});
|
|
2929
|
+
registerIfAllowed("shipmail_revoke_mailbox_app_password", () => {
|
|
2930
|
+
server.registerTool(
|
|
2931
|
+
"shipmail_revoke_mailbox_app_password",
|
|
2932
|
+
{
|
|
2933
|
+
title: "Revoke Mailbox App Password",
|
|
2934
|
+
description: "Permanently revoke one mailbox app password. The associated client will lose access immediately.",
|
|
2935
|
+
inputSchema: revokeMailboxAppPasswordInputSchema,
|
|
2936
|
+
outputSchema: acknowledgmentOutputSchema,
|
|
2937
|
+
annotations: {
|
|
2938
|
+
readOnlyHint: false,
|
|
2939
|
+
destructiveHint: true,
|
|
2940
|
+
idempotentHint: true,
|
|
2941
|
+
openWorldHint: false
|
|
2942
|
+
}
|
|
2943
|
+
},
|
|
2944
|
+
async ({ id, app_password_id }) => runTool("shipmail_revoke_mailbox_app_password", acknowledgmentOutputSchema, async () => {
|
|
2945
|
+
await client.mailboxes.revokeAppPassword(id, app_password_id);
|
|
2946
|
+
return { result: { ok: true, id: app_password_id } };
|
|
2947
|
+
})
|
|
2948
|
+
);
|
|
2949
|
+
});
|
|
2699
2950
|
registerIfAllowed("shipmail_suspend_mailbox", () => {
|
|
2700
2951
|
server.registerTool(
|
|
2701
2952
|
"shipmail_suspend_mailbox",
|
|
@@ -2751,9 +3002,24 @@ function registerTools(server, client, selectedTools) {
|
|
|
2751
3002
|
openWorldHint: false
|
|
2752
3003
|
}
|
|
2753
3004
|
},
|
|
2754
|
-
async (args) => runTool("shipmail_create_mailbox", mailboxOutputSchema, async () =>
|
|
2755
|
-
|
|
2756
|
-
|
|
3005
|
+
async (args) => runTool("shipmail_create_mailbox", mailboxOutputSchema, async () => {
|
|
3006
|
+
const base = {
|
|
3007
|
+
domain_id: args.domain_id,
|
|
3008
|
+
address: args.address,
|
|
3009
|
+
...args.display_name === void 0 ? {} : { display_name: args.display_name }
|
|
3010
|
+
};
|
|
3011
|
+
let params;
|
|
3012
|
+
if (args.generate_password === true) {
|
|
3013
|
+
params = { ...base, generate_password: true };
|
|
3014
|
+
} else if (args.password !== void 0) {
|
|
3015
|
+
params = { ...base, password: args.password };
|
|
3016
|
+
} else {
|
|
3017
|
+
throw new Error("Mailbox password validation failed.");
|
|
3018
|
+
}
|
|
3019
|
+
return {
|
|
3020
|
+
mailbox: await client.mailboxes.create(params, mutationOptions(args))
|
|
3021
|
+
};
|
|
3022
|
+
})
|
|
2757
3023
|
);
|
|
2758
3024
|
});
|
|
2759
3025
|
registerIfAllowed("shipmail_create_mailbox_export", () => {
|
|
@@ -4493,7 +4759,7 @@ function registerTools(server, client, selectedTools) {
|
|
|
4493
4759
|
"shipmail_create_booking_page",
|
|
4494
4760
|
{
|
|
4495
4761
|
title: "Create Booking Page",
|
|
4496
|
-
description: "Create a booking page exposing one mailbox's availability. availability_days is 0=Sunday..6=Saturday.",
|
|
4762
|
+
description: "Create a booking page exposing one mailbox's availability. availability_days is 0=Sunday..6=Saturday. conferencing_provider is opt-in and must already be connected to the mailbox.",
|
|
4497
4763
|
inputSchema: createBookingPageInputSchema,
|
|
4498
4764
|
outputSchema: bookingPageOutputSchema,
|
|
4499
4765
|
annotations: {
|
|
@@ -4516,7 +4782,7 @@ function registerTools(server, client, selectedTools) {
|
|
|
4516
4782
|
"shipmail_update_booking_page",
|
|
4517
4783
|
{
|
|
4518
4784
|
title: "Update Booking Page",
|
|
4519
|
-
description: "Update a booking page. All fields optional; provide at least one.",
|
|
4785
|
+
description: "Update a booking page. All fields optional; provide at least one. Set conferencing_provider to null to stop creating meeting links.",
|
|
4520
4786
|
inputSchema: updateBookingPageInputSchema,
|
|
4521
4787
|
outputSchema: bookingPageOutputSchema,
|
|
4522
4788
|
annotations: {
|
|
@@ -4555,6 +4821,204 @@ function registerTools(server, client, selectedTools) {
|
|
|
4555
4821
|
})
|
|
4556
4822
|
);
|
|
4557
4823
|
});
|
|
4824
|
+
registerIfAllowed("shipmail_list_partner_organizations", () => {
|
|
4825
|
+
server.registerTool(
|
|
4826
|
+
"shipmail_list_partner_organizations",
|
|
4827
|
+
{
|
|
4828
|
+
title: "List Partner Organizations",
|
|
4829
|
+
description: "List operator-owned organizations connected to the partner account.",
|
|
4830
|
+
outputSchema: partnerOrganizationsOutputSchema,
|
|
4831
|
+
annotations: { readOnlyHint: true, openWorldHint: false }
|
|
4832
|
+
},
|
|
4833
|
+
async () => runTool(
|
|
4834
|
+
"shipmail_list_partner_organizations",
|
|
4835
|
+
partnerOrganizationsOutputSchema,
|
|
4836
|
+
() => client.partner.listOrganizations()
|
|
4837
|
+
)
|
|
4838
|
+
);
|
|
4839
|
+
});
|
|
4840
|
+
registerIfAllowed("shipmail_create_partner_organization", () => {
|
|
4841
|
+
server.registerTool(
|
|
4842
|
+
"shipmail_create_partner_organization",
|
|
4843
|
+
{
|
|
4844
|
+
title: "Create Partner Organization",
|
|
4845
|
+
description: "Create an operator organization and email its ownership invitation. No domain or mailbox is created.",
|
|
4846
|
+
inputSchema: createPartnerOrganizationInputSchema,
|
|
4847
|
+
outputSchema: createdPartnerOrganizationOutputSchema,
|
|
4848
|
+
annotations: {
|
|
4849
|
+
readOnlyHint: false,
|
|
4850
|
+
destructiveHint: false,
|
|
4851
|
+
idempotentHint: true,
|
|
4852
|
+
openWorldHint: false
|
|
4853
|
+
}
|
|
4854
|
+
},
|
|
4855
|
+
async (args) => runTool(
|
|
4856
|
+
"shipmail_create_partner_organization",
|
|
4857
|
+
createdPartnerOrganizationOutputSchema,
|
|
4858
|
+
async () => ({
|
|
4859
|
+
organization: await client.partner.createOrganization(
|
|
4860
|
+
stripIdempotencyKey(args),
|
|
4861
|
+
mutationOptions(args)
|
|
4862
|
+
)
|
|
4863
|
+
})
|
|
4864
|
+
)
|
|
4865
|
+
);
|
|
4866
|
+
});
|
|
4867
|
+
registerIfAllowed("shipmail_get_partner_organization", () => {
|
|
4868
|
+
server.registerTool(
|
|
4869
|
+
"shipmail_get_partner_organization",
|
|
4870
|
+
{
|
|
4871
|
+
title: "Get Partner Organization",
|
|
4872
|
+
description: "Get one partner child relationship and its ownership state.",
|
|
4873
|
+
inputSchema: partnerOrganizationByIdInputSchema,
|
|
4874
|
+
outputSchema: partnerOrganizationOutputSchema,
|
|
4875
|
+
annotations: { readOnlyHint: true, openWorldHint: false }
|
|
4876
|
+
},
|
|
4877
|
+
async ({ id }) => runTool("shipmail_get_partner_organization", partnerOrganizationOutputSchema, async () => ({
|
|
4878
|
+
organization: await client.partner.getOrganization(id)
|
|
4879
|
+
}))
|
|
4880
|
+
);
|
|
4881
|
+
});
|
|
4882
|
+
registerIfAllowed("shipmail_update_partner_organization", () => {
|
|
4883
|
+
server.registerTool(
|
|
4884
|
+
"shipmail_update_partner_organization",
|
|
4885
|
+
{
|
|
4886
|
+
title: "Update Partner Organization",
|
|
4887
|
+
description: "Update an operator organization name or mailbox allocation.",
|
|
4888
|
+
inputSchema: updatePartnerOrganizationInputSchema,
|
|
4889
|
+
outputSchema: partnerOrganizationOutputSchema,
|
|
4890
|
+
annotations: {
|
|
4891
|
+
readOnlyHint: false,
|
|
4892
|
+
destructiveHint: false,
|
|
4893
|
+
idempotentHint: true,
|
|
4894
|
+
openWorldHint: false
|
|
4895
|
+
}
|
|
4896
|
+
},
|
|
4897
|
+
async (args) => runTool(
|
|
4898
|
+
"shipmail_update_partner_organization",
|
|
4899
|
+
partnerOrganizationOutputSchema,
|
|
4900
|
+
async () => {
|
|
4901
|
+
const { id, idempotency_key: _key, ...params } = args;
|
|
4902
|
+
return {
|
|
4903
|
+
organization: await client.partner.updateOrganization(
|
|
4904
|
+
id,
|
|
4905
|
+
params,
|
|
4906
|
+
mutationOptions(args)
|
|
4907
|
+
)
|
|
4908
|
+
};
|
|
4909
|
+
}
|
|
4910
|
+
)
|
|
4911
|
+
);
|
|
4912
|
+
});
|
|
4913
|
+
registerIfAllowed("shipmail_resend_partner_ownership_invitation", () => {
|
|
4914
|
+
server.registerTool(
|
|
4915
|
+
"shipmail_resend_partner_ownership_invitation",
|
|
4916
|
+
{
|
|
4917
|
+
title: "Resend Partner Ownership Invitation",
|
|
4918
|
+
description: "Revoke the pending ownership link and email a new single-use link.",
|
|
4919
|
+
inputSchema: resendPartnerInvitationInputSchema,
|
|
4920
|
+
outputSchema: partnerInvitationOutputSchema,
|
|
4921
|
+
annotations: {
|
|
4922
|
+
readOnlyHint: false,
|
|
4923
|
+
destructiveHint: false,
|
|
4924
|
+
idempotentHint: true,
|
|
4925
|
+
openWorldHint: true
|
|
4926
|
+
}
|
|
4927
|
+
},
|
|
4928
|
+
async (args) => runTool(
|
|
4929
|
+
"shipmail_resend_partner_ownership_invitation",
|
|
4930
|
+
partnerInvitationOutputSchema,
|
|
4931
|
+
async () => ({
|
|
4932
|
+
invitation: await client.partner.resendOwnershipInvitation(
|
|
4933
|
+
args.id,
|
|
4934
|
+
{ owner_email: args.owner_email },
|
|
4935
|
+
mutationOptions(args)
|
|
4936
|
+
)
|
|
4937
|
+
})
|
|
4938
|
+
)
|
|
4939
|
+
);
|
|
4940
|
+
});
|
|
4941
|
+
for (const transition of ["suspend", "resume", "offboard"]) {
|
|
4942
|
+
const toolName = `shipmail_${transition}_partner_organization`;
|
|
4943
|
+
registerIfAllowed(toolName, () => {
|
|
4944
|
+
server.registerTool(
|
|
4945
|
+
toolName,
|
|
4946
|
+
{
|
|
4947
|
+
title: `${transition[0]?.toUpperCase() ?? ""}${transition.slice(1)} Partner Organization`,
|
|
4948
|
+
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.",
|
|
4949
|
+
inputSchema: partnerOrganizationByIdInputSchema,
|
|
4950
|
+
outputSchema: partnerOrganizationOutputSchema,
|
|
4951
|
+
annotations: {
|
|
4952
|
+
readOnlyHint: false,
|
|
4953
|
+
destructiveHint: transition !== "resume",
|
|
4954
|
+
idempotentHint: true,
|
|
4955
|
+
openWorldHint: false
|
|
4956
|
+
}
|
|
4957
|
+
},
|
|
4958
|
+
async ({ id }) => runTool(toolName, partnerOrganizationOutputSchema, async () => ({
|
|
4959
|
+
organization: transition === "suspend" ? await client.partner.suspendOrganization(id) : transition === "resume" ? await client.partner.resumeOrganization(id) : await client.partner.offboardOrganization(id)
|
|
4960
|
+
}))
|
|
4961
|
+
);
|
|
4962
|
+
});
|
|
4963
|
+
}
|
|
4964
|
+
registerIfAllowed("shipmail_consume_partner_mailbox_credential_grant", () => {
|
|
4965
|
+
server.registerTool(
|
|
4966
|
+
"shipmail_consume_partner_mailbox_credential_grant",
|
|
4967
|
+
{
|
|
4968
|
+
title: "Consume Partner Mailbox Credential Grant",
|
|
4969
|
+
description: "Consume an operator-approved, single-use grant and issue an embedded-webmail credential. The secret is returned exactly once and the operator is notified. Call only after explicit partner approval.",
|
|
4970
|
+
inputSchema: consumePartnerMailboxCredentialGrantInputSchema,
|
|
4971
|
+
outputSchema: partnerMailboxCredentialOutputSchema,
|
|
4972
|
+
annotations: {
|
|
4973
|
+
readOnlyHint: false,
|
|
4974
|
+
destructiveHint: true,
|
|
4975
|
+
idempotentHint: false,
|
|
4976
|
+
openWorldHint: true
|
|
4977
|
+
}
|
|
4978
|
+
},
|
|
4979
|
+
async (args) => runTool(
|
|
4980
|
+
"shipmail_consume_partner_mailbox_credential_grant",
|
|
4981
|
+
partnerMailboxCredentialOutputSchema,
|
|
4982
|
+
async () => ({
|
|
4983
|
+
credential: await client.partner.consumeMailboxCredentialGrant(args.grant_id, {
|
|
4984
|
+
...args.name ? { name: args.name } : {},
|
|
4985
|
+
...args.expires_at ? { expires_at: args.expires_at } : {},
|
|
4986
|
+
...args.allowed_cidrs ? { allowed_cidrs: args.allowed_cidrs } : {}
|
|
4987
|
+
})
|
|
4988
|
+
})
|
|
4989
|
+
)
|
|
4990
|
+
);
|
|
4991
|
+
});
|
|
4992
|
+
registerIfAllowed("shipmail_list_partner_mailbox_credential_grants", () => {
|
|
4993
|
+
server.registerTool(
|
|
4994
|
+
"shipmail_list_partner_mailbox_credential_grants",
|
|
4995
|
+
{
|
|
4996
|
+
title: "List Partner Mailbox Credential Grants",
|
|
4997
|
+
description: "List active ten-minute mailbox approvals created by operator owners. Grant metadata contains no app-password secret.",
|
|
4998
|
+
outputSchema: partnerMailboxCredentialGrantsOutputSchema,
|
|
4999
|
+
annotations: { readOnlyHint: true, openWorldHint: false }
|
|
5000
|
+
},
|
|
5001
|
+
async () => runTool(
|
|
5002
|
+
"shipmail_list_partner_mailbox_credential_grants",
|
|
5003
|
+
partnerMailboxCredentialGrantsOutputSchema,
|
|
5004
|
+
async () => ({ grants: await client.partner.listMailboxCredentialGrants() })
|
|
5005
|
+
)
|
|
5006
|
+
);
|
|
5007
|
+
});
|
|
5008
|
+
registerIfAllowed("shipmail_get_partner_usage", () => {
|
|
5009
|
+
server.registerTool(
|
|
5010
|
+
"shipmail_get_partner_usage",
|
|
5011
|
+
{
|
|
5012
|
+
title: "Get Partner Usage",
|
|
5013
|
+
description: "Get consolidated child and mailbox usage for the current UTC month.",
|
|
5014
|
+
outputSchema: partnerUsageOutputSchema,
|
|
5015
|
+
annotations: { readOnlyHint: true, openWorldHint: false }
|
|
5016
|
+
},
|
|
5017
|
+
async () => runTool("shipmail_get_partner_usage", partnerUsageOutputSchema, async () => ({
|
|
5018
|
+
usage: await client.partner.usage()
|
|
5019
|
+
}))
|
|
5020
|
+
);
|
|
5021
|
+
});
|
|
4558
5022
|
if (selectedTools) {
|
|
4559
5023
|
const unknown = [...selectedTools].filter((name) => !knownTools.includes(name));
|
|
4560
5024
|
if (unknown.length > 0) {
|
|
@@ -4565,7 +5029,7 @@ function registerTools(server, client, selectedTools) {
|
|
|
4565
5029
|
}
|
|
4566
5030
|
|
|
4567
5031
|
// src/version.ts
|
|
4568
|
-
var VERSION = "0.
|
|
5032
|
+
var VERSION = "0.3.0";
|
|
4569
5033
|
|
|
4570
5034
|
// src/server.ts
|
|
4571
5035
|
var INSTRUCTIONS = `ShipMail MCP exposes business email tools for domains, mailboxes, messages, threads, webhooks, and suppressions.
|
|
@@ -4590,6 +5054,7 @@ function createShipMailMcpServer(config) {
|
|
|
4590
5054
|
const client = new ShipMailClient({
|
|
4591
5055
|
apiKey: config.apiKey,
|
|
4592
5056
|
...config.baseUrl ? { baseUrl: config.baseUrl } : {},
|
|
5057
|
+
...config.organizationId ? { organizationId: config.organizationId } : {},
|
|
4593
5058
|
defaultHeaders
|
|
4594
5059
|
});
|
|
4595
5060
|
const server = new McpServer4(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shipmail-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"mcpName": "io.github.jcoulaud/shipmail-mcp",
|
|
5
5
|
"description": "Official Model Context Protocol (MCP) server for Shipmail, a business email provider with REST API, webhooks, and custom-domain inboxes for AI agents.",
|
|
6
6
|
"type": "module",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
62
|
-
"shipmail": "0.
|
|
62
|
+
"shipmail": "0.2.0",
|
|
63
63
|
"zod": "4.4.3"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
package/server.json
CHANGED
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
"url": "https://github.com/jcoulaud/shipmail-mcp",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.3.0",
|
|
10
10
|
"websiteUrl": "https://shipmail.to/docs/mcp",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
15
15
|
"identifier": "shipmail-mcp",
|
|
16
|
-
"version": "0.
|
|
16
|
+
"version": "0.3.0",
|
|
17
17
|
"transport": {
|
|
18
18
|
"type": "stdio"
|
|
19
19
|
},
|
package/smithery.yaml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Smithery configuration file: https://smithery.ai/docs/build/project-config/smithery-yaml
|
|
2
2
|
name: shipmail-mcp
|
|
3
|
-
version: 0.
|
|
3
|
+
version: 0.3.0
|
|
4
4
|
description: Official Shipmail MCP server for AI-agent custom-domain business email inboxes with REST API and webhooks.
|
|
5
5
|
author: ShipMail
|
|
6
6
|
repository: https://github.com/jcoulaud/shipmail-mcp
|