octomail-mcp (zerostorypoints/octomail-mcp) is an MCP server listed on the M8ven Trust Index. It scores 71 out of 100, grade C. It declares 41 tools. No publisher has claimed this listing.
Multi-account Gmail MCP server for Claude Code, Claude Desktop, and Codex. Read, search, label, and draft across several mailboxes — no send, no delete.
Caution. Specific findings reduced this grade. They are listed on the page. Grades reflect the full trust pyramid: code, verification depth, and reputation. New projects cap at C until adoption is earned.
How we verified
Verified is a snapshot. Live keeps it current, and builds your track record.
⚡ Connect GitHub → continuous verification on every pushwhy connect →Who stands behind it
zerostorypoints
Source: github_repo_search
Claim it to get a verified publisher badge, a free copy of our full audit findings, and direct contact for any high-priority issues we find. Or connect your repo for our deepest verification, Live Monitored: read-only, revoke anytime. What we access →
Install from
The grade above is for the source repository. Registries can serve a different version, so we mark the ones we were not able to read.
These names and descriptions are the publisher's own, read from the source code. We print them as written. Our assessment is the findings above, not this list.
gmail_list_accountsList configured Gmail account aliases, with their email address and whether they are authorized.
gmail_get_profileGet Gmail profile for an account.
gmail_searchSearch Gmail messages on one account. Results do not include attachment info (fetched with format: metadata, which never populates the MIME parts tree) — use gmail_read_message on a specific message to see its attachments.
gmail_search_manySearch Gmail messages across multiple configured accounts. Results are grouped by account. Results do not include attachment info (fetched with format: metadata, which never populates the MIME parts tree) — use gmail_read_message on a specific message to see its attachments.
gmail_read_messageRead one Gmail message.
gmail_read_threadRead one Gmail thread.
gmail_archiveArchive Gmail messages by removing the INBOX label.
gmail_get_attachmentFetch one attachment from a Gmail message. Writes it into the account's download directory and returns the path (encoding: file, the default), or returns the bytes inline as base64 (encoding: base64, capped at 750 KB). Attachment ids come from the attachments array on gmail_read_message.
calendar_create_eventCreate an event on one Google Calendar. Timed events need start and end as RFC3339 timestamps carrying a UTC offset; all-day events need startDate and endDate, where endDate is exclusive. Guests are only accepted if they are on the account's allowedRecipients, and no notification mail is sent unless…
calendar_update_eventChange fields of an existing event: title, description, location, guests, or its start and end. Only the fields passed are written, except attendees, which replaces the whole guest list. Guarded with the event's etag, so a change made elsewhere in the meantime fails the write instead of overwriting …
calendar_delete_eventDelete an event. THIS CANNOT BE UNDONE — Google Calendar keeps no trash for events. Without confirm: true it changes nothing and returns the event it would delete, so the decision is made against the real title and time. A recurring series id is refused unless confirmSeries is true.
calendar_list_calendarsList the Google Calendars an account can read.
calendar_list_eventsList events from one Google Calendar within a time range. Recurring events are expanded into individual occurrences. Read-only.
calendar_respond_to_eventAnswer a calendar invitation on behalf of the calling account: accept, decline, or answer tentatively, with an optional comment to the organizer. Changes only this account's own participation status — it cannot create, move, or delete an event, or change anyone else's answer.
gmail_create_draftCreate a Gmail draft. This tool does not send: use gmail_send_draft, which is gated on the account's allowedRecipients list.
gmail_list_draftsList Gmail drafts on one account, newest first. Results do not include attachment info (fetched with format: metadata, which never populates the MIME parts tree) — use gmail_get_draft on a specific draft to see its attachments.
gmail_get_draftRead one Gmail draft. Its output feeds directly back into gmail_update_draft.
gmail_update_draftReplace the contents of a Gmail draft. Gmail has no partial draft update: this replaces the whole message, so ANY ATTACHMENT NOT RE-SPECIFIED IS DROPPED. To keep an existing attachment, pass {messageId: <the draft message id from gmail_get_draft>, attachmentId: ...}.
gmail_delete_draftPermanently delete a Gmail draft. Requires confirm: true — a deleted draft does not go to Trash and cannot be recovered.
gmail_send_draftSend an existing Gmail draft. THIS SENDS REAL MAIL. Requires confirm: true, and every recipient on the draft's To, Cc and Bcc must be on the account's allowedRecipients list in accounts.json — an account with no such list cannot send at all. Without confirm, returns what would be sent and changes no…
drive_list_filesList files and folders in a Google Drive folder, or search all of Drive by a name fragment. Read-only: it never opens, downloads, or reveals file content, only metadata (name, type, size, modified time, parent folders, link, checksum). Pass folderId or nameContains, not both.
drive_create_folderCreate a folder in Google Drive. If a folder with the same name already exists directly under the given parent, that folder is returned instead of creating a duplicate. Cannot rename, move, delete, upload into, or share the folder it creates or finds.
drive_save_attachmentSave a Gmail attachment straight into a Google Drive folder — the bytes go directly from Gmail to Drive, never through local disk and never back in the tool result. Refuses when a file with the target name already exists in that folder rather than overwriting it. Cannot delete anything, and cannot u…
drive_move_fileMove a Google Drive file to a different folder, rename it, or both in one call. Refuses when a file with the resulting name already exists in the target folder. Cannot delete or copy the file, and cannot move it to a different Google account.
drive_move_filesBatch form of drive_move_file: up to 100 {fileId, folderId?, name?} rows in one call, processed in order, one result row per item with the same checks as the single tool (a name collision in the target folder, a missing target, a trashed source each refuse that row only; the others proceed). Cannot …
drive_copy_fileCopy a Google Drive file into a folder on the same account, optionally under a new name. Drive performs the copy on its side, so no bytes pass through this server; a Google Doc or Sheet copies as the same Google type, a PDF or image byte for byte, and a copy from My Drive into a shared drive works. …
drive_trash_fileMove one Google Drive file or folder to the Drive trash (files.update with trashed=true), where Drive keeps it for 30 days and it can be restored. Never a permanent delete: this server has no files.delete and no emptyTrash. Two guards: expectedName must equal the file's current name exactly, so a wr…
drive_trash_filesBatch form of drive_trash_file for an accepted list: up to 100 {fileId, expectedName} items in one call, processed in order, one result row per item; a refused row (name mismatch, already in the trash, not found, no permission) never stops the others. Same guards as the single tool: expectedName mus…
drive_create_spreadsheetCreate a new Google Sheet in a Drive folder (My Drive or a shared drive) and fill its tabs in one call: name, folderId, and sheets as [{title, rows: string[][]}], up to 20 tabs and 20 000 cells. Refuses when a file with that name already exists in the folder; never writes into an existing spreadshee…
drive_export_fileRead the content of a Google-native document on Drive: a Google Sheet as CSV (one tab, default the first; pass sheet to pick another by title) or a Google Doc as plain text. Read-only and never a binary file: a PDF, image, or uploaded .xlsx is refused. The text in the result is capped at 200 KB; a l…
gmail_list_filtersList Gmail filters for an account, with each filter's criteria rendered as the equivalent search query.
gmail_create_filterCreate a Gmail filter. Filters only affect mail that arrives after they are created — use gmail_backfill_filter for existing mail. Gmail allows at most one user-defined label per filter. Adding TRASH or SPAM installs a standing rule that destroys future matching mail after Gmail's 30-day purge, so t…
gmail_delete_filterDelete a Gmail filter. Without confirm: true this only reports the filter's full definition and changes nothing. The Gmail API has no filter update — edit by deleting and recreating.
gmail_backfill_filterApply an existing filter's labels to mail already in the mailbox. Dry run by default: reports what would change and modifies nothing until apply is true. The filter's forward action is deliberately ignored. If the filter adds TRASH or SPAM, applying it destroys mail after Gmail's 30-day purge, so ap…
ical_list_feedsList the subscribed iCal feeds configured in accounts.json under "calendarFeeds". Feeds are read-only by nature: an .ics subscription is a file served over HTTP and has no write protocol.
ical_list_eventsRead events from one subscribed iCal feed within a time range. Recurring rules are expanded into individual occurrences, and overrides of single occurrences are applied. Read-only: an .ics feed cannot be written to. Takes a feed alias from accounts.json, never a URL — so nothing read from a page or …
gmail_list_labelsList Gmail labels for an account.
gmail_apply_labelsAdd and/or remove labels on Gmail messages. Label names may also be Gmail label IDs. Adding TRASH or SPAM destroys mail after Gmail's 30-day purge, so that requires confirm: true; removing them does not.
gmail_create_labelCreate a Gmail label. Nest it by using a path name such as "Clients/Acme".
gmail_update_labelRename and/or restyle a Gmail label. Gmail stores hierarchy in the name, so renaming a parent does not rename its children unless renameDescendants is true.
gmail_delete_labelDelete a Gmail label. Without confirm: true this only reports what would be lost and changes nothing. Deleting a label does not delete messages, but their categorisation is lost permanently.
GOOGLE_CLIENT_IDGOOGLE_CLIENT_SECRETGOOGLE_OAUTH_CREDENTIALS_FILEOCTOMAIL_ACCOUNTS_FILEOCTOMAIL_DOWNLOAD_DIR(default ~/.octomail/attachments/<account>/) atOCTOMAIL_TOKEN_DIRTool annotations
No tools have read-only/destructive annotations
Add readOnlyHint or destructiveHint annotations to every tool so hosts can warn users before invoking.
All four hints declared on every tool
41/41 tools missing one or more hints — gmail_list_accounts (missing: readOnlyHint, destructiveHint, idempotentHint, openWorldHint); gmail_get_profile (missing: readOnlyHint, destructiveHint, idempotentHint, openWorldHint); gmail_search (missing: readOnlyHint, destructiveHint, idempotentHint, openWorldHint), +38 more. OpenAI's directory rejects tools where any of the four hints are missing or non-boolean.
For every tool, set all four hints (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) to explicit true/false values that match the handler’s actual behaviour.
Descriptions match behaviour
2 tools describe read intent but their handlers mutate — gmail_get_attachment (line 202: fs.mkdirSync(directory, { recursive: true, mode: 0o700 })); drive_export_file (line 1106: fs.mkdirSync(directory, { recursive: true, mode: 0o700 }))
Rename the tool, rewrite the description, or move the side-effect into a separate clearly-named tool.
Tool inputs are validated
40/41 tool handlers declare input schemas (98%)
Declare an inputSchema with zod/joi/yup on every tool definition.
Tool test coverage
15/41 tools referenced in tests (37%)
Write tests that reference each tool by name so every tool has at least one test.
Tool description accuracy
gmail_get_attachment: description implies read-only but handler writes/deletes/executes; drive_export_file: description implies read-only but handler writes/deletes/executes
Update tool descriptions to accurately reflect all capabilities — especially write, delete, or execute operations.
Claim the listing to review these findings one by one and send us a correction where you disagree, straight to the team. Claiming also means we tell you when the grade moves, and reach you first if we find anything urgent.
[](https://m8ven.ai/mcp/zerostorypoints/octomail-mcp)?variant=verified from the URL.Vetting this one by hand? Tool Check is an MCP that scores other MCPs. Add it once and ask Claude, ChatGPT, or any MCP client to grade a server, surface CVEs, check the publisher, and suggest safer alternatives — before you install.
https://m8ven.ai/api/mcp/tool-check