outlook-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@outlook-mcpshow my inbox summary"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
outlook-mcp
A local MCP server for a personal Outlook.com / Hotmail / Live account (not a work/school Microsoft 365 account). It talks to Microsoft Graph directly using an OAuth device-code login, so it runs entirely on your own machine — no third-party service sees your mail.
Tools it exposes: list_folders, inbox_summary, list_messages,
get_message, archive_message, move_message, delete_message,
mark_read, create_reply_draft, bulk variants bulk_mark_read,
bulk_move_messages, bulk_archive_messages, bulk_delete_messages
(all backed by Graph's $batch endpoint, chunked to 20 ops/call),
bulk_by_query (match + act in one call, ids never leave the server),
create_draft (compose a new draft), create_folder, sender_summary
(per-sender counts and read rates), find_newsletters, unsubscribe,
unsubscribe_many and protected_senders (a keep-list bulk ops won't touch).
Common workflows
Decide what to keep — measure, don't guess.
sender_summarygroups a folder by exact sending address and reports count, read, unread andread_pctper sender. A sender nobody opens is evidence; a sender whose name sounds like junk is not. Rows carry a heuristicbrandlabel for display only — grouping is always by the full address, andbrand_sharedflags addresses whose brand collides with another, becausehello@edfenergy.com(bills) andhello@home.edfenergy.com(marketing) are two different senders that must never be merged.Triage a big folder / clear old mail. Use
bulk_by_querywith asearchterm andreceived_beforeto sweep, e.g. delete old shipping notifications:action="delete", search="delivery", received_before="2026-06-01". It runsdry_runfirst (count + sample), then executes on the second call. Custom folders work by name —action="move", destination_folder="Receipts"resolves the name to its id (create it first withcreate_folderif needed).Unsubscribe from newsletters.
find_newsletterslists bulk senders (grouped by sender, with read counts and the best unsubscribe method for each);unsubscribe_many(refs, execute=True)then does the whole sweep in one call. RFC 8058 one-click senders are unsubscribed with a single POST (no browser);mailtosenders get an unsubscribe draft to send; link-only senders — and one-click endpoints that reject the POST, which some privacy portals do with a 405 — come back underneeds_browserwith a URL to open yourself (never auto-fetched). The List-Unsubscribe header means "bulk sender", not "junk": order confirmations, delivery updates, bank statements and voucher codes all carry it, so treat the output as candidates to show a human, never as a sweep list. Then clear the wanted ones withbulk_by_query(action="archive", only_newsletters=True)— theonly_newslettersfilter keeps just the bulk mail (List-Unsubscribe header) among the matches, so you can e.g. archive every newsletter older than a week. Note: unsubscribing confirms your address is live — do it for legitimate senders; for real spam, just delete/block.Protect the mail you can't afford to lose.
protected_senders(add=[...])stores a keep-list — benefits, medical, legal, bills, anything with a case number. A pattern with*/?is a glob over the whole address (*@edfenergy.com, which deliberately does not match a marketing subdomain); one without is a substring test (dwp).bulk_by_querythen excludes protected senders from every sweep and reports how many it held back (on_protected="error"to abort instead,"include"to ignore the list), andbulk_delete_messagesrefuses outright unless called withallow_protected=True. The list lives in~/.outlook_mcp_config.json(override withOUTLOOK_MCP_CONFIG).Act on specific senders.
bulk_by_query(senders_only=[...])filters matches to an exact set of addresses client-side — Graph rejects a sender$filteralongside$orderby, so this is the supported route.Draft an email.
create_draft(to, subject, body)saves to Drafts and never sends — you review and send from Outlook. (This server holdsMail.ReadWrite, which can create drafts but deliberately cannot send.)list_messagesalso takesfetch_all=Trueto page past the default 25-message limit (up tomax_results, default 500) instead of returning a single page.
Token efficiency
Graph message ids are ~150 characters of opaque base64 each, which dominates token cost when listing or bulk-triaging a mailbox. To keep tool traffic small:
Short refs. Listings return a compact
ref(e.g.m12) per message instead of the raw id. Every tool accepts a ref in place of an id and resolves it server-side, so you passm12, not a 150-char string. Refs are stable for the life of the server process; after a restart, just re-list.Lean listings.
list_messagesreturns only triage fields by default. For content, preferinclude_keywords=True(a short salient-word list per message — denser than a preview) and reach forget_messagefor a full read.include_preview=Truestill attaches the full plaintext preview when wanted.Plaintext, truncated bodies.
get_messageasks Graph for the plaintext body (not raw HTML) and truncates tomax_chars(default 4000);include_body=Falsegives metadata only.Compact bulk results. The
bulk_*tools return{"ok": <count>, "failed_count": <n>, "failed": [...]}— succeeded ids are counted, not echoed back.Filter-and-act — ids never touch the conversation.
bulk_by_querymatches messages by folder/filter_query/searchand applies one action (archive/delete/mark_read/mark_unread/move) to all of them server-side, returning just a count. This is the cheapest way to triage: no id list is ever streamed through the model. It runsdry_run=Trueby default (returns a count + small sample and does nothing) so a bad filter can't silently nuke the wrong mail — call again withdry_run=Falseto execute.
1. Create a free Azure app registration (one-time, ~10 min)
You need this to get a client_id. It costs nothing — no Azure subscription
or credit card required for this.
Go to https://portal.azure.com and sign in with your Microsoft account (your outlook.com account works fine as the sign-in).
Search for "App registrations" and click New registration.
Name it anything, e.g.
outlook-mcp-personal.Under Supported account types, choose: "Personal Microsoft accounts only" (or the "any organizational directory and personal Microsoft accounts" option — either works).
Leave Redirect URI blank for now. Click Register.
Copy the Application (client) ID shown on the Overview page — you'll need it below.
In the left nav, go to Authentication → Add a platform → Mobile and desktop applications → check the
https://login.microsoftonline.com/common/oauth2/nativeclientbox → Configure.Still on the Authentication page, scroll down to Advanced settings and set "Allow public client flows" to Yes. Save.
In the left nav, go to API permissions → Add a permission → Microsoft Graph → Delegated permissions → add
Mail.ReadWrite,MailboxSettings.Read,User.Read,offline_access(offline_access is usually pre-added). Click Add permissions. (No admin consent needed for a personal account signing into their own app.)
That's it — no client secret needed, this is a "public client."
Related MCP server: email-mcp
2. Install
cd outlook-mcp
pip install -e .3. Configure
Set the client ID from step 1:
export OUTLOOK_MCP_CLIENT_ID="<your-application-client-id>"(Put this in your shell profile so it persists.)
4. Add to Claude Desktop / Cowork
Edit your Claude Desktop MCP config (Settings → Developer → Edit Config, or
directly at ~/Library/Application Support/Claude/claude_desktop_config.json
on macOS) and add:
{
"mcpServers": {
"outlook-personal": {
"command": "outlook-mcp",
"env": {
"OUTLOOK_MCP_CLIENT_ID": "<your-application-client-id>"
}
}
}
}Restart Claude Desktop. The first time you call a tool, the server prints a
device-login URL and code — open the URL in a browser, enter the code, sign
in with your outlook.com account, and approve. After that, tokens refresh
silently and you won't be prompted again (cached in
~/.outlook_mcp_token_cache.json, permissions 600).
Notes / limitations
delete_messageis a soft delete (moves to Deleted Items), matching how Graph's message DELETE actually behaves — nothing is purged permanently by this tool.create_reply_draftonly creates a draft; it never sends mail on its own.This is a personal single-user tool: the token cache is a plain JSON file on disk, meant for your own machine, not a shared/multi-user deployment.
If you ever want to turn this into a shareable connector, the gap to close is: move off device-code flow to a proper auth-code + PKCE flow with a redirect, host it somewhere, get Microsoft's app verification for the requested scopes, and register it in Claude's MCP directory.
Available Tools
21 toolsarchive_messageB
Move a message (by ref or raw id) to the Archive folder.
| Name | Required | Description | Default |
|---|---|---|---|
| message_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It discloses the outcome location (Archive folder) but says nothing about permissions, idempotency when the message is already archived, reversibility, or failure behavior for invalid ids.
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 short sentence, front-loaded with the action and destination, with zero wasted words.
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 one-parameter mutation tool with no output schema the definition is minimally workable, but the missing id-format detail and lack of any behavioral notes leave an agent with gaps it would have to discover by trial.
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 0%, so the description must compensate. It does add value by noting message_id accepts either a ref or a raw id, but it never defines what a 'ref' looks like or whether both forms are accepted everywhere, leaving the single parameter partly specified.
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 (move/archive) and resource (message) plus a concrete destination (Archive folder), which implicitly separates it from generic move_message. It never explicitly names a sibling, so it falls 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?
Single-message scope is implied by the name and the destination implies a lighter-touch alternative to delete_message, but there is no explicit when/when-not guidance or mention of bulk_archive_messages / move_message as alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bulk_archive_messagesB
Move many messages (refs or raw ids) to the Archive folder in one call.
| Name | Required | Description | Default |
|---|---|---|---|
| message_ids | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It says messages are moved to Archive but omits whether the operation is reversible, permission requirements, partial-failure behavior for invalid ids, and any batch size limits — significant gaps for a bulk mutation tool.
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 puts the action and scope first, with zero filler. Nothing in it repeats structured fields verbatim.
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 bulk mutation tool with no annotations and no output schema, the description is too thin — an agent cannot tell how failures are reported or what happens to a batch with partially invalid ids. The absence of any annotation safety signal leaves the behavioral profile largely undescribed.
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?
There is one parameter with 0% schema description coverage, so the schema says nothing about the argument. The description partially compensates by stating the array accepts 'refs or raw ids', which is genuinely useful identifier-format guidance beyond the schema, but it says nothing about array size limits or empty-list behavior.
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 (move) and resource (many messages) plus the destination (Archive folder) and the batching intent ('in one call'). It differentiates from the singular sibling archive_message through 'many', though it never names the sibling 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?
'in one call' implies this is the batch alternative to archive_message, but the description never states when to prefer the bulk form or whether individual calls are ever appropriate. No exclusions or preconditions are mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bulk_by_queryA
Find every message matching a query and apply one action to all of them in a single call — the message ids never enter the conversation, so this is by far the cheapest way to triage in bulk.
action: one of archive, delete, mark_read, mark_unread, move
(move requires destination_folder, which may be a folder display name).
folder / filter_query / search: same matching semantics as list_messages
(fetches all matches up to max_results).
received_before / received_after: ISO dates (e.g. "2026-01-01"); applied
client-side AFTER matching, so they compose with search — which Graph
itself won't combine with a date $filter. Use these for "old "
sweeps, e.g. search="delivery" + received_before to clear old shipping mail.
only_newsletters: keep only bulk/newsletter mail (messages with a
List-Unsubscribe header) among the matches, e.g. archive all newsletters
older than a week. Costs an extra batched header pass over the matches.
Note this is a bulk-sender signal, not a junk one — plenty of wanted
mail (order updates, voucher codes, statements) carries the header too.
senders_only: keep only matches from these sending addresses (exact,
case-insensitive). Graph rejects a sender $filter combined with
$orderby, so this is applied client-side — it is the supported way to
act per sender. Pair it with sender_summary to pick the addresses.
on_protected: what to do about matches from protected senders (see
protected_senders): "exclude" (default, skip them and report),
"error" (do nothing at all and report), "include" (ignore the list).
dry_run: TRUE by default — returns how many messages would be affected plus a
small sample of subjects/senders, and does nothing. Review it, then call
again with dry_run=False to actually run the action. This guards against
a bad filter nuking the wrong mail.
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | ||
| folder | No | inbox | |
| search | No | ||
| dry_run | No | ||
| max_results | No | ||
| filter_query | No | ||
| on_protected | No | exclude | |
| senders_only | No | ||
| received_after | No | ||
| received_before | No | ||
| only_newsletters | No | ||
| destination_folder | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does most of it: it discloses that dry_run is TRUE by default and what it returns, that on_protected skips protected senders by default, that date/sender filters are applied client-side, and that only_newsletters costs an extra header pass. It stops short of stating whether delete is permanent or recoverable and what the final report looks like.
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?
Long but front-loaded and organized as one labeled block per parameter, so an agent can skim to the field it needs. A few parenthetical asides (the 'old <topic>' sweep example, the newsletter-vs-junk lecture) run longer than strictly necessary, but nothing is wasted 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?
For a 12-parameter, no-annotation, no-output-schema mutation tool this is close to complete: safety defaults, filtering composition rules, and protected-sender behavior are all covered. The remaining gaps are max_results truncation behavior and the shape of the non-dry-run result.
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 0%, so the description must compensate for all 12 parameters, and it explains roughly ten of them including the undocumented-in-schema action enum values and the destination_folder requirement for move. max_results is only mentioned in passing as an upper bound with no default or truncation semantics, and folder's default of inbox is left implicit.
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 — find every message matching a query and apply one action to all of them in a single call — plus the distinguishing benefit (ids never enter the conversation). It is clearly the general filter-driven counterpart to the action-specific siblings (bulk_archive_messages, bulk_move_messages, etc.).
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 prescribes the dry_run-then-rerun workflow, spells out the on_protected policy choices, and tells the agent when to prefer received_before/after over a Graph date $filter and when to use senders_only instead of a sender $filter. It even routes the agent to sender_summary for picking addresses.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bulk_delete_messagesA
Move many messages (refs or raw ids) to Deleted Items in one call, marking them read first (mark_as_read=False to keep them unread).
Refuses and deletes nothing if any message is from a protected sender (see protected_senders) — re-call with allow_protected=True to override. Senders are only known for messages this server has already listed or read; refs it has never seen cannot be checked.
| Name | Required | Description | Default |
|---|---|---|---|
| message_ids | Yes | ||
| mark_as_read | No | ||
| allow_protected | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so well: it discloses the default side effect (marks read first), the all-or-nothing refusal semantics ('deletes nothing if any message is from a protected sender'), the override flag, and a real limitation (senders unknown for unlisted refs). That is non-obvious, decision-critical behavior an agent cannot infer from the 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?
Roughly three short sentences, front-loaded with the action and destination, then the refusal rule and the data-availability caveat. No filler; every clause adds 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?
Covers action, defaults, failure mode, and override for a mutation tool with no annotations and no output schema. It omits what the call returns (counts, per-id results) and how unknown or malformed ids are handled, but the agent has enough to invoke it correctly.
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 0%, so the description must compensate and does: message_ids accepts 'refs or raw ids', mark_as_read defaults true with the False case explained, and allow_protected is tied to the protected-sender refusal. All three parameters get meaning beyond their bare type and default.
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 scope: 'Move many messages (refs or raw ids) to Deleted Items in one call.' The bulk framing plus the destination folder distinguishes it implicitly from the singular delete_message and from bulk_move_messages, which targets arbitrary folders.
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 path: if the call refuses due to a protected sender, 're-call with allow_protected=True to override.' It does not explicitly route the agent to delete_message for single messages or bulk_move_messages for other folders, so it falls short of full when/when-not coverage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bulk_mark_readB
Mark many messages (refs or raw ids) read/unread in one call (Graph $batch).
| Name | Required | Description | Default |
|---|---|---|---|
| is_read | No | ||
| message_ids | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden. It usefully discloses the underlying Graph $batch mechanism and that the operation toggles rather than only sets read state, but says nothing about per-message failure handling, batch limits, or required permissions.
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 with no filler. The only cost is terse jargon ('refs', '$batch') that may need unpacking.
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 2-parameter bulk mutation with no annotations and no output schema, the description covers the core action but leaves out failure semantics and batching constraints an agent would need to call it safely.
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 0%, so the description must compensate. It does add real meaning for message_ids by noting 'refs or raw ids', and 'read/unread' hints at the is_read boolean, but is_read is never named and no format details or default (true) are given in prose.
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 ('Mark many messages ... read/unread in one call') and the parenthetical '(refs or raw ids)' plus 'many ... in one call' implicitly separates it from the singular mark_read sibling. It does not explicitly name the alternative, 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?
Usage is only implied: 'many ... in one call' signals this is the bulk/efficient path versus mark_read, but the description never says when to prefer it, whether there is a batch size limit, or when to fall back to the single-message tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bulk_move_messagesB
Move many messages (refs or raw ids) to a folder (id or well-known name) in one call.
| Name | Required | Description | Default |
|---|---|---|---|
| message_ids | Yes | ||
| destination_folder | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full disclosure burden. It signals batching ('in one call') but says nothing about permissions needed, behavior on unknown message ids or missing folders, whether the batch is atomic or partially applied, or batch size limits — significant gaps for a mutation tool.
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 verb and resource, with zero filler. It is efficient, though the terseness leaves little room for the behavioral and parameter detail a bulk mutation tool arguably 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?
With no annotations, no output schema, and 0% schema description coverage, the description should cover more: mutation semantics, failure modes, and return/confirmation behavior are all absent. An agent can form a call but cannot anticipate how errors or partial failures are handled.
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 0%, so the description must compensate, and it does partially: message_ids accepts 'refs or raw ids' and destination_folder accepts an 'id or well-known name.' This adds real meaning beyond the bare string/array types, but leaves 'ref' undefined and gives no examples for either 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 ('Move many messages') plus the bulk scope 'in one call,' which implicitly separates it from the sibling move_message. It does not explicitly name that sibling, but an agent can distinguish bulk from single-message moves without reading the 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?
Usage is implied by 'many messages ... in one call,' suggesting it is for batch relocation rather than single moves. However, there is no explicit when-to-use/when-not guidance, no mention of when to prefer bulk_by_query or move_message, and no note on prerequisites such as folder existence.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_draftA
Compose a brand-new draft email (NOT a reply). It is saved to Drafts and never sent — you review and send it from Outlook.
Args: to: recipient email addresses. subject: subject line. body: message body (plain text by default; set html=True to send HTML). cc: optional cc email addresses. html: treat body as HTML instead of plain text.
| Name | Required | Description | Default |
|---|---|---|---|
| cc | No | ||
| to | Yes | ||
| body | Yes | ||
| html | No | ||
| subject | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It usefully discloses that the message is saved to Drafts and never sent, but it does not mention permissions/auth needs, return behavior, or what happens on invalid recipients.
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-loads the key purpose and non-sending behavior, then uses a compact Args list for parameters. There is no wasted text.
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 no annotations and no output schema, the description is mostly complete for calling the tool: it explains the action, non-send guarantee, storage location, and all parameters. It could be stronger with auth/error or return details, but the core invocation needs are covered.
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 0%, so the description must compensate, and it does document all five parameters: to, subject, body, optional cc, and html. It adds useful semantics such as body being plain text by default and html=True making it HTML, though array/string details are left to 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 (compose a brand-new draft email) and explicitly excludes replies, which distinguishes it from the sibling create_reply_draft. It also clarifies that the draft is saved, not sent.
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 context: brand-new email, not a reply, saved to Drafts and not sent. The alternative create_reply_draft is strongly implied by 'NOT a reply,' though not explicitly named as the tool to use instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_folderB
Create a mail folder. parent_folder (id or display name) nests it; omit for a top-level folder. Useful before moving mail into a new folder.
| Name | Required | Description | Default |
|---|---|---|---|
| display_name | Yes | ||
| parent_folder | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It does not say what happens on a duplicate display_name, whether creation is idempotent, what permissions are required, or what the call returns (a folder id would plausibly be needed for later moves). For a mutation tool with zero annotation coverage this is a substantial 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?
Two sentences with the core action and the key parameter behavior front-loaded, followed by a short usage hint. Nothing is padded, though the trailing usage sentence is thinner than it could be.
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 annotations, no output schema, and 0% schema description coverage, the definition should explain return value and duplicate-name behavior. It covers the parameters' meaning adequately but leaves the agent guessing about failure modes and what it gets back.
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 0%, so the description must compensate, and it does half the job: parent_folder is explained as accepting an id or display name and being omittable for a top-level folder, which the schema does not convey. display_name is only implicitly characterized as the folder's name; no constraints (uniqueness, length, allowed characters) are given.
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 ('Create a mail folder'), which no sibling shares — list_folders reads, create_folder writes. It also distinguishes the nested vs top-level case. It stops short of noting what the call returns or how it differs from other creation tools like create_draft, but the resource 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 phrase 'Useful before moving mail into a new folder' implies the workflow (create_folder then move_message) but never names move_message or states when not to use it. Usage context is implied rather than spelled out, so an agent must infer the sequencing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_reply_draftA
Create a draft reply to a message (by ref or raw id). Does NOT send it; a human reviews/sends from Outlook.
| Name | Required | Description | Default |
|---|---|---|---|
| comment | No | ||
| message_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and does disclose the crucial non-sending, human-review behavior. It omits whether it produces a reply vs reply-all, and whether existing draft conflicts overwrite anything.
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 compact sentences, front-loaded with the action and immediately followed by the non-send caveat. 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?
For a simple 2-param tool with no output schema this is nearly adequate, but the undefined 'comment' parameter and no guidance on return value or draft location leave a real 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 coverage is 0%, so both parameters are undocumented in structured data. The description explains message_id accepts 'ref or raw id', but the 'comment' parameter is never mentioned, leaving its role (reply body?) entirely unclear.
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 ('Create a draft reply to a message') with an explicit parenthetical on id format. It is distinguishable from create_draft, though it doesn't explicitly contrast with that sibling.
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 clause 'Does NOT send it; a human reviews/sends from Outlook' implies this is the right choice when you want a human-gated reply rather than a send. However, it never explicitly says when to use this versus create_draft or which message types are eligible.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_messageA
Move a message (by ref or raw id) to Deleted Items — recoverable from there until you empty it. Marks it read first (mark_as_read=False to keep it unread) so deleted mail doesn't linger in your unread count.
| Name | Required | Description | Default |
|---|---|---|---|
| message_id | Yes | ||
| mark_as_read | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does real work: it discloses the soft-delete/recoverability model ('recoverable from there until you empty it') and an otherwise invisible side effect (message is marked read before deletion, configurable via mark_as_read). It stops short of error behavior for already-deleted or missing messages.
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, no filler: destination and recoverability first, then the side effect and its override. Every clause earns 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?
For a two-parameter mutation with no annotations and no output schema, the description covers destination, reversibility, and side effects. What remains unstated (error/idempotency behavior on an already-deleted message, return value) is minor but not zero.
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 0%, so the description must compensate, and it does for mark_as_read — naming the default's purpose (keep deleted mail out of the unread count) and the opt-out (mark_as_read=False). It also clarifies that message_id accepts either a reference or a raw id, which the bare 'string' schema does not convey.
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 ('Move a message ... to Deleted Items') plus the accepted identifier forms ('by ref or raw id'), which distinguishes it from move_message (arbitrary destination) and bulk_delete_messages (plural). An agent can pick it without opening the 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?
The recoverable-vs-permanent distinction implies this is a soft delete, but it never states when to prefer delete_message over archive_message, move_message, or bulk_delete_messages, nor any precondition (e.g. message must not already be deleted). Usage is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_newslettersA
Scan a folder for bulk mail (messages carrying a List-Unsubscribe header) and report how each sender can be unsubscribed.
Grouped by sender by default, because unsubscribing is per sender while the underlying listing is per message — the ungrouped form makes the model dedupe 200 rows by hand to reach the ~50 decisions that actually exist. Each row carries read/unread counts so a sender can be judged on engagement rather than on what its name suggests.
IMPORTANT: the List-Unsubscribe header marks a bulk sender, not junk. Order confirmations, delivery updates, statements and voucher codes all carry it. Treat this as a list of candidates to show the user, never as a list to sweep.
Returns {checked, headers_ok, header_fetch_failed, newsletter_messages, senders: [...]}. The header counts are there so a discrepancy between this and bulk_by_query(only_newsletters=True) is visible rather than mysterious: header sub-requests that fail are silently dropped from the scan.
Args: folder: folder id or well-known name. max_check: how many recent messages to scan. group_by_sender: set False for the raw per-message rows.
| Name | Required | Description | Default |
|---|---|---|---|
| folder | No | inbox | |
| max_check | No | ||
| group_by_sender | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the full burden and does: it discloses that failing header sub-requests are silently dropped, explains the resulting discrepancy against bulk_by_query(only_newsletters=True), and warns that the List-Unsubscribe header marks bulk senders rather than junk. This is exactly the kind of failure-mode and misinterpretation context an agent needs.
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 action and the detection rule, then the IMPORTANT caveat, then the return shape, then args — a sound ordering. It runs a little long, and the sentence about the model deduping 200 rows by hand is motivational rather than operational, but 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?
With no annotations and no output schema, the description supplies the return shape ({checked, headers_ok, header_fetch_failed, newsletter_messages, senders}), the rationale for those fields, and the semantic trap to avoid. Nothing an agent needs in order to call it or interpret it 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 0%, so the description must compensate, and it documents all three parameters: folder accepts an id or well-known name, max_check bounds how many recent messages are scanned, and group_by_sender=False yields raw per-message rows. It does not give an example of a well-known folder name, which would have closed the gap fully.
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 ('Scan a folder for bulk mail... and report how each sender can be unsubscribed') and pins down the detection criterion (List-Unsubscribe header). It is clearly distinct from unsubscribe/unsubscribe_many (discovery, not action) and from bulk_by_query, which it names 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?
Gives a strong exclusion ('Treat this as a list of candidates to show the user, never as a list to sweep') and explains why grouping is the default and when to set group_by_sender=False. It stops short of explicitly naming the sibling that performs the unsubscribe, leaving that hop implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_messageA
Get one message by ref (or raw id). Body is returned as plaintext and truncated to max_chars to keep it token-cheap.
Args: message_id: a short ref from list_messages (e.g. "m12"), or a raw Graph id. include_body: set False to get metadata only (subject/from/date), no body. max_chars: truncate the plaintext body to this many characters (0 = no limit).
| Name | Required | Description | Default |
|---|---|---|---|
| max_chars | No | ||
| message_id | Yes | ||
| include_body | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations the description carries the full load, and it discloses non-obvious traits: body is converted to plaintext, truncated, and the truncation exists for token economy. It does not cover invalid/expired ref behavior or whether attachments/HTML structure are dropped, which are the remaining gaps for a read tool.
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 sentence states purpose and the two most important behaviors (plaintext, truncation) before the Args breakdown. The Args block is tight, though it slightly duplicates the schema's field names.
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, and the description covers what comes back: subject/from/date in metadata-only mode and a plaintext body otherwise, plus the size cap. Error handling and ref lifetime are the only notable omissions for a single-item read 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 0%, so the description must compensate, and it does: it explains the accepted id formats, the effect of include_body, and the semantics of max_chars including the 0 sentinel. It omits the actual default values (4000 and true) that the schema declares, so an agent must open the schema for those.
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 ('Get one message by ref') and pins the identifier form ('a short ref from list_messages, or a raw Graph id'). It is clearly differentiable from list_messages, which is named as the source of refs.
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 actionable per-parameter usage: include_body=False for metadata-only, max_chars=0 for no limit. The ref-from-list_messages hint establishes the workflow. It stops short of explicit when-not-to-use guidance (e.g., use list_messages for searching, or bulk tools for many messages).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
inbox_summaryA
Quick counts for the inbox: total messages and unread messages.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are supplied, so the description must carry behavioral disclosure. It does say what the tool returns (two counts), implying a lightweight read, but it does not state whether the operation is read-only, whether counts are scoped to a folder, or how counts are affected by unread state — modest but not rich 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?
A single front-loaded sentence that identifies the tool and its output with zero wasted words.
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-parameter summary tool with no output schema, the description conveys the essentials of what is returned. It could clarify scope (which inbox/folder) and read-only nature, but it is close to complete for this complexity level.
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?
The schema has zero parameters and 100% coverage, so there is nothing for the description to disambiguate. The baseline for a no-parameter tool 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 ('quick counts') and resource ('the inbox') plus the two values returned: total messages and unread messages. An agent can tell this is a summary/count tool distinct from siblings like list_messages or sender_summary, though it does not explicitly name those alternatives.
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 word 'quick' implies this is a lightweight overview rather than a message-listing tool, but there is no explicit statement of when to use it versus list_messages or sender_summary, and no exclusions are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_foldersA
List all mail folders (Inbox, Archive, Deleted Items, custom folders, etc.) with their ids and display names.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden of behavioral disclosure. It communicates scope by saying "all mail folders" and lists returned fields, but it does not explicitly state that the operation is read-only, whether folders are ordered or nested, or any permission 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?
The description is a single, front-loaded sentence that immediately states the action and return fields. The examples are useful and 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?
For a zero-parameter listing tool with an output schema, the description is nearly complete: it names the resource, scope, and returned fields. Minor gaps remain around folder hierarchy, ordering, or whether all folder types are always included.
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?
The tool has zero parameters, so the baseline score is 4 under the rubric. The description does not need to explain parameter semantics, and the empty schema is consistent with 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?
The description states a specific verb and resource: "List all mail folders," and adds concrete examples such as Inbox, Archive, and custom folders. It clearly distinguishes folder listing from message listing, though it does not explicitly contrast with sibling tools like create_folder or list_messages.
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: an agent would call this to discover folder ids and display names before operations like move_message or list_messages. However, the description does not explicitly state when to use this tool versus alternatives, nor does it include exclusions or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_messagesA
List messages in a folder, newest first (unless searching).
Returns compact rows keyed by a short ref handle (not the raw Graph id) —
pass that ref to get_message / move / delete / the bulk_* tools.
Args:
folder: folder id or well-known name (inbox, archive, deleteditems, sentitems, drafts, junkemail).
top: max number of messages to return per page (ignored if fetch_all is True).
skip: number of messages to skip, for manual paging (ignored if fetch_all is True).
filter_query: raw OData $filter, e.g. "receivedDateTime le 2026-01-01T00:00:00Z" or "isRead eq false".
search: free-text search (Graph $search); when set, filter_query/order are ignored.
fetch_all: if True, follow pagination automatically and return up to max_results messages
instead of a single page of top. Use this for bulk operations over a whole folder.
max_results: cap on messages returned when fetch_all is True (safety limit, default 500).
include_keywords: attach a short salient-keyword list per message (subject+preview) for triage.
include_preview: attach the full plaintext preview per message. Prefer include_keywords for triage
and get_message for a full read — a preview per message across a big folder is costly.
| Name | Required | Description | Default |
|---|---|---|---|
| top | No | ||
| skip | No | ||
| folder | No | inbox | |
| search | No | ||
| fetch_all | No | ||
| max_results | No | ||
| filter_query | No | ||
| include_preview | No | ||
| include_keywords | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the full burden and does well: it discloses default ordering, the `ref` handle indirection, automatic pagination under fetch_all, a default safety cap of 500, and an explicit cost warning that per-message previews across a big folder are expensive. It stops short of stating read-only semantics, auth/permission needs, 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?
Front-loaded with the one-line purpose, ordering, and the critical `ref` handoff before the Args block, and each Args line adds real information rather than restating a name. It runs long, but the length is driven by nine undocumented parameters, so little 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 elaboration beyond the `ref` handoff, which is supplied anyway. For a zero-required-parameter, nine-argument listing tool with no annotations, an agent has everything needed to page, filter, search, or bulk-fetch correctly.
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 0%, so the description must compensate entirely and it does — all nine parameters are explained with behavior the schema cannot express: well-known folder names enumerated, top/skip nullified by fetch_all, an OData $filter example, search precedence over filter, and max_results described as a safety limit with its default.
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 messages in a folder') plus the default ordering and the one condition that changes it ('newest first (unless searching)'). It also explains the returned shape ('compact rows keyed by a short `ref` handle (not the raw Graph id)'), which instantly distinguishes it from get_message and the bulk_* siblings.
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 conditions for the tricky flags: fetch_all for whole-folder bulk work, include_keywords for triage vs get_message for a full read, and notes that search causes filter_query/order to be ignored. It does not, however, route the agent between this tool and siblings like inbox_summary, sender_summary, or bulk_by_query, so the alternatives coverage is partial.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mark_readB
Mark a message (by ref or raw id) as read or unread.
| Name | Required | Description | Default |
|---|---|---|---|
| is_read | No | ||
| message_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the full burden. It helpfully discloses that the operation is a toggle (read OR unread), but says nothing about idempotency, permission requirements, behavior for an unknown message_id, or what is returned — significant gaps for a mutation tool.
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 with zero waste. The action and the toggle semantics are both delivered immediately.
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 two-parameter mutation with no annotations and no output schema, the description covers the core semantics but leaves the agent guessing about idempotency, error behavior, and return value. Adequate minimum, with clear gaps.
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 0%, so the description must compensate. It adds real meaning to message_id by revealing it accepts 'a ref or raw id', and to is_read via 'as read or unread', but it does not explain the ref format, why two input forms exist, or the default of is_read=true — so the compensation is only partial.
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 ('mark a message ... as read or unread'), and the singular 'a message' implicitly distinguishes it from the bulk_mark_read sibling. However, it never names or contrasts that sibling explicitly, so the 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?
Usage is only implied: the singular 'a message' suggests single-message operation, and the sibling list contains bulk_mark_read, but the description never states when to use this versus the bulk variant. No prerequisites or exclusions are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
move_messageB
Move a message (by ref or raw id) to a folder (id or well-known name).
| Name | Required | Description | Default |
|---|---|---|---|
| message_id | Yes | ||
| destination_folder | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It does not say whether the destination folder must already exist, whether moving requires permissions, what happens on invalid IDs, or what the response looks like.
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 tightly-worded sentence that front-loads the action and resource with zero waste. The parenthetical parameter hints are efficient rather than verbose.
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 annotations, no output schema, and 0% schema description coverage, the description needs to do more. It covers the basic action and parameter formats but omits error behavior, folder prerequisites, and return semantics for a simple two-parameter mutation.
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 0%, so the description must compensate and does so partially: it clarifies message_id accepts a ref or raw id and destination_folder accepts an id or well-known name. That adds real meaning beyond the bare schema, but the accepted formats/values are not fully specified.
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 (move) and resource (message) plus the destination concept (folder). It is clear what the tool does, though it does not explicitly name a sibling like bulk_move_messages to distinguish the single-message case.
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 only implied by the singular 'a message', which suggests it is for one message rather than bulk operations. It never states when to use this instead of bulk_move_messages or archive_message, leaving the agent to infer the single-vs-bulk distinction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
protected_sendersA
Read or edit the keep-list of senders that bulk operations won't touch.
Patterns are matched case-insensitively against the sending address: one containing * or ? is a glob over the whole address ("*@edfenergy.com"), one without is a substring test ("dwp"). Use this for the mail that would be expensive to lose — benefits, legal, medical, bills, anything with a case number — so a broad sweep can't reach it.
bulk_by_query excludes protected senders by default and says how many it held back; bulk_delete_messages refuses outright. Both can be overridden per call once you've looked.
Call with no arguments to just read the list.
| Name | Required | Description | Default |
|---|---|---|---|
| add | No | ||
| remove | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so well: it discloses case-insensitive matching, glob vs substring semantics, default exclusion behavior in bulk_by_query, outright refusal in bulk_delete_messages, and per-call override 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?
The description is front-loaded with the core purpose, then adds only relevant pattern and bulk-operation details. Every sentence contributes useful 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 low-complexity tool with optional parameters and no output schema, the description is nearly complete. Minor gaps remain around return shape for reads and edge cases such as duplicates or invalid patterns.
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 0%, so the description needs to compensate. It explains the pattern syntax well and clarifies no-argument reads, but does not explicitly describe the add and remove array parameters beyond what their names imply.
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 pair: reading or editing a keep-list of protected senders. It also distinguishes the tool from bulk siblings by explaining that bulk operations will not touch these senders.
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 explicitly says when to use the tool, gives examples of valuable mail to protect, explains that no arguments means read-only access, and describes how bulk_by_query and bulk_delete_messages behave with this list.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sender_summaryA
Group a whole folder by sending address and report, per sender, how many messages there are and how many were actually opened.
This is the tool to reach for before proposing anything for deletion. A sender's read rate is measured evidence of whether the mailbox owner wants their mail; guessing from the brand name is not, and gets it wrong.
Returns rows {sender, brand, domain, count, read, unread, read_pct,
newest, oldest, sample_ref}, biggest sender first. brand is a heuristic
display label — never group or delete by it. brand_shared: true marks a
row whose brand label also belongs to another address in the result
(e.g. a billing subdomain and a marketing subdomain of one company):
those are different senders and must stay separate.
Args: folder: folder id or well-known name. min_count: drop senders with fewer than this many messages. top: return at most this many sender rows (after sorting by count). max_results: cap on messages scanned. unread_only: summarise only unread mail.
| Name | Required | Description | Default |
|---|---|---|---|
| top | No | ||
| folder | No | inbox | |
| min_count | No | ||
| max_results | No | ||
| unread_only | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden well: it discloses return fields, sorting order, the max_results scan cap, and important caveats about heuristic brand labels and shared brands. It does not cover error behavior or permissions, but for a read-only summary tool this is substantially transparent.
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 purpose is front-loaded, then usage rationale, return shape, and caveats follow in a logical order. The length is justified by the grouping semantics and the brand-label warning.
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 or annotations exist, yet the description explains the returned row fields, ordering, and the key grouping caveat around brand and brand_shared. That is enough for an agent to invoke and interpret the summary correctly.
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 0%, but the Args block explains all five parameters, including folder identification, min_count filtering, top row limits, max_results message scanning, and unread_only. This adds clear meaning beyond the bare schema titles and defaults.
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: group a folder by sending address and report per-sender message/read counts. The scope is precise enough to distinguish it from generic message-listing or folder-summary siblings.
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 says to use it before proposing deletion and explains why read-rate evidence matters. It does not name sibling alternatives such as find_newsletters or protective-sender tools, so it stops short of full when/when-not routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
unsubscribeA
Unsubscribe from the bulk sender of a message (ref or raw id).
Reads the message's List-Unsubscribe headers and:
method "one-click": with execute=True, performs the RFC 8058 one-click POST and returns the HTTP status — no browser needed.
method "mailto": with execute=True, creates a DRAFT unsubscribe email to the sender's unsubscribe address for you to send (our mail scope can create but not send mail).
method "weblink": returns the URL for you to open in a browser; not auto-fetched, since blindly GETting links embedded in email is unsafe.
With execute=False (default) it only reports the available method/target so you can decide. Caveat: unsubscribing confirms your address is live, so do it for legitimate senders — for actual spam, prefer delete/block instead.
| Name | Required | Description | Default |
|---|---|---|---|
| execute | No | ||
| message_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so: it discloses the three method branches, that one-click returns HTTP status, that mailto only creates a DRAFT (scope cannot send), that weblinks are deliberately not auto-fetched for safety, and the caveat that unsubscribing confirms the address is live. These are exactly the side effects and risks an agent needs before mutating state.
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 a scannable bullet list per method, ending with the important caveat. Dense and mostly waste-free, though the repeated 'with execute=True' phrasing in each bullet is slightly redundant against the standalone default sentence.
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 and no annotations, yet the description explains what each branch returns (HTTP status, draft, URL, or a method/target report). It doesn't say what happens when a message has no List-Unsubscribe header, the one gap an agent might hit in practice.
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 0%, so the description must compensate, and it does: 'message_id' is described as a ref or raw id, and 'execute' is fully explained as the gate between report-only and performing the action, far beyond the bare boolean/default in 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 ('Unsubscribe from the bulk sender of a message') and clarifies the identifier accepts a ref or raw id. It is easily separable from siblings like delete_message, unsubscribe_many, and find_newsletters because it names the exact mechanism (List-Unsubscribe headers).
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 documents that execute=False is a dry-run report and execute=True performs the action, with behavior varying by method. It also gives a real exclusion rule: 'for actual spam, prefer delete/block instead,' routing the agent to sibling tools for the wrong case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
unsubscribe_manyA
Unsubscribe from many bulk senders in one call.
Deduplicates on the unsubscribe target, never on the sender: LinkedIn job alerts all arrive from one address but carry a different savedSearchId each, so skipping by sender leaves most streams subscribed while reporting success. Two messages for the same stream still carry different per-message tokens and so both get posted — a wasted request is cheaper than a missed unsubscribe.
Same per-message semantics as unsubscribe(), but the header fetch is batched and the whole sweep is one tool call instead of one per sender.
Returns {attempted, unsubscribed, needs_browser, drafted, failed,
results: [...]}. needs_browser collects the senders whose only working
route is a URL a human must open — including one-click endpoints that
rejected the POST — so nothing fails silently.
| Name | Required | Description | Default |
|---|---|---|---|
| execute | No | ||
| message_ids | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and does well: it discloses dedup keying on target rather than sender, the deliberate tradeoff of duplicate requests over missed unsubscribes, batching of the header fetch, and the needs_browser bucket so 'nothing fails silently'. It omits any mention of the execute flag's default-false/dry-run behavior and required permissions, which are the most consequential behaviors for a mutation tool.
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 and the sibling comparison are front-loaded, and the dedup rationale, while long, explains behavior an agent may need to reason about. Some of the savedSearchId narrative is more justification than instruction and could be tightened.
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?
The return shape is spelled out well, which is valuable with no output schema, and the batching/dedup model is covered. But for a two-param mutation tool with no annotations, leaving the execute dry-run flag completely unexplained is a material 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 coverage is 0% and neither parameter is described. message_ids is only indirectly implied by talk of per-message tokens and savedSearchId, and the execute boolean (default false) is never mentioned at all — the agent cannot tell from the definition whether the call actually unsubscribes or only previews.
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 and scale ('Unsubscribe from many bulk senders in one call'), and explicitly contrasts itself with the sibling unsubscribe() as the batched variant. An agent can distinguish it from unsubscribe and from bulk_* tools 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?
Names the alternative ('Same per-message semantics as unsubscribe(), but ... one tool call instead of one per sender'), which tells the agent to prefer this for multi-sender sweeps. It never states the inverse condition (when to use the single-message tool, or that a single ID should go to unsubscribe()), so the guidance is clear but not fully two-sided.
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.
21 tool updates
v0.1.0- First observed
archive_message - First observed
bulk_archive_messages - First observed
bulk_by_query - First observed
bulk_delete_messages - First observed
bulk_mark_read - First observed
bulk_move_messages - First observed
create_draft - First observed
create_folder - First observed
create_reply_draft - First observed
delete_message - First observed
find_newsletters - First observed
get_message - First observed
inbox_summary - First observed
list_folders - First observed
list_messages - First observed
mark_read - First observed
move_message - First observed
protected_senders - First observed
sender_summary - First observed
unsubscribe - First observed
unsubscribe_many
TDQS
Scored across 21 tools
The core distinction between single-message and bulk tools is mostly clear, but bulk_by_query overlaps heavily with the dedicated bulk_* tools and with archive_message/move_message/delete_message/mark_read. archive_message also largely duplicates move_message to Archive, and find_newsletters overlaps with bulk_by_query(only_newsletters=True), so an agent has several plausible routes for the same operation.
Most tools use snake_case and are readable, but the naming convention is mixed: many are verb_noun (list_messages, move_message, create_draft), while others are noun-centric or phrase-based (inbox_summary, sender_summary, bulk_by_query, protected_senders). It is not chaotic, but the pattern is not predictable enough for a high score.
At 21 tools, the server is in the heavy borderline range. The domain is complex enough to justify many operations, but there is noticeable duplication between general bulk actions, dedicated bulk tools, and single-message action tools, which inflates the surface.
The tool set covers the main mail triage lifecycle well: folders, listing/reading messages, summaries, drafts and reply drafts, single and bulk move/delete/archive/mark operations, newsletter discovery/unsubscribe, and protected senders. Minor gaps remain, such as sending mail, attachment handling, folder rename/delete, and draft editing, but core workflows are covered.
Maintenance
Related MCP Connectors
Your IMAP mailbox as an MCP server: read, search and (if you allow it) organize mail. Open source.
Hosted email MCP for your own Gmail, Outlook.com, Microsoft 365, iCloud or IMAP inbox: read, search, draft, reply in thread, forward and file mail. It moves or flags up to 500 messages in one call, and a send leaves exactly one copy in Sent. A calendar is a separate connection, and connecting one adds diary and scheduling tools.
MCP server for Nylas — read email, calendars, events and contacts, and send email or create events.
MCP server for MailTempo's public free temporary email inboxes.
Related MCP Servers
- FlicenseAqualityDmaintenanceA lightweight MCP server for personal Microsoft Outlook/Hotmail accounts, enabling email search, reading, attachment management, and folder operations via Microsoft Graph API with OAuth device-code flow.61-
- AlicenseAqualityDmaintenanceLocal MCP server for multi-account IMAP/SMTP email (iCloud + Gmail via app-specific passwords). Never marks mail read. Cross-folder search, idempotent sends, TLS verified.823 PyPIMIT
- AlicenseAqualityDmaintenanceA local MCP server that connects Claude Desktop to a personal Hotmail/Outlook.com mailbox via Microsoft Graph API, enabling email management, rule handling, and composing messages.25MIT
- AlicenseNot gradedqualityDmaintenanceMCP server providing full control over Outlook.com, Hotmail, Live, or Microsoft 365 email via Microsoft Graph API, enabling reading, searching, sending, and managing messages and folders securely.1MIT