MCP server providing access to IMAP email accounts and CalDAV calendar accounts with email sending, message management, and calendar event operations
Strong foundation with 24 well-named tools covering email and calendar domains. All tools have descriptions (avg 150 chars) and explicit JSON Schema inputs with type constraints. Naming follows verb_noun convention consistently (list_*, get_*, send_*, create_*, etc.). Parameters include descriptions and constraints (min/max, enums, formats). However, output schemas are not formally documented, responses are inferred from code (jsonResult/errorResult pattern). Error handling returns structured messages but lacks recovery guidance. Tool annotations (readOnlyHint/destructiveHint) are absent despite clear risk levels. Some parameter descriptions could be more prescriptive about format/constraints.
Copy messages to another folder.
Create a new calendar event. Pass tz to anchor the event to a real timezone — recurring events then survive DST correctly.
Create a new IMAP folder.
Delete a calendar event. Pass the etag for optimistic concurrency control.
Delete an IMAP folder.
Delete messages (mark for deletion and expunge).
Output schemas not formally documented. Responses use jsonResult() helper returning {content: [{type: 'text', text: JSON.stringify(...)}]} but LLMs cannot infer structure of returned JSON fields. Missing documented return types for all 24 tools.
Tool annotations missing. All 24 tools lack readOnlyHint, destructiveHint, or idempotentHint despite clear risk levels (READ_ONLY, WRITE, DESTRUCTIVE). Agents cannot infer safety properties without explicit annotations.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | A | 84 | <=2025-11-25 | v2 |
Find free time slots for a list of attendees within a date range.
Download an attachment from a message.
Get a single event by UID. Returns the event with etag for optimistic concurrency control.
Fetch a full message (headers, text, HTML, attachment metadata).
Get all messages in a conversation thread (by Message-ID and References).
List the IMAP/SMTP email accounts configured by the current user.
List the CalDAV calendar accounts configured by the current user.
List calendars in a CalDAV account.
List events in a calendar within a date range. Recurring events can be expanded to individual occurrences.
List the folders (mailboxes) of an account.
List message headers in a folder (default: the 50 most recent).
Move messages to another folder.
Rename an IMAP folder.
Reply to a message. Follows the same writing style instructions as send_message. The In-Reply-To and References headers are set automatically.
IMAP search (from, to, subject, body, date ranges, unread only).
Send an email through the account's SMTP. Before drafting, call list_accounts and follow the chosen account's `writingStyleInstructions` verbatim — it encodes language, tone, greetings, length and any custom rules the user configured. The HTML signature is appended when include_signature=true. File attachments are accepted as base64. A copy of the sent message is IMAP-appended to the Sent folder for every provider except Gmail (which already saves to Sent through SMTP).
Set IMAP flags on a message (read, starred, etc.).
Update an existing calendar event. Pass the etag returned by get_event or list_events for optimistic concurrency control.
Error handling lacks recovery guidance. errorResult() returns bare error messages without actionable next steps. E.g., 'Account not found' should suggest 'Call list_accounts() to discover valid account IDs.'
Destructive operations (delete_messages, delete_folder, delete_event) lack confirmation/dry-run support. Agents can permanently delete data without a safety gate.
Parameter descriptions for folder/calendar_url could be more prescriptive. E.g., 'folder' in list_messages defaults to 'INBOX' but does not document IMAP folder path format or how to discover valid folder names.