run402-mcp
Version:
MCP server for Run402 — full-stack backend infrastructure for AI agents: Postgres, auth, storage, serverless functions and atomic deploys. Paid with x402/MPP. Includes $0.03 image generation.
372 lines • 15.9 kB
TypeScript
/**
* `email` namespace — project mailboxes (defaults, send / list / get / raw /
* delete) and mailbox webhooks.
*/
import type { Client } from "../kernel.js";
declare const MESSAGE_DIRECTIONS: readonly ["inbound", "outbound"];
declare const DELIVERY_STATUSES: readonly ["pending", "in_flight", "delivered", "failed_permanent"];
declare const MAILBOX_FOOTER_POLICIES: readonly ["run402_transparency", "none"];
/** Direction filter for `email.list`. Omit to list both sent + received. */
export type MessageDirection = (typeof MESSAGE_DIRECTIONS)[number];
/** Durable webhook delivery lifecycle status. `failed_permanent` is the DLQ. */
export type WebhookDeliveryStatus = (typeof DELIVERY_STATUSES)[number];
/** Outbound footer policy configured on a mailbox. */
export type MailboxFooterPolicy = (typeof MAILBOX_FOOTER_POLICIES)[number];
export interface MailboxRecord {
mailbox_id: string;
/** Primary address for sends. This is custom-domain address only after DKIM is verified and inbound is enabled. */
address: string;
/** Immutable Run402-managed address, usually `<slug>@<project-mail-host>.mail.run402.com`. */
managed_address?: string;
slug: string;
project_id: string;
status: "active" | "suspended" | "deleted";
sends_today: number;
unique_recipients: number;
created_at: string;
updated_at: string;
/** True when this mailbox is configured as the project's outbound default. */
is_default_outbound?: boolean;
/** True when this mailbox is configured as the auth/session email sender. */
is_auth_sender?: boolean;
/** Whether the mailbox can currently send outbound mail. */
can_send?: boolean;
/** Present when `can_send` is false, e.g. domain verification or suspension. */
send_blocked_reason?: string | null;
/** Run402-managed project mail host vs a project-owned sender domain. Future strings are valid. */
domain_kind?: string;
/** Domain portion of `address`. */
address_domain?: string;
/** Domain portion of `managed_address`. */
managed_domain?: string;
/** True when a custom sender domain is verified and inbound-enabled, so it can be primary. */
custom_domain_ready?: boolean;
/** Whether inbound mail can be received at `address`. */
can_receive?: boolean;
/** Configured outbound footer policy for this mailbox. */
footer_policy?: MailboxFooterPolicy;
/** Effective policy after tier locks/defaults are applied. */
effective_footer_policy?: MailboxFooterPolicy;
/** Present when the requested footer policy is locked by tier or platform policy. */
footer_policy_locked_reason?: string | null;
}
export interface MailboxSettings {
default_outbound_mailbox_id: string | null;
auth_sender_mailbox_id: string | null;
}
export interface MailboxNextAction {
type?: string;
action?: string;
method?: string;
path?: string;
auth?: string;
why?: string;
command?: string;
[key: string]: unknown;
}
export interface MailboxProviderReadiness {
status?: string;
provider?: string;
reason?: string;
[key: string]: unknown;
}
export interface MailboxSelectionEnvelope {
mailbox_settings?: MailboxSettings;
provider_readiness?: MailboxProviderReadiness;
next_actions?: MailboxNextAction[];
}
export type CreateMailboxResult = MailboxRecord & MailboxSelectionEnvelope;
export type MailboxInfo = MailboxRecord;
export interface MailboxListResult extends MailboxSelectionEnvelope {
mailboxes: MailboxRecord[];
}
export type MailboxListResponse = MailboxListResult;
export interface SetMailboxDefaultsOptions {
default_outbound_mailbox_id?: string | null;
auth_sender_mailbox_id?: string | null;
}
export type SetMailboxDefaultsResult = MailboxListResult;
export interface UpdateMailboxOptions {
/** Target mailbox by slug or `mbx_...` id; omit only on single-mailbox projects. */
mailbox?: MailboxSelector;
/** Outbound footer policy. Prototype projects are locked to `run402_transparency`. */
footer_policy?: MailboxFooterPolicy;
}
export type UpdateMailboxResult = MailboxInfo;
export interface DeleteMailboxResult {
mailbox_id: string;
address: string;
managed_address?: string;
}
export type EmailTemplate = "project_invite" | "magic_link" | "notification";
/** Selects a target mailbox on a project: a mailbox id (`mbx_…`) or a project-scoped local-part slug. */
export type MailboxSelector = string;
/** A single binary attachment (raw mode only). `content_base64` is the file's bytes, base64-encoded. */
export interface EmailAttachment {
filename: string;
content_base64: string;
content_type: string;
}
/** Attachment metadata recorded on a sent message (names/types/sizes — never the bytes). */
export interface EmailAttachmentMeta {
filename: string;
content_type: string;
size_bytes: number;
}
export interface SendEmailOptions {
to: string;
template?: EmailTemplate;
variables?: Record<string, string>;
subject?: string;
html?: string;
text?: string;
from_name?: string;
/**
* Binary attachments — RAW MODE ONLY (with `subject` + `html`, not `template`).
* At most 5; each ≤ 7 MB and ≤ 7 MB total (decoded). The platform sends a
* multipart/mixed MIME when present.
*/
attachments?: EmailAttachment[];
in_reply_to?: string;
/**
* Target mailbox (slug or `mbx_…` id). Omit to use the configured
* `default_outbound_mailbox_id` when the gateway returns mailbox settings.
* Missing or invalid defaults surface typed repair errors.
*/
mailbox?: MailboxSelector;
}
/** Options carrying just a mailbox selector, for `get` / `getRaw` / webhook reads. */
export interface MailboxScopedOptions {
mailbox?: MailboxSelector;
}
export interface SendEmailResult {
message_id: string;
status: string;
to: string;
template: string | null;
subject: string | null;
sent_at: string;
/** The actual mailbox used for the send, echoed by the gateway. */
mailbox_id?: string;
/** The actual From address used for the send, echoed by the gateway. */
from_address?: string;
}
export interface EmailSummary {
id: string;
/** Core gateways may expose this spelling on the wire; SDK normalizes `id`. */
message_id?: string;
/** "inbound" (received) or "outbound" (sent). */
direction: string;
template: string | null;
to: string;
status: string;
created_at: string;
/** Present (non-null) when the send carried attachments; names/types/sizes only. */
attachments_meta?: EmailAttachmentMeta[] | null;
}
export interface EmailDetail {
id: string;
/** Core gateways may expose this spelling on the wire; SDK normalizes `id`. */
message_id?: string;
template: string | null;
to: string;
status: string;
variables?: Record<string, string>;
subject?: string | null;
mailbox_id?: string;
from_address?: string;
delivery_state?: string;
provider?: string | null;
provider_message_id?: string | null;
created_at: string;
updated_at?: string;
sent_at?: string | null;
/** Present (non-null) when the send carried attachments; names/types/sizes only. */
attachments_meta?: EmailAttachmentMeta[] | null;
replies?: Array<{
id: string;
from: string;
body: string;
received_at: string;
}>;
}
export interface ListEmailsOptions {
limit?: number;
after?: string;
/**
* Filter to one direction. Omit to list BOTH sent (outbound) and received
* (inbound) messages — `inbound` is the reconciliation backstop for a lost
* `reply_received` webhook.
*/
direction?: MessageDirection;
/** Target mailbox (slug or `mbx_…` id); omit only on single-mailbox projects. */
mailbox?: MailboxSelector;
}
export interface RawEmailResult {
content_type: string;
bytes: Uint8Array;
}
export interface MailboxWebhookSummary {
webhook_id: string;
url: string;
events: string[];
created_at: string;
}
export interface MailboxWebhooksResult {
webhooks: MailboxWebhookSummary[];
}
export interface RegisterWebhookOptions {
url: string;
events: string[];
/** Target mailbox (slug or `mbx_…` id); omit only on single-mailbox projects. */
mailbox?: MailboxSelector;
}
export interface UpdateWebhookOptions {
url?: string;
events?: string[];
/** Target mailbox (slug or `mbx_…` id); omit only on single-mailbox projects. */
mailbox?: MailboxSelector;
}
/**
* A single durable webhook delivery row. Delivery is at-least-once: the same
* event may arrive more than once, so consumers MUST dedupe on the envelope's
* `idempotency_key` (also sent as the `Run402-Webhook-Id` header).
*/
export interface WebhookDeliverySummary {
delivery_id: string;
webhook_id: string | null;
event_type: string;
status: WebhookDeliveryStatus;
attempts: number;
last_status: number | null;
last_error: string | null;
next_attempt_at: string | null;
delivered_at: string | null;
created_at: string;
}
export interface WebhookDeliveriesResult {
deliveries: WebhookDeliverySummary[];
has_more: boolean;
next_cursor: string | null;
}
export interface ListDeliveriesOptions {
/** Filter by lifecycle status. `failed_permanent` is the dead-letter queue. */
status?: WebhookDeliveryStatus;
limit?: number;
after?: string;
/** Target mailbox (slug or `mbx_…` id); omit only on single-mailbox projects. */
mailbox?: MailboxSelector;
}
export interface RedriveDeliveryResult {
status: "requeued";
delivery: WebhookDeliverySummary;
}
export declare class Webhooks {
private readonly client;
private readonly resolveMailbox;
constructor(client: Client, resolveMailbox: (projectId: string, selector?: MailboxSelector) => Promise<{
id: string;
serviceKey: string;
}>);
/**
* List durable webhook delivery rows for the mailbox, optionally filtered by
* status. `failed_permanent` is the dead-letter queue. Delivery is
* at-least-once — consumers MUST dedupe on the envelope `idempotency_key`.
*/
listDeliveries(projectId: string, opts?: ListDeliveriesOptions): Promise<WebhookDeliveriesResult>;
/** Re-queue a dead-lettered (`failed_permanent`) delivery for another attempt. */
redriveDelivery(projectId: string, deliveryId: string, opts?: MailboxScopedOptions): Promise<RedriveDeliveryResult>;
register(projectId: string, opts: RegisterWebhookOptions): Promise<MailboxWebhookSummary>;
list(projectId: string, opts?: MailboxScopedOptions): Promise<MailboxWebhooksResult>;
get(projectId: string, webhookId: string, opts?: MailboxScopedOptions): Promise<MailboxWebhookSummary>;
update(projectId: string, webhookId: string, opts: UpdateWebhookOptions): Promise<MailboxWebhookSummary>;
delete(projectId: string, webhookId: string, opts?: MailboxScopedOptions): Promise<void>;
}
export declare class Email {
private readonly client;
readonly webhooks: Webhooks;
readonly create: (projectId: string, slug: string) => Promise<CreateMailboxResult>;
readonly status: (projectId: string, mailbox?: MailboxSelector) => Promise<MailboxInfo>;
readonly info: (projectId: string, mailbox?: MailboxSelector) => Promise<MailboxInfo>;
readonly delete: (projectId: string, mailbox?: MailboxSelector) => Promise<DeleteMailboxResult>;
readonly update: (projectId: string, opts: UpdateMailboxOptions) => Promise<UpdateMailboxResult>;
constructor(client: Client);
/**
* Resolve a project mailbox to `{ id, serviceKey }` for an operation.
*
* - `selector` is a mailbox id (`mbx_…`) → used directly; the gateway 403s
* if the id belongs to a different project, so no list call is needed.
* - `selector` is a slug → the project's mailboxes are listed and matched.
* - `selector` omitted for sends → use the configured
* `default_outbound_mailbox_id`. When the gateway returns
* `mailbox_settings` and no default is set, throw
* `DEFAULT_MAILBOX_REQUIRED`; do not silently pick the first/single row.
* - `selector` omitted for reads/webhooks → require a unique mailbox, as
* before. This keeps non-send flows from guessing that the outbound
* default is also the intended read/webhook target.
*
* The cached `mailbox_id` is intentionally NOT used to resolve when a
* selector is omitted — trusting it would silently target an arbitrary
* mailbox on a multi-mailbox project.
*/
private resolveMailbox;
private pickDefaultOutboundMailbox;
/**
* Choose a mailbox from a project's list given an optional selector.
* `selector` matches by exact mailbox id or slug. With no selector: 0 →
* "create one first" (404), 1 → that one, 2+ → ambiguity error (409) naming
* the available slugs.
*/
private pickMailbox;
/** Best-effort refresh of the single-mailbox convenience cache. */
private cacheMailbox;
private listMailboxEnvelope;
/** List project mailboxes plus default-role settings and gateway repair hints. */
listMailboxes(projectId: string): Promise<MailboxListResult>;
/**
* Configure the project's mailbox defaults. Values are mailbox ids
* (`mbx_…`) or `null` to clear when the gateway allows clearing.
*/
setMailboxDefaults(projectId: string, opts: SetMailboxDefaultsOptions): Promise<SetMailboxDefaultsResult>;
/**
* Update per-mailbox settings. Currently supports the outbound
* `footer_policy` field accepted by PATCH /mailboxes/v1/:mailbox_id.
*/
updateMailbox(projectId: string, opts: UpdateMailboxOptions): Promise<UpdateMailboxResult>;
/**
* Create a mailbox for a project.
*
* NOT idempotent. A 409 from the gateway now means `Slug already in use`,
* `Address is in cooldown period`, or `Project mailbox limit reached (5)` —
* none of which mean "you already own this slug" — so the 409 is surfaced
* verbatim rather than silently returning some other existing mailbox.
* Callers that want create-or-get should `list`/`getMailbox` explicitly.
*/
createMailbox(projectId: string, slug: string): Promise<CreateMailboxResult>;
/** Send an email via template or raw (subject + html) mode. */
send(projectId: string, opts: SendEmailOptions): Promise<SendEmailResult>;
/** List messages in the project's mailbox. */
list(projectId: string, opts?: ListEmailsOptions): Promise<EmailSummary[]>;
/** Get a single message by id, including any replies. */
get(projectId: string, messageId: string, opts?: MailboxScopedOptions): Promise<EmailDetail>;
/**
* Fetch the raw RFC-822 bytes of an inbound message. Returns `Uint8Array`
* so the consumer can decode / store / forward without re-encoding.
*/
getRaw(projectId: string, messageId: string, opts?: MailboxScopedOptions): Promise<RawEmailResult>;
/**
* Get a project mailbox's info. With a `selector` (slug or `mbx_…` id),
* returns that mailbox; without one, returns the project's only mailbox or
* throws an ambiguity error when it has more than one.
*/
getMailbox(projectId: string, selector?: MailboxSelector): Promise<MailboxInfo>;
/**
* Delete the project's mailbox. Destructive — drops all messages and
* webhook subscriptions. Pass `mailboxId` explicitly to delete a specific
* mailbox; otherwise the project's current mailbox is resolved. Returns
* the deleted record echoed by the gateway.
*/
deleteMailbox(projectId: string, selector?: MailboxSelector): Promise<DeleteMailboxResult>;
}
export {};
//# sourceMappingURL=email.d.ts.map