Skip to main content
Glama
ai-zerolab

MCP Email Server

by ai-zerolab

list_emails_metadata

Retrieve email metadata including subject, sender, recipients, and date. Filter by mailbox, date range, sender, subject, read status, and more. Obtain email IDs to fetch full content separately.

Instructions

List email metadata (email_id, subject, sender, recipients, date) without body content. Returns email_id for use with get_emails_content.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
account_nameYesThe name of the email account.
pageNoThe page number to retrieve (starting from 1).
page_sizeNoThe number of emails to retrieve per page.
beforeNoRetrieve emails before this datetime (UTC).
sinceNoRetrieve emails since this datetime (UTC).
subjectNoFilter emails by subject.
from_addressNoFilter emails by sender address.
to_addressNoFilter emails by recipient address.
orderNoOrder emails by field. `asc` or `desc`.desc
mailboxNoThe mailbox to search.INBOX
seenNoFilter by read status: True=read, False=unread, None=all.
flaggedNoFilter by flagged/starred status: True=flagged, False=unflagged, None=all.
answeredNoFilter by replied status: True=replied, False=not replied, None=all.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
pageYes
page_sizeYes
beforeYes
sinceYes
subjectYes
emailsYes
totalYes

Implementation Reference

  • The MCP tool function 'list_emails_metadata' registered with @mcp.tool decorator. It accepts filtering parameters (page, page_size, before, since, subject, from_address, to_address, order, mailbox, seen, flagged, answered) and dispatches to handler.get_emails_metadata().
    async def list_emails_metadata(
        account_name: Annotated[str, Field(description="The name of the email account.")],
        page: Annotated[
            int,
            Field(default=1, description="The page number to retrieve (starting from 1)."),
        ] = 1,
        page_size: Annotated[int, Field(default=10, description="The number of emails to retrieve per page.")] = 10,
        before: Annotated[
            datetime | None,
            Field(default=None, description="Retrieve emails before this datetime (UTC)."),
        ] = None,
        since: Annotated[
            datetime | None,
            Field(default=None, description="Retrieve emails since this datetime (UTC)."),
        ] = None,
        subject: Annotated[str | None, Field(default=None, description="Filter emails by subject.")] = None,
        from_address: Annotated[str | None, Field(default=None, description="Filter emails by sender address.")] = None,
        to_address: Annotated[
            str | None,
            Field(default=None, description="Filter emails by recipient address."),
        ] = None,
        order: Annotated[
            Literal["asc", "desc"],
            Field(default=None, description="Order emails by field. `asc` or `desc`."),
        ] = "desc",
        mailbox: Annotated[str, Field(default="INBOX", description="The mailbox to search.")] = "INBOX",
        seen: Annotated[
            bool | None,
            Field(default=None, description="Filter by read status: True=read, False=unread, None=all."),
        ] = None,
        flagged: Annotated[
            bool | None,
            Field(default=None, description="Filter by flagged/starred status: True=flagged, False=unflagged, None=all."),
        ] = None,
        answered: Annotated[
            bool | None,
            Field(default=None, description="Filter by replied status: True=replied, False=not replied, None=all."),
        ] = None,
    ) -> EmailMetadataPageResponse:
        handler = dispatch_handler(account_name)
    
        return await handler.get_emails_metadata(
            page=page,
            page_size=page_size,
            before=before,
            since=since,
            subject=subject,
            from_address=from_address,
            to_address=to_address,
            order=order,
            mailbox=mailbox,
            seen=seen,
            flagged=flagged,
            answered=answered,
        )
  • The @mcp.tool decorator registering 'list_emails_metadata' as an MCP tool with a description explaining it lists email metadata without body content.
    @mcp.tool(
        description="List email metadata (email_id, subject, sender, recipients, date) without body content. Returns email_id for use with get_emails_content."
    )
  • EmailMetadataPageResponse - the return type schema for list_emails_metadata, containing page info, filters, email list, and total count.
    class EmailMetadataPageResponse(BaseModel):
        """Paged email metadata response"""
    
        page: int
        page_size: int
        before: datetime | None
        since: datetime | None
        subject: str | None
        emails: list[EmailMetadata]
        total: int
  • EmailMetadata model representing individual email metadata returned by list_emails_metadata (email_id, subject, sender, recipients, date, attachments).
    class EmailMetadata(BaseModel):
        """Email metadata"""
    
        email_id: str
        message_id: str | None = None  # RFC 5322 Message-ID header for reply threading
        subject: str
        sender: str
        recipients: list[str]  # Recipient list
        date: datetime
        attachments: list[str]
    
        @classmethod
        def from_email(cls, email: dict[str, Any]):
            return cls(
                email_id=email["email_id"],
                message_id=email.get("message_id"),
                subject=email["subject"],
                sender=email["from"],
                recipients=email.get("to", []),
                date=email["date"],
                attachments=email["attachments"],
            )
  • ClassicEmailHandler class that implements get_emails_metadata(), which is called by the tool handler. It streams metadata from the IMAP EmailClient.
    class ClassicEmailHandler(EmailHandler):
        def __init__(self, email_settings: EmailSettings):
            self.email_settings = email_settings
            self.incoming_client = EmailClient(email_settings.incoming)
            self.outgoing_client = EmailClient(
                email_settings.outgoing,
                sender=f"{email_settings.full_name} <{email_settings.email_address}>",
            )
            self.save_to_sent = email_settings.save_to_sent
            self.sent_folder_name = email_settings.sent_folder_name
    
        async def get_emails_metadata(
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must carry the full burden. It states the tool lists metadata without body content, but does not disclose read-only behavior, pagination details, or any side effects. The description is minimal on behavioral traits beyond the obvious.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence that front-loads the key information: what the tool does, what it omits, and how the output is used. Every part is essential and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 13 parameters and the existence of an output schema, the description is sufficiently complete. It mentions the return of email_id for chaining with get_emails_content, which adds context. However, it does not mention pagination defaults or filtering options beyond what the schema provides.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with descriptions for all parameters, so the baseline is 3. The description does not add any additional semantics beyond what the schema already provides, such as parameter relationships or constraints.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'List', the resource 'email metadata', and specifies the fields returned. It also differentiates from the sibling tool 'get_emails_content' by noting it does not include body content and returns email_id for further use.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies a workflow by stating 'Returns email_id for use with get_emails_content', but does not explicitly state when to use this over other siblings like delete_emails or search. It provides clear context with a hint of best practice.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ai-zerolab/mcp-email-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server