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.

C
Caution
71/100

octomail-mcp

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

⚡ Live Monitored: not connected

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

Is this your MCP?

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.

// key findings
⚠️
Tool descriptions don’t match what handlers do
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 }))
No credential exfiltration, no sensitive file access, no obfuscation
Static analysis found nothing flowing your secrets to unexpected places.
Open source with a license and README
Anyone can audit the code, the license is declared, and the publisher documents what it does.
🔐
You'll be asked for 1 credential: GOOGLE_CLIENT_SECRET
These are read from process.env at runtime. Make sure you trust where they’ll be sent.
// tools this server exposes41 tools

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_accounts

List configured Gmail account aliases, with their email address and whether they are authorized.

gmail_get_profile

Get Gmail profile for an account.

gmail_search

Search 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_many

Search 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_message

Read one Gmail message.

gmail_read_thread

Read one Gmail thread.

gmail_archive

Archive Gmail messages by removing the INBOX label.

gmail_get_attachment

Fetch 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_event

Create 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_event

Change 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_event

Delete 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_calendars

List the Google Calendars an account can read.

calendar_list_events

List events from one Google Calendar within a time range. Recurring events are expanded into individual occurrences. Read-only.

calendar_respond_to_event

Answer 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_draft

Create a Gmail draft. This tool does not send: use gmail_send_draft, which is gated on the account's allowedRecipients list.

gmail_list_drafts

List 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_draft

Read one Gmail draft. Its output feeds directly back into gmail_update_draft.

gmail_update_draft

Replace 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_draft

Permanently delete a Gmail draft. Requires confirm: true — a deleted draft does not go to Trash and cannot be recovered.

gmail_send_draft

Send 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_files

List 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_folder

Create 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_attachment

Save 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_file

Move 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_files

Batch 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_file

Copy 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_file

Move 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_files

Batch 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_spreadsheet

Create 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_file

Read 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_filters

List Gmail filters for an account, with each filter's criteria rendered as the equivalent search query.

gmail_create_filter

Create 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_filter

Delete 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_filter

Apply 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_feeds

List 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_events

Read 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_labels

List Gmail labels for an account.

gmail_apply_labels

Add 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_label

Create a Gmail label. Nest it by using a path name such as "Clients/Acme".

gmail_update_label

Rename 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_label

Delete 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.

// environment variables
To run this server yourself, you supply these values. They go in your own MCP client configuration and stay on your machine. The secret label means the value is sensitive, not that the server mishandles it.
configGOOGLE_CLIENT_ID
🔐 secretGOOGLE_CLIENT_SECRET
configGOOGLE_OAUTH_CREDENTIALS_FILE
configOCTOMAIL_ACCOUNTS_FILE
configOCTOMAIL_DOWNLOAD_DIR(default ~/.octomail/attachments/<account>/) at
configOCTOMAIL_TOKEN_DIR
// quality suggestions

Tool 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.

// full audit trail
The findings above are the summary. The full trail, every check we ran, each deduction, the network hosts observed and the dependency advisories, goes to verified publishers, along with an alert whenever a new one lands. Verified publishers can also review each finding and dispute it in one click. Publisher corrections have sharpened several of our checks this month, because the maintainer knows the codebase better than any scanner.
// improvement guidance — verified publishers only
We have 6 concrete improvements we can share with the publisher of this MCP. Each comes with specific guidance to raise the trust score.
// embed badge in your README
[![M8ven Verified](https://m8ven.ai/badge/mcp/zerostorypoints/octomail-mcp?variant=verified)](https://m8ven.ai/mcp/zerostorypoints/octomail-mcp)
Shows verification status without the grade. Want the grade badge instead? Remove ?variant=verified from the URL.
commit: f1389fbddc8d2620d275c707bd85298e2c47e069
code hash: ee169098c999593209e372e764147d5a664096305a99ad3469c6a1e5681ca764
view raw JSON →
Check MCPs from inside your assistant
Tool Check · MCP

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
check_toolsearch_toolscompare_toolsrecommend_alternativescheck_publisherreport_concern
How to add it →Free · no account needed · works in any MCP client