Skip to content
cd ..

Building an MCP Server with 62 Tools for Agent Email

// · 5 min read

The Model Context Protocol (MCP) is quickly becoming the standard way for AI models to interact with external tools. When I built AgenticMail, I knew it needed a first class MCP integration. Not a thin wrapper around a REST API, but a proper MCP server that gives models everything they need to work with email effectively.

The result is 62 tools exposed over stdio transport.

Why 62 tools?

It sounds like a lot. But email is a surprisingly complex domain when you break it down into discrete operations. You need tools for:

Mailbox operations: list messages, read a message, search by various criteria, move messages, delete messages, mark as read/unread, manage folders.

Composition: send email, reply, reply all, forward, send with attachments, draft management.

Contact management: list contacts, search contacts, create contact, update contact.

Agent management: list agents, get agent details, update agent configuration, manage agent capabilities.

Task system: create task, assign task, claim task, complete task, list tasks, get task status, RPC calls.

Gateway operations: check gateway status, configure relay mode, configure domain mode, test connectivity.

Security: check message spam score, view quarantine, release from quarantine, manage allowlists and blocklists.

Administration: server health, statistics, queue management, log access.

Each of these is a distinct tool with its own input schema. I could have collapsed some of them (a single “email” tool with a sub action parameter, for example), but granular tools work much better with current language models. The model can see exactly what each tool does from its name and schema, without having to reason about which sub action to use.

Stateless design over stdio

The MCP server uses stdio transport, which means it communicates through standard input and output. This is the simplest MCP transport and the most widely supported. Every MCP client, from Claude Desktop to custom integrations, can talk to a stdio server.

The server itself is completely stateless. Every tool call is an independent HTTP request to the AgenticMail API. There’s no session state held in the MCP process, no cached connections, no background threads. If the MCP server crashes and restarts, nothing is lost.

This was a deliberate choice. Stateful MCP servers are fragile. They accumulate state that can get out of sync, they leak memory over long sessions, and they’re harder to debug. By pushing all state to the AgenticMail API server, the MCP layer stays thin and reliable.

The call flow is: model sends a tool call via MCP, the MCP server translates it to an HTTP request, sends it to the AgenticMail API, gets the response, and translates it back to an MCP tool result. Clean and predictable.

Rich input schemas

Every tool has a detailed JSON Schema definition for its inputs. This isn’t just type checking; the schemas include descriptions, examples, enums for constrained values, and validation rules.

For instance, the send_email tool’s schema specifies that to is an array of email address strings, subject is a required string, body is a required string, cc and bcc are optional arrays, and attachments is an optional array of objects with filename, content, and mimeType fields.

These rich schemas serve two purposes. First, they help the model construct valid tool calls. Second, they serve as documentation that’s always in sync with the implementation, since the schemas are generated from the same TypeScript types that the API uses.

Telemetry integration

Every tool call gets logged with timing information, success/failure status, and anonymized parameters. This feeds into the AgenticMail dashboard where you can see which tools agents use most, which ones fail, and where the bottlenecks are.

The telemetry is especially useful for debugging agent behavior. If an agent is struggling with a particular workflow, you can look at the tool call sequence and see exactly where it went wrong. Did it call the wrong tool? Did it pass bad parameters? Did the API return an error? The telemetry tells you.

Follow up reminders via drainFollowUps()

One of the more interesting features is the follow up reminder system. When an agent sends an email and expects a reply, it can schedule a follow up. If no reply arrives within the specified window, the system generates a reminder.

The drainFollowUps() function is called periodically to check for pending follow ups that have matured. It returns a list of reminders that the agent should act on, typically by sending a follow up email or escalating to the agent’s operator.

This is implemented as a tool rather than an automatic background process, because the agent should decide when and how to handle follow ups. Some agents might check every few minutes. Others might drain follow ups once a day. The MCP tool gives them the flexibility to choose.

Source Code

The full tool definitions live in tools.ts, where each of the 62 tools is declared with its name, description, and JSON Schema input definition. The MCP server entrypoint in index.ts registers all tools over stdio transport and wires them to the AgenticMail API.

View the tools definition on GitHub

View the MCP server entrypoint on GitHub

62 tools might sound like overkill, but when you’re giving an AI agent full autonomy over an email system, you want granular, well defined, strongly typed operations. No magic, no ambiguity, just clear tools that do exactly what they say.

// share

// subscribe

New posts and updates straight to your inbox. No noise.

cd ..