·
Guides
Agents
MCP

Wake your agent when an email arrives: inbox watches, webhooks and polling over MCP

Agents that poll search_emails every few minutes burn quota to answer one question: is there anything new? Inbox watches answer it for them. One tool call registers a watch, your mail server pushes over IMAP IDLE, and your agent gets events by cursor or on a signed webhook.

Every autonomous email agent has the same loop at its heart: check the inbox, decide, act, sleep, repeat. The check is the expensive part. Run it every five minutes and a quiet mailbox costs 288 searches a day for nothing, every one of them a live IMAP connection to your provider. Inbox watches replace that loop with an event: your mail server tells us the moment a message lands (IMAP IDLE, the same push your phone uses), we turn it into an event, and your agent reads it whenever it wakes up, or gets woken by it.

One tool call to set it up

From any MCP client connected to anymailmcp.com, ask your agent to watch the inbox. Under the hood it calls watch_inbox:

watch_inbox({
  mailbox: "jean@agence.fr",          // optional when you have one mailbox
  folder: "INBOX",                    // any folder from list_folders
  from: "acme.com",                   // optional filters: from, to,
  subject_contains: "invoice",        //   subject_contains, has_attachment,
  webhook_url: "https://hooks.example.com/anymail"   // optional
})

The answer carries a watch_id, a cursor, and, when you gave a webhook, a secret shown once. The watch is live within about twenty seconds. From then on every new message in that folder that matches the filter becomes an event.

What an event looks like

{
  "id": "evt_1042",
  "type": "message.new",
  "occurred_at": "2026-09-05T08:14:11.000Z",
  "watch_id": "7",
  "mailbox": "jean@agence.fr",
  "folder": "INBOX",
  "uid": 48213,
  "message_id": "<…@mail.acme.com>",
  "from": "Client <client@acme.com>",
  "to": ["jean@agence.fr"],
  "subject": "Re: invoice September",
  "date": "2026-09-05T08:14:03.000Z",
  "has_attachments": true
}

Deliberately, that is the envelope and nothing else: no body, no snippet, no attachment names. Your agent calls read_email with the uid when it actually needs the content, exactly as before. Events are kept for seven days so an agent that was offline can catch up; the message itself never leaves your mail server.

Two ways to receive events

1. Pull, from any client: poll_events

Give it the last cursor you saw and it returns everything after it, oldest first, with a next_cursor to keep. Add wait_seconds: 25 and it long-polls: the call returns as soon as one event exists, or after 25 seconds with an empty list. This works in every MCP client without any inbound URL: Claude.ai, ChatGPT, Cursor, Claude Code, Cowork, Grok. A scheduled task that calls poll_events every fifteen minutes is the simplest email agent there is, and it costs one tool call per run instead of one search per folder.

2. Push, to a webhook

Give watch_inbox an https URL and we POST {"events":[…]} to it as mail arrives, up to twenty events per request. Every request carries X-Anymail-Signature: t=<unix>, v1=<hex> where v1 is HMAC-SHA256 of t + "." + rawBody with your secret, the scheme every Stripe verification snippet already implements. We require a 2xx to a signed test POST before the watch is saved, never follow redirects, time out after ten seconds, and retry failures after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours. After the fifth failure the watch pauses and says why in list_watches; fix the endpoint and re-enable it with delete_watch({ watch_id, resume: true }). Events keep accumulating while paused, so nothing is lost.

Recipes

  • Claude Code: a routine that runs every 15 minutes, calls poll_events with the stored cursor, triages what came in and drafts replies for your approval. Sessions that expose an inbound webhook URL can be woken directly instead.
  • Cowork, ChatGPT tasks, Grok routines: the same scheduled-poll pattern; no URL needed.
  • n8n, Zapier, Make: point the webhook at a Webhook trigger node and route the event to any model or workflow. This is how Claude.ai and Cursor users get true push today.
  • Waiting for one specific email (a confirmation code, a signed contract): watch with from or subject_contains, then poll_events with wait_seconds: 25 in a short loop.

Limits and plan

Watches are part of the Solo plan (4.99 € a month, up to three watches per account; Team has no limit). poll_events is an ordinary tool call; webhook deliveries are pushed by us and never count against anything. A watch needs only read access on its mailbox, and disconnecting the mailbox deletes its watches and events on the spot. Every provider we support works, Gmail, iCloud, OVH, Zoho, Fastmail and self-hosted servers included; servers without IDLE are polled every two minutes instead.

Set up

Why not a native MCP trigger?

Because the protocol does not have one yet. The 2026-07-28 MCP release can push resource-changed notifications on a client-held stream, and a Triggers and Events working group is designing real server-initiated callbacks, but no assistant wakes an agent on either today. Watches are built so they become that mechanism's subscriptions when it lands; until then, cursor polling and signed webhooks are what every harness can actually use.

Ready to let your assistant into your inbox?

Get started, free