Self-hosted email inboxes for AI agents on Cloudflare Workers. Receive, read, reply, send, webhooks, MCP.
DearAgent demonstrates solid definition quality with consistent naming conventions, reasonable descriptions, and complete input schemas across all 16 tools. All tools follow verb_noun patterns (list_, create_, get_, search_, update_, reply_, forward_, compose_, delete_). Descriptions are generally substantive (median ~150 chars) and explain WHAT each tool does and WHEN to use it. Input schemas use Zod with proper type declarations and include descriptions for most parameters. However, there are notable gaps: (1) output schemas are not documented in the tool registration, they are inferred from code but not declared to the LLM; (2) several parameters lack descriptions (cc, bcc in reply/forward/compose; to in forward; attachments arrays); (3) error handling is minimal, no actionable recovery guidance for failed operations; (4) parameter relationships are undocumented (e.g., quote_original behavior in reply_message, reply_all interaction); (5) no permission declarations or scope hints. The server handles a coherent email domain (inbox/thread/message/attachment hierarchy) with clear chaining (list_inboxes → create_inbox → list_messages → get_message → reply_message), which is good composition. Destructive tools (delete_message, delete_thread) lack confirmation or dry-run patterns.
Compose and send a new message.
Create an inbox (email address) that this agent can receive mail at. Omit all fields to get a random address at the configured domain. Mail sent to any address at a configured domain is accepted even without creating an inbox first (when ALLOW_UNKNOWN_INBOX is true).
Permanently delete a message.
Permanently delete a thread and all its messages.
Forward a message to one or more recipients.
Download one attachment from a message. Text-like attachments (text/*, JSON, XML, CSV) are returned as `text`; everything else as `content_base64`. Set `encoding` to "base64" to force raw bytes. Attachments larger than max_bytes (default 4 MB) are refused; use the REST attachment URL for those.
Output schemas are not declared in tool registration. While code clearly structures responses, the LLM cannot see what fields to expect from list_inboxes, get_thread, reply_message, etc. This forces LLMs to guess at response structure and may cause parsing errors.
Parameters cc, bcc, to, and attachments in reply_message, forward_message, and compose_message lack descriptions. The schema shows these are objects or arrays, but the LLM cannot infer their structure or expected format (e.g., is 'to' a string, array, or object with name/email fields?).
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | A | 82 | 2026-07-28+ | v2 |
Return the newest message in an inbox (optionally only if newer than a given instant).
Get one message with full text/html bodies and attachment metadata.
Get a thread with all of its messages (full bodies), oldest first.
List email inboxes on this server (newest first).
List messages in an inbox, newest first. Returns snippets; use get_message for full bodies.
List conversation threads in an inbox, most recent activity first.
Reply to a message in a thread.
Full-text search over messages in an inbox.
Update message metadata (read status, labels).
Poll for new messages in an inbox with a timeout. Useful for agents to wait for replies.
Destructive operations (delete_message, delete_thread) offer no confirmation pattern, dry-run option, or undo capability. Agents can permanently delete threads without explicit user approval, violating the confirmation-request pattern for irreversible actions.
Error handling is minimal. Errors are returned as plain text (via the fail() wrapper) with no guidance on whether the error is retryable, user-fixable, or fatal. For example, a 'quota exceeded' error should suggest 'wait_for_message uses long-polling with a 25-second timeout; consider reducing frequency' but does not.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint) are declared. LLMs cannot quickly identify which tools are safe to retry (idempotent), which modify state (destructive), or which only read. This is required by the MCP 2026-07-28 spec.
Parameter relationships are undocumented. For example, reply_message has both 'quote_original' (boolean) and 'subject', it's unclear whether subject is used to override the original subject or is ignored. Similarly, 'reply_all' is not explained: does it include all recipients or only the original sender?
No permission or scope declarations. Tools like reply_message and delete_message do not advertise what permissions they require (e.g., 'write:email', 'delete:message'). This prevents least-privilege agent configurations and makes audit trails ambiguous.
Description text includes example IDs in create_inbox (e.g., 'agent-x7k2@mail.example.com'). LLMs tend to reuse example values literally. Consider moving examples to parameter constraints or schemas.