# MCP · wait_for_email

{/* // BLOCK UNTIL IT LANDS */}

`wait_for_email` is the tool that makes Postern feel different from "an inbox you poll." It **blocks**
until the next matching message lands and returns it with the **OTP code and verification link already
extracted** — so the agent can act on the code in the same turn, before the window closes.

## Tool definition

```jsonc title="wait_for_email — input schema (zod)"
{
  "name": "wait_for_email",
  "annotations": { "readOnlyHint": true },
  "inputSchema": {
    "address":         "string  // the mailbox to watch (required)",
    "from":            "string? // match sender (substring, case-insensitive)",
    "subject":         "string? // match subject (substring, case-insensitive)",
    "regex":           "string? // match the body against a regular expression",
    "since":           "string? // ISO timestamp; only newer messages (default: now)",
    "timeout_seconds": "number? // how long to block; server-capped (default 120)"
  }
}
```

## Result

```json title="result"
{
  "timed_out": false,
  "message": {
    "id": "msg_8Tz",
    "from": "no-reply@acme.test",
    "subject": "Verify your email",
    "received_at": "2026-06-12T18:05:42Z"
  },
  "extracted": {
    "otp_code": "492013",
    "verification_link": "https://acme.test/verify?token=…",
    "credentials": null
  }
}
```

When nothing matches before the timeout, the call returns `{ "timed_out": true }` rather than
erroring — so the agent can decide whether to retry, lengthen the wait, or re-trigger the sign-up.

## Canonical flow

```text
1. redeem_enrollment   → scoped agent key
2. create_inbox        → signup-agent@x4p.mszazu.com
3. (agent triggers a sign-up that emails the inbox)
4. wait_for_email      → { otp_code: "492013", verification_link: "…" }
5. (agent submits the code back to the form)
```

This is the high-value, time-boxed task agents do constantly — sign up, confirm, proceed — and
`wait_for_email` collapses it into a single blocking call with a structured answer.

## How the blocking works

The server holds the connection open and watches the mailbox via **IMAP IDLE** on WildDuck. The
moment a matching message is delivered, it's parsed, the OTP/link extraction runs, and the result is
returned. There is no client-side polling loop and no busy-waiting — the agent's turn simply resumes
when the email arrives.

<Aside type="caution" title="Respect the server's max wait">
  `timeout_seconds` is capped by the server's `POSTERN_MAX_WAIT_MS` (default 300s). Requesting longer
  is clamped. For local hosts, make sure your transport's read timeout exceeds the wait — the MCP
  server handles this, but a custom client wrapper should too.
</Aside>

## Extraction fields

| Field | Meaning |
|---|---|
| `otp_code` | The one-time code found in the message, if any. |
| `verification_link` | The first click-through verification URL, if any. |
| `credentials` | Username/password pairs, when the message contains them. |

These come from the same extraction machinery used across Postern (and available standalone in the
SDK as `extractOtp` / `extractLink` / `extractCredentials`).

## Next

- [Client configuration](https://docs.agents.mszazu.com/mcp/client-configuration/) — wire the server into your host.
- [Quickstart · wait_for_email](https://docs.agents.mszazu.com/quickstart/wait-for-email/) — the full OTP walkthrough.
- [API · wait_for_email](https://docs.agents.mszazu.com/api/wait/) — the REST endpoint behind the tool.