mailmcp
mailmcp gives an AI assistant read, search, draft, send, and organize access to several email mailboxes at once (IMAP/SMTP or Microsoft Graph), with permissions gated per mailbox and per token.
Accounts & folders: list mailboxes (
list_accounts, withplan,backend,reauth_by, optional connection check) and folders/labels with message and unseen counts.Search:
search_messagesacross one account or all (account="all"), Gmail syntax on Gmail plus structured filters (from, to, subject, since/before, unseen, flagged, has_attachment); ChatGPT-compatiblesearch+fetch.Read:
get_message(sanitized, truncated body + attachments) andget_threadfor a conversation.Attachments in:
get_attachmentas text/binary or one-hour download link, optionally saved to disk.Drafting:
create_draft,reply_draft, templates, andset_signature/get_signature.Sending:
send_message,reply_send,send_draft,forward_message— only if sending is enabled and every recipient is on the allowlist; drafts are the safe default.Attachments out:
upload_attachment(inline/base64) orrequest_upload(one-hour upload link), then attach to drafts or sends;list_uploadsshows pending files.Organizing:
modify_message(read/unread, star, Gmail labels, Outlook categories, move, archive) andtrash_message(never permanent deletion).Outlook / Microsoft 365 via Graph (string message ids, categories, ~90-day reauth) alongside IMAP/SMTP providers.
Guardrails: every tool needs the matching token permission (read, draft, send, modify, delete), plus verification-email protection levels and per-token UI panels.
Provides access to Gmail mailboxes over IMAP/SMTP, including searching messages, reading threads, downloading attachments, creating drafts, and sending email with an app password.
Provides access to iCloud mailboxes over IMAP/SMTP, allowing the assistant to search, read, draft, send, and manage messages and attachments.
Provides access to Zoho mailboxes over IMAP/SMTP, enabling message search, reading, drafting, sending, and attachment handling.
mailmcp is a self-hosted MCP server that gives ChatGPT, Claude and other MCP clients access to your e-mail over IMAP and SMTP: several mailboxes at once, any provider, attachments in both directions. This repository is the prebuilt distribution (minified bundles in dist/, no build step) under a commercial licence; it runs as a free tier without a key. The source code is not provided.
Ask "What came in from accounting this week?" and get one answer across Gmail, iCloud and the company mail server: the invoice as a download link, a reply already drafted.
When to use it
Use mailmcp when you have more than one mailbox, a provider without an official connector, or you need attachments. As of September 2026 the official Gmail and Outlook connectors in ChatGPT and Claude handle one mailbox each and cannot send attachments.
Official connectors | mailmcp | |
Mailboxes | one per connector | several at once, one token |
Providers | Gmail, Outlook | Gmail, Outlook.com, Microsoft 365, iCloud, Fastmail, Yahoo, Zoho, Seznam.cz and any IMAP/SMTP server with password sign-in, including your own domain |
Attachments | read some, send none | one-hour download links; sending from the mailbox, from a file the assistant uploads, or by forwarding |
Authentication | OAuth grant held by the AI vendor | an app password, encrypted in your browser into a token; the server keeps one master key and no database |
Hosting | the vendor's | yours: Vercel, Docker, any Node 22 host, or Claude Desktop without a server |
Cost | included in the assistant's plan | free with a signature in sent mail, or one payment (€19 / €149) |
Related MCP server: IMAP MCP
Quickstart
Requirements. Node 22 (or Vercel, or Docker), an HTTPS address (ChatGPT and Claude only connect over HTTPS), and an app password for each mailbox. Gmail: turn on 2-Step Verification first, otherwise Google hides the app-passwords page (organisation policies or Advanced Protection can hide it too). Outlook.com and Microsoft 365 need no password: the user signs in at Microsoft on the setup page (see "Outlook and Microsoft 365" below).
Set an invite code. A server that issues user tokens must say who may create one, otherwise anyone who knows the address can spend your quota. Pick
MAILMCP_INVITE_CODE(at least 8 characters) and hand it to the people who may create a token; without it the server issues no tokens and the setup page shows a notice for you. Forgot the code? Read it in your Vercel or Docker environment, or set a new one and redeploy: tokens already issued keep working. A deliberately public server setsMAILMCP_OPEN_SIGNUP=1instead.Deploy. Click the Vercel button above; it asks for
MAILMCP_KEY(32 random bytes as base64url,node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"),MAILMCP_LICENSE(your key, or empty for the free tier) and the invite code from step 1. Or run it yourself:docker build -t mailmcp . && docker run -d -p 8080:8080 \ -e MAILMCP_KEY=… -e MAILMCP_LICENSE=… -e MAILMCP_INVITE_CODE=… \ -e MAILMCP_PUBLIC_URL=https://mail.example.com mailmcp # without Docker: node dist/node.js with the same variablesOpen
https://<your-server>/startand follow it: on the setup page pick the provider, paste the e-mail and the app password, tick what the assistant may do (reading is on by default; drafts are a good second step; sending only with an allowlist of recipients). The page encrypts the password in your browser and hands you one token.Connect. ChatGPT → Settings → Apps → Create → URL
https://<your-server>/mcp; claude.ai → Settings → Connectors → Add custom connector. Sign in with the token. Then ask: "List my mail accounts."
Try it without deploying. The shared server at mailmcp.ai/setup runs this same code; create a token there and connect. The operator of any shared server can technically see your configuration while it serves your requests, which is why companies run their own.
Claude Desktop, no server. Download mailmcp.mcpb from the latest release, open it in Claude Desktop, paste the configuration from /setup → "Values for your own deployment".
Behind a reverse proxy set MAILMCP_PUBLIC_URL or MAILMCP_TRUST_PROXY=1. Company mail servers on private addresses need MAILMCP_ALLOW_PRIVATE_MAIL_HOSTS=1. Changing MAILMCP_KEY invalidates every token. All variables: .env.example.
Variable | What it does |
| The one master key; seals user tokens and signs OAuth artifacts. Changing it invalidates every token. |
| Your licence key. Empty runs the free tier. |
| Required on a token-issuing server: the code your users type on |
|
|
| Your own Entra app registration id for the Microsoft sign-in. Required for any Microsoft sign-in on your server (the vendor's app is used on mailmcp.ai only). |
|
|
|
|
|
|
| stdio only: folders (separated by |
|
|
| Server copies: |
|
|
|
|
| The public address, when the server is behind your own reverse proxy. |
|
|
Outlook and Microsoft 365
These mailboxes have no password: Microsoft rejects password sign-in on most accounts. The user picks the provider Outlook / Microsoft 365 on /setup and clicks Sign in with Microsoft. This needs your own Entra app registration (MAILMCP_MS_CLIENT_ID, steps below); without it the setup page offers no Microsoft sign-in. When your server's origin is a registered redirect URI (MAILMCP_MS_REDIRECT=1) the button opens a popup with the account picker; otherwise the page asks whether the user signs in with a personal account (Outlook.com, Hotmail) or a work or school account (Microsoft 365) and shows a short code to type at microsoft.com/link or login.microsoft.com/device respectively. Either way the sign-in sits behind your invite code (the device-code relay requires one even with MAILMCP_OPEN_SIGNUP=1), and your users see your app's name on the consent screen. No token reaches the vendor: your server runs the sign-in.
What to tell your users: at most three Outlook mailboxes per token; the consented Microsoft permissions follow the capabilities they tick (Mail.Read for read-only, otherwise Mail.ReadWrite and Mail.Send), so widening them later needs a new sign-in; a sign-in lasts about 90 days (the date is on /setup and in list_accounts as reauth_by, and clients that refresh through our OAuth have it rolled automatically); changing the mailbox password does not end it, revoking the app at Microsoft does, for every token that used that account. Tenants that leave consent to administrators need a one-off approval at https://login.microsoftonline.com/organizations/adminconsent?client_id=<your client id>. Mail then flows over Microsoft Graph, so message ids are strings rather than numbers and labels are Outlook categories. Full guide: mailmcp.ai/docs.
Your own Microsoft app registration
Microsoft sign-in on your server needs an app registration of your own (the vendor's registration is used on mailmcp.ai only). Register it and use the popup flow, which works for personal and work accounts alike; new Microsoft 365 tenants block sign-in with a code (security defaults, AADSTS530035):
Microsoft Entra → App registrations → New registration; supported account types: Accounts in any organizational directory and personal Microsoft accounts.
Authentication → add the platform Mobile and desktop applications (not Web) with the redirect URI
https://<your host>/api/ms/callback. mailmcp is a public client with no secret; under the Web platform Microsoft demands one and the sign-in fails with AADSTS7000218.Authentication → Allow public client flows: Yes.
API permissions → delegated Microsoft Graph
Mail.Read,Mail.ReadWrite,Mail.Send,User.Read,offline_access.Set
MAILMCP_MS_CLIENT_ID=<Application (client) ID>andMAILMCP_MS_REDIRECT=1, redeploy.
Tenants that allow user consent only for verified publishers additionally need publisher verification on your registration (Microsoft AI Cloud Partner Program), or an admin's consent for the whole tenant.
What the assistant can do
Every tool is gated by the permissions in the token, per mailbox:
Permission | Tools |
read (default) |
|
draft |
|
send |
|
modify |
|
delete |
|
Each mailbox also has a protection level for verification emails (Off, Basic, Standard, Strict, Custom; new mailboxes start at Standard): hidden mail stays out of every answer, and from Standard up codes and sign-in links in other mail are removed. It catches typical verification emails, not every possible one. Where your app supports MCP Apps, triage, digest, the draft tools and bulk_preview also show a clickable panel; switch the panels off per token on the setup page (or MAILMCP_UI=off over stdio).
Every tool is listed to the client; a call the token does not permit fails with an error naming the missing permission.
Security and data flow
Credentials. The setup page encrypts mailbox passwords in your browser into a split-key token. The server holds one master key, decrypts the configuration only while serving your request, keeps it in memory for at most 15 minutes after the last one, and has no database and no copy of your mail.
What leaves the server. IMAP/SMTP traffic to your mail provider and tool results to your assistant (so the AI vendor sees the results of every tool call, never the passwords). Licence verification is offline. The only request to the vendor is the daily update check with the usage statistics described below, and the Buy buttons link to the vendor.
Prompt injection. Message bodies are marked as untrusted data, hidden text is stripped and header fields are sanitized, which reduces the risk of instructions planted in an e-mail; it cannot make a model immune.
Protocol. OAuth 2.1 with PKCE, dynamic client registration and client metadata documents, encrypted tokens with replay guards, login throttling. Read-only defaults, send allowlists, no permanent deletion.
Revocation. Delete the app password at your provider; the token is then useless no matter who holds it. Outlook mailboxes carry a Microsoft refresh token instead of a password: revoke the app at account.live.com/consent/Manage or in My Apps for work accounts. Rotating
MAILMCP_KEYinvalidates all tokens on a server.Review. An internal, AI-assisted security review of version 0.4.1 (September 2026) with every finding, fix and accepted trade-off is public: mailmcp.ai/audit.
Usage statistics
Once a day (at most) every copy asks mailmcp.ai whether a newer version exists; Claude Desktop asks at each start. Server copies (Vercel production, Docker, Node) also send usage statistics with that request unless you switch them off; Claude Desktop and other desktop (stdio) copies send them only if you turn them on, and at most once a day however often they start. The whole body is:
{"s":1,"v":"0.13","r":"docker","d":"…"}s is the schema, v the version as major.minor, r the runtime (vercel, docker, node, claude-desktop or stdio), and d a number that stays the same for one calendar month, computed from values that never leave your server (the Vercel project id, elsewhere the machine id or a random salt the copy writes once to ~/.mailmcp/stats-salt, mixed with MAILMCP_KEY when it is set; ~/.mailmcp/stats-sent-* holds the day of each instance's last ping). No licence key, configuration, address, mailbox or content is sent. mailmcp.ai keeps only daily and monthly counts per version and per runtime; from what it stores it cannot tell which installation sent a request. Our host Vercel logs the IP address of every request for 1 day, as for any website; our code never stores it. Vercel preview deployments send only the update check; CI runs and builds from source send nothing. Every copy logs one line at start saying whether statistics are ON or OFF.
Switches (1, true, yes or on): MAILMCP_NO_STATS=1 or MAILMCP_STATS=0 (statistics off, the update check stays), MAILMCP_NO_UPDATE_CHECK=1 (no request at all), DO_NOT_TRACK=1 (statistics off). In Claude Desktop: the extension settings “Anonymous usage statistics” (off by default) and “Check for updates” (unticked, nothing is sent). Everything collected and the totals are public at mailmcp.ai/stats.
Pricing
Free | Personal, €19 once | Unlimited, €149 once |
All tools included, up to 2 mailboxes in total per person (the server checks 2 per token; tokens created before 0.7.0 keep 5). Every message the assistant composes (drafts, sends, forwards) ends with "Sent with mailmcp.ai". | One user, up to 5 mailboxes in total whoever owns them, no signature, on your own server or in Claude Desktop. | One server for one organization (a company or a sole trader and its employees), unlimited users and mailboxes. |
All 0.x updates are included; a 1.0 upgrade may carry a fee, and 0.x keeps working. 14-day refund, no questions asked. Company deployment, €990: two hours of online onboarding on your Vercel or cloud, Unlimited licence included. Buy at mailmcp.ai/pricing: the key appears right after payment and Stripe e-mails the invoice.
Updating
Upgrading to 0.8. Token-mode servers now need MAILMCP_INVITE_CODE (at least 8 characters), or MAILMCP_OPEN_SIGNUP=1 for a deliberately public server. Set one of the two before you deploy 0.8 (Vercel: Settings → Environment Variables → Production, then redeploy), otherwise /setup stops issuing tokens and shows a notice for you. Tokens already issued keep working either way; the full list is in CHANGELOG.md under 0.8.0. 0.8 also adds Outlook and Microsoft 365 mailboxes through a Microsoft sign-in; nothing has to be configured for that unless you want your own Entra registration or the kill switches above.
Upgrading to 0.13. Nothing has to be configured. Server copies now send the daily usage statistics described above unless you set MAILMCP_NO_STATS=1. Existing tokens keep protection Off until you pick a level on the setup page and replace the token in every assistant. In ChatGPT, refresh the connector (Settings → Connectors → mailmcp → Refresh) to see the new tools; in Claude Desktop, install the new mailmcp.mcpb. IMAP servers that support neither MOVE nor UIDPLUS now refuse moves instead of risking other messages. The full list is in CHANGELOG.md under 0.13.0.
Releases are tagged here and listed in CHANGELOG.md. If you deployed with the Vercel button, Vercel created your own copy of this repository: pull the new tag into it (git pull https://github.com/kojott/mailmcp-dist.git main and push), and Vercel deploys the push. Docker and Node: pull, rebuild or restart. To roll back, deploy the previous tag. Your tokens keep working across versions as long as MAILMCP_KEY stays the same.
Questions people ask
Google says the app-passwords setting "is not available for your account". Turn on 2-Step Verification and reload; if it is still missing, an organisation policy or Advanced Protection is blocking app passwords.
I lost my token. Tokens cannot be recovered. Create a new one on the setup page (with an edit password this time, so you can load and change it later) and swap it in your assistant.
Can the assistant send mail on its own? Only if you enabled sending, and only to addresses on the allowlist. Drafts are the safer default.
Attachment links. Download and upload links are valid for one hour and carry the token in encrypted form; anyone with the link can use it during that hour.
Licence, support, reporting problems
The licence agreement is in LICENSE (English translation first, the Czech original governs): one key, one running installation, no redistribution, no serving other people's mailboxes or running mailmcp as a hosted service without a separate agreement; removing the licence check or the free-tier signature is prohibited. This is closed-source software, so pull requests are not accepted, but bug reports in Issues are welcome. Security problems: write to info@swingingdogs.com instead of opening an issue. Privacy policy: https://mailmcp.ai/privacy, terms: https://mailmcp.ai/terms.
Guide for people: mailmcp.ai/docs. Guide for assistants, paste the link into ChatGPT or Claude and let it walk you through: mailmcp.ai/llms.txt. Support: jiridolejs.cz/kontakt.
Version 0.13.12. Made in Prague by Jiří Dolejš.
Available Tools
33 toolsawaiting_repliesFind sent mail still waiting for a replyARead-onlyIdempotentInspect
Lists threads where the owner wrote last: their newest message is older than older_than_days and no reply from someone else was found. Each item says whether the scan proved no reply (no_reply_found) or not (unknown). Needs read; every plan.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Default 30 | |
| account | Yes | Account id, or "all" | |
| exclude | No | Addresses or @domains to leave out | |
| within_days | No | Default 30 | |
| older_than_days | No | Default 3 |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | Yes | |
| accounts | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already say readOnly, idempotent, openWorld, and non-destructive, so the behavioral bar is lower. The description adds meaningful context beyond annotations: it discloses the auth/plan requirement and explains that items distinguish proved no-reply from unknown. It does not cover pagination, rate limits, or broader operational caveats, so 4 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three tight sentences, front-loading the filtering rule before the output status and auth requirement. Every clause earns its place by adding selection criteria or invocation context. There is no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists, the description need not explain return values, and the annotations cover safety. It provides the core filtering semantics, the unknown/no_reply_found caveat, and auth/plan requirements, which is nearly complete for a list-style tool. It leaves within_days semantics and some parameter interactions to the schema, so 4 rather than 5.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all five parameters. The description adds real semantic value for older_than_days by defining it as the threshold for the owner's newest message being too old, but it does not clarify within_days, limit, account, or exclude beyond the schema. That is enough for a 4 but not a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a precise verb and resource: it lists threads where the owner wrote last and no reply exists. The criteria, including older_than_days and the no_reply_found/unknown distinction, make the tool's purpose clear. It does not explicitly name a sibling such as list_followups, so it gets a 4 rather than 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives the core condition for use: sent mail waiting for a reply based on owner-last-written threads and older_than_days. It does not state when to prefer this over list_followups, search_messages, or triage, nor does it state when not to use it. The prerequisite wording 'Needs read; every plan' helps, but usage guidance remains implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bulk_applyApply a previewed bulk actionADestructiveIdempotentInspect
Applies exactly the batch a bulk_preview sealed (fewer if some changed; never more), after the owner agreed. Never deletes permanently; a repeated confirm changes nothing. Needs read and modify (trash: delete); 50 per call on Free, 500 paid.
| Name | Required | Description | Default |
|---|---|---|---|
| undo | No | Undo the batch (paid, 7 days) | |
| batch | No | Batch id from bulk_apply | |
| count | No | will_process | |
| action | No | ||
| account | Yes | ||
| confirm | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations by disclosing the bounded behavior ('fewer if some changed; never more'), the required scopes ('read and modify (trash: delete)'), and per-call limits ('50 Free, 500 paid'). These are exactly the operational facts the annotations (destructive/idempotent hints) do not carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Densely front-loaded: the core action leads, followed by bounded-scope, safety, auth, and quota clauses. Every sentence carries a distinct constraint with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be described. It covers safety, idempotency, auth, and quota well; the only slight gap is the undo path, which relies on the schema description.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
At 50% schema coverage the description should compensate, and it clarifies the batch's origin and the trash scope, but leaves the meaning of count, confirm, and undo to the schema. Adds marginal value, so baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Applies) and resource (the batch a bulk_preview sealed), and implicitly contrasts itself with the sibling bulk_preview. An agent can immediately tell this commits what preview proposed.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The workflow is clear: it must follow a bulk_preview and 'after the owner agreed,' which conveys the required precondition. It does not explicitly state when-not to use it or name alternatives beyond the preview relationship, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bulk_previewPreview a bulk actionARead-onlyIdempotentInspect
Selects the exact messages a bulk action would act on (explicit uids or criteria, oldest first) and returns a count, senders, a sample and a confirm ref for bulk_apply. Changes nothing. Show the preview to the owner. Needs read and modify (trash: delete); 50 per call on Free, 500 paid.
| Name | Required | Description | Default |
|---|---|---|---|
| uids | No | Explicit messages, all in `folder` | |
| batch | No | Batch id from bulk_apply | |
| label | No | action=label: label or category | |
| action | No | ||
| folder | No | Source folder; default INBOX | |
| account | Yes | list_accounts id | |
| criteria | No | ||
| scan_from | No | Continues an earlier preview's scan | |
| to_folder | No | action=move | |
| create_folder | No | action=move: bulk_apply creates to_folder if it does not exist |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | |
| plan | No | |
| batch | No | |
| count | No | |
| confirm | No | |
| will_process | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnly/idempotent/non-destructive, and the description pays for itself with details annotations cannot carry: the required auth scopes (read + modify, delete for trash) and the per-call caps (50 on Free, 500 paid). It also confirms 'Changes nothing', which is consistent with readOnlyHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Six tight sentences, front-loaded with what it selects and what it returns, then safety, then procedure, then constraints. No filler and nothing repeated from the annotations or schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 10-parameter, nested-criteria preview tool with an output schema, the description covers selection mode, ordering, return contents, safety, scopes and quotas — everything needed to call it correctly. Anything omitted (e.g. scan_from continuation, batch reuse) is already documented in the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 80%, so the baseline is 3, but the description adds semantics not in the schema: the two selection modes (uids vs criteria) and the ordering guarantee ('oldest first'). That ordering detail is meaningful behavior an agent could not infer from the parameter list alone. The uids/criteria mutual exclusivity is only implied, not stated.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — selecting the exact messages a bulk action would act on — and pins the selection semantics (explicit uids or criteria, oldest first). It also distinguishes itself from the sibling it feeds by stating it returns a confirm ref for bulk_apply, so an agent can tell bulk_preview and bulk_apply apart without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives real operating context: 'Changes nothing. Show the preview to the owner' and a required scope (read and modify, delete for trash). The confirm-ref clause implicitly routes to bulk_apply. It stops short of an explicit when-not-to-use or a direct contrast with search_messages, so it is clear context rather than full routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_draftCreate draftAInspect
Saves a draft in the account's Drafts folder. Nothing is sent; the owner reviews and sends it (or asks you to send_draft). Attachments: mailbox attachments, files from upload_attachment/request_upload, or inline content. The preferred way to prepare replies.
| Name | Required | Description | Default |
|---|---|---|---|
| cc | No | ||
| to | Yes | Recipient addresses | |
| bcc | No | ||
| html | No | Optional HTML (scripts stripped) | |
| text | No | Plain-text body | |
| vars | No | Values for its {{placeholders}} | |
| quote | No | Quote the original (default true when replying) | |
| account | Yes | list_accounts id | |
| subject | No | ||
| template | No | list_templates name (paid) | |
| attachments | No | ||
| in_reply_to_uid | No | uid being answered; prefer reply_draft / reply_send | |
| in_reply_to_folder | No | Default: Gmail All Mail, else INBOX |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare a non-destructive write, but the description adds the crucial nuance that nothing is transmitted until the owner reviews and sends it, plus the permitted attachment sources. This is meaningful behavioral context beyond the annotations, though it omits any note on return values or permission/scope requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, all front-loaded and each earning its place: purpose, send behavior, attachment sourcing, reply preference. No filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 13-parameter write tool with no output schema, the description covers purpose, non-sending behavior, attachment sources, and reply intent adequately. It could say more about the account requirement and reply-context parameters, but nothing critical to a correct call is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 69% schema coverage and nested attachment objects, the schema carries most of the burden. The description adds the tool names that feed attachments (upload_attachment/request_upload) but says nothing about the reply parameters (in_reply_to_uid, quote, vars) or how they interact, so it only marginally extends the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource with location ("Saves a draft in the account's Drafts folder") and immediately distinguishes the outcome from its siblings ("Nothing is sent... or asks you to send_draft"). An agent can tell this apart from send_draft and reply_draft without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context ("The preferred way to prepare replies") and names the alternative for sending (send_draft). It does not, however, address when to prefer reply_draft/reply_send for replies, so the routing is only partially complete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
digestDigest since the last runARead-onlyIdempotentInspect
Read-only summary for scheduled runs: reply candidates, calendar, lists, automated mail, threads waiting on others, follow-ups and snoozes due since the cursor. Pass the returned cursor back next time; without one it covers 24 hours. Reports coverage per account. Needs read; every plan.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Items per bucket, default 25 | |
| cursor | No | From the previous digest; or an ISO date-time | |
| folder | No | Default: INBOX (Outlook: Inbox) | |
| account | No | Default "all" |
Output Schema
| Name | Required | Description |
|---|---|---|
| cursor | Yes | |
| triage | Yes | |
| accounts | Yes | |
| awaiting | Yes | |
| snoozes_due | Yes | |
| followups_due | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint. The description adds behavior beyond them: cursor chaining semantics, the 24-hour default window when no cursor is supplied, and the authorization/plan requirement ('Needs read; every plan') — useful operational context that annotations do not carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four compact sentences, front-loaded with the purpose and scope before the cursor mechanics. Every clause carries information; slight density of 'Needs read; every plan' and 'Reports coverage per account' reads as terse notes rather than flowing prose, but nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the description covers the remaining gaps an agent needs: scope, cursor lifecycle, default window, per-account coverage reporting, and auth requirements. Nothing required to invoke or chain the tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description earns an extra point by explaining cursor pass-back behavior and the no-cursor fallback ('without one it covers 24 hours'), which clarifies the cursor parameter beyond 'From the previous digest; or an ISO date-time'. It adds nothing for limit/folder/account, which the schema already documents.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb+resource ('Read-only summary for scheduled runs') and enumerates the exact buckets it covers (reply candidates, calendar, lists, automated mail, threads waiting on others, follow-ups, snoozes). It does not explicitly position itself against overlapping siblings such as awaiting_replies or list_followups, which cover some of the same ground, so an agent must infer the distinction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states the usage context clearly ('for scheduled runs') and gives operational guidance on the cursor: pass the returned cursor back next time, otherwise it covers 24 hours. It also states the access requirement ('Needs read; every plan'). No explicit when-not-to-use or sibling alternative is named, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetchFetch document (ChatGPT-compatible)ARead-onlyIdempotentInspect
Returns the full sanitized text of one email by the id returned from search.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Document id from search |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint, so the safety profile is covered. The description adds one genuinely useful trait beyond them — the returned text is 'sanitized' and 'full' — but says nothing about truncation, size limits, or failure modes when the id is stale or invalid.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with the return value and ending with the input constraint. Nothing is redundant or padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 1-parameter read tool with rich annotations and no output schema, this is minimally sufficient. But with close siblings like get_message, get_thread, and get_attachment, the absence of any statement about how this differs is a real completeness gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single id parameter is already documented as 'Document id from search'. The description restates the same origin of the id without adding format, validation, or scope details, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: returns the full sanitized text of one email, identified by an id. It also scopes the input source ('by the id returned from `search`'). However, it never distinguishes itself from the sibling get_message, which an agent would reasonably assume does the same thing.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: the mention that the id comes from `search` tells the agent this is a follow-up call after a search. There is no explicit when-to-use/when-not guidance and no mention of when get_message or get_thread would be preferred instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
forward_messageForward a messageADestructiveInspect
Forwards a message with all its attachments, without the files passing through the chat; the comment goes above it. Recipients must match send_allowlist; with as_draft the forward is saved to Drafts instead.
| Name | Required | Description | Default |
|---|---|---|---|
| cc | No | ||
| to | Yes | ||
| bcc | No | ||
| uid | Yes | uid from search_messages | |
| folder | No | Default: Gmail All Mail, else INBOX | |
| account | Yes | list_accounts id | |
| comment | No | Text above the forward | |
| subject | No | Defaults to "Fwd: <original subject>" | |
| as_draft | No | Save to Drafts instead of sending | |
| include_attachments | No | Default true |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds real context beyond the annotations: attachments bypass the chat, the comment is placed above the forward, and recipients are constrained by send_allowlist. This is meaningful behavioral disclosure for a destructive/openWorld tool, though reversibility and failure modes are not addressed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight clauses with zero filler, and the core action plus its distinguishing trait (attachments not passing through the chat) is front-loaded before the constraints.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the salient behaviors for a 10-parameter send tool and annotations carry the safety profile, but with no output schema and 30% of parameters undocumented, an agent gets no help on recipient limits or the folder default.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
At 70% schema description coverage the schema already documents comment, as_draft, subject, folder, and include_attachments. The description mostly restates comment placement and as_draft rather than extending them, and says nothing about the cc/bcc/to recipient arrays or their 50-item cap. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (forwards) and resource (a message) plus its full payload (all its attachments). 'Forward' is clearly distinct from the send_message/reply_send/create_draft siblings, so an agent can route to it without opening another schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a hard precondition ('Recipients must match send_allowlist') and explains the as_draft variant, but never states when to prefer this tool over reply_send, send_message, or create_draft. Usage is implied by the verb rather than explicitly framed as a routing decision.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_attachmentGet attachmentAInspect
Downloads one attachment (max 2097152 bytes into the conversation; with save_to up to 26214400 bytes to disk). Text-like types and PDFs with a text layer are returned as text, others as embedded binary. Pass save_to with a directory inside policy.attachment_dirs to write the file to disk instead; the result names the path.
| Name | Required | Description | Default |
|---|---|---|---|
| uid | Yes | uid from search_messages | |
| part | Yes | part id from get_message | |
| folder | No | Default: Gmail All Mail, else INBOX | |
| inline | No | Embed the bytes instead of a link | |
| account | Yes | list_accounts id | |
| save_to | No | stdio: folder in policy.attachment_dirs; returns the path |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With readOnlyHint=false conveying the write aspect, the description still adds rich detail beyond annotations: exact size ceilings (2097152 in-chat, 26214400 to disk), content-type handling (text-like/PDF-with-text-layer vs embedded binary), the policy.attachment_dirs constraint, and that the result names the written path. This is substantive behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then dense but purposeful clauses on limits, format, and save behavior. Every sentence carries information, though the size figures and mode switching make it slightly dense to parse in one pass.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description carries the return-shape burden, and it does so by saying text-like/PDF return as text, others as binary, and save_to names the path. That covers the essentials; finer details like inline/link behavior in the result are left to the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real meaning for save_to (must be inside policy.attachment_dirs; result returns the path) and clarifies the size interaction between the two modes. It goes beyond the schema on the most consequential parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Downloads one attachment'. An agent can tell what it does unambiguously. However, it never names or contrasts with siblings (e.g., get_message for part ids, upload_attachment as the inverse), so it stops short of full sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explains the two modes clearly: default in-conversation retrieval vs. 'Pass save_to ... to write the file to disk instead'. The triggering condition for save_to is stated. It doesn't name alternative tools or exclusions, but the when-to-use context is strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_messageRead a messageARead-onlyIdempotentInspect
Returns headers, sanitized text body and the attachment list of one message. Body is truncated to the configured limit.
| Name | Required | Description | Default |
|---|---|---|---|
| uid | Yes | uid from search_messages | |
| folder | No | Default: Gmail All Mail, else INBOX | |
| account | Yes | list_accounts id | |
| max_chars | No | ||
| include_quoted | No | Keep quoted replies (default false) |
Output Schema
| Name | Required | Description |
|---|---|---|
| uid | Yes | |
| text | Yes | |
| folder | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint, so the safety profile is covered. The description adds genuinely useful behavior not in annotations: the body is sanitized and truncated to a configured limit, and an attachment list is returned, telling the agent to expect possibly incomplete content.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with the payload description front-loaded and the truncation caveat immediately after; no filler, no repetition of schema fields.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the description still sketches the payload plus the truncation behavior. The main omission is how to retrieve untruncated body content or which folder the read defaults to in non-Gmail accounts, which the schema only partially covers.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 80%, so uid, folder, account, and include_quoted are already documented in the schema (max_chars is not). The description's only parameter-relevant contribution is the implicit link between truncation and max_chars; it adds no syntax, defaults, or range detail beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete verb and resource ('Returns headers, sanitized text body and the attachment list of one message'), which is specific enough to separate it from get_thread and get_attachment by payload shape. It does not, however, explicitly name the sibling tools it is distinct from.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'of one message' implicitly scopes usage to single-message reads, and the required uid parameter (documented in the schema as 'uid from search_messages') implies the search-then-fetch flow. But there is no explicit when-to-use or when-to-prefer-get_thread/get_attachment guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_signatureShow the mailbox signatureARead-onlyIdempotentInspect
Returns the signature mailmcp appends under replies: the newest message in "mailmcp-signature" (HTML, inline images) when the account uses it, else the plain-text signature from the token.
| Name | Required | Description | Default |
|---|---|---|---|
| account | Yes | list_accounts id |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, and openWorld, so the safety profile is covered. The description adds real behavioral context beyond that: the two-tier resolution logic (folder message first, token fallback) and the returned content shape (HTML with inline images vs plain text). It stops short of saying what happens when no signature exists at all.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence that leads with the verb and resource, then qualifies the resolution path. The quoted folder name and parenthetical format note are dense but each earns its place; there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description correctly carries the burden of describing the return value, and it does so in detail (source folder, HTML vs plain text, inline images). The only real gap is behavior when neither signature source exists, which an agent would want to know.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the sole parameter (account) is documented in the schema as a "list_accounts id". The description adds nothing about the parameter — e.g. that it selects which account's signature is resolved — so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ("Returns") and resource (the signature appended under replies), and goes further by explaining where the value comes from — the newest message in the "mailmcp-signature" folder or the plain-text token fallback. It implicitly contrasts with the write-side set_signature but never names it, so sibling differentiation is left to inference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains what the tool returns but gives no when-to-use, when-not-to-use, or alternative guidance, despite set_signature being an obvious sibling. An agent must infer that this is the read counterpart to set_signature.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_threadGet conversation threadARead-onlyIdempotentInspect
Lists the conversation of a message across folders (Gmail: All Mail; other IMAP: the folder, INBOX, Sent, Archive; Outlook: whole mailbox), oldest first. coverage says what was searched and if it was complete. A thread groups by conversation; it does not prove who replied to whom.
| Name | Required | Description | Default |
|---|---|---|---|
| uid | Yes | uid from search_messages | |
| folder | No | Default: Gmail All Mail, else INBOX | |
| account | Yes | list_accounts id | |
| include_bodies | No | Text of the newest 20 (no quotes, 60,000 chars) |
Output Schema
| Name | Required | Description |
|---|---|---|
| kind | Yes | |
| coverage | Yes | |
| messages | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, open-world, non-destructive behavior, so the safety profile is covered. The description adds real value beyond that: ordering (oldest first), provider-specific folder search scope, the meaning of the `coverage` field, and an important caveat that thread grouping 'does not prove who replied to whom'.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense sentences that are front-loaded with the core purpose, with the provider-specific parenthetical kept compact. Every sentence earns its place, though the provider enumeration adds some length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a full output schema, return values need not be re-explained, and the description still usefully flags the `coverage` field and ordering. Together with 100% schema coverage and clear annotations, the definition is complete enough for correct invocation, with the only gap being explicit alternative-tool routing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all four parameters (uid, folder, account, include_bodies) are already documented in the schema, including the default folder and body-text limits. The description adds no parameter-level syntax or constraints beyond that, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Lists') and resource ('the conversation of a message'), and specifies the folder scope per provider (Gmail All Mail, other IMAP folder/INBOX/Sent/Archive, Outlook whole mailbox). It is clearly distinguishable from get_message. However, it never names a sibling tool (e.g. get_message or search_messages) to contrast against, so it falls short of the explicit differentiation a 5 requires.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage context is implied rather than stated: the schema ties 'uid' to search_messages and the description explains which folders get searched, so an agent can infer this is the thread-expansion step after a search. But there is no explicit when-to-use/when-not guidance or mention of alternatives like get_message.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_accountsList mail accountsBRead-onlyIdempotentInspect
Lists the mailboxes: ids, addresses and permitted operations. backend "graph" is Outlook (string ids; labels are categories); reauth_by: when the owner must sign in to Microsoft again (setup page); plan: the mailmcp plan and, near expiry, how to renew. protection: verification emails hidden from you.
| Name | Required | Description | Default |
|---|---|---|---|
| check_connection | No | Also test every login (slower) |
Output Schema
| Name | Required | Description |
|---|---|---|
| accounts | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so safety is covered. The description does add genuinely useful behavioral context the annotations cannot: that 'graph' backends are Outlook with string ids and category labels, that reauth_by signals re-authentication via a setup page, and notably that 'protection' hides verification emails from the agent. That is real disclosure, though it is framed as output-field semantics rather than operation behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in the first clause, but the remainder is a dense backtick glossary whose phrasing is uneven (e.g. '`plan`: the mailmcp plan and, near expiry, how to renew'). It is compact but cryptic in places.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so the description need not have spent most of its length re-explaining return fields, and it leaves the actual gap — when to call this tool and when to enable check_connection — unfilled. Adequate but with clear gaps for a read-only listing tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for the single check_connection parameter, so the schema fully documents it ('Also test every login (slower)'). The description says nothing about this parameter and adds no syntax or timing detail, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence gives a specific verb and resource ('Lists the mailboxes: ids, addresses and permitted operations'), which is clearly distinguishable from sibling list_* tools such as list_folders or list_templates. However, it never explicitly frames itself as the accounts-level listing versus those siblings, so differentiation is inferred rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use guidance at all: nothing says when to call list_accounts, when to prefer list_folders, or when to set check_connection=true. The rest of the text is a field glossary, so the agent gets no routing help.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_foldersList folders / labelsBRead-onlyIdempotentInspect
Lists folders (Gmail: labels) with message and unseen counts. On Outlook path is an opaque id and name the hierarchy ("Projects/2026"); tools accept either as a folder.
| Name | Required | Description | Default |
|---|---|---|---|
| account | Yes | list_accounts id |
Output Schema
| Name | Required | Description |
|---|---|---|
| account | Yes | |
| folders | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint, covering the safety profile. The description adds that results carry message and unseen counts and explains the Outlook path-vs-name relationship, which is useful cross-provider context, though return-format detail is largely delegated to the output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences, front-loaded with the core purpose and followed by the one cross-provider nuance that matters. No filler, though the parenthetical Gmail/Outlook framing is slightly dense.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read tool with an output schema and full annotation coverage, the description supplies what is needed: purpose, terminology mapping, and what the results contain. Missing explicit usage guidance keeps it just short of a 5.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single input param (account) is fully documented, so baseline is 3. The description's mentions of `path` and `name` refer to folder fields used by other tools rather than this tool's inputs, so it clarifies surrounding semantics but adds nothing to the account parameter itself.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Lists folders') and adds a valuable cross-provider clarification that Gmail calls these 'labels' and includes message/unseen counts. It does not distinguish itself from any named sibling (e.g. list_accounts, search), but the purpose is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description never says when to call this versus alternatives such as search or list_accounts, nor any prerequisites. The second sentence addresses parameter semantics across tools, not usage selection, so an agent gets no routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_followupsList follow-ups and snoozed mailARead-onlyIdempotentInspect
Shows due follow-ups (optionally later ones) and snoozed messages across one or all mailboxes, including flags set in Outlook itself. Read-only; reports what it could not cover. Needs read; every plan.
| Name | Required | Description | Default |
|---|---|---|---|
| account | No | Default "all" | |
| continue | No | From an incomplete result | |
| due_before | No | Default now | |
| include_later | No | ||
| include_snoozed | No | Default true |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), so the bar is lower. The description adds genuine context beyond them: it discloses the required auth scope ('Needs read') and that the tool self-reports incomplete coverage ('reports what it could not cover'), which is unusual and useful.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three compact clauses with the resource and scope front-loaded and no filler. 'Needs read; every plan' is terse to the point of being slightly cryptic, but it still earns its place as a permission note.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description should carry more of the return-shape burden. It hints at partial results ('reports what it could not cover') but never explains the continue/pagination flow, which is material for a tool with a 4096-char cursor parameter.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 80% and the schema already documents each parameter, but the description adds behavioral meaning: 'optionally later ones' ties include_later to intent, and 'across one or all mailboxes' clarifies the account parameter's scope. It doesn't cover the continue token, which is the one real gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (lists follow-ups and snoozed messages) and scopes it to one or all mailboxes. It clearly differs from write-side siblings like set_followup and wake_snoozed, though it never names those alternatives explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when the tool applies ('due follow-ups', 'optionally later ones', 'snoozed messages'), but gives no explicit when-to-use vs. when-not guidance relative to siblings such as wake_snoozed or set_followup. Usage must be inferred from the scope clause.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_templatesList templates and writing samplesARead-onlyIdempotentInspect
Lists templates in "mailmcp-templates", or one in full by name. samples=true returns the style profile and samples of the owner's sent mail, for tone, length and language only. Needs read; every plan.
| Name | Required | Description | Default |
|---|---|---|---|
| n | No | Samples, default 5 | |
| to | No | samples: sent to this address first | |
| name | No | ||
| account | Yes | list_accounts id | |
| samples | No | ||
| continue | No | From an incomplete result | |
| max_chars | No | Per sample, default 600 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive/openWorld, so the safety profile is covered. The description adds value beyond that: it states the auth requirement ('Needs read') and scopes the samples output to 'tone, length and language only', which is useful behavioral context. It omits pagination behavior for 'continue', keeping it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences with the primary listing behavior front-loaded and no filler. The terse phrasing is efficient, though the quoted internal name 'mailmcp-templates' is unexplained and slightly opaque.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries some burden for describing what comes back; it covers templates and the samples style profile reasonably but does not explain the template structure, pagination via 'continue', or how list-mode and samples-mode relate. Adequate but with clear gaps for a 7-parameter tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 71% and the schema already documents n, to, continue, and max_chars. The description adds meaning for samples=true and for retrieving one template by name, but does not explain the other parameters beyond what the schema provides, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb (lists) plus resource (templates in 'mailmcp-templates') and a second mode ('one in full by name'), and clarifies that samples=true returns a style profile rather than templates. It does not name or contrast with any sibling such as save_template, so it stops short of 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'samples=true returns...' implies the condition for the alternate mode, and 'Needs read; every plan' hints at when it is expected to be consulted. However, there is no explicit when-not guidance and no routing to alternatives like save_template, leaving usage largely inferred.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_uploadsList uploaded filesARead-onlyIdempotentInspect
Files waiting in "mailmcp-uploads" of an account (from upload_attachment or an upload link), newest first, with the {folder, uid, part} needed to attach them.
| Name | Required | Description | Default |
|---|---|---|---|
| account | Yes | list_accounts id |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and openWorld, so the safety profile is covered. The description adds genuinely new context beyond that: the storage folder name, the ordering guarantee (newest first), and the shape of the returned identifiers used for attaching. It does not mention pagination or limits, which keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with the resource and its location, then the provenance and the return payload. No filler or redundant restatement of the tool name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description usefully sketches the returned identifiers ({folder, uid, part}) and the ordering, and annotations cover the safety profile. It leaves other return fields and any result-size limits unspecified, so it is nearly but not fully complete for a one-parameter listing tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single parameter (account, described as a "list_accounts id") is fully documented in the schema. The description only restates "of an account" without adding format or sourcing detail beyond what the schema already provides, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (list files waiting in the "mailmcp-uploads" folder of an account) and names the originating operations (upload_attachment or an upload link), which cleanly distinguishes it from siblings like upload_attachment and request_upload. It also states ordering (newest first) and the key fields returned.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes the usage context clear: this is where you look to find files that have been uploaded and are waiting, and it gives the reason to call it (to obtain the {folder, uid, part} needed to attach them). It does not explicitly name an alternative tool or state a when-not-to-use condition, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
modify_messageModify messageADestructiveIdempotentInspect
Mark read/unread, star/unstar, add/remove labels (Gmail labels, Outlook categories), move to a folder or archive. A move can change the id of the message: when the result carries moved_uid, use that id from then on.
| Name | Required | Description | Default |
|---|---|---|---|
| uid | Yes | uid from search_messages | |
| seen | No | ||
| folder | No | Default: Gmail All Mail, else INBOX | |
| account | Yes | list_accounts id | |
| archive | No | Remove from inbox (Gmail) or move to Archive | |
| flagged | No | ||
| move_to | No | Destination folder path | |
| add_labels | No | Gmail only | |
| create_folder | No | With move_to: create the folder first if it does not exist | |
| remove_labels | No | Gmail only |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true and readOnlyHint=false, so the safety profile is covered. The description adds a genuinely non-obvious behavioral trait beyond the annotations: a move can change the message id, and the moved_uid in the result must be used thereafter. It still omits permission/auth requirements and what happens when a label or folder does not exist.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero padding. The operation list is front-loaded and the id-change caveat follows immediately, which is exactly the ordering an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 10-parameter destructive mutation with no output schema, the description covers the main operation set plus the critical id-stability gotcha. Remaining gaps (create_folder interaction, failure behavior, permissions) are partly handled by the schema descriptions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 80%, so most parameters are self-documenting. The description nonetheless adds cross-provider semantics the schema lacks (Gmail labels vs Outlook categories) and clarifies the relationship between moving, archiving and folder defaults. It does not resolve the schema's 'Gmail only' wording for add_labels/remove_labels, which the Outlook mention partially contradicts.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the resource (message) and enumerates the concrete operations: mark read/unread, star/unstar, add/remove labels, move/archive. An agent can tell this is the message-mutation tool. It does not, however, distinguish itself from the sibling trash_message, so the delete-vs-move boundary is left to inference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The enumerated operations imply when the tool applies, but there is no explicit when-to-use guidance, no prerequisites, and no named alternative (e.g., trash_message for deletion, or bulk_apply for multi-message changes). Usage is inferable from the verb list rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reply_draftReply as a draftAInspect
Saves a reply to a message into Drafts, in the same thread: threading headers, "Re:" subject, recipients (sender, or all with reply_all) and the quoted original are set by the server. Use whenever the owner says "reply / write a draft" ("odpověz", "napiš koncept"). Nothing is sent.
| Name | Required | Description | Default |
|---|---|---|---|
| uid | Yes | uid being answered | |
| html | No | Optional HTML of your text (the quote is added below) | |
| lang | No | "On … wrote:" language | |
| text | No | Plain text; the original is quoted | |
| vars | No | Values for its {{placeholders}} | |
| quote | No | Quote the original (default true) | |
| folder | No | Default: Gmail All Mail, else INBOX | |
| account | Yes | list_accounts id | |
| template | No | list_templates name (paid) | |
| reply_all | No | Reply to all (default: sender only) | |
| attachments | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations mark it non-read-only, non-idempotent, non-destructive; the description adds substantive behavior beyond that by describing server-side auto-population of threading headers, 'Re:' subject, recipients, and the quoted original. It does not mention return value or resulting draft id/folder placement beyond defaults.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three compact sentences, each carrying distinct information: action, auto-populated behavior, and usage triggers plus guarantee. No filler, front-loaded with the core verb.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 11-param nested-schema mutation tool, the description covers thread mechanics and side effects well. It could note where the draft lands (folder default) or an output identifier, but annotations plus schema cover the rest adequately.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 91%, so the schema already documents parameters thoroughly (including quote default true and folder default). The description adds context on reply_all recipient behavior and server-side threading, but does not explain params like template or vars beyond what the schema states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Saves a reply... into Drafts'), the resource (a message draft in the same thread), and explicitly distinguishes from send operations with 'Nothing is sent.' Differentiates from create_draft/reply_send siblings by anchoring the reply to an existing message thread.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives trigger phrasing for the owner ('reply / write a draft', plus Czech synonyms) which is unusually actionable. Does not contrast against create_draft or reply_send directly, so the when-not condition is only implied by 'Nothing is sent.'
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reply_sendReply and sendADestructiveInspect
Sends a reply to a message in the same thread (threading headers, "Re:" subject, recipients and the quoted original are set by the server). Only when the owner enabled sending AND every recipient matches send_allowlist; otherwise use reply_draft. Only when the owner says "send" ("pošli", "odešli").
| Name | Required | Description | Default |
|---|---|---|---|
| uid | Yes | uid being answered | |
| html | No | Optional HTML of your text (the quote is added below) | |
| lang | No | "On … wrote:" language | |
| text | Yes | Plain text; the original is quoted | |
| quote | No | Quote the original (default true) | |
| folder | No | Default: Gmail All Mail, else INBOX | |
| account | Yes | list_accounts id | |
| reply_all | No | Reply to all (default: sender only) | |
| attachments | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true and openWorldHint=true, and the description adds real value beyond them: threading headers, 'Re:' subject, recipients and quoted original are set server-side, plus the two gating conditions that determine whether the call is allowed at all. It stops short of stating irreversibility or what happens on allowlist failure, so not a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense sentences, front-loaded with the action, then the gating rules, then the consent trigger. Each sentence earns its place, though the final 'Only when the owner says "send"' fragment is terse enough to read as a tag rather than a complete rule.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 9-parameter mutation tool with no output schema, the description covers the action, the alternates, the authorization gates and the server-derived fields an agent would otherwise try to set. Nothing essential to calling it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 89%, so the schema already carries most parameter meaning (baseline 3). The description adds non-schema context by stating that recipients, subject and quote are populated by the server, telling the agent there is no recipient/subject parameter to supply. It does not clarify reply_all vs. sender-only beyond what the schema says.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb+resource ('Sends a reply to a message in the same thread') and immediately distinguishes itself from the sibling reply_draft by describing the server-side threading behavior. An agent can tell it apart from send_message and reply_draft without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit preconditions for use (owner enabled sending AND all recipients match send_allowlist) and names the fallback tool ('otherwise use reply_draft'). It also encodes the consent condition (owner must say 'send'). Nothing about when-to-use is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
request_uploadGet an upload linkAInspect
Returns a one-hour HTTPS upload link: PUT/POST a file to it (curl -T file , or open it in a browser); the file lands in "mailmcp-uploads" and appears in list_uploads. Anyone with the link can upload. Upload it yourself if you can run commands; otherwise give the link to the user.
| Name | Required | Description | Default |
|---|---|---|---|
| account | Yes | list_accounts id |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover safety (readOnly=false, destructive=false), and the description adds real behavioral context beyond them: the link expires in one hour, anyone holding it can upload, and the resulting file surfaces in list_uploads. That is valuable operational detail the annotations don't carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One dense paragraph, front-loaded with what is returned, followed by invocation mechanics and the routing decision. Every clause carries information; nothing is padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema is needed because the description already explains the return value (a one-hour URL), how to consume it, and the side effect (file appears in list_uploads). For a one-parameter tool this is fully sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With a single parameter and 100% schema description coverage, the schema already explains 'account' as the list_accounts id. The description adds no further parameter meaning, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific resource and outcome: returns a one-hour HTTPS upload link, where the file lands ("mailmcp-uploads"), and that it shows up in list_uploads. An agent can distinguish this from siblings like upload_attachment without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit conditional: upload it yourself if you can run commands, otherwise hand the link to the user. It doesn't name the alternative sibling (e.g. upload_attachment) explicitly, so the routing is clear but not tied to a named tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
save_templateSave or delete a templateADestructiveIdempotentInspect
Saves a text template, or with kind=profile a style profile (tone only), in "mailmcp-templates"; delete=true moves one mailmcp saved to Trash. Needs draft; templates are paid, profiles and deleting free.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | ||
| name | Yes | ||
| text | No | {{name}} placeholders; {{body}} for your text | |
| delete | No | ||
| account | Yes | list_accounts id | |
| subject | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true; the description adds genuinely useful context by explaining that delete=true routes to Trash (not permanent), that a draft is required, and that templates are paid while profiles/deletes are free. This enriches the behavioral picture beyond the structured hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is a single run-on sentence cramming save, profile, storage location, delete behavior, prerequisite, and pricing into one breath. No filler, but the density hurts front-loading and parseability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described, and the pricing/prerequisite details are helpful. Still, for a 6-parameter tool the description omits what name/subject do and gives no hint that it writes into a specific 'mailmcp-templates' location for the profile case beyond the quoted folder name.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 33%, so the description must compensate. It does explain kind (profile = tone-only style) and delete semantics, but leaves account, name, and subject entirely undocumented in prose. Partial compensation justifies the baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb+resource ('Saves a text template'), names the kind=profile variant, and covers the delete path via 'delete=true moves one mailmcp saved to Trash'. It clearly differs from the read-oriented list_templates sibling. It loses a point only because the phrasing is dense and the profile vs template distinction is squeezed into a single clause.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It offers real context ('Needs draft; templates are paid, profiles and deleting free') that implies the prerequisites for calling it. However, it never states when to choose this over siblings like create_draft or list_templates, so usage guidance remains implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchSearch (ChatGPT-compatible)ARead-onlyIdempotentInspect
Searches every readable mailbox with one query; returns documents for fetch. Gmail syntax on Gmail (from:, newer_than:7d, has:attachment), plain words elsewhere; prefix "account: " for one mailbox. Outlook: Inbox only; Gmail: All Mail; search_messages with a folder looks elsewhere.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Search query |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, and open-world. The description adds valuable behavioral context beyond that: the scope of mailboxes searched (Outlook Inbox only, Gmail All Mail) and the fact that results feed into fetch. It does not discuss result caps or pagination, keeping it short of full transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense but front-loaded: scope and return flow come first, then syntax rules, then folder caveats. Every clause conveys distinct information, though the packing of multiple rules into semicolon-separated fragments is slightly heavy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-param, no-output-schema tool with rich annotations, the description covers scope, syntax, alternatives, and result routing sufficiently. Minor gaps remain around result limits and pagination, but the essential context for correct invocation is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% but the schema itself only says 'Search query'. The description meaningfully enriches the parameter's semantics by documenting syntax variants (from:, newer_than:7d, has:attachment), the plain-words fallback, and the account-prefix mechanism, which is real added meaning over the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (searches) and resource (every readable mailbox) with scope (one query) and the downstream tool (returns documents for fetch). It also distinguishes itself from the sibling search_messages by contrasting folder behavior ('search_messages with a folder looks elsewhere').
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear usage conditions: Gmail syntax on Gmail, plain words elsewhere, and the 'account:<id> ' prefix for a single mailbox. It points to search_messages for folder-scoped searches, implying the alternative, though it does not spell out a full when/when-not decision between the two.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_messagesSearch messagesARead-onlyIdempotentInspect
Searches one account, or all with account="all". Gmail: query takes Gmail syntax (from:, newer_than:7d, has:attachment, label:); elsewhere full text plus the filters. Newest first, with uid + folder and header hints. Outlook: total counts returned results only; from is exact.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | ||
| from | No | ||
| limit | No | Default 20, max 50 | |
| query | No | Gmail syntax on Gmail, else plain text | |
| since | No | ISO date, e.g. 2026-09-01 | |
| before | No | ISO date | |
| folder | No | Default: Gmail All Mail, else INBOX | |
| offset | No | Hits to skip (keep small) | |
| unseen | No | Only unread | |
| account | Yes | "all", or a list_accounts id | |
| flagged | No | Only starred/flagged | |
| subject | No | ||
| has_attachment | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| count | Yes | |
| messages | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only/idempotent/non-destructive safety, and the description adds real behavioral value: result ordering ('newest first'), Backend-specific quirks ('Outlook: total counts returned results only; from is exact'), and Gmail query support. It does not disclose pagination interaction with offset/limit beyond what schema states.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Information-dense and front-loaded, with the account scope leading. The backtick-laden, semicolon-joined style is telegraphic, and the 'uid + folder and header hints' clause slightly duplicates the output schema, but no sentence is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values needn't be detailed, and the description correctly focuses on the ambiguous parts (account scoping, per-backend query semantics). For a 13-parameter search tool it is largely complete, though it omits guidance on combining filters.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 69%, and the description adds genuine meaning: `query` semantics differ per backend (Gmail syntax vs. full text), `account="all"` is explained, and Outlook `from`/`total` behavior is clarified. It leaves less-obvious params like `offset` interplay with `limit` unaddressed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a clear verb+resource ('Searches' messages) and immediately scopes it ('one account, or all with account="all"'). It never names the sibling 'search' or explains how it differs from get_message/fetch, so it falls short of full sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied through the account and query scoping, and it explains Gmail vs. non-Gmail query behavior, but there is no explicit when-to-use vs. when-not, nor any named alternative (search, fetch, triage) to route the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_draftSend a saved draftADestructiveInspect
Sends a draft exactly as stored in the Drafts folder (including its attachments); it leaves Drafts (on Outlook it moves to Sent). Recipients are taken from the draft and must match send_allowlist.
| Name | Required | Description | Default |
|---|---|---|---|
| uid | Yes | Draft uid (create_draft, or a search in Drafts) | |
| folder | No | Drafts folder if not the default | |
| account | Yes | list_accounts id | |
| expect_fingerprint | No | From the draft result; refused if the draft changed |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and non-idempotent, and the description reinforces the mutation by explaining the draft leaves Drafts (to Sent on Outlook). It adds context annotations cannot carry: attachments are sent as stored and the recipient allowlist constraint. Remaining gaps (failure behavior when the allowlist rejects) are minor.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One dense sentence that front-loads the core action and folds side effects and the allowlist constraint into parentheticals — no filler, nothing that fails to earn its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and strong annotation coverage of the safety profile, the description supplies what an agent still needs: attachments included, the draft's removal from Drafts, and the allowlist precondition. It could say more about what happens when the send is refused, but it is largely complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all four parameters are already documented in the schema, including expect_fingerprint's refusal-on-change semantics. The description adds only the indirect point that recipients are not parameters but come from the draft; baseline 3 applies when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Sends a draft exactly as stored in the Drafts folder') plus scope details (attachments included, leaves Drafts, moves to Sent on Outlook), which clearly separates it from send_message and reply_send without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a real precondition — recipients come from the stored draft and must match send_allowlist — and the schema notes the uid comes from create_draft or a Drafts search, implying this is the follow-up to composing. It never explicitly routes the agent away from send_message/reply_send, so it is clear context rather than full when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_messageSend emailADestructiveInspect
Sends an email via SMTP, optionally with attachments (existing mailbox attachments, uploaded files, inline content). Only allowed when the owner enabled sending for the account AND every recipient matches send_allowlist. Otherwise use create_draft.
| Name | Required | Description | Default |
|---|---|---|---|
| cc | No | ||
| to | Yes | Recipient addresses | |
| bcc | No | ||
| html | No | Optional HTML (scripts stripped) | |
| text | Yes | Plain-text body | |
| quote | No | Quote the original (default true when replying) | |
| account | Yes | list_accounts id | |
| subject | Yes | ||
| attachments | No | ||
| in_reply_to_uid | No | uid being answered; prefer reply_draft / reply_send | |
| in_reply_to_folder | No | Default: Gmail All Mail, else INBOX |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and openWorldHint=true, so the safety profile is covered. The description adds non-obvious policy gating (per-account send enablement, send_allowlist recipient matching) that the annotations cannot express, plus the range of attachment sources. It stops short of describing delivery failure behavior or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero filler, with the action front-loaded and the escape hatch pushed to the end. Every clause carries load: mechanism, optionality, preconditions, alternative.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-output-schema send tool whose annotations already flag it as destructive and open-world, the description covers the critical invocation gates and the correct alternative. It does not address what a rejected send returns or how partial-recipient failures behave, a minor gap against the complexity of an 11-parameter tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 64% (moderate), so the schema carries much of the burden already; the inline attachment-object description in the schema largely duplicates the description's mention of mailbox attachments, uploads, and inline content. The description adds little format-level detail for the 11 parameters beyond that.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource ("Sends an email via SMTP") and immediately scopes the capability around attachments. It also names the sibling it is not (create_draft), so an agent can distinguish it from the draft/reply family without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States the two hard preconditions for use (owner enabled sending for the account AND every recipient matches send_allowlist) and gives the explicit fallback ("Otherwise use create_draft"). This is a clear when/when-not/alternative statement rather than implied guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_followupSet or clear a follow-upADestructiveIdempotentInspect
Marks a message to come back to by a date: a record in "mailmcp-state" plus a star or flag. It resurfaces when list_followups or a scheduled task runs; clear=true removes it. Needs read and modify; setting is paid, clearing free.
| Name | Required | Description | Default |
|---|---|---|---|
| tz | No | IANA time zone | |
| due | No | Date or date-time; required unless clear | |
| uid | Yes | uid from search_messages | |
| clear | No | ||
| folder | No | Default: Gmail All Mail, else INBOX | |
| account | Yes | list_accounts id | |
| if_no_reply | No | Only if nobody replied by then | |
| discard_unverified | No | With clear: trash records not ours |
Output Schema
| Name | Required | Description |
|---|---|---|
| uid | Yes | |
| account | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the mutation profile (readOnlyHint=false, destructiveHint=true, idempotentHint=true), so the bar is lower, yet the description still adds real context: the read+modify scope requirement, the paid-when-setting / free-when-clearing cost model, and the persistent record plus star/flag side effect. It does not explain the destructive path the annotation implies (the trash-unverified behavior, which only appears in the schema), leaving a small gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight clauses pack purpose, lifecycle, and auth/cost into roughly two sentences with the primary action front-loaded. Slightly dense but no filler; every clause carries information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described. Given that, the description covers side effects, lifecycle, auth, and cost, which is enough to call this correctly. The only omission is any routing against snooze/wake_snoozed, a minor completeness gap rather than a blocker.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 88%, so the schema already documents account, uid, due, folder, tz, and if_no_reply. The description adds only that clear=true removes the follow-up and that a due date drives the mark, which does not meaningfully exceed the schema. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: marks a message to come back to by a date, and also clears it. It even names the storage mechanism (a record in "mailmcp-state" plus a star or flag), which is unusually concrete. It does not distinguish itself from the close sibling snooze, so it falls short of the top mark.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"It resurfaces when list_followups or a scheduled task runs" explains the lifecycle, and clear=true removes it, so the set/clear duality is implied. However, there is no explicit guidance on when to choose this over snooze, which occupies the same conceptual space and is likely the main source of agent confusion.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_signatureSet the mailbox signatureADestructiveIdempotentInspect
Stores the signature (HTML and/or text) as a message in the folder "mailmcp-signature". With a photo or logo the owner instead mails one to themselves and moves it there. Needs the mailbox signature enabled on the setup page and the draft capability.
| Name | Required | Description | Default |
|---|---|---|---|
| html | No | HTML (scripts stripped) | |
| text | No | Plain text; default: derived from html | |
| account | Yes | list_accounts id |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the mutation profile (readOnlyHint=false, destructiveHint=true, idempotentHint=true, openWorldHint=true), so the description only needs to add context. It does so meaningfully: the signature is persisted as a message in the 'mailmcp-signature' folder, photo/logo signatures take a different path, and two capabilities must be enabled first. It stops short of explaining what the destructive hint actually overwrites.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the core action before the edge-case path and prerequisites. It is slightly diluted by implementation detail (storing as a message, mailing to self) that is not essential for tool selection.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool the safety profile is covered by annotations and all parameters are documented, so the essentials are present. The notable gap is that destructiveHint=true is never explained – the agent is not told that an existing signature is replaced rather than appended.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the schema already documents maxLength, script stripping, and the html-derived default for text. The description only restates 'HTML and/or text' and adds nothing about the required 'account' parameter, so baseline 3 is correct.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a concrete verb (stores) and resource (the mailbox signature) and even names the storage location, so the agent knows this writes a signature. It does not explicitly contrast with the sibling get_signature, which would have earned a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states real preconditions ('Needs the mailbox signature enabled on the setup page and the draft capability') and describes a photo/logo branch, which is useful context for when the call will succeed. However it never explicitly routes the agent against alternatives such as get_signature, leaving the read-vs-write choice implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
snoozeSnooze a messageADestructiveInspect
Moves one message (not its thread) to "mailmcp-snoozed" until a time, noting its origin; wake_snoozed or cancel=true brings it back. Needs read and modify; paid (cancel free).
| Name | Required | Description | Default |
|---|---|---|---|
| tz | No | IANA time zone | |
| uid | Yes | uid from search_messages | |
| until | No | Date/time; required unless cancel | |
| cancel | No | ||
| folder | No | Default: Gmail All Mail, else INBOX | |
| account | Yes | list_accounts id | |
| discard_unverified | No | With cancel: trash records not ours |
Output Schema
| Name | Required | Description |
|---|---|---|
| uid | Yes | |
| account | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructive/non-idempotent/open-world, and the description adds context those do not carry: the destination folder, that origin is noted, the required read+modify scopes, and the cost model ('paid (cancel free)'). That is meaningful behavioral disclosure beyond the structured hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences, front-loaded with the core action and scope before the reversal and permission details. No wasted words, though the cost/permission clause is slightly tacked on.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained. The description covers scope, destination, reversal, permissions, and cost, leaving only the when-to-use-vs-alternatives dimension thin.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 86%, so the schema already documents nearly every parameter. The description adds only a little (cancel=true is the reversal switch, until is the target time), which is consistent with the baseline 3 when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Moves one message') plus a crucial scope qualifier ('not its thread') and the destination ('mailmcp-snoozed'). An agent can distinguish this from sibling mutation tools like modify_message or trash_message immediately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the reversal path ('wake_snoozed or cancel=true brings it back'), giving clear guidance on how to undo. It does not, however, say when to prefer snoozing over related scheduling tools like set_followup, so it stops short of full when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
trash_messageMove to trashBDestructiveIdempotentInspect
Moves a message to the Trash folder. Never deletes permanently.
| Name | Required | Description | Default |
|---|---|---|---|
| uid | Yes | uid from search_messages | |
| folder | No | Default: Gmail All Mail, else INBOX | |
| account | Yes | list_accounts id |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true, and readOnlyHint=false, so the safety profile is largely covered. The description adds the recoverability nuance 'Never deletes permanently,' which is genuinely useful context beyond the annotations. However it says nothing about permissions, behavior when the message is already in Trash, or side effects on labels/threads.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero waste, with the primary action stated first and the non-permanence caveat immediately after. Nothing could be cut without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple 3-parameter mutation with full schema coverage and annotations declaring its destructive/idempotent nature, the description plus structured fields give an agent enough to call it correctly. The gap is the absence of usage routing against similar siblings, which is minor for a tool this narrow.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% — uid, folder, and account are each documented in the schema, including the default-folder rule. The description adds no parameter meaning whatsoever, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Moves a message to the Trash folder.' An agent can immediately tell this relocates a message rather than deleting it or modifying labels. It does not name any sibling (e.g. modify_message, bulk_apply) for differentiation, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use guidance and no alternatives named, even though siblings like modify_message, bulk_apply, and delete-adjacent flows exist. The only hint is the implicit 'trash a message' context carried by the name and title.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
triageTriage recent mailARead-onlyIdempotentInspect
Sorts recent mail into reply_candidates, waiting_on, newsletter, lists, calendar, automated and other from headers only (no bodies). Items carry reasons; you and the owner decide what needs a reply. Reports coverage per account. Needs read; every plan.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Per account, newest first; default 60 | |
| since | No | ISO date/time; default 3 days ago, at most 30 back | |
| folder | No | Default: INBOX (Outlook: Inbox) | |
| account | Yes | Account id, or "all" | |
| unread_only | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| since | Yes | |
| counts | Yes | |
| buckets | Yes | |
| accounts | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, open-world). The description adds genuinely useful behavior beyond that: classification is done 'from headers only (no bodies)', items carry reasons, and coverage is reported per account, plus the permission requirement 'Needs read; every plan'. This meaningfully informs the agent about data access and output character.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tightly packed sentences, front-loaded with what the tool does and its category output. The telegraphic final sentence 'Needs read; every plan.' is slightly terse but carries real prerequisite information without padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description need not explain return values, and it covers purpose, category buckets, header-only scope, and the read requirement. For a read-only classifier this is nearly complete; only explicit sibling routing is absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 80%, so the schema already documents limit, since, folder, and account. The description only echoes 'recent mail' and 'per account' without adding format or default details beyond what the schema provides, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (sorts) and resource (recent mail) and enumerates the exact output categories, so the agent knows precisely what it produces. It does not explicitly differentiate itself from siblings like awaiting_replies or digest, whose output overlaps with the waiting_on bucket, so it falls just short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied (triage recent mail to decide what needs a reply) and the prerequisite 'Needs read; every plan' is stated, which is useful context. However, there is no explicit when-to-use versus awaiting_replies/digest/search, and no exclusions or conditions for choosing this over alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
unsubscribeUnsubscribe from a mailing listADestructiveIdempotentInspect
Reads unsubscribe headers. The dry run (default) says if mailmcp can send an RFC 8058 one-click POST: only if your provider verified the signer's DKIM on them and the link is on its domain; else the manual link. Only when the owner asks. Needs read (execute: unsubscribe); every plan.
| Name | Required | Description | Default |
|---|---|---|---|
| uid | Yes | uid from search_messages | |
| folder | No | Default: Gmail All Mail, else INBOX | |
| account | Yes | list_accounts id | |
| confirm | No | From the dry run | |
| dry_run | No | Default true |
Output Schema
| Name | Required | Description |
|---|---|---|
| can_execute | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true, and openWorldHint=true, but the description adds substantive context beyond them: the dry run is the default, the one-click POST only fires when the provider verified the signer's DKIM and the link is on its domain, and it requires the 'execute: unsubscribe' read permission on every plan. This is meaningful workflow and auth disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Very compact with every clause carrying information (default behavior, condition for POST, fallback, usage restriction, permissions). The telegraphic, run-on phrasing ('else the manual link. Only when the owner asks.') is dense and slightly disjointed but front-loads the dry-run behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need no explanation, and the description covers the dry-run workflow, the conditions for the automated POST, and the required permission. For a destructive, open-world tool the safety posture is adequately conveyed, though a hint about reversibility or irreversibility of the POST could add more.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents all five parameters including account, uid, folder, confirm, and dry_run defaults. The description reinforces dry_run's default and the confirm-from-dry-run flow but adds little syntax or format detail beyond what the schema already provides, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The title and description together establish that this tool unsubscribes from mailing lists, and the text names the specific mechanism (RFC 8058 one-click POST vs manual link). However, the lead sentence 'Reads unsubscribe headers' foregrounds the dry-run read behavior rather than the destructive unsubscribe action, which could momentarily confuse an agent about what the tool actually does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Only when the owner asks' is an explicit, restrictive when-to-use condition, and the dry-run-default design implicitly guides the intended two-step workflow. It does not name alternative tools (e.g. modify_message, trash_message), so it stops short of full alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upload_attachmentHand a file to mailmcpAInspect
Stores a file (text, or base64 for binary; up to policy.max_upload_bytes) in "mailmcp-uploads" and returns {folder, uid, part} to attach; it is removed once attached. Large or local files: request_upload.
| Name | Required | Description | Default |
|---|---|---|---|
| account | Yes | list_accounts id | |
| content | Yes | UTF-8 text or base64 | |
| encoding | No | ||
| filename | Yes | ||
| content_type | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnlyHint=false, destructiveHint=false, idempotentHint=false, openWorldHint=true), so the bar is lower. The description adds genuinely non-obvious behavior: the file is a temporary staging artifact that is removed once attached, plus the one-shot return tuple despite there being no output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence: purpose, encoding rule, size limit, and return value, followed by a one-clause routing note. Dense but every clause carries information; only the heavy compression of the return tuple is slightly terse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and only 40% schema coverage, the description still covers the return shape, the size ceiling, the one-shot lifecycle, and the sibling alternative. Remaining gaps are the unexplained account/filename/content_type parameters rather than anything that would cause a wrong invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 40%, so the description must compensate. It clarifies the content parameter (UTF-8 text or base64 for binary) and the implied utf8/base64 encoding enum, but account, filename, and content_type receive no added meaning anywhere.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (stores a file), names the storage location ("mailmcp-uploads"), and gives the return contract {folder, uid, part}. It also names the sibling request_upload as the alternative, so an agent can separate it from other upload-related tools without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes large or local files to request_upload and states the size cap (policy.max_upload_bytes), which is real usage guidance. It does not, however, explain when the text-vs-base64 branch should be chosen or any prerequisites tied to the required account parameter.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wake_snoozedBring back snoozed mail that is dueAIdempotentInspect
Moves due messages from "mailmcp-snoozed" back where they were, unread. Safe to repeat and to run concurrently. orphans=true moves snoozed mail without a record to INBOX (only when the owner asks). Needs read and modify; every plan.
| Name | Required | Description | Default |
|---|---|---|---|
| uid | No | Wake this message now | |
| account | No | Default "all" | |
| dry_run | No | ||
| orphans | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| woken | Yes | |
| pending | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial behavior beyond the annotations: restored messages are marked unread, the operation is safe to repeat and to run concurrently, the orphan fallback targets INBOX, and it declares the permission model ("Needs read and modify; every plan"). This exceeds the idempotent/destructive hints already provided.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense and front-loaded: the core move happens first, then caveats. Every sentence carries weight, though the final permission clause is slightly clipped ('every plan') in a way that reads as shorthand rather than intent.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be described, and the description covers the mutation's permission model, idempotency, and orphan edge case. Remaining gap is the undocumented `dry_run`/`account` parameters for a tool that is safe to invoke without required args.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 50% schema coverage, the description compensates partially by explaining `orphans` (schema gives it no description) and the unread/restore semantics tied to `uid`. It says nothing about `dry_run` or `account`, leaving half the parameters undocumented in both places.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: "Moves due messages from 'mailmcp-snoozed' back where they were, unread." The folder name and 'due' qualifier make it unmistakably distinct from its inverse sibling `snooze` without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives one conditional gateway ("orphans=true ... only when the owner asks"), which is real when-to-use guidance, but never states the general trigger or explicitly contrasts with `snooze`. Usage is implied rather than spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
31 tool updates
v0.13.12- Added
awaiting_replies - Added
bulk_apply - Added
bulk_preview - Changed
create_draft19 fields changed- changed
Input schema / properties / account / descriptionPrevious value: -"Account id from list_accounts"New value: +"list_accounts id" - removed
Input schema / properties / attachments / descriptionRemoved value: -"Files to attach: existing mailbox attachments, uploaded files (folder \"mailmcp-uploads\"), inline content, or local paths" - changed
Input schema / properties / attachments / items / descriptionPrevious value: -"Attach a mailbox attachment {uid, part[, folder, account]}, inline content {filename, content[, encoding]}, or a local file {path}"New value: +"{uid, part[, folder, account]} from a mailbox, {filename, content[, encoding]} or {path}" - removed
Input schema / properties / attachments / items / properties / account / descriptionRemoved value: -"Account holding the file (defaults to the sending account)" - removed
Input schema / properties / attachments / items / properties / content / descriptionRemoved value: -"File content, UTF-8 text or base64 (see encoding); for files the assistant writes itself" - removed
Input schema / properties / attachments / items / properties / content_type / descriptionRemoved value: -"MIME type of inline content, e.g. text/csv" - removed
Input schema / properties / attachments / items / properties / encoding / descriptionRemoved value: -"How `content` is encoded, default utf8" - removed
Input schema / properties / attachments / items / properties / filename / descriptionRemoved value: -"File name (required for inline content)" - removed
Input schema / properties / attachments / items / properties / folder / descriptionRemoved value: -"Folder of the source message (e.g. \"mailmcp-uploads\" for uploaded files)" - changed
Input schema / properties / attachments / items / properties / part / descriptionPrevious value: -"Attachment part id from get_message / list_uploads"New value: +"Part id from get_message / list_uploads" - changed
Input schema / properties / attachments / items / properties / path / descriptionPrevious value: -"Local file path (Claude Desktop / Claude Code only, within policy.attachment_dirs)"New value: +"Local path (stdio only, inside policy.attachment_dirs)" - removed
Input schema / properties / attachments / items / properties / uid / descriptionRemoved value: -"uid of the source message" - changed
Input schema / properties / html / descriptionPrevious value: -"Optional HTML body (scripts are stripped); when absent it is rendered from text"New value: +"Optional HTML (scripts stripped)" - changed
Input schema / properties / in_reply_to_folder / descriptionPrevious value: -"Folder/label path. Defaults to All Mail on Gmail, INBOX elsewhere."New value: +"Default: Gmail All Mail, else INBOX" - changed
Input schema / properties / in_reply_to_uid / descriptionPrevious value: -"uid of the message being answered: sets In-Reply-To/References, keeps the Re: subject and quotes the original. Prefer reply_draft / reply_send."New value: +"uid being answered; prefer reply_draft / reply_send" - changed
Input schema / properties / quote / descriptionPrevious value: -"Quote the original under the reply (default true when replying)"New value: +"Quote the original (default true when replying)" - added
Input schema / properties / templateAdded value: +{ + "description": "list_templates name (paid)", + "maxLength": 60, + "type": "string" +} - added
Input schema / properties / varsAdded value: +{ + "additionalProperties": { + "maxLength": 2000, + "type": "string" + }, + "description": "Values for its {{placeholders}}", + "propertyNames": { + "pattern": "^[a-z_][a-z0-9_]{0,30}$", + "type": "string" + }, + "type": "object" +} - changed
Input schema / requiredPrevious value: -[ - "account", - "to", - "subject", - "text" -]New value: +[ + "account", + "to" +]
- Added
digest - Changed
forward_message4 fields changed- changed
Input schema / properties / account / descriptionPrevious value: -"Account id from list_accounts"New value: +"list_accounts id" - changed
Input schema / properties / comment / descriptionPrevious value: -"Text to put above the forwarded message"New value: +"Text above the forward" - changed
Input schema / properties / folder / descriptionPrevious value: -"Folder/label path. Defaults to All Mail on Gmail, INBOX elsewhere."New value: +"Default: Gmail All Mail, else INBOX" - changed
Input schema / properties / uid / descriptionPrevious value: -"uid from search_messages: a number on IMAP mailboxes, an id string on Outlook; pass it back exactly as returned"New value: +"uid from search_messages"
- Changed
get_attachment5 fields changed- changed
Input schema / properties / account / descriptionPrevious value: -"Account id from list_accounts"New value: +"list_accounts id" - changed
Input schema / properties / folder / descriptionPrevious value: -"Folder/label path. Defaults to All Mail on Gmail, INBOX elsewhere."New value: +"Default: Gmail All Mail, else INBOX" - changed
Input schema / properties / inline / descriptionPrevious value: -"Embed the binary content in the result instead of returning a link"New value: +"Embed the bytes instead of a link" - changed
Input schema / properties / save_to / descriptionPrevious value: -"Claude Desktop / Claude Code only: directory inside policy.attachment_dirs to write the file into; the tool returns the path"New value: +"stdio: folder in policy.attachment_dirs; returns the path" - changed
Input schema / properties / uid / descriptionPrevious value: -"uid from search_messages: a number on IMAP mailboxes, an id string on Outlook; pass it back exactly as returned"New value: +"uid from search_messages"
- Changed
get_message4 fields changed- changed
Input schema / properties / account / descriptionPrevious value: -"Account id from list_accounts"New value: +"list_accounts id" - changed
Input schema / properties / folder / descriptionPrevious value: -"Folder/label path. Defaults to All Mail on Gmail, INBOX elsewhere."New value: +"Default: Gmail All Mail, else INBOX" - changed
Input schema / properties / uid / descriptionPrevious value: -"uid from search_messages: a number on IMAP mailboxes, an id string on Outlook; pass it back exactly as returned"New value: +"uid from search_messages" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": {}, + "properties": { + "folder": { + "type": "string" + }, + "text": { + "type": "string" + }, + "uid": { + "type": [ + "string", + "number" + ] + } + }, + "required": [ + "uid", + "folder", + "text" + ], + "type": "object" +}
- Changed
get_signature1 field changed- changed
Input schema / properties / account / descriptionPrevious value: -"Account id from list_accounts"New value: +"list_accounts id"
- Changed
get_thread5 fields changed- changed
Input schema / properties / account / descriptionPrevious value: -"Account id from list_accounts"New value: +"list_accounts id" - changed
Input schema / properties / folder / descriptionPrevious value: -"Folder/label path. Defaults to All Mail on Gmail, INBOX elsewhere."New value: +"Default: Gmail All Mail, else INBOX" - added
Input schema / properties / include_bodiesAdded value: +{ + "description": "Text of the newest 20 (no quotes, 60,000 chars)", + "type": "boolean" +} - changed
Input schema / properties / uid / descriptionPrevious value: -"uid from search_messages: a number on IMAP mailboxes, an id string on Outlook; pass it back exactly as returned"New value: +"uid from search_messages" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": {}, + "properties": { + "coverage": { + "additionalProperties": {}, + "properties": { + "complete": { + "type": "boolean" + } + }, + "required": [ + "complete" + ], + "type": "object" + }, + "kind": { + "const": "thread", + "type": "string" + }, + "messages": { + "items": { + "additionalProperties": {}, + "properties": { + "folder": { + "type": "string" + }, + "omitted": { + "enum": [ + "size", + "time", + "protected" + ], + "type": "string" + }, + "uid": { + "type": [ + "string", + "number" + ] + } + }, + "required": [ + "uid", + "folder" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "kind", + "coverage", + "messages" + ], + "type": "object" +}
- Changed
list_accounts2 fields changed- changed
Input schema / properties / check_connection / descriptionPrevious value: -"Also test the login of every account: IMAP, or the Microsoft sign-in (slower)."New value: +"Also test every login (slower)" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": {}, + "properties": { + "accounts": { + "items": {}, + "type": "array" + } + }, + "required": [ + "accounts" + ], + "type": "object" +}
- Changed
list_folders2 fields changed- changed
Input schema / properties / account / descriptionPrevious value: -"Account id from list_accounts"New value: +"list_accounts id" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": {}, + "properties": { + "account": { + "type": "string" + }, + "folders": { + "items": {}, + "type": "array" + } + }, + "required": [ + "account", + "folders" + ], + "type": "object" +}
- Added
list_followups - Added
list_templates - Changed
list_uploads1 field changed- changed
Input schema / properties / account / descriptionPrevious value: -"Account id from list_accounts"New value: +"list_accounts id"
- Changed
modify_message4 fields changed- changed
Input schema / properties / account / descriptionPrevious value: -"Account id from list_accounts"New value: +"list_accounts id" - added
Input schema / properties / create_folderAdded value: +{ + "description": "With move_to: create the folder first if it does not exist", + "type": "boolean" +} - changed
Input schema / properties / folder / descriptionPrevious value: -"Folder/label path. Defaults to All Mail on Gmail, INBOX elsewhere."New value: +"Default: Gmail All Mail, else INBOX" - changed
Input schema / properties / uid / descriptionPrevious value: -"uid from search_messages: a number on IMAP mailboxes, an id string on Outlook; pass it back exactly as returned"New value: +"uid from search_messages"
- Changed
reply_draft21 fields changed- changed
Input schema / properties / account / descriptionPrevious value: -"Account id from list_accounts"New value: +"list_accounts id" - changed
Input schema / properties / attachments / items / descriptionPrevious value: -"Attach a mailbox attachment {uid, part[, folder, account]}, inline content {filename, content[, encoding]}, or a local file {path}"New value: +"{uid, part[, folder, account]} from a mailbox, {filename, content[, encoding]} or {path}" - removed
Input schema / properties / attachments / items / properties / account / descriptionRemoved value: -"Account holding the file (defaults to the sending account)" - removed
Input schema / properties / attachments / items / properties / content / descriptionRemoved value: -"File content, UTF-8 text or base64 (see encoding); for files the assistant writes itself" - removed
Input schema / properties / attachments / items / properties / content_type / descriptionRemoved value: -"MIME type of inline content, e.g. text/csv" - removed
Input schema / properties / attachments / items / properties / encoding / descriptionRemoved value: -"How `content` is encoded, default utf8" - removed
Input schema / properties / attachments / items / properties / filename / descriptionRemoved value: -"File name (required for inline content)" - removed
Input schema / properties / attachments / items / properties / folder / descriptionRemoved value: -"Folder of the source message (e.g. \"mailmcp-uploads\" for uploaded files)" - changed
Input schema / properties / attachments / items / properties / part / descriptionPrevious value: -"Attachment part id from get_message / list_uploads"New value: +"Part id from get_message / list_uploads" - changed
Input schema / properties / attachments / items / properties / path / descriptionPrevious value: -"Local file path (Claude Desktop / Claude Code only, within policy.attachment_dirs)"New value: +"Local path (stdio only, inside policy.attachment_dirs)" - removed
Input schema / properties / attachments / items / properties / uid / descriptionRemoved value: -"uid of the source message" - changed
Input schema / properties / folder / descriptionPrevious value: -"Folder/label path. Defaults to All Mail on Gmail, INBOX elsewhere."New value: +"Default: Gmail All Mail, else INBOX" - changed
Input schema / properties / html / descriptionPrevious value: -"Optional HTML version of the reply body"New value: +"Optional HTML of your text (the quote is added below)" - changed
Input schema / properties / lang / descriptionPrevious value: -"Language of the \"On … wrote:\" line (default: guessed from the reply)"New value: +"\"On … wrote:\" language" - changed
Input schema / properties / quote / descriptionPrevious value: -"Quote the original under the reply (default true)"New value: +"Quote the original (default true)" - changed
Input schema / properties / reply_all / descriptionPrevious value: -"Reply to every recipient of the original (default: sender only)"New value: +"Reply to all (default: sender only)" - added
Input schema / properties / templateAdded value: +{ + "description": "list_templates name (paid)", + "maxLength": 60, + "type": "string" +} - changed
Input schema / properties / text / descriptionPrevious value: -"The reply itself, plain text, without greeting-to-quote artefacts; the original is quoted automatically"New value: +"Plain text; the original is quoted" - changed
Input schema / properties / uid / descriptionPrevious value: -"uid of the message being answered (from search_messages / get_message / get_thread)"New value: +"uid being answered" - added
Input schema / properties / varsAdded value: +{ + "additionalProperties": { + "maxLength": 2000, + "type": "string" + }, + "description": "Values for its {{placeholders}}", + "propertyNames": { + "pattern": "^[a-z_][a-z0-9_]{0,30}$", + "type": "string" + }, + "type": "object" +} - changed
Input schema / requiredPrevious value: -[ - "account", - "uid", - "text" -]New value: +[ + "account", + "uid" +]
- Changed
reply_send18 fields changed- changed
Input schema / properties / account / descriptionPrevious value: -"Account id from list_accounts"New value: +"list_accounts id" - changed
Input schema / properties / attachments / items / descriptionPrevious value: -"Attach a mailbox attachment {uid, part[, folder, account]}, inline content {filename, content[, encoding]}, or a local file {path}"New value: +"{uid, part[, folder, account]} from a mailbox, {filename, content[, encoding]} or {path}" - removed
Input schema / properties / attachments / items / properties / account / descriptionRemoved value: -"Account holding the file (defaults to the sending account)" - removed
Input schema / properties / attachments / items / properties / content / descriptionRemoved value: -"File content, UTF-8 text or base64 (see encoding); for files the assistant writes itself" - removed
Input schema / properties / attachments / items / properties / content_type / descriptionRemoved value: -"MIME type of inline content, e.g. text/csv" - removed
Input schema / properties / attachments / items / properties / encoding / descriptionRemoved value: -"How `content` is encoded, default utf8" - removed
Input schema / properties / attachments / items / properties / filename / descriptionRemoved value: -"File name (required for inline content)" - removed
Input schema / properties / attachments / items / properties / folder / descriptionRemoved value: -"Folder of the source message (e.g. \"mailmcp-uploads\" for uploaded files)" - changed
Input schema / properties / attachments / items / properties / part / descriptionPrevious value: -"Attachment part id from get_message / list_uploads"New value: +"Part id from get_message / list_uploads" - changed
Input schema / properties / attachments / items / properties / path / descriptionPrevious value: -"Local file path (Claude Desktop / Claude Code only, within policy.attachment_dirs)"New value: +"Local path (stdio only, inside policy.attachment_dirs)" - removed
Input schema / properties / attachments / items / properties / uid / descriptionRemoved value: -"uid of the source message" - changed
Input schema / properties / folder / descriptionPrevious value: -"Folder/label path. Defaults to All Mail on Gmail, INBOX elsewhere."New value: +"Default: Gmail All Mail, else INBOX" - changed
Input schema / properties / html / descriptionPrevious value: -"Optional HTML version of the reply body"New value: +"Optional HTML of your text (the quote is added below)" - changed
Input schema / properties / lang / descriptionPrevious value: -"Language of the \"On … wrote:\" line (default: guessed from the reply)"New value: +"\"On … wrote:\" language" - changed
Input schema / properties / quote / descriptionPrevious value: -"Quote the original under the reply (default true)"New value: +"Quote the original (default true)" - changed
Input schema / properties / reply_all / descriptionPrevious value: -"Reply to every recipient of the original (default: sender only)"New value: +"Reply to all (default: sender only)" - changed
Input schema / properties / text / descriptionPrevious value: -"The reply itself, plain text, without greeting-to-quote artefacts; the original is quoted automatically"New value: +"Plain text; the original is quoted" - changed
Input schema / properties / uid / descriptionPrevious value: -"uid of the message being answered (from search_messages / get_message / get_thread)"New value: +"uid being answered"
- Changed
request_upload1 field changed- changed
Input schema / properties / account / descriptionPrevious value: -"Account id from list_accounts"New value: +"list_accounts id"
- Added
save_template - Changed
search_messages5 fields changed- changed
Input schema / properties / account / descriptionPrevious value: -"Account id, or \"all\" to search every readable account"New value: +"\"all\", or a list_accounts id" - changed
Input schema / properties / folder / descriptionPrevious value: -"Folder/label path. Defaults to All Mail on Gmail, INBOX elsewhere."New value: +"Default: Gmail All Mail, else INBOX" - changed
Input schema / properties / offset / descriptionPrevious value: -"Skip this many hits; the window Graph and IMAP fetch grows with it, so keep it small"New value: +"Hits to skip (keep small)" - changed
Input schema / properties / query / descriptionPrevious value: -"Gmail search syntax on Gmail; plain text elsewhere"New value: +"Gmail syntax on Gmail, else plain text" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": {}, + "properties": { + "count": { + "type": "number" + }, + "messages": { + "items": { + "additionalProperties": {}, + "properties": { + "folder": { + "type": "string" + }, + "uid": { + "type": [ + "string", + "number" + ] + } + }, + "required": [ + "uid", + "folder" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "count", + "messages" + ], + "type": "object" +}
- Changed
send_draft4 fields changed- changed
Input schema / properties / account / descriptionPrevious value: -"Account id from list_accounts"New value: +"list_accounts id" - added
Input schema / properties / expect_fingerprintAdded value: +{ + "description": "From the draft result; refused if the draft changed", + "maxLength": 64, + "type": "string" +} - changed
Input schema / properties / folder / descriptionPrevious value: -"Drafts folder path if not the default"New value: +"Drafts folder if not the default" - changed
Input schema / properties / uid / descriptionPrevious value: -"uid of the draft (from create_draft or search_messages in the Drafts folder)"New value: +"Draft uid (create_draft, or a search in Drafts)"
- Changed
send_message16 fields changed- changed
Input schema / properties / account / descriptionPrevious value: -"Account id from list_accounts"New value: +"list_accounts id" - removed
Input schema / properties / attachments / descriptionRemoved value: -"Files to attach: existing mailbox attachments, uploaded files (folder \"mailmcp-uploads\"), inline content, or local paths" - changed
Input schema / properties / attachments / items / descriptionPrevious value: -"Attach a mailbox attachment {uid, part[, folder, account]}, inline content {filename, content[, encoding]}, or a local file {path}"New value: +"{uid, part[, folder, account]} from a mailbox, {filename, content[, encoding]} or {path}" - removed
Input schema / properties / attachments / items / properties / account / descriptionRemoved value: -"Account holding the file (defaults to the sending account)" - removed
Input schema / properties / attachments / items / properties / content / descriptionRemoved value: -"File content, UTF-8 text or base64 (see encoding); for files the assistant writes itself" - removed
Input schema / properties / attachments / items / properties / content_type / descriptionRemoved value: -"MIME type of inline content, e.g. text/csv" - removed
Input schema / properties / attachments / items / properties / encoding / descriptionRemoved value: -"How `content` is encoded, default utf8" - removed
Input schema / properties / attachments / items / properties / filename / descriptionRemoved value: -"File name (required for inline content)" - removed
Input schema / properties / attachments / items / properties / folder / descriptionRemoved value: -"Folder of the source message (e.g. \"mailmcp-uploads\" for uploaded files)" - changed
Input schema / properties / attachments / items / properties / part / descriptionPrevious value: -"Attachment part id from get_message / list_uploads"New value: +"Part id from get_message / list_uploads" - changed
Input schema / properties / attachments / items / properties / path / descriptionPrevious value: -"Local file path (Claude Desktop / Claude Code only, within policy.attachment_dirs)"New value: +"Local path (stdio only, inside policy.attachment_dirs)" - removed
Input schema / properties / attachments / items / properties / uid / descriptionRemoved value: -"uid of the source message" - changed
Input schema / properties / html / descriptionPrevious value: -"Optional HTML body (scripts are stripped); when absent it is rendered from text"New value: +"Optional HTML (scripts stripped)" - changed
Input schema / properties / in_reply_to_folder / descriptionPrevious value: -"Folder/label path. Defaults to All Mail on Gmail, INBOX elsewhere."New value: +"Default: Gmail All Mail, else INBOX" - changed
Input schema / properties / in_reply_to_uid / descriptionPrevious value: -"uid of the message being answered: sets In-Reply-To/References, keeps the Re: subject and quotes the original. Prefer reply_draft / reply_send."New value: +"uid being answered; prefer reply_draft / reply_send" - changed
Input schema / properties / quote / descriptionPrevious value: -"Quote the original under the reply (default true when replying)"New value: +"Quote the original (default true when replying)"
- Added
set_followup - Changed
set_signature3 fields changed- changed
Input schema / properties / account / descriptionPrevious value: -"Account id from list_accounts"New value: +"list_accounts id" - changed
Input schema / properties / html / descriptionPrevious value: -"HTML signature (scripts are stripped)"New value: +"HTML (scripts stripped)" - changed
Input schema / properties / text / descriptionPrevious value: -"Plain-text signature; derived from html when omitted"New value: +"Plain text; default: derived from html"
- Added
snooze - Changed
trash_message3 fields changed- changed
Input schema / properties / account / descriptionPrevious value: -"Account id from list_accounts"New value: +"list_accounts id" - changed
Input schema / properties / folder / descriptionPrevious value: -"Folder/label path. Defaults to All Mail on Gmail, INBOX elsewhere."New value: +"Default: Gmail All Mail, else INBOX" - changed
Input schema / properties / uid / descriptionPrevious value: -"uid from search_messages: a number on IMAP mailboxes, an id string on Outlook; pass it back exactly as returned"New value: +"uid from search_messages"
- Added
triage - Added
unsubscribe - Changed
upload_attachment1 field changed- changed
Input schema / properties / account / descriptionPrevious value: -"Account id from list_accounts"New value: +"list_accounts id"
- Added
wake_snoozed
13 tool updates
v0.8.1- Changed
create_draft11 fields changed- added
Input schema / properties / attachments / items / properties / uid / maxLengthAdded value: +512 - removed
Input schema / properties / attachments / items / properties / uid / maximumRemoved value: -9007199254740991 - added
Input schema / properties / attachments / items / properties / uid / minLengthAdded value: +1 - removed
Input schema / properties / attachments / items / properties / uid / minimumRemoved value: -1 - changed
Input schema / properties / attachments / items / properties / uid / typePrevious value: -"integer"New value: +"string" - added
Input schema / properties / attachments / maxItemsAdded value: +20 - added
Input schema / properties / in_reply_to_uid / maxLengthAdded value: +512 - removed
Input schema / properties / in_reply_to_uid / maximumRemoved value: -9007199254740991 - added
Input schema / properties / in_reply_to_uid / minLengthAdded value: +1 - removed
Input schema / properties / in_reply_to_uid / minimumRemoved value: -1 - changed
Input schema / properties / in_reply_to_uid / typePrevious value: -"integer"New value: +"string"
- Changed
forward_message6 fields changed- added
Input schema / properties / uid / descriptionAdded value: +"uid from search_messages: a number on IMAP mailboxes, an id string on Outlook; pass it back exactly as returned" - added
Input schema / properties / uid / maxLengthAdded value: +512 - removed
Input schema / properties / uid / maximumRemoved value: -9007199254740991 - added
Input schema / properties / uid / minLengthAdded value: +1 - removed
Input schema / properties / uid / minimumRemoved value: -1 - changed
Input schema / properties / uid / typePrevious value: -"integer"New value: +"string"
- Changed
get_attachment7 fields changed- added
Input schema / properties / save_toAdded value: +{ + "description": "Claude Desktop / Claude Code only: directory inside policy.attachment_dirs to write the file into; the tool returns the path", + "type": "string" +} - added
Input schema / properties / uid / descriptionAdded value: +"uid from search_messages: a number on IMAP mailboxes, an id string on Outlook; pass it back exactly as returned" - added
Input schema / properties / uid / maxLengthAdded value: +512 - removed
Input schema / properties / uid / maximumRemoved value: -9007199254740991 - added
Input schema / properties / uid / minLengthAdded value: +1 - removed
Input schema / properties / uid / minimumRemoved value: -1 - changed
Input schema / properties / uid / typePrevious value: -"integer"New value: +"string"
- Changed
get_message6 fields changed- changed
Input schema / properties / uid / descriptionPrevious value: -"uid from search_messages"New value: +"uid from search_messages: a number on IMAP mailboxes, an id string on Outlook; pass it back exactly as returned" - added
Input schema / properties / uid / maxLengthAdded value: +512 - removed
Input schema / properties / uid / maximumRemoved value: -9007199254740991 - added
Input schema / properties / uid / minLengthAdded value: +1 - removed
Input schema / properties / uid / minimumRemoved value: -1 - changed
Input schema / properties / uid / typePrevious value: -"integer"New value: +"string"
- Changed
get_thread6 fields changed- added
Input schema / properties / uid / descriptionAdded value: +"uid from search_messages: a number on IMAP mailboxes, an id string on Outlook; pass it back exactly as returned" - added
Input schema / properties / uid / maxLengthAdded value: +512 - removed
Input schema / properties / uid / maximumRemoved value: -9007199254740991 - added
Input schema / properties / uid / minLengthAdded value: +1 - removed
Input schema / properties / uid / minimumRemoved value: -1 - changed
Input schema / properties / uid / typePrevious value: -"integer"New value: +"string"
- Changed
list_accounts1 field changed- changed
Input schema / properties / check_connection / descriptionPrevious value: -"Also test the IMAP login of every account (slower)."New value: +"Also test the login of every account: IMAP, or the Microsoft sign-in (slower)."
- Changed
modify_message6 fields changed- added
Input schema / properties / uid / descriptionAdded value: +"uid from search_messages: a number on IMAP mailboxes, an id string on Outlook; pass it back exactly as returned" - added
Input schema / properties / uid / maxLengthAdded value: +512 - removed
Input schema / properties / uid / maximumRemoved value: -9007199254740991 - added
Input schema / properties / uid / minLengthAdded value: +1 - removed
Input schema / properties / uid / minimumRemoved value: -1 - changed
Input schema / properties / uid / typePrevious value: -"integer"New value: +"string"
- Changed
reply_draft11 fields changed- added
Input schema / properties / attachments / items / properties / uid / maxLengthAdded value: +512 - removed
Input schema / properties / attachments / items / properties / uid / maximumRemoved value: -9007199254740991 - added
Input schema / properties / attachments / items / properties / uid / minLengthAdded value: +1 - removed
Input schema / properties / attachments / items / properties / uid / minimumRemoved value: -1 - changed
Input schema / properties / attachments / items / properties / uid / typePrevious value: -"integer"New value: +"string" - added
Input schema / properties / attachments / maxItemsAdded value: +20 - added
Input schema / properties / uid / maxLengthAdded value: +512 - removed
Input schema / properties / uid / maximumRemoved value: -9007199254740991 - added
Input schema / properties / uid / minLengthAdded value: +1 - removed
Input schema / properties / uid / minimumRemoved value: -1 - changed
Input schema / properties / uid / typePrevious value: -"integer"New value: +"string"
- Changed
reply_send11 fields changed- added
Input schema / properties / attachments / items / properties / uid / maxLengthAdded value: +512 - removed
Input schema / properties / attachments / items / properties / uid / maximumRemoved value: -9007199254740991 - added
Input schema / properties / attachments / items / properties / uid / minLengthAdded value: +1 - removed
Input schema / properties / attachments / items / properties / uid / minimumRemoved value: -1 - changed
Input schema / properties / attachments / items / properties / uid / typePrevious value: -"integer"New value: +"string" - added
Input schema / properties / attachments / maxItemsAdded value: +20 - added
Input schema / properties / uid / maxLengthAdded value: +512 - removed
Input schema / properties / uid / maximumRemoved value: -9007199254740991 - added
Input schema / properties / uid / minLengthAdded value: +1 - removed
Input schema / properties / uid / minimumRemoved value: -1 - changed
Input schema / properties / uid / typePrevious value: -"integer"New value: +"string"
- Changed
search_messages2 fields changed- added
Input schema / properties / offset / descriptionAdded value: +"Skip this many hits; the window Graph and IMAP fetch grows with it, so keep it small" - changed
Input schema / properties / offset / maximumPrevious value: -9007199254740991New value: +5000
- Changed
send_draft5 fields changed- added
Input schema / properties / uid / maxLengthAdded value: +512 - removed
Input schema / properties / uid / maximumRemoved value: -9007199254740991 - added
Input schema / properties / uid / minLengthAdded value: +1 - removed
Input schema / properties / uid / minimumRemoved value: -1 - changed
Input schema / properties / uid / typePrevious value: -"integer"New value: +"string"
- Changed
send_message11 fields changed- added
Input schema / properties / attachments / items / properties / uid / maxLengthAdded value: +512 - removed
Input schema / properties / attachments / items / properties / uid / maximumRemoved value: -9007199254740991 - added
Input schema / properties / attachments / items / properties / uid / minLengthAdded value: +1 - removed
Input schema / properties / attachments / items / properties / uid / minimumRemoved value: -1 - changed
Input schema / properties / attachments / items / properties / uid / typePrevious value: -"integer"New value: +"string" - added
Input schema / properties / attachments / maxItemsAdded value: +20 - added
Input schema / properties / in_reply_to_uid / maxLengthAdded value: +512 - removed
Input schema / properties / in_reply_to_uid / maximumRemoved value: -9007199254740991 - added
Input schema / properties / in_reply_to_uid / minLengthAdded value: +1 - removed
Input schema / properties / in_reply_to_uid / minimumRemoved value: -1 - changed
Input schema / properties / in_reply_to_uid / typePrevious value: -"integer"New value: +"string"
- Changed
trash_message6 fields changed- added
Input schema / properties / uid / descriptionAdded value: +"uid from search_messages: a number on IMAP mailboxes, an id string on Outlook; pass it back exactly as returned" - added
Input schema / properties / uid / maxLengthAdded value: +512 - removed
Input schema / properties / uid / maximumRemoved value: -9007199254740991 - added
Input schema / properties / uid / minLengthAdded value: +1 - removed
Input schema / properties / uid / minimumRemoved value: -1 - changed
Input schema / properties / uid / typePrevious value: -"integer"New value: +"string"
21 tool updates
v0.1.0- First observed
create_draft - First observed
fetch - First observed
forward_message - First observed
get_attachment - First observed
get_message - First observed
get_signature - First observed
get_thread - First observed
list_accounts - First observed
list_folders - First observed
list_uploads - First observed
modify_message - First observed
reply_draft - First observed
reply_send - First observed
request_upload - First observed
search - First observed
search_messages - First observed
send_draft - First observed
send_message - First observed
set_signature - First observed
trash_message - First observed
upload_attachment
TDQS
Scored across 33 tools
Many boundaries are documented, but the set contains overlapping pairs such as search/search_messages, get_message/fetch, create_draft/reply_draft, and send_message/reply_send/send_draft. Descriptions help, yet an agent could still misselect among these similar mail operations.
Most names use snake_case with a verb_noun pattern (list_folders, get_message, create_draft, modify_message), which is readable and consistent. There are minor deviations such as single verbs (search, fetch, snooze) and awkward variants like reply_send and wake_snoozed.
With 33 tools, the server is well beyond the typical 3-15 range and enters the 25+ territory that makes selection and maintenance heavy. The domain is broad, but the surface feels over-expanded rather than tightly scoped.
Coverage spans accounts, folders, search, retrieval, attachments, drafts, replies, sending, forwarding, modifications, trash, triage, follow-ups, snoozing, unsubscribe, signatures, and templates. No obvious mail lifecycle gap stands out for the stated purpose.
Maintenance
Related MCP Connectors
Connect any mailbox to Claude, ChatGPT & AI: read, send, reply, schedule & search emails.
Email for AI agents: read, search and send from your Gmail, Outlook, Yahoo, iCloud or IMAP inbox.
Mac & Windows: let ChatGPT, Claude & Cursor use your email, calendar, iMessage, Teams, files.
Gmail, Outlook, iCloud, Fastmail and any IMAP mailbox for your agent. Scoped OAuth, approved sends.
Related MCP Servers
- AlicenseAqualityAmaintenanceHosted email for AI agents. Connect Gmail, Outlook / Microsoft 365 or any IMAP mailbox to Claude, ChatGPT, Cursor and other MCP clients, then read, search, send, organize, draft, schedule and auto-triage mail. Email is fetched live and never stored. Free for 1 inbox.2313AGPL 3.0
- AlicenseAqualityAmaintenanceLets Claude Desktop read any IMAP mailbox and send emails via SMTP, with support for multiple mailboxes and locally stored credentials.1366 npmMIT
- AlicenseNot gradedqualityBmaintenanceEnables Claude and ChatGPT to read, search, and organize mail in a user's own email account, including folders, threads, attachments, drafts, and optional sending, with per-user permission levels and OAuth-secured remote connections.MIT
- AlicenseNot gradedqualityAmaintenanceEnables Claude to search and read multiple Gmail or Google Workspace mail accounts at once through a local, read-only MCP server, with every result labeled by the account it came from. Tokens stay in the OS keychain, no server is run by the authors, and write actions such as sending, deleting, or archiving are not supported.8 npm1AGPL 3.0