# MCP Mailtrap Server The MCP Mailtrap Server is an official Model Context Protocol (MCP) server that integrates Mailtrap's email service capabilities into AI assistants and development tools. Built on the MCP SDK, this server enables AI agents to send transactional emails, manage email templates, and test email functionality through Mailtrap's sandbox environment. The server acts as a bridge between AI applications (like Claude Desktop, Cursor, or VS Code) and Mailtrap's API, allowing natural language commands to be translated into email operations. This implementation follows the MCP protocol specification and provides six core tools for email operations: sending transactional emails, sending sandbox test emails, creating templates, listing templates, updating templates, and deleting templates. The server uses TypeScript for type safety, Zod schemas for input validation, and the official Mailtrap Node.js SDK for API communication. It supports flexible configuration through environment variables and can be installed via NPX, Smithery CLI, or as an MCP Bundle (MCPB) file for easy distribution. ## Installation and Configuration ### Quick Installation via NPX ```json { "mcpServers": { "mailtrap": { "command": "npx", "args": ["-y", "mcp-mailtrap"], "env": { "MAILTRAP_API_TOKEN": "your_api_token_here", "DEFAULT_FROM_EMAIL": "sender@yourdomain.com", "MAILTRAP_ACCOUNT_ID": "123456", "MAILTRAP_TEST_INBOX_ID": "789012" } } } } ``` ### Local Development Setup ```bash # Clone and install dependencies git clone https://github.com/mailtrap/mailtrap-mcp.git cd mailtrap-mcp npm install # Build the TypeScript source npm run build # Run with MCP Inspector for testing npm run dev ``` ### Claude Desktop Configuration (Mac) ```bash # Edit config file nano ~/Library/Application\ Support/Claude/claude_desktop_config.json ``` ```json { "mcpServers": { "mailtrap": { "command": "node", "args": ["/absolute/path/to/mailtrap-mcp/dist/index.js"], "env": { "MAILTRAP_API_TOKEN": "your_api_token_here", "DEFAULT_FROM_EMAIL": "sender@yourdomain.com", "MAILTRAP_ACCOUNT_ID": "123456", "MAILTRAP_TEST_INBOX_ID": "789012" } } } } ``` ## Send Transactional Email Sends a production email through Mailtrap's transactional email service to real recipients. ```typescript // MCP tool call structure { "name": "send-email", "arguments": { "to": "recipient@example.com", "subject": "Welcome to Our Platform", "text": "Thank you for signing up!", "html": "

Welcome!

Thank you for signing up!

", "from": "noreply@yourdomain.com", "category": "onboarding", "cc": ["manager@example.com"], "bcc": ["archive@example.com"] } } // Successful response { "content": [{ "type": "text", "text": "Email sent successfully to recipient@example.com.\nMessage IDs: abc123xyz\nStatus: Success" }] } // Error response { "content": [{ "type": "text", "text": "Failed to send email: MAILTRAP_API_TOKEN environment variable is required" }], "isError": true } ``` ### Send to Multiple Recipients ```typescript { "name": "send-email", "arguments": { "to": ["user1@example.com", "user2@example.com", "user3@example.com"], "subject": "Team Meeting Tomorrow", "text": "Don't forget our team meeting at 10 AM tomorrow.", "category": "internal-communication" } } // Response { "content": [{ "type": "text", "text": "Email sent successfully to user1@example.com, user2@example.com, user3@example.com.\nMessage IDs: msg_1,msg_2,msg_3\nStatus: Success" }] } ``` ## Send Sandbox Email Sends a test email to Mailtrap's sandbox inbox for testing without delivering to real recipients. ```typescript // MCP tool call for sandbox testing { "name": "send-sandbox-email", "arguments": { "to": "test@example.com", "subject": "Test Email Template", "html": "

Testing Header

This is a test email to preview styling.

", "text": "Testing Header\n\nThis is a test email to preview styling.", "from": "test@yourdomain.com", "category": "test" } } // Successful response { "content": [{ "type": "text", "text": "Sandbox email sent successfully to test@example.com.\nMessage IDs: sandbox_123\nStatus: Success" }] } // Error when MAILTRAP_TEST_INBOX_ID is not configured { "content": [{ "type": "text", "text": "Failed to send sandbox email: MAILTRAP_TEST_INBOX_ID environment variable is required for sandbox mode" }], "isError": true } ``` ### Multiple Sandbox Recipients ```typescript { "name": "send-sandbox-email", "arguments": { "to": "dev1@test.com, dev2@test.com, qa@test.com", "subject": "QA Testing - User Registration Email", "html": "

Welcome!

Your account has been created.

", "category": "qa-testing" } } ``` ## Create Email Template Creates a reusable email template in your Mailtrap account. ```typescript // Create a welcome email template { "name": "create-template", "arguments": { "name": "Welcome Email", "subject": "Welcome to {{company_name}}!", "html": "

Welcome {{user_name}}!

We're excited to have you on board.

Your account ID: {{account_id}}

", "text": "Welcome {{user_name}}!\n\nWe're excited to have you on board.\n\nYour account ID: {{account_id}}", "category": "onboarding" } } // Successful response { "content": [{ "type": "text", "text": "Template \"Welcome Email\" created successfully!\nTemplate ID: 12345\nTemplate UUID: abc-123-def-456" }] } // Error when missing required content { "content": [{ "type": "text", "text": "Failed to create template: At least one of 'html' or 'text' content must be provided." }], "isError": true } ``` ### Password Reset Template ```typescript { "name": "create-template", "arguments": { "name": "Password Reset", "subject": "Reset Your Password", "html": "

Password Reset Request

Click the link below to reset your password:

Reset Password

This link expires in 24 hours.

", "text": "Password Reset Request\n\nClick the link below to reset your password:\n{{reset_link}}\n\nThis link expires in 24 hours.", "category": "security" } } ``` ## List Email Templates Retrieves all email templates from your Mailtrap account. ```typescript // List all templates { "name": "list-templates", "arguments": {} } // Response with templates { "content": [{ "type": "text", "text": "Found 3 template(s):\n\n• Welcome Email (ID: 12345, UUID: abc-123-def-456)\n Subject: Welcome to {{company_name}}!\n Category: onboarding\n Created: 2024-01-15T10:30:00Z\n\n• Password Reset (ID: 12346, UUID: abc-124-def-457)\n Subject: Reset Your Password\n Category: security\n Created: 2024-01-16T14:20:00Z\n\n• Invoice Notification (ID: 12347, UUID: abc-125-def-458)\n Subject: Your Invoice is Ready\n Category: billing\n Created: 2024-01-17T09:15:00Z\n" }] } // Response when no templates exist { "content": [{ "type": "text", "text": "No templates found in your Mailtrap account." }] } // Error response { "content": [{ "type": "text", "text": "Failed to list templates: MAILTRAP_API_TOKEN environment variable is required" }], "isError": true } ``` ## Update Email Template Updates an existing email template by ID. ```typescript // Update template subject and HTML { "name": "update-template", "arguments": { "template_id": 12345, "subject": "Welcome to {{company_name}} - Get Started!", "html": "

Welcome {{user_name}}!

We're excited to have you on board.

Your account ID: {{account_id}}

Go to Dashboard" } } // Successful response { "content": [{ "type": "text", "text": "Template \"Welcome Email\" updated successfully!\nTemplate ID: 12345\nTemplate UUID: abc-123-def-456" }] } // Update only the category { "name": "update-template", "arguments": { "template_id": 12345, "category": "user-engagement" } } // Error when no fields provided { "content": [{ "type": "text", "text": "Error: At least one update field (name, subject, html, text, or category) must be provided" }], "isError": true } ``` ### Complete Template Overhaul ```typescript { "name": "update-template", "arguments": { "template_id": 12346, "name": "Password Reset v2", "subject": "Security Alert - Password Reset Requested", "html": "

Password Reset Request

Hello {{user_name}},

We received a request to reset your password.

Reset Password

This link expires in 24 hours.

If you didn't request this, please ignore this email.

", "text": "Password Reset Request\n\nHello {{user_name}},\n\nWe received a request to reset your password.\n\nReset link: {{reset_link}}\n\nThis link expires in 24 hours.\n\nIf you didn't request this, please ignore this email.", "category": "security" } } ``` ## Delete Email Template Deletes an email template by ID. ```typescript // Delete template { "name": "delete-template", "arguments": { "template_id": 12347 } } // Successful response { "content": [{ "type": "text", "text": "Template with ID 12347 deleted successfully!" }] } // Error when template doesn't exist { "content": [{ "type": "text", "text": "Failed to delete template: Template not found" }], "isError": true } // Error when API token is missing { "content": [{ "type": "text", "text": "Failed to delete template: MAILTRAP_API_TOKEN environment variable is required" }], "isError": true } ``` ## Core Client Implementation ```typescript // src/client.ts - Mailtrap client initialization import { MailtrapClient } from "mailtrap"; const { MAILTRAP_API_TOKEN, MAILTRAP_ACCOUNT_ID, MAILTRAP_TEST_INBOX_ID } = process.env; // Production client for transactional emails const client = MAILTRAP_API_TOKEN ? new MailtrapClient({ token: MAILTRAP_API_TOKEN, userAgent: "mcp-mailtrap/0.0.3", ...(MAILTRAP_ACCOUNT_ID && !Number.isNaN(Number(MAILTRAP_ACCOUNT_ID)) ? { accountId: Number(MAILTRAP_ACCOUNT_ID) } : {}), }) : null; // Sandbox client for testing const sandboxClient = (MAILTRAP_API_TOKEN && MAILTRAP_TEST_INBOX_ID) ? new MailtrapClient({ token: MAILTRAP_API_TOKEN, userAgent: "mcp-mailtrap/0.0.3", testInboxId: Number(MAILTRAP_TEST_INBOX_ID), sandbox: true, ...(MAILTRAP_ACCOUNT_ID && !Number.isNaN(Number(MAILTRAP_ACCOUNT_ID)) ? { accountId: Number(MAILTRAP_ACCOUNT_ID) } : {}), }) : null; export { client, sandboxClient }; ``` ## MCP Server Setup ```typescript // src/server.ts - Server initialization and tool registration import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js"; const tools = [ { name: "send-email", description: "Send transactional email using Mailtrap", inputSchema: sendEmailSchema, handler: sendEmail, }, { name: "send-sandbox-email", description: "Send email in sandbox mode to a test inbox", inputSchema: sendSandboxEmailSchema, handler: sendSandboxEmail, }, { name: "create-template", description: "Create a new email template", inputSchema: createTemplateSchema, handler: createTemplate, }, { name: "list-templates", description: "List all email templates", inputSchema: listTemplatesSchema, handler: listTemplates, }, { name: "update-template", description: "Update an existing email template", inputSchema: updateTemplateSchema, handler: updateTemplate, }, { name: "delete-template", description: "Delete an existing email template", inputSchema: deleteTemplateSchema, handler: deleteTemplate, }, ]; export function createServer(): Server { const server = new Server( { name: "mcp-mailtrap", version: "0.0.3" }, { capabilities: { tools: {}, prompts: {}, resources: {} } } ); server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: tools.map((tool) => ({ name: tool.name, description: tool.description, inputSchema: tool.inputSchema, })), })); server.setRequestHandler(CallToolRequestSchema, async (request) => { const tool = tools.find((t) => t.name === request.params.name); if (!tool) throw new Error(`Unknown tool: ${request.params.name}`); return tool.handler(request.params.arguments as any); }); return server; } export async function startServer(server: Server): Promise { const transport = new StdioServerTransport(); await server.connect(transport); console.error("Server connected to transport"); } ``` ## Testing and Development ```bash # Run all tests with Jest npm test # Watch mode for development npm run test:watch # Generate coverage report npm run test:coverage # Run MCP Inspector for interactive testing npm run dev # Lint code with ESLint and TypeScript npm run lint # Build TypeScript to JavaScript npm run build # Create MCPB bundle for distribution npm run mcpb:pack npm run mcpb:info npm run mcpb:sign ``` ## Environment Variables Reference ```bash # Required for all functionality MAILTRAP_API_TOKEN=your_api_token_from_mailtrap_settings # Required for sending emails (can be omitted if "from" is always provided in requests) DEFAULT_FROM_EMAIL=noreply@yourdomain.com # Required for template operations (create, list, update, delete) MAILTRAP_ACCOUNT_ID=123456 # Required ONLY for sandbox email functionality MAILTRAP_TEST_INBOX_ID=789012 # Optional: Enable debug logging DEBUG=true ``` ## Error Handling Patterns ```typescript // All tool handlers follow this error handling pattern async function toolHandler(params: RequestType): Promise<{ content: any[]; isError?: boolean }> { try { // Validate environment variables if (!client) { throw new Error("MAILTRAP_API_TOKEN environment variable is required"); } // Validate input parameters if (!params.requiredField) { throw new Error("Required field is missing"); } // Execute Mailtrap API operation const result = await client.someOperation(params); // Return success response return { content: [{ type: "text", text: "Operation successful!" }] }; } catch (error) { // Log error to stderr (doesn't interfere with JSON-RPC) console.error("Error description:", error); // Return structured error response const errorMessage = error instanceof Error ? error.message : String(error); return { content: [{ type: "text", text: `Failed to perform operation: ${errorMessage}` }], isError: true }; } } ``` ## Summary The MCP Mailtrap Server provides a comprehensive email management solution through the Model Context Protocol, enabling AI assistants to handle transactional emails and template operations seamlessly. The six core tools (send-email, send-sandbox-email, create-template, list-templates, update-template, delete-template) cover the complete lifecycle of email operations, from sending production emails to managing reusable templates. The sandbox functionality allows developers to test email rendering and content without sending to real recipients, making it ideal for development and QA workflows. Integration is straightforward across multiple platforms including Claude Desktop, Cursor, VS Code, and any MCP-compatible client. The server can be installed via NPX for quick setup, through Smithery CLI for managed installations, or as an MCPB bundle for offline distribution. The codebase follows MCP best practices with structured error handling, comprehensive TypeScript types, Zod schema validation, and extensive test coverage. All operations include proper error responses with actionable messages, timeout protection, and secure handling of sensitive data through environment variables. The server logs to stderr to maintain JSON-RPC protocol compatibility while providing debugging capabilities when needed.