Skip to main content
Glama
eleanorreem

email

by eleanorreem

Email MCP Server

A Model Context Protocol (MCP) server that enables Claude Desktop to manage emails via SMTP and IMAP. Send emails, fetch unread messages, and create draft replies directly from conversations.

Features

  • Send Emails - Send emails via SMTP with subject and body

  • Fetch Unread Emails - Retrieve unread messages from your inbox

  • Create Draft Replies - Generate and save draft responses to emails

  • Multi-Provider Support - Works with Gmail, Outlook, and Yahoo

  • Input Validation - Comprehensive validation and sanitization

  • Type Safety - Full TypeScript implementation with runtime type guards

Related MCP server: Gmail MCP Server

Architecture

Built with a clean, modular architecture following SOLID principles:

src/
├── index.ts                  # Main server entry point
├── config/
│   └── email-config.ts       # Multi-provider configuration
├── services/
│   ├── smtp-service.ts       # SMTP operations
│   ├── imap-service.ts       # IMAP operations (async/await)
│   └── email-formatter.ts    # Email formatting utilities
├── tools/
│   ├── send-email.ts         # Send email tool
│   ├── get-unread.ts         # Fetch unread emails tool
│   └── create-draft.ts       # Create draft reply tool
├── types/
│   ├── email.types.ts        # TypeScript type definitions
│   └── type-guards.ts        # Runtime type validation
└── utils/
    ├── validation.ts         # Input validation & sanitization
    └── text-utils.ts         # Text processing utilities

Installation

Prerequisites

  • Node.js 18+

  • An email account with SMTP/IMAP access

  • For Gmail: App Password (not your regular password)

Setup

  1. Clone the repository

    git clone https://github.com/yourusername/email-mcp-server.git
    cd email-mcp-server
  2. Install dependencies

    npm install
  3. Build the project

    npm run build
  4. Configure environment variables (optional for standalone testing)

    cp .env.example .env
    # Edit .env with your credentials

Configuration

Claude Desktop Setup

Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):

{
  "mcpServers": {
    "email": {
      "command": "node",
      "args": ["/absolute/path/to/email-mcp-server/build/index.js"],
      "env": {
        "EMAIL_USER": "your-email@gmail.com",
        "EMAIL_APP_PASSWORD": "your-16-character-app-password",
        "EMAIL_PROVIDER": "gmail"
      }
    }
  }
}

Supported Providers

  • Gmail (default)

    • SMTP: smtp.gmail.com:587

    • IMAP: imap.gmail.com:993

    • Requires App Password

  • Outlook

    • SMTP: smtp-mail.outlook.com:587

    • IMAP: outlook.office365.com:993

  • Yahoo

    • SMTP: smtp.mail.yahoo.com:587

    • IMAP: imap.mail.yahoo.com:993

Set EMAIL_PROVIDER to gmail, outlook, or yahoo.

Usage

Once configured, Claude Desktop can use these tools:

Send Email

Send an email to user@example.com with subject "Meeting Tomorrow"
and body "Let's meet at 2 PM to discuss the project."

Fetch Unread Emails

Show me my last 5 unread emails

Create Draft Reply

Create a draft reply to email ID 123 from user@example.com

Security

  • Input Validation: Email addresses, subject lines, and body content are validated

  • Size Limits:

    • Subject lines: 998 characters (RFC 2822)

    • Email body: 500KB

  • Content Sanitization: Control characters removed to prevent injection

  • No Credential Storage: Credentials passed via environment variables only

  • Type Safety: Runtime type guards prevent invalid tool arguments

Development

Building

npm run build       # Compile TypeScript
npm run watch      # Watch mode for development

Project Structure

  • Functional Programming: All services use pure functions, no classes

  • Separation of Concerns: Clear boundaries between config, services, tools, and utilities

  • Type Guards: Runtime validation with TypeScript type narrowing

  • Error Handling: Comprehensive error messages with context

Technical Highlights

Async/Await IMAP

Converted callback-based IMAP library to clean async/await:

export async function getUnreadEmails(limit: number = 10): Promise<Email[]> {
  const imap = await createConnection();
  try {
    await openBox(imap, "INBOX", false);
    const results = await search(imap, ["UNSEEN"]);
    // ... fetch and parse
  } finally {
    imap.end();
  }
}

Runtime Type Validation

Type guards ensure type safety at runtime:

export function isSendEmailParams(args: unknown): args is SendEmailParams {
  const obj = args as Record<string, unknown>;
  return (
    typeof obj === "object" &&
    obj !== null &&
    typeof obj.to === "string" &&
    typeof obj.subject === "string" &&
    typeof obj.body === "string"
  );
}

Multi-Provider Configuration

Easily switch between email providers:

export function getProvider(): EmailProvider {
  const provider = process.env.EMAIL_PROVIDER?.toLowerCase() || "gmail";
  switch (provider) {
    case "gmail": return { /* Gmail config */ };
    case "outlook": return { /* Outlook config */ };
    // ...
  }
}

License

MIT

Contributing

Contributions welcome! Please ensure:

  • TypeScript compiles without errors

  • Code follows functional programming patterns

  • Input validation is maintained

  • No credentials are committed

Available Tools

3 tools
create_draft_replyA

Save a draft reply to an email in Gmail. Generate the reply content in our conversation first, then use this tool to save it.

ParametersJSON Schema
NameRequiredDescriptionDefault
email_idYesThe unique email ID/message ID to reply to
email_bodyNoThe original email body (for confirmation/context)
email_fromYesThe sender's email address
reply_bodyYesThe draft reply content to save (generate this in our conversation)
email_subjectYesThe original email subject

TDQS

A4/5.0
Behavior3/5

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

With no annotations, the description carries the full burden. It transparently states that the tool creates a draft and does not send it, and it adds a useful generate-first workflow. However, it doesn't disclose whether the draft overwrites an existing one, whether it returns a draft identifier, or any auth/permission requirements.

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?

Two sentences, no filler. The core action is front-loaded, and the second sentence provides essential workflow guidance without unnecessary elaboration.

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?

For a low-complexity tool with five simple parameters and full schema coverage, the description is mostly sufficient. It captures the main workflow and purpose. It could be stronger by explicitly contrasting with send_email, but the current wording already implies the difference.

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 description coverage is 100%, so the baseline is 3. The description reinforces that reply_body should be generated in conversation first, but it does not add meaningful semantic detail beyond the schema's per-parameter descriptions.

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 states a specific verb and resource: 'Save a draft reply to an email in Gmail.' This clearly distinguishes it from its siblings, send_email and get_unread_emails, since it is about saving rather than sending or reading.

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 gives clear workflow guidance: generate the reply content in the conversation first, then use this tool to save it. It doesn't explicitly state when not to use it or mention alternatives, but the save-vs-send distinction is clear enough from the wording.

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

get_unread_emailsB

Fetch unread emails from inbox

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of unread emails to fetch (default: 10)

TDQS

B3.1/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full burden of behavioral disclosure. It conveys that the tool fetches unread emails, suggesting a read operation, but does not state whether fetched emails are marked as read, how results are ordered, whether pagination exists, or what the response shape looks like.

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?

One concise sentence with no filler; the core action and resource are front-loaded. Every word earns its place.

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

Completeness3/5

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

For a simple one-parameter read tool, the description is mostly adequate, but with no output schema and no annotations, it leaves return format and potential side effects such as marking emails read unstated. It is not severely incomplete, but it could provide more context.

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 description coverage is 100%, and the single 'limit' parameter is already well documented with type, default, and meaning. The description adds no parameter-specific details, but the schema fully carries that burden, so the baseline 3 is appropriate.

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

Purpose4/5

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

The description uses a specific verb ('Fetch') and resource ('unread emails from inbox'), making the tool's purpose immediately clear. It is distinguishable from siblings send_email and create_draft_reply by the read-vs-write action, though it does not explicitly name those alternatives.

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

Usage Guidelines2/5

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

There is no guidance on when to use this tool versus the sibling tools, and no mention of prerequisites or exclusions. Usage context is only implied by the tool name and the obvious contrast with send_email and create_draft_reply.

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

send_emailB

Send an email via SMTP

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesRecipient email address
bodyYesEmail body content
subjectYesEmail subject

TDQS

B3.3/5.0
Behavior2/5

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

No annotations are provided, so the description must disclose behavioral implications. It reveals the action and the SMTP protocol but does not mention that sending is an external side effect, cannot be undone, requires authorization, or what result the caller should expect.

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 with no filler or repetition. It is front-loaded with the core action ('Send an email') and adds the useful protocol qualifier 'via SMTP' without unnecessary detail.

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

Completeness3/5

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

This is a minimally viable description for a simple tool with fully documented required parameters. However, there is no output schema and no annotations, so the agent is left uninformed about return values, error behavior, delivery guarantees, or side effects of sending an email.

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?

The input schema already documents all three parameters with a description coverage of 100%, establishing baseline clarity. The description adds no additional parameter meaning or constraints beyond what the schema provides.

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 states a specific verb and resource: 'Send an email via SMTP'. This clearly distinguishes it from the sibling tools: get_unread_emails is a read operation and create_draft_reply only creates a draft rather than sending it.

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

Usage Guidelines2/5

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

The description gives no guidance on when to use this tool instead of create_draft_reply or get_unread_emails. There are no conditions, exclusions, or alternative-tool hints provided.

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 3 tool updatesv1.0.0
    • First observedcreate_draft_reply
    • First observedget_unread_emails
    • First observedsend_email

TDQS

A3.7/5.0

Scored across 3 tools

Disambiguation5/5

Each tool targets a clearly distinct operation: sending an email, fetching unread emails, and saving a draft reply. There is no meaningful overlap in purpose or action.

Naming Consistency5/5

All tool names follow a consistent snake_case verb_noun pattern: send_email, get_unread_emails, create_draft_reply. The naming is predictable and easy to infer.

Tool Count5/5

Three tools is a compact but well-scoped set for a basic email server. Each tool serves a distinct and necessary function without redundancy.

Completeness3/5

Core send, fetch unread, and draft reply operations are covered, but common email workflows like marking messages as read, deleting emails, sending drafts, or searching are missing. Agents can work around some gaps but will hit dead ends for basic inbox management.

Maintenance

ActivityInactive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    A Model Context Protocol server that provides a seamless email management interface through Claude, allowing users to search, read, and send emails directly through natural language conversations.
    4
    114
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    A Model Context Protocol (MCP) server that enables Claude Desktop to interact with Gmail through secure OAuth 2.0 authentication. Send emails, search messages, read emails, and manage multiple Gmail accounts directly from Claude Desktop.
    62 npm
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    A Model Context Protocol (MCP) server that enables Claude Desktop to interact with iCloud email accounts. This server provides full email functionality including reading, sending, and managing emails through your iCloud account.
    1
    -
  • F
    license
    Not graded
    quality
    C
    maintenance
    Local IMAP/SMTP MCP server that lets Claude read, search, draft, send, flag, and move mail across multiple IMAP mailboxes. Credentials stay on your machine.
    -