MCP for AI agents
Virtual inboxes
A registered recipient pattern that acts as a saved filter, optional webhook, and optional forward over the soft-sandbox capture table. Built for AI test loops.
What is it
A virtual inbox is a project-scoped recipient pattern. When the soft-sandbox capture path writes a row to sandbox_messages, every inbox whose pattern matches its addresses_seen or intended_to receives that row. Multi-match is intentional; one send can land in several inboxes.
Pattern shapes
"*": catch-all (auto-provisioned per project)."@example.com": any address at that domain (case-insensitive)."user@example.com": exact address (case-insensitive on both parts).
Agent pattern: wait-for-message test loops
Use virtual_inbox_message_wait instead of polling messages_list. The tool blocks server-side until a matching capture arrives, ortimeout_seconds elapses (default 30, max 120). On timeout it returns { timeout: true }; on capture it returns the same shape as virtual_inbox_message_get.
agent: virtual_inbox_create(address_pattern="me@mysite.com")
→ { id: "inbox-uuid" }
agent: writes contact-form.html that posts to /v1/messages
agent: virtual_inbox_message_wait(
id_or_address="me@mysite.com",
timeout_seconds=120
) # blocks here
user submits the form; the capture path inserts a row,
the in-process pub/sub publishes on the (project, inbox) topic
agent's wait unblocks, receives the message synchronously
agent → user: "Got it. Subject 'X', body matched. Form is working."REST surface (mirrors MCP)
GET /v1/inboxes list project inboxes
POST /v1/inboxes create
GET /v1/inboxes/lookup?address=... by pattern
GET /v1/inboxes/{id} detail
PATCH /v1/inboxes/{id} update mutable fields
DELETE /v1/inboxes/{id} delete
GET /v1/inboxes/{id}/messages list captures
GET /v1/inboxes/{id}/messages/{id} message detail
POST /v1/inboxes/{id}/wait?since=&timeout=30 long-pollNotify webhooks
When notify_webhook_url is set, each matching capture fires a single POST to that URL with a Mailnix-Virtual-Inbox-Signature header (Stripe-compatible HMAC-SHA256: t=<unix>,v1=<hex>). The shared signing secret is rotatable via the SES_API_VIRTUAL_INBOX_HMAC_SECRET env var; when unset, a per-inbox derived key (sha256("vinbox:" + inbox_id)) signs instead.
Delivery is best-effort: single attempt, no retry. For durable customer subscriptions with retry-and-backoff, use the outbound-webhook surface POST /v1/webhooks.
Virtual inboxes vs inbound routes
Two unrelated systems. Inbound routes handle REAL incoming mail at *@inbound.mailnix.ch (durable, retried). Virtual inboxes observe CAPTURED outbound sends from the soft-sandbox path (best-effort). A real email never lands in a virtual inbox; a captured send never fires an inbound-route webhook.
Full reference
The complete contract lives at VIRTUAL_INBOXES.md.