Browse the docs
Recipes
Build an email agent
Build an AI email agent: give it its own address, connect it to Inboundr's MCP server, and let it read and triage its inbox.
Inboundr was built for this setup: an agent with its own inbox that reads incoming mail and decides what to do with it, using only MCP tools. You don't write any email-handling code.
What you'll set up#
Give the agent an address
On a verified domain, create an inbox for the agent. A store-only address, one with no endpoint, works best: the agent reads mail when it acts, so it doesn't need a server listening for webhooks.
bash curl https://inboundr.net/api/v1/addresses \ -H "Authorization: Bearer $INBOUNDR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "domainId": "dom_123", "localPart": "ada" }'Now
ada@yourdomain.comaccepts mail and keeps it for the agent to read.Connect the MCP server
Point your MCP client at Inboundr with the same
inb_key:json { "mcpServers": { "inboundr": { "url": "https://inboundr.net/api/mcp", "headers": { "Authorization": "Bearer inb_xxxxxxxxxxxx" } } } }The agent can now call
list_emails,get_email,get_threadand the other tools. See the full tool list.Run the loop
Give the agent a short instruction and let it use the tools:
Check
ada@yourdomain.comfor new mail. For each new message, read the thread for context and decide what it needs: file it, escalate it, or flag the sender.To do that, the agent will:
- call
list_emailswithdirection: "inbound"to find new mail, - call
get_threadto read the conversation, - call
create_shield_ruleif future mail like it should be blocked, allowed, routed or quarantined.
- call
The loop in pseudocode#
loop:
new = list_emails(direction="inbound", to="ada@yourdomain.com")
for email in new:
thread = get_thread(email.threadId)
action = «your model decides what this needs, given `thread`»
handle(action) # file a ticket, post to a channel, escalate:
# whatever your own systems do with itDesign tips#
Track what's already handled
Inboundr stores every message but doesn't mark any as handled. Keep your own
record, such as the newest receivedAt you've processed or a list of
handled email IDs, so the agent doesn't act on the same message twice.
Give the model the whole thread
Call get_thread before deciding anything. The latest message on its own
rarely has enough context; the whole conversation usually does.
Check risky actions first
For actions with big consequences, such as a Shield rule that blocks a whole domain, have the agent draft the change and a person approve it first.
Give each agent its own address
Separate inboxes (sales@, support@, ada@) keep each agent's context
separate and make it clear which agent owns a conversation. The catch-all
still covers every other address.
Prefer a server?#
If your agent runs as an always-on service, route the address to a webhook endpoint instead of polling. Each message is pushed to you as it arrives, and the rest of the loop stays the same.
MCP referenceEvery tool, its parameters, and how to connect.