Complete documentation for all 4 MCP tools provided by Mail MCP Bridge.
Get the absolute file path of a single email by Message-ID.
| Parameter | Type | Required | Description |
|---|---|---|---|
message_id |
string | ✅ | RFC Message-ID, e.g. <abc@example.com> |
Note: Angle brackets are optional - the tool will auto-add them if missing.
Success:
{
"success": true,
"message_id": "<abc@example.com>",
"file_path": "/Users/xxx/Library/Mail/V10/UUID/INBOX.mbox/12345.emlx"
}Error:
{
"success": false,
"message_id": "<abc@example.com>",
"error": "Email file not found",
"possible_reasons": [
"Message-ID does not exist",
"Email file has been deleted",
"Email is in a different Mail database version"
]
}- Debug email file location
- Custom email processing scripts
- Verify email existence
Query Flow:
Message-ID → SQLite: SELECT ROWID, mailbox_url
WHERE message_id_header = '<...>'
↓
Parse mailbox URL → Build directory path
↓
find {mbox_path} -name {ROWID}*.emlx
↓
Return file path
Database Tables Used:
messages- For ROWID and mailbox referencemessage_global_data- For Message-ID lookupmailboxes- For mailbox URL
Get file paths of all emails in a conversation thread.
| Parameter | Type | Required | Description |
|---|---|---|---|
message_id |
string | ✅ | Any Message-ID from the thread |
Success:
{
"success": true,
"message_id": "<abc@example.com>",
"thread_size": 3,
"file_paths": [
"/path/to/email1.emlx",
"/path/to/email2.emlx",
"/path/to/email3.emlx"
]
}Error:
{
"success": false,
"message_id": "<abc@example.com>",
"error": "Email thread not found or thread has no email files"
}- Analyze complete conversation history
- Thread-level email operations
- Email thread backup
How it works:
- Query
conversation_idfrom Message-ID - Find all emails with same
conversation_id - Sort by
date_sentASC (chronological order) - Get file path for each email
- Return sorted file paths
SQL Query:
-- Step 1: Get conversation_id
SELECT m.conversation_id
FROM messages m
LEFT JOIN message_global_data mgd ON m.global_message_id = mgd.ROWID
WHERE mgd.message_id_header = '<message-id@example.com>'
-- Step 2: Get all emails in thread
SELECT mgd.message_id_header
FROM messages m
LEFT JOIN message_global_data mgd ON m.global_message_id = mgd.ROWID
WHERE m.conversation_id = 12345
ORDER BY m.date_sent ASCWhat is a Thread?
Mail groups related emails into conversations using conversation_id:
- Same subject (Re:, Fwd:)
- Same participants (From, To, Cc)
- Reply/forward relationships
Parse and read plain text content of a single email.
| Parameter | Type | Required | Description |
|---|---|---|---|
message_id |
string | ✅ | RFC Message-ID |
Success:
{
"success": true,
"message_id": "<abc@example.com>",
"subject": "Project Update",
"from": "Sender Name <sender@example.com>",
"to": "Recipient Name <recipient@example.com>",
"cc": "cc@example.com",
"date": "Wed, 25 Dec 2024 10:30:00 +0800",
"references": "<original@example.com> <prev@example.com>",
"in_reply_to": "<prev@example.com>",
"body_text": "Plain text email body..."
}Error:
{
"success": false,
"error": "Parse failed: ..."
}- AI email analysis
- Email content extraction
- Email summarization
- Content indexing
What gets extracted:
- ✅ Plain text body (
text/plainparts only) - ✅ Key headers (Subject, From, To, Cc, Date)
- ✅ Threading headers (References, In-Reply-To)
- ✅ Decoded header values (e.g.
=?UTF-8?B?...?=) - ❌ Attachments (skipped)
- ❌ HTML content (skipped)
- ❌ Embedded images (skipped)
- ❌ Rich text/RTF (skipped)
- ❌ Full raw headers (not included)
Email Parsing Process:
1. Read .emlx file
2. Skip first line (file size)
3. Extract email content (before plist XML)
4. Parse RFC 5322 format
5. Decode headers (charset detection)
6. Extract text/plain body
7. Decode body using charset from Content-Type
Character Encoding:
- Headers: Auto-detect and decode (UTF-8, GBK, ISO-8859-1, etc.)
- Body: Use charset from
Content-Typeheader - Fallback: UTF-8 with error replacement (�)
Multipart Email Handling:
- Walk through all MIME parts
- Skip attachments (
Content-Disposition: attachment) - Find first
text/plainpart - Decode and return
- Ignore
text/html,image/*, etc.
Parse and read entire email thread.
| Parameter | Type | Required | Description |
|---|---|---|---|
message_id |
string | ✅ | Any Message-ID from the thread |
Success:
{
"success": true,
"message_id": "<abc@example.com>",
"thread_size": 3,
"emails": [
{
"success": true,
"message_id": "<msg1@example.com>",
"subject": "Re: Project Update",
"from": "Alice <alice@example.com>",
"to": "Bob <bob@example.com>",
"cc": "",
"date": "Mon, 23 Dec 2024 09:00:00 +0800",
"references": "<original@example.com>",
"in_reply_to": "",
"body_text": "Hi Bob, how's the project going?"
},
{
"success": true,
"message_id": "<msg2@example.com>",
"subject": "Re: Project Update",
"from": "Bob <bob@example.com>",
"to": "Alice <alice@example.com>",
"cc": "",
"date": "Tue, 24 Dec 2024 10:30:00 +0800",
"references": "<original@example.com> <msg1@example.com>",
"in_reply_to": "<msg1@example.com>",
"body_text": "Making good progress..."
},
{
"success": true,
"message_id": "<msg3@example.com>",
"subject": "Re: Project Update",
"from": "Alice <alice@example.com>",
"to": "Bob <bob@example.com>",
"cc": "",
"date": "Wed, 25 Dec 2024 15:45:00 +0800",
"references": "<original@example.com> <msg1@example.com> <msg2@example.com>",
"in_reply_to": "<msg2@example.com>",
"body_text": "Great to hear!"
}
]
}Error:
{
"success": false,
"message_id": "<abc@example.com>",
"error": "Email thread not found or thread has no email files"
}- Conversation analysis
- Thread summarization
- Progress tracking across multiple emails
- Email thread visualization
Process:
- Get all Message-IDs in thread (using
get_thread_pathslogic) - For each Message-ID:
- Get file path
- Parse email file
- Extract structured data
- Sort all emails by
date_sent(already sorted from step 1) - Return array of email objects
Each email object has the same structure as read_email return value.
Sorting: Emails are returned in chronological order (oldest first).
All tools follow this error response format:
{
"success": false,
"error": "Human-readable error message"
}Additional fields may be included depending on the error:
message_id- When Message-ID is providedpossible_reasons- Array of likely causes (forget_email_path)
| Error | Cause | Solution |
|---|---|---|
| "Email file not found" | Message-ID doesn't exist or email deleted | Verify Message-ID format (<...>) |
| "Mail database not found" | Mail V10 database missing | Check Mail app version (requires macOS 12+) |
| "Parse failed" | Corrupted .emlx file | Open email in Mail app to verify |
| "Thread not found" | Message-ID invalid or not in a thread | Use single email tools instead |
| Operation | Typical Time | Notes |
|---|---|---|
get_email_path |
5-20ms | SQLite query + file system lookup |
get_thread_paths |
10-50ms | Depends on thread size |
read_email |
10-30ms | File I/O + parsing |
read_thread |
50-200ms | Depends on thread size and email content |
Optimizations:
- SQLite indexes on
message_id_headerandconversation_id - File system cache (macOS)
- Direct property access in AppleScript (no email source parsing)
Performance Tips:
- Use
get_thread_pathsfirst if you need both paths and content - Cache results if repeatedly accessing the same emails
- Large threads (>50 emails) may take longer
- ARCHITECTURE.md - Technical architecture and database structure
- README.md - Quick start guide and usage examples