How to integrate Agent mail MCP with Mastra AI

Connect Mastra AI to Agent mail MCP. Show me unread emails from today, send a status update to your team, and more using natural language, with authentication handled for you.

Agent mail logoAgent mail
Api Key

Agent mail provides AI agents with dedicated email inboxes for sending, receiving, and managing emails. It empowers agents to communicate autonomously with people, services, and other agents—no human intervention needed.

93 Tools1 Triggers

Introduction

This guide walks you through connecting Agent mail to Mastra AI using the Composio tool router. By the end, you'll have a working Agent mail agent that can create inboxes, send and reply to emails, manage drafts and threads, schedule calendar events, and set up webhooks through natural language commands.

This guide will help you understand how to give your Mastra AI agent real control over a Agent mail account through Composio's Agent mail MCP server.

Before we dive in, let's take a quick look at the key ideas and tools involved.

Also integrate Agent mail with

TL;DR

Here's what you'll learn:
  • Set up your environment so Mastra, OpenAI, and Composio work together
  • Create a Tool Router session in Composio that exposes Agent mail tools
  • Connect Mastra's MCP client to the Composio generated MCP URL
  • Fetch Agent mail tool definitions and attach them as a toolset
  • Build a Mastra agent that can reason, call tools, and return structured results
  • Run an interactive CLI where you can chat with your Agent mail agent

What is Mastra AI?

Mastra AI is a TypeScript framework for building AI agents with tool support. It provides a clean API for creating agents that can use external services through MCP.

Key features include:

  • MCP Client: Built-in support for Model Context Protocol servers
  • Toolsets: Organize tools into logical groups
  • Step Callbacks: Monitor and debug agent execution
  • OpenAI Integration: Works with OpenAI models via @ai-sdk/openai

What is the Agent mail MCP server, and what's possible with it?

The Agent mail MCP server is an implementation of the Model Context Protocol that connects your AI agent and assistants like Claude, Cursor, etc directly to your Agent mail account. It provides structured and secure access to your agent's dedicated inbox, so your agent can send emails, receive incoming messages, fetch specific conversations, and automate email-based workflows on your behalf.

  • Automated email sending: Instruct your agent to compose and send emails to any recipient, perfect for status updates, notifications, or outreach.
  • Message listing and inbox scanning: Let your agent quickly list all recent messages in the inbox to summarize, monitor, or trigger follow-up actions.
  • Targeted message retrieval: Have your agent fetch a specific message by ID, making it easy to pull full email content for context-aware decisions or replies.
  • Streamlined agent-to-agent communication: Enable your AI to directly interact with other agents or services via email, automating routine communication flows.

What is the Composio tool router, and how does it fit here?

What is Composio SDK?

Composio's Composio SDK helps agents find the right tools for a task at runtime. You can plug in multiple toolkits (like Gmail, HubSpot, and GitHub), and the agent will identify the relevant app and action to complete multi-step workflows. This can reduce token usage and improve the reliability of tool calls. Read more here: Getting started with Composio SDK

The tool router generates a secure MCP URL that your agents can access to perform actions.

How the Composio SDK works

The Composio SDK follows a three-phase workflow:

  1. Discovery: Searches for tools matching your task and returns relevant toolkits with their details.
  2. Authentication: Checks for active connections. If missing, creates an auth config and returns a connection URL via Auth Link.
  3. Execution: Executes the action using the authenticated connection.

Step-by-step Guide

Step by step09 STEPS
1

Prerequisites

Before starting, make sure you have:
  • Node.js 18 or higher
  • A Composio account with an active API key
  • An OpenAI API key
  • Basic familiarity with TypeScript
2

Getting API Keys for OpenAI and Composio

OpenAI API Key
  • Go to the OpenAI dashboard and create an API key.
  • You need credits or a connected billing setup to use the models.
  • Store the key somewhere safe.
Composio API Key
  • Log in to the Composio dashboard.
  • Go to Settings and copy your API key.
  • This key lets your Mastra agent talk to Composio and reach Agent mail through MCP.
3

Install dependencies

bash
npm install @composio/core @mastra/core @mastra/mcp @ai-sdk/openai dotenv

Install the required packages.

What's happening:

  • @composio/core is the Composio SDK for creating MCP sessions
  • @mastra/core provides the Agent class
  • @mastra/mcp is Mastra's MCP client
  • @ai-sdk/openai is the model wrapper for OpenAI
  • dotenv loads environment variables from .env
4

Set up environment variables

bash
COMPOSIO_API_KEY=your_composio_api_key_here
COMPOSIO_USER_ID=your_user_id_here
OPENAI_API_KEY=your_openai_api_key_here

Create a .env file in your project root.

What's happening:

  • COMPOSIO_API_KEY authenticates your requests to Composio
  • COMPOSIO_USER_ID tells Composio which user this session belongs to
  • OPENAI_API_KEY lets the Mastra agent call OpenAI models
5

Import libraries and validate environment

typescript
import "dotenv/config";
import { openai } from "@ai-sdk/openai";
import { Agent } from "@mastra/core/agent";
import { MCPClient } from "@mastra/mcp";
import { Composio } from "@composio/core";
import * as readline from "readline";

import type { AiMessageType } from "@mastra/core/agent";

const openaiAPIKey = process.env.OPENAI_API_KEY;
const composioAPIKey = process.env.COMPOSIO_API_KEY;
const composioUserID = process.env.COMPOSIO_USER_ID;

if (!openaiAPIKey) throw new Error("OPENAI_API_KEY is not set");
if (!composioAPIKey) throw new Error("COMPOSIO_API_KEY is not set");
if (!composioUserID) throw new Error("COMPOSIO_USER_ID is not set");

const composio = new Composio({
  apiKey: composioAPIKey as string,
});
What's happening:
  • dotenv/config auto loads your .env so process.env.* is available
  • openai gives you a Mastra compatible model wrapper
  • Agent is the Mastra agent that will call tools and produce answers
  • MCPClient connects Mastra to your Composio MCP server
  • Composio is used to create a Tool Router session
6

Create a Tool Router session for Agent mail

typescript
async function main() {
  const session = await composio.create(
    composioUserID as string,
    {
      toolkits: ["agent_mail"],
    },
  );

  const composioMCPUrl = session.mcp.url;
  console.log("Agent mail MCP URL:", composioMCPUrl);
What's happening:
  • create spins up a short-lived MCP HTTP endpoint for this user
  • The toolkits array contains "agent_mail" for Agent mail access
  • session.mcp.url is the MCP URL that Mastra's MCPClient will connect to
7

Configure Mastra MCP client and fetch tools

typescript
const mcpClient = new MCPClient({
    id: composioUserID as string,
    servers: {
      nasdaq: {
        url: new URL(composioMCPUrl),
        requestInit: {
          headers: session.mcp.headers,
        },
      },
    },
    timeout: 30_000,
  });

console.log("Fetching MCP tools from Composio...");
const composioTools = await mcpClient.getTools();
console.log("Number of tools:", Object.keys(composioTools).length);
What's happening:
  • MCPClient takes an id for this client and a list of MCP servers
  • The headers property includes the x-api-key for authentication
  • getTools fetches the tool definitions exposed by the Agent mail toolkit
8

Create the Mastra agent

typescript
const agent = new Agent({
    name: "agent_mail-mastra-agent",
    instructions: "You are an AI agent with Agent mail tools via Composio.",
    model: "openai/gpt-5",
  });
What's happening:
  • Agent is the core Mastra agent
  • name is just an identifier for logging and debugging
  • instructions guide the agent to use tools instead of only answering in natural language
  • model uses openai("gpt-5") to configure the underlying LLM
9

Set up interactive chat interface

typescript
let messages: AiMessageType[] = [];

console.log("Chat started! Type 'exit' or 'quit' to end.\n");

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  prompt: "> ",
});

rl.prompt();

rl.on("line", async (userInput: string) => {
  const trimmedInput = userInput.trim();

  if (["exit", "quit", "bye"].includes(trimmedInput.toLowerCase())) {
    console.log("\nGoodbye!");
    rl.close();
    process.exit(0);
  }

  if (!trimmedInput) {
    rl.prompt();
    return;
  }

  messages.push({
    id: crypto.randomUUID(),
    role: "user",
    content: trimmedInput,
  });

  console.log("\nAgent is thinking...\n");

  try {
    const response = await agent.generate(messages, {
      toolsets: {
        agent_mail: composioTools,
      },
      maxSteps: 8,
    });

    const { text } = response;

    if (text && text.trim().length > 0) {
      console.log(`Agent: ${text}\n`);
        messages.push({
          id: crypto.randomUUID(),
          role: "assistant",
          content: text,
        });
      }
    } catch (error) {
      console.error("\nError:", error);
    }

    rl.prompt();
  });

  rl.on("close", async () => {
    console.log("\nSession ended.");
    await mcpClient.disconnect();
    process.exit(0);
  });
}

main().catch((err) => {
  console.error("Fatal error:", err);
  process.exit(1);
});
What's happening:
  • messages keeps the full conversation history in Mastra's expected format
  • agent.generate runs the agent with conversation history and Agent mail toolsets
  • maxSteps limits how many tool calls the agent can take in a single run
  • onStepFinish is a hook that prints intermediate steps for debugging

Complete Code

Here's the complete code to get you started with Agent mail and Mastra AI:

typescript
import "dotenv/config";
import { openai } from "@ai-sdk/openai";
import { Agent } from "@mastra/core/agent";
import { MCPClient } from "@mastra/mcp";
import { Composio } from "@composio/core";
import * as readline from "readline";

import type { AiMessageType } from "@mastra/core/agent";

const openaiAPIKey = process.env.OPENAI_API_KEY;
const composioAPIKey = process.env.COMPOSIO_API_KEY;
const composioUserID = process.env.COMPOSIO_USER_ID;

if (!openaiAPIKey) throw new Error("OPENAI_API_KEY is not set");
if (!composioAPIKey) throw new Error("COMPOSIO_API_KEY is not set");
if (!composioUserID) throw new Error("COMPOSIO_USER_ID is not set");

const composio = new Composio({ apiKey: composioAPIKey as string });

async function main() {
  const session = await composio.create(composioUserID as string, {
    toolkits: ["agent_mail"],
  });

  const composioMCPUrl = session.mcp.url;

  const mcpClient = new MCPClient({
    id: composioUserID as string,
    servers: {
      agent_mail: {
        url: new URL(composioMCPUrl),
        requestInit: {
          headers: session.mcp.headers,
        },
      },
    },
    timeout: 30_000,
  });

  const composioTools = await mcpClient.getTools();

  const agent = new Agent({
    name: "agent_mail-mastra-agent",
    instructions: "You are an AI agent with Agent mail tools via Composio.",
    model: "openai/gpt-5",
  });

  let messages: AiMessageType[] = [];

  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
    prompt: "> ",
  });

  rl.prompt();

  rl.on("line", async (input: string) => {
    const trimmed = input.trim();
    if (["exit", "quit"].includes(trimmed.toLowerCase())) {
      rl.close();
      return;
    }

    messages.push({ id: crypto.randomUUID(), role: "user", content: trimmed });

    const { text } = await agent.generate(messages, {
      toolsets: { agent_mail: composioTools },
      maxSteps: 8,
    });

    if (text) {
      console.log(`Agent: ${text}\n`);
      messages.push({ id: crypto.randomUUID(), role: "assistant", content: text });
    }

    rl.prompt();
  });

  rl.on("close", async () => {
    await mcpClient.disconnect();
    process.exit(0);
  });
}

main();

Conclusion

You've built a Mastra AI agent that can interact with Agent mail through Composio's Tool Router. You can extend this further by:
  • Adding other toolkits like Gmail, Slack, or GitHub
  • Building a web-based chat interface around this agent
  • Using multiple MCP endpoints to enable cross-app workflows
TOOLS & TRIGGERS

Supported Tools and Triggers

Every Agent mail action and event your agent gets out of the box.

Batch Get Messages

Return metadata for up to 500 messages from one inbox in a single request.

Batch Update Message Labels

Atomically add or remove the same labels on up to 50 messages in one inbox.

Complete File Upload

Mark a pending Agent Drive file ready after its bytes have been PUT to the presigned URL returned by CREATE_FILE.

Create Agent Armor Feedback

Record whether Agent Armor's completed verdict on a message was correct.

Create Calendar Event

Create a one-off or recurring event on a US-only inbox calendar.

Create Draft

Create a draft, optionally scheduling its automatic delivery with send_at.

Create File

Initialize a pending Agent Drive file and return instructions for a direct storage upload.

Create Inbox

Create a new AgentMail inbox via API.

Create Inbox API Key

Create an inbox-scoped bearer key and return its one-time secret.

Create Inbox in Pod

Create an inbox inside an explicitly selected AgentMail pod, optionally choosing its address, initial status, idempotency ID, and metadata.

Create Inbox Polling Webhook

Create or resume a polling webhook scoped to one inbox.

Create Inbox Webhook

Create a regular webhook scoped to one AgentMail inbox for a non-empty set of event types.

Create Allowlist or Blocklist Entry

Add an email address or domain to an organization-wide send, receive, or reply allowlist or blocklist.

Create Pod

Create an AgentMail pod for grouping inboxes and related resources.

Create Polling Webhook

Create or resume an organization-level polling webhook for a non-empty set of event types, optionally filtered to at most 10 inboxes and pods combined.

Create Webhook

Create an organization-level webhook for a non-empty set of event types, optionally filtered to at most 10 inboxes and pods combined.

Delete Calendar Event

Accept asynchronous deletion of a US-only calendar event or cancel recurring dates.

Delete Draft

Permanently delete one unsent draft from an inbox.

Delete File

Permanently delete a pending or ready Agent Drive file and free its path.

Delete Inbox

Permanently delete one inbox by ID.

Delete Inbox Polling Webhook

Permanently delete an inbox-scoped polling webhook by webhook_id or client_id, invalidate its polling token, and free its subscription slot.

Delete Inbox Webhook

Permanently delete a regular webhook created for a selected AgentMail inbox and stop future deliveries.

Delete Allowlist or Blocklist Entry

Remove one email address or domain from an organization-wide send, receive, or reply allowlist or blocklist.

Delete Message

Permanently delete one message from an inbox.

Delete Pod

Permanently delete one AgentMail pod by its unique ID.

Delete Pod Inbox

Permanently delete an inbox through its explicitly selected AgentMail pod, preserving the pod tenant boundary.

Delete Polling Webhook

Permanently delete an organization-level polling webhook by webhook_id or client_id, invalidate its polling token, and free its subscription slot.

Delete Thread

Permanently delete one AgentMail thread and all of its messages.

Delete Webhook

Permanently delete an organization-level webhook and stop future deliveries.

Forward Message

Immediately forward an existing message to new recipients with optional added content and attachments.

Get Agenda

Get one page of non-cancelled calendar dates in a UTC window, expanding recurring events and ordering dates by start time.

Get API Key

Retrieve API-key metadata without exposing bearer secret values.

Get Calendar

Get an inbox's US-only calendar settings, event count, and ETag.

Get Calendar Event

Get the full current form of a US-only calendar event or recurring-event date, including its opaque ETag for conditional mutations.

Get Current Identity

Return the connected AgentMail identity and its organization, pod, or inbox access boundary without exposing the credential itself.

Get Domain

Return an AgentMail custom domain, its domain and tracking verification statuses, and all required DNS records.

Get Domain Setup Link

Build a one-click Domain Connect DNS setup link when supported.

Get Domain Zone File

Download the AgentMail-generated DNS zone file for a custom domain as a bounded binary file reference.

Get Draft

Retrieve the complete contents and scheduling details of one draft.

Get Draft Attachment

Get a temporary download reference for one draft attachment.

Get File

Get Agent Drive file metadata.

Get Inbox

Retrieve one AgentMail inbox and its metadata by ID or email address.

Get Inbox Polling Webhook

Get one inbox-scoped polling webhook by webhook_id or client_id.

Get Inbox Webhook

Get one regular webhook created for a selected AgentMail inbox.

Get Inbox Webhook Headers

List only the names of custom delivery headers on an inbox-scoped regular webhook.

Get Message

Retrieve an email message from an AgentMail inbox, including sender, recipients, labels, and available subject, body and attachment metadata.

Get Message Attachment

Get a temporary download reference for one message attachment.

Get Organization

Return the connected AgentMail organization's identifiers, current inbox and domain counts, configured resource limits, and timestamps.

Get Pod

Retrieve one AgentMail pod by its unique ID.

Get Pod Inbox

Get an AgentMail inbox through an explicitly selected pod, preserving the pod tenant boundary.

Get Polling Webhook

Get one organization-level polling webhook by webhook_id or client_id.

Get Raw Message

Get a temporary download reference for one message's raw RFC 5322 source, including its original headers and MIME structure.

Get Thread

Retrieve one AgentMail thread and a paginated page of its messages.

Get Thread Attachment

Get a temporary download reference for an attachment using its thread and attachment IDs.

Get Webhook

Get one organization-level webhook configuration by ID.

Get Webhook Headers

List only the names of custom delivery headers on an organization-level webhook.

List Calendar Event Instances

List one page of non-cancelled dates computed for a recurring US-only calendar event in a UTC window, including dates beyond the agenda horizon.

List Calendar Events

List one US-only calendar page of stored one-off events, recurring series, and edited series dates, including cancelled events, by most recent update.

List Domains

List one page of AgentMail custom domains and return the continuation token for the next page.

List Drafts

List unsent drafts in an AgentMail inbox with filters and pagination.

List Files

List one page of an inbox's Agent Drive files in path order, including pending files.

List Inbox API Keys

List API-key metadata scoped to an inbox without exposing secret values.

List Inboxes

List a page of inboxes available to the authenticated AgentMail account.

List Inbox Events

List label-change events from an AgentMail inbox.

List Inbox Polling Webhooks

List polling webhooks created through one inbox route.

List Inbox Webhooks

List one page of regular webhooks created for a selected AgentMail inbox.

List Allowlist or Blocklist Entries

List one page of organization-wide send, receive, or reply allowlist or blocklist entries.

List Messages

List messages from an AgentMail inbox.

List Pod Inboxes

List one page of inboxes inside an explicitly selected AgentMail pod, or supply query to search addresses and display names.

List Pods

Return one page of AgentMail pods and its continuation token.

List Polling Webhooks

List organization-level polling webhooks created through the organization route.

List Threads

List conversation threads in an AgentMail inbox with filters.

List Webhooks

List AgentMail webhook configurations.

Query Inbox Event Metrics

Query timestamped email-event counts for an AgentMail inbox.

Query Metrics

Query organization-wide email event counts or cumulative resource-usage time series over a bounded time range.

Query Rate Metrics

Query organization-wide rolling bounce and complaint rates.

Release Held Message

Release a message that Agent Armor held for review, emit its delivery and security override events, and remove the agent-armor-held label.

Reply To Message

Reply to a selected message while preserving its AgentMail thread.

Respond to Calendar Event

Accept, decline, or tentatively accept an email invitation on a US-only inbox calendar.

Send Draft

Immediately send and consume a draft, optionally changing message labels.

Send Email

Send an email using AgentMail API

Send Message

Immediately send a new email from an AgentMail inbox with optional HTML, attachments, custom headers, labels, and open tracking.

Update Calendar

Change an inbox calendar's default time zone in US production.

Update Calendar Event

Patch a US-only calendar event, one recurring date, or that date and future dates.

Update Draft

Edit a draft, reschedule delivery, or cancel a scheduled send with null.

Update Inbox

Update an inbox's display name, status, or custom metadata.

Update Inbox Webhook

Update an inbox-scoped regular webhook's enabled state or replace its event types.

Update Inbox Webhook Headers

Atomically set, replace, or remove custom delivery headers on an inbox-scoped regular webhook.

Update Message Labels

Add or remove labels from one message in an inbox.

Update Pod Inbox

Update the display name, active or paused status, or metadata of an inbox inside an explicitly selected AgentMail pod.

Update Thread Labels

Add or remove custom labels from every message in one thread.

Update Webhook

Update an organization-level webhook's enabled state, event types, or inbox and pod subscriptions.

Update Webhook Headers

Atomically set, replace, or remove custom delivery headers on an organization-level webhook.

FAQ

Frequently asked questions

With a standalone Agent mail MCP server, the agents and LLMs can only access a fixed set of Agent mail tools tied to that server. However, with the Composio Tool Router, agents can dynamically load tools from Agent mail and many other apps based on the task at hand, all through a single MCP endpoint.

Yes, you can. Mastra AI fully supports MCP integration. You get structured tool calling, message history handling, and model orchestration while Tool Router takes care of discovering and serving the right Agent mail tools.

Yes, absolutely. You can configure which Agent mail scopes and actions are allowed when connecting your account to Composio. You can also bring your own OAuth credentials or API configuration so you keep full control over what the agent can do.

All sensitive data such as tokens, keys, and configuration is fully encrypted at rest and in transit. Composio is SOC 2 Type 2 compliant and follows strict security practices so your Agent mail data and credentials are handled as safely as possible.

Start with Agent mail.It takes 30 seconds.

Managed auth, hosted MCP servers, and every Agent mail tool your agent needs.Free to start.

Start building