Email MCP Server
A remote MCP (Model Context Protocol) server that connects Claude to Microsoft 365 Outlook and Google Gmail via their respective APIs. Deployed on Vercel with Claude Connector OAuth - Anthropic handles all authentication.
Architecture
┌─────────────┐ ┌──────────────┐ ┌─────────────────┐
│ Claude │────►│ Anthropic │────►│ Microsoft/ │
│ Client │ │ (OAuth) │ │ Google OAuth │
└─────────────┘ └──────────────┘ └─────────────────┘
│
▼
┌──────────────┐
│ Email MCP │ ◄── Bearer token on every request
│ (Vercel) │
└──────────────┘
Key points:
- Users connect via Claude Settings → Connectors
- Anthropic handles the OAuth flow (authorization, token refresh, secure storage)
- MCP server receives
Authorization: Bearer <token>with each request - Server is stateless - no token storage, no auth tools, no database
Features
Microsoft 365 (Outlook)
- Search emails by date, sender, subject, attachments, read status
- Invoice detection with multi-language keywords (English + Hebrew)
- Read full email content
- Download attachments with PDF text extraction
- Folder management (list, create, find)
- Move emails between folders (single or batch)
- Create drafts
Google (Gmail)
- Search with Gmail query syntax
- Invoice detection with keyword matching
- Read emails and full conversation threads
- Download attachments
- Label management (list, create, delete, modify)
- Create drafts
Shared Features
- Session-based short IDs - Uses 1, 2, 3... instead of long API IDs
- Invoice keyword detection - invoice, receipt, billing, payment, חשבונית, חשבוניות
- Provider extraction - Extracts vendor names from email domains
- PDF text extraction - Extracts text from PDF attachments
- Image vision - Returns images for Claude to analyze
Session-Based Short IDs
The MCP uses short IDs instead of long Graph/Gmail IDs:
Graph ID: AAMkADQ5NWE3...longstring...AAAA=
↓
Short ID: 1
Benefits:
- Reduces token usage
- Easier to reference in follow-up commands
- Works with messages, folders, attachments, and labels
Note: Short IDs are stored in-memory and reset when the session ends.
Setup
Prerequisites
- Vercel account - vercel.com
- Azure AD App Registration (for Microsoft 365)
- Google Cloud OAuth credentials (for Gmail)
Azure AD Setup
- Go to Azure Portal → Azure Active Directory → App registrations
- Create new registration
- Add API permissions:
Mail.ReadWrite,User.Read,offline_access - Add redirect URI:
https://claude.ai/api/mcp/auth_callback - Copy the Application (client) ID and Directory (tenant) ID
Google Cloud Setup
- Go to Google Cloud Console
- Enable the Gmail API
- Configure OAuth consent screen
- Create OAuth 2.0 credentials
- Add redirect URI:
https://claude.ai/api/mcp/auth_callback - Add scopes:
https://www.googleapis.com/auth/gmail.readonlyhttps://www.googleapis.com/auth/gmail.modifyhttps://www.googleapis.com/auth/gmail.labels
Deployment
- Clone the repository
- Link to Vercel:
vercel link - Set environment variables in Vercel Dashboard:
AZURE_CLIENT_ID- Azure app client IDAZURE_TENANT_ID- Azure tenant ID
- Deploy:
vercel deploy --prod
Note: Client secrets are NOT stored in the MCP server - Anthropic handles OAuth securely.
Connecting to Claude
After deployment:
- Go to Claude.ai → Settings → Connectors
- Add your Vercel deployment URL
- Authorize with Microsoft and/or Google when prompted
- Start using email tools in Claude
Available Tools
Microsoft 365 (Outlook)
| Tool | Description | |------|-------------| | m365_search_emails | Search emails with flexible filtering | | m365_search_invoice_emails | Find invoice emails with keyword detection | | m365_read_email | Read full email content | | m365_list_attachments | List attachments of an email | | m365_download_attachment | Download a specific attachment | | m365_download_attachment_by_name | Download attachment by filename | | m365_download_all_invoices | Batch download invoice attachments | | m365_list_folders | List mail folders | | m365_find_folder | Find folder by path or name | | m365_get_folder_tree | Get complete folder hierarchy | | m365_create_folder | Create a new mail folder | | m365_move_email | Move a single email | | m365_move_emails | Move multiple emails | | m365_list_providers | List vendors from invoice emails | | m365_create_draft | Create a draft (does not send) |
Google (Gmail)
| Tool | Description | |------|-------------| | google_search_emails | Search with Gmail query syntax | | google_search_invoice_emails | Find invoice emails | | google_read_email | Read full message content | | google_read_thread | Read entire conversation thread | | google_list_attachments | List attachments of a message | | google_download_attachment | Download attachment by filename | | google_list_labels | List all Gmail labels | | google_get_label | Get label details | | google_create_label | Create a new label | | google_delete_label | Delete a label | | google_modify_labels | Add/remove labels from messages | | google_list_providers | List vendors from invoice emails | | google_create_draft | Create a draft (does not send) |
Example Workflows
Organize Invoices (Microsoft 365)
1. m365_search_invoice_emails(year: 2024) → Find invoices
2. m365_create_folder(displayName: "Invoices") → Create folder
3. m365_move_emails(messageIds: [...], destinationFolderName: "Invoices")
Search and Label (Gmail)
1. google_search_emails(query: "from:amazon.com has:attachment")
2. google_search_invoice_emails(year: 2024)
3. google_modify_labels(messageIds: [...], addLabelIds: ["Label_123"])
Read Conversation
1. google_search_emails(sender: "support@company.com")
2. google_read_thread(threadId: ...)
Tool Parameters
General Email Search
| Parameter | Type | Description | |-----------|------|-------------| | startDate | string | Start date (ISO format) | | endDate | string | End date (ISO format) | | year | number | Year to search | | month | number | Month (1-12) | | sender | string | Sender email address | | subject | string | Subject contains | | hasAttachments | boolean | Filter by attachments | | isUnread | boolean | Filter by read status | | folderId/labelId | string | Search within folder/label | | maxResults | number | Maximum results | | format | string | "full", "summary", "minimal", "ids" |
Invoice Search
| Parameter | Type | Description | |-----------|------|-------------| | year | number | Required. Year to search | | month | number | Month (1-12) | | sender | string | Sender email address | | keywords | string[] | Custom search keywords | | maxResults | number | Maximum results |
Move Emails (M365)
| Parameter | Type | Description | |-----------|------|-------------| | messageId/messageIds | string/string[] | Email ID(s) to move | | destinationFolderId | string | Folder ID or well-known name | | destinationFolderName | string | Folder display name | | createIfNotExists | boolean | Create folder if missing |
Well-known folders: inbox, drafts, sentitems, deleteditems, archive, junkemail, outbox
Development
Local Testing
npm run dev # Start local Next.js server
# Connect MCP Inspector to http://localhost:3000/api/mcp
Build
npm run build # Build for production
Invoice Detection
The server searches for emails containing these keywords:
- English: invoice, receipt, bill, payment, billing, statement, order confirmation, tax invoice
- Hebrew: חשבונית, קבלה, תשלום, חשבונית מס, אישור הזמנה
Attachment Filtering
Only downloads invoice-relevant files:
- PDF files
- Images (PNG, JPG, JPEG, TIFF)
Skips:
- Calendar files (.ics)
- Contact files (.vcf)
- HTML files
- Signature images (files containing "signature", "logo", "banner")
License
MIT












