← Help

Connecting an AI agent

Who's this for? Anyone using an AI chat client that speaks MCP — Claude Desktop, Claude Code, Codex, Copilot, or your own. Connect once and your agent can read, search, summarise, and reply to mail in your inboxy inbox.

The short setup. Most chat clients only need one URL: https://mcp.inboxy.net. Paste it into your client's MCP config, restart, sign in once via OAuth. Skip to Connecting Claude Desktop for the click-through, or read on for the lay of the land.

What changes after you connect: your agent gains a set of tools grouped by prefix — mail_* for inbox, feed_* and article_* for RSS, address_* for your aliases, account_* for your plan. Read tools are unlimited; the four send-mail tools are scoped so a leaked credential can't be turned into a spam cannon (full rules under What an agent can send).

What the agent can do

Tools are grouped by prefix; most chat clients render them under headings.

mail_* — your inbox

Tool Purpose
mail_list Recent mail, filterable by classification, unread, address, since
mail_count { total, unread } matching a filter — single round-trip
mail_get One message: metadata + attachment list
mail_get_body Parsed text body + headers
mail_show Render an email as Markdown with inline images (proxied)
mail_summarise One-line summary via your client's LLM (MCP sampling — temporarily disabled; degrades to subject + classification)
mail_forward Forward to your verified personal_email (recipient locked server-side, idempotent). Does not consume mail_send_quota
mail_reply Reply to the original sender — recipient + From locked server-side, 5/hour cap, spam-classified messages refused, 30-day age window, every reply audit-logged. Does not consume mail_send_quota
mail_mark_read / mail_mark_unread Single-message read state
mail_mark_all_read Bulk; optional address_id / classification / before filter
mail_keep / mail_unkeep Pin/unpin a message so the retention sweep won't delete it. Cap: 10 currently kept
mail_unsubscribe Surface the unsubscribe methods for a message — List-Unsubscribe header (mailto + URL), RFC 8058 one-click POST flag, and body links matching /unsubscribe|opt-out/. Read-only: returns the URL, never visits or POSTs it
mail_send Send a brand-new message from one of your @inboxy.net aliases to any recipient (external or @inboxy.net). Debits one unit of mail_send_quota per recipient — the same counter the web compose UI debits. Refusal quota_exhausted when the bucket is empty. Internal @inboxy.net → @inboxy.net is DB-only (no SMTP, no footer); external recipients go via the sender worker and get the inboxy attribution footer. Self-loops and reserved @inboxy.net local-parts are refused
mail_invite Invite a friend to sign up for inboxy. to is any external email. Capped at 10 per rolling 30 days per user — independent counter from mail_send_quota, refusal invite_cap_reached. Caller supplies personal_note ≤ 500 chars; subject + body template are operator-controlled. Sent from the mail. transactional subdomain. If the invitee signs up via the included one-time link, the inviter is recorded for a future reward feature. Refused if the address already belongs to an inboxy user (recipient_already_user)
mail_get_attachment Attachment bytes (inline for small images) + signed download URL
mail_search Semantic search across your messages
mail_delete Permanently delete a message and its embedding. Refused for kept messages

outbox_* — sent replies

Tool Purpose
outbox_list List replies you have sent via mail_reply, newest first. Filter by status / kind / in_reply_to_message_id
outbox_get One sent reply — header block + full body_text and body_html
outbox_count { total } for a status / kind filter — single round-trip
outbox_delete Permanently delete one sent reply. Refused if the row is kept

Status reflects the send pipeline: queued (in-flight), sent (delivered to the recipient's MX), rejected (refused by the sender worker — see status_reason), suppressed (recipient on the hard-bounce list), failed (queue exhausted retries).

feed_* — RSS feeds

Tool Purpose
feed_list List subscriptions with status + per-feed { total, unread } counts
feed_add Subscribe to a feed URL
feed_remove Unsubscribe
feed_get Detail for one subscription
feed_refresh Force a re-poll of one feed (benefits every subscriber)
feed_summarise One-paragraph digest of one feed via your LLM (sampling temporarily disabled)

article_* — feed articles

Tool Purpose
article_list Articles across your feeds, newest first
article_count { total, unread } across your subscriptions or one feed
article_get One article — link-rewritten HTML + plain text
article_mark_read / article_mark_unread Per-article state
article_mark_all_read Bulk; optional feed_id / before filter
article_summarise One-line summary of one article via your LLM (sampling temporarily disabled)

address_* — your aliases

Tool Purpose
address_list Your @inboxy.net aliases with per-alias { total, unread } counts (include_retired opt-in)
address_mint Mint a new alias (adjective-noun or opaque scheme)
address_retire Stop accepting mail on an alias

account_* — plan + quota

Tool Purpose
account_get One blob: user, subscription (name / since / renews_at), quota (used vs limit, including kept_messages, mail_send_remaining, invites_remaining), rate-limits, retention

mark_* — cross-domain bulk

Tool Purpose
mark_all_read Zero both unread mail AND unread articles in one call. Optional before ISO-8601 scopes the cut-off. Returns { mail_marked, articles_marked }

What an agent CAN send

inboxy is a "give your AI an inbox" service, not "give your AI your Gmail". Every outbound surface is scoped server-side so a leaked credential can't be turned into a spam cannon.

Surface Recipient rule Quota Footer? Where it ends up
mail_reply Locked to the original sender of the message you're replying to. Own 5/hour cap; no mail_send_quota debit. Yes (external). The sender's MX, via the outbound queue.
mail_forward Locked to your verified personal_email. Idempotent; no mail_send_quota debit. Yes (external). Your verified inbox.
mail_send Any address, external or @inboxy.net. Refused if it resolves to your own personal_email / own alias / reserved local-part. Debits mail_send_quota (one per recipient). Shared with the web compose UI. Refusal quota_exhausted. Yes for external; no for @inboxy.net. Recipient's mailbox (DB-only for @inboxy.net).
mail_invite Any external address that isn't already an inboxy user (recipient_already_user). 10 per rolling 30 days, independent counter. Refusal invite_cap_reached. Yes (the friend should know who's inviting them). Recipient's mailbox, via the mail. transactional subdomain. Signup link is one-time and binds the inviter→invitee relationship in the invites table for a future reward.

The internal-vs-external rule: an @inboxy.net → @inboxy.net send (whether between two aliases on your account or across users) is delivered in-network — a messages row on the recipient with the raw MIME stored in our EU R2 bucket, fed into the same classifier pipeline that handles inbound MX mail. No SMTP egress, no Cloudflare Email Sending binding involved. Any other recipient is queued onto outbound-send and the sender worker emits SMTP via the apex inboxy.net domain — that's where the attribution footer lands.

Why a footer at all? When inboxy is acting as your agentic sender to a third party, that third party deserves to know what they're replying to. The footer is one line of plain text plus a small HTML block; the sender worker is the single place it's injected, so all four tools above behave identically.

Drop-in skill file

If your client supports user-installed skills (e.g. Claude Code's ~/.claude/skills/), grab the inboxy skill from https://inboxy.net/docs/skill (raw markdown) and drop it at ~/.claude/skills/inboxy/SKILL.md. The rendered version lives at https://inboxy.net/help/skill. The skill briefs the agent on every tool plus the workflow patterns we recommend.

Available prompts

If your chat client supports MCP prompts (e.g. Claude Desktop's / menu), inboxy publishes the following templated prompts. Selecting one seeds a complete playbook into the conversation:

Prompt What it does
triage_unread Walks your unread inbox, marks spam-ish stuff read, proposes drafts
find_receipts_this_month Extracts vendor / amount / date from this month's receipts
summarise_feed 24-hour digest of one feed (asks you for a feed_id)
draft_unsubscribe_list Finds dead newsletters, surfaces unsubscribe URLs
daily_brief One paragraph: urgent mail, headlines, account warnings
verify_login_codes Lists OTPs / login links from the last hour

REST callers can read the same prompt bodies via the MCP prompts/get endpoint or hard-code the equivalent system message in their own client.

Connecting Claude Desktop

The MCP server speaks OAuth — no API key needed for chat clients.

  1. Open Claude Desktop → Settings → Developer → Edit Config.

  2. Add:

    {
      "mcpServers": {
        "inboxy": {
          "url": "https://mcp.inboxy.net"
        }
      }
    }
    
  3. Restart Claude Desktop. On first use, it will redirect to inboxy.net to sign you in via OAuth.

Connecting Claude Code / other MCP clients

Same URL: https://mcp.inboxy.net. The client handles OAuth itself.

For clients that need a static API key (CI scripts, server-side automations), use the REST API at https://api.inboxy.net with a key minted under Account → API keys. The MCP server and REST API expose the same data.

Connecting OpenClaw (and other unattended agents)

OpenClaw — and similar third-party agent runners (Codex, Microsoft Scout, Hermes Agent, …) — should be wired against a dedicated alias so the credential, the inbound mailbox, and the outbound From: are all scoped to that one agent. If the key leaks, blast radius is one alias.

1. Mint an alias for the agent

  1. Account → Addresses → New address. Pick the adjective-noun scheme (memorable) or opaque (un-guessable).
  2. Label it for the agent ("openclaw", "codex", etc.) so the inbox view stays legible.

2. Mint an address-scoped API key

  1. Account → API keys → New key.
  2. Set Scope = manage and Address = <your-alias>@inboxy.net (the dropdown lists your active aliases).
  3. Copy the token — it's shown once. Store it in OpenClaw's secret manager (never in repo).

A key scoped to an address can only act on that one alias: mail_list / mail_search only see that alias's messages, and mail_send (or mail_reply / mail_forward) auto-pin from_local_part to the bound alias — a caller-supplied value is ignored. Unscoped or wrong-kind keys get a 403.

3. Wire the credential into OpenClaw

mcp.inboxy.net accepts either an OAuth grant (Claude Desktop, Claude Code) or an Authorization: Bearer ik_... API key. For unattended agents like OpenClaw, the bearer path is the right one — it skips the browser sign-in and carries your key's address scope through every tool call.

One-shot install (from your OpenClaw shell):

export INBOXY_KEY=ik_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
openclaw mcp add inboxy \
  --url https://mcp.inboxy.net \
  --header "Authorization=Bearer $INBOXY_KEY"

A couple of OpenClaw-specific quirks to know:

  • --header parses as Name=Value, not Name: Value. Using a colon produces "Authorization: Bearer …" is an invalid header name.
  • Set INBOXY_KEY in your shell or secret store first so the token never lands in OpenClaw's ~/.openclaw/openclaw.json (where --header values are persisted) or your shell history. Treat ~/.openclaw/openclaw.json like a credential file.

If your OpenClaw build prefers a JSON config block instead of the CLI, the equivalent is:

{
  "mcpServers": {
    "inboxy": {
      "url": "https://mcp.inboxy.net",
      "headers": { "Authorization": "Bearer ik_…" }
    }
  }
}

3b. Wire the credential into Hermes Agent

Hermes (Nous Research) reads its MCP server list from ~/.hermes/config.yaml. Add an inboxy entry under mcp_servers using the bearer-token form:

mcp_servers:
  inboxy:
    url: "https://mcp.inboxy.net"
    headers:
      Authorization: "Bearer ${INBOXY_KEY}"

Hermes resolves ${VAR} placeholders against ~/.hermes/.env, so drop the token there rather than committing it inline:

# ~/.hermes/.env
INBOXY_KEY=ik_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Hermes-specific quirks vs OpenClaw:

  • Headers use colon syntax (Authorization: "Bearer …"), not Name=Value. That's the opposite of OpenClaw's CLI quirk — if you copy-paste between the two, watch the separator.
  • The config is YAML, indentation matters; mis-indenting headers: puts the token on the wrong server entry.
  • Hermes also supports auth: oauth instead of static headers, which triggers the same OAuth 2.1 + DCR flow Claude Desktop uses. We recommend the bearer path for unattended setups because address-scoping carries through every tool call.

4. Verify

From OpenClaw, ask the agent to call account_get — should return your plan + quota (including mail_send_remaining). Then address_list should return only the one alias (the key is scoped — if you see other addresses, the scope didn't take). Finally test outbound:

mail_send to=<your-personal-email> subject="hello" text="ping"

You'll see a row in Account → Outbox with source = mail_send and your mail_send_remaining decremented by 1.

Caps and limits to remember

  • mail_send_quota is per-user, not per-alias — the same counter the web compose UI debits. A leaked address-scoped key can still burn through your bucket, but only from one alias and only against the same per-user cap.
  • Reserved local-parts (abuse, security, support, privacy, dpo, dmarc-rua) are refused as recipients.
  • Self-loops are refused — the agent can't mail your own personal_email or any of your own aliases via mail_send. Use mail_forward (which is itself locked to your personal_email) if you want a copy of an inbox item delivered upstream.
  • Invites have their own counter: 10 per rolling 30 days, independent of mail_send_quota. Use mail_invite rather than mail_send when introducing a friend to inboxy.

Why attachment URLs don't need an API key

mail_get_attachment returns either inline bytes (small images) or a short-lived signed URL pointing at api.inboxy.net/v1/attachments/{token}/download. That URL does not require a separate Authorization header — the embedded HMAC token is the auth, validated locally by the api worker. The api bearer-auth middleware explicitly bypasses this path for that reason.

So an MCP client that has OAuth-authorised against mcp.inboxy.net can follow the returned URL with a plain fetch — no extra credentials, no separate API key.

The URL is single-attachment-scoped and expires (TTL 1 hour). If a token leaks, only that one attachment is exposed, and only until it expires.

Browser extensions

For Chrome / Firefox / Edge extensions that want to read inboxy mail without going through an agent, use the browser extension — it does device-bound (DPoP) auth, which doesn't need a long-lived bearer key.

Revoking access

  • Revoke an OAuth grant from Account → MCP / OAuth clients.
  • Revoke an API key from Account → API keys.

Revocation is immediate; the next request returns 401.


Still need help? support@inboxy.net

Add Inboxy to your Home Screen

  1. Tap the Share button in Safari’s toolbar.
  2. Scroll and tap Add to Home Screen.
  3. Tap Add in the top-right corner.