imap-mcp
Click on "Install 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., "@imap-mcpFind the latest email from my bank and save the PDF attachment."
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.
imap-mcp
A Model Context Protocol (MCP) server for any IMAP mailbox. It speaks IMAP rather than one vendor's API, so it works with whatever provider you already have.
Lets MCP clients like Claude Code, Claude Desktop or Codex read and search your mail, organise it into folders, save attachments and draft replies — with every message fenced as untrusted content, and the write tools off unless you turn them on.
Eleven tools, not fifty: a mail account is a workflow, not an API surface, so related
operations are folded into one tool with a mode rather than split across many. And eleven is
the ceiling, not the floor — IMAP_ALLOW_TOOLS=essential registers a curated six instead, and
under the read-only default that narrows to four. See
choosing which tools load.
What makes it different
It cannot send mail. That is the feature. An agent with access to private data, exposure to
untrusted content, and a channel to the outside world is exploitable by anyone who can put a
message in the inbox — the pattern that produced
EchoLeak, where one
crafted email exfiltrated internal data from Microsoft 365 Copilot with no user interaction.
This server has the first two and deliberately not the third. save_draft writes the reply
into your Drafts folder; you send it from your own mail client. No amount of clever text in a
message can make this server post anything anywhere.
Writes are off until you turn them on. With only IMAP_HOST, IMAP_USER and
IMAP_PASSWORD set, the server registers six read tools and nothing else. The mailbox tools
appear with IMAP_READ_ONLY=false — note the default is true, the opposite of the other
servers in this family, because this one reaches a mailbox. Tools that are off are not registered at all — a
capability the model cannot see is one it cannot be talked into using.
Mail is treated as hostile input, because it is. Anyone in the world can put text in your inbox. Message bodies are fenced between markers carrying a per-call random nonce, and every line inside them is prefixed with that nonce, so the "this is data" signal does not stop at the edges of a long forwarded thread. A reminder follows the block, because otherwise the last instruction-shaped sentence in the model's context is the attacker's. Zero-width characters and directional overrides are stripped before the model sees anything, hidden HTML elements are dropped on a best-effort basis (the fencing, not the stripping, is what carries the weight), and markdown image syntax — inline and reference style — is defused so a rendering client cannot be made to fetch a tracking URL.
Alongside the message you get a server-side assessment: the SPF/DKIM/DMARC verdicts with the authserv-id they came from, which prompt-injection shapes matched, and which words mix Latin with Cyrillic or Greek letters. When something matches, the warning is the first thing in the result rather than a field buried in JSON.
Those verdicts carry a forgeable flag, and by default it is always true. A sender can write
an Authentication-Results header of their own, and if your provider does not add one, theirs
is the only one there — nothing inside the message distinguishes the two. Set
IMAP_TRUSTED_AUTHSERV_ID to the id your provider stamps (it is the first token of the header
on any message you already have) and only that id counts as authentic. Until you do, spf=pass
is reported as what it is: a claim, from a header anyone could have written.
"New mail" that actually works. The server tags messages it has handed over with a custom
IMAP keyword (AiSeen by default), so list_new_messages returns each message once. The human
\Seen state is never touched — everything is read with BODY.PEEK.
Deleting asks a person. Where the client supports MCP elicitation, delete_messages and
deleting a folder raise a real dialog that the model cannot answer on its behalf. Where it does
not, they fall back to a two-call token — and say so, rather than implying somebody approved.
Related MCP server: Mac Local Mail MCP
Requirements
Node.js 22 or newer
An IMAP account. Providers with two-factor authentication generally need an app-specific password.
Configuration
Variable | Required | Default | Description |
| yes | — | Hostname of the IMAP server, e.g. |
| yes | — | Account username, usually the address |
| yes | — | Password or app-specific password |
| no |
| Defaults by TLS mode |
| no |
|
|
| no |
| Mailbox the message tools default to |
| no |
| Exactly |
| no | — | Tool names, |
| no | — | Same syntax; subtracted from the allow list |
| no |
| Keyword for new-mail tracking; empty turns it off |
| no | — | The authserv-id your provider stamps; see below |
| no | auto | Overrides the folder found via the |
| no |
| Default page size |
| no |
| Ceiling for returning an attachment inline |
| no |
| Ceiling for writing one to disk |
| no | see below | Comma-separated content-type allowlist |
| no | — | Setting it allows saving attachments there |
| no |
| Exactly |
Booleans are compared against the literal string true; 1, yes and True are not true.
IMAP_READ_ONLY is the mirror image: only the literal false turns it off, so a typo leaves
the write tools unregistered.
IMAP_ALLOW_WRITEis gone. It has been replaced byIMAP_READ_ONLY, and an installation that still sets it refuses to start. Silently ignoring a removed security variable is the worst of the options: whoever set it once believes it is still in force. The default is unchanged — writes are still off unless you ask for them.
Choosing which tools load
IMAP_ALLOW_TOOLS and IMAP_DENY_TOOLS take comma-separated tool names; a trailing *
matches a whole family. essential is a curated preset of six — list_mailboxes,
list_new_messages, list_messages, get_message, set_message_flags and move_messages.
Four of those are read tools, so it stays useful under the read-only default.
IMAP_ALLOW_TOOLS=essential
IMAP_ALLOW_TOOLS=list_new_messages,get_message,move_messages
IMAP_DENY_TOOLS=delete_messagesAn entry that matches no tool aborts startup and names it, so a typo cannot silently hide a
tool — an absent tool is not something anyone traces back to an environment variable. A
filtered tool is never registered, so it is absent from tools/list and unknown to
tools/call alike, exactly like a write tool under IMAP_READ_ONLY.
It covers tools. The attachment resources this server also exposes are not filtered.
If you run several of these servers at once, mcp-hub is the other
answer — its /hub endpoint replaces every server's tools with six meta-tools.
The password is deleted from the process environment as soon as it is read, so it is not
visible to child processes or in /proc/<pid>/environ.
Without IMAP_DOWNLOAD_DIR this server never writes to the filesystem. The two size limits are
separate on purpose: one protects the model's context window, the other protects your disk.
The server starts without credentials on purpose — it completes the handshake and lists its tools, and every call then fails with setup instructions instead of reaching a server.
Installation
Claude Code
claude mcp add imap-mcp \
-e IMAP_HOST=imap.example.net -e IMAP_USER=you@example.net -e IMAP_PASSWORD=… \
-- npx -y @ni-c/imap-mcpClaude Desktop
{
"mcpServers": {
"imap-mcp": {
"command": "npx",
"args": ["-y", "@ni-c/imap-mcp"],
"env": {
"IMAP_HOST": "imap.example.net",
"IMAP_USER": "you@example.net",
"IMAP_PASSWORD": "…"
}
}
}
}Codex
[mcp_servers.imap-mcp]
command = "npx"
args = ["-y", "@ni-c/imap-mcp"]
env = { IMAP_HOST = "imap.example.net", IMAP_USER = "you@example.net", IMAP_PASSWORD = "…" }Docker
docker run --rm -i \
-e IMAP_HOST=imap.example.net \
-e IMAP_USER=you@example.net \
-e IMAP_PASSWORD=… \
ghcr.io/ni-c/imap-mcpSaving attachments needs a writable directory, and the image runs as uid 1000 — so a
bind mount has to be owned by it on the host: -e IMAP_DOWNLOAD_DIR=/data -v "$PWD/attachments:/data" with chown 1000:1000 attachments. Without
IMAP_DOWNLOAD_DIR the container never writes anything.
Tools
Read — always registered
Tool | What it does |
| Capabilities, permanent flags, whether the keyword is storable, which tool groups are on |
| Every folder with message and unseen counts and its special-use role |
| Lists and searches: sender, recipient, subject, body, date range, flags |
| Messages not handed over yet; marks them afterwards, |
| Headers and body, fenced untrusted, plus the security assessment; |
| Without |
Mailbox — needs IMAP_READ_ONLY=false
Tool | Confirmation |
| none — flags are reversible, and |
| 🔒 for both |
| 👤 asks the user, 🔒 where the client cannot |
| 👤 for |
| none — a draft does not leave the mailbox |
👤 raises a dialog the model cannot answer · 🔒 needs a confirmation token: call once to receive one, then again with it.
copy is confirmed as well as move, because the thing that cannot be taken back is not
the deletion — it is the disclosure. A destination is a free-form folder name, and on a
shared account or a public namespace one call hands every message to everyone who can read
it, leaving the source folder untouched. For the same reason set_message_flags refuses to
add \Deleted: it is half a deletion, and the next client to close the mailbox may finish
it. Use delete_messages, which asks.
Neither a confirmation nor a dialog quotes a mailbox name inside its own sentence — folder names come from the account, which on a shared mailbox means a colleague chose them.
Attachments are also available as MCP resources at imap://message/{uid}/part/{partId}, which
matters where the server has no useful filesystem. The resource path runs the same allowlist,
size limit and magic-byte check as the tool — it is not a second, unguarded door.
Not exposed, on purpose
No sending, no SMTP, no raw IMAP passthrough, no APPEND of arbitrary MIME, no HTML
composition, no OAuth2. The first is the whole security argument (see SECURITY.md); the
second would make every guard here optional; the last is planned but needs a test account
before it ships.
And one thing the tool filter does not cover: attachment resources. IMAP_ALLOW_TOOLS
narrows tools/list, not resources/list, so a server with a narrow allow list still serves
those. IMAP_DOWNLOAD_DIR and the content-type allowlist are what constrain them — worth
knowing before concluding that a filtered install reaches less of the mailbox than it does.
Safety
Every result carrying mailbox content is marked untrusted, message bodies additionally fenced with a per-call nonce and marked line by line.
Attachments pass two independent gates. The declaration is checked against a content-type allowlist, an executable-extension refusal list and a size ceiling; the bytes are then checked against magic numbers. An executable renamed to
.pdfand declaredapplication/pdfclears every declaration check and fails on its bytes — including when saving to disk, where it would be more dangerous, not less.A
part_idmust come from a listing call, so the body cannot be pulled out through the attachment tool and escape its framing.Downloads cannot escape their directory. The target comes only from the environment, the filename is sanitised, the resolved path is re-checked, and the file is opened with
wxand mode0600— so nothing is overwritten and no planted symlink is followed.Mailbox names, flags and addresses are refused if they contain line breaks. IMAP is a line protocol and a draft is a mail header; a CR is an injection primitive, not a typo.
TLS is never disabled globally.
IMAP_INSECURE_TLSis scoped to the connection it names;NODE_TLS_REJECT_UNAUTHORIZEDappears nowhere.Every change to the mailbox is logged to stderr with the UIDs and folder — never the subject. stderr is the one channel the model does not read.
Responses are bounded. Whole items are dropped rather than the JSON being sliced, and the truncation notice comes first so the recovery hint survives.
SECURITY.md has the trust model, what these measures do not cover, and how to report a
vulnerability.
Development
npm install
npm test
npm run buildThe test suite runs against an in-memory IMAP fake, so it needs no server and no network. For a live server to point the real thing at, see CONTRIBUTING.md — it starts a throwaway mailbox in a container.
Releasing
Add the CHANGELOG entry and bump
package.json.npm run lint && npm run build && npm run test:coverageCommit, then push a signed tag:
git tag -s vX.Y.Z -m "vX.Y.Z" && git push origin main vX.Y.Z
The release workflow publishes to npm (Trusted Publishing, with provenance), creates the GitHub release from the CHANGELOG section and updates the MCP Registry entry.
License
MIT © Willi Thiel
Available Tools
6 toolsget_attachmentsList or download attachmentsARead-only
Without part_id: lists the attachments of a message with their type, size and whether the policy allows fetching them. With part_id: returns that one attachment. Small text and images come back inline so you can read them; anything larger is written to the download directory and you get the path. part_id must come from a listing call of this same tool. Executables are refused even when they claim to be something else — including when writing to disk.
| Name | Required | Description | Default |
|---|---|---|---|
| uid | Yes | IMAP UID of the message, as returned by the listing tools. | |
| mode | No | "auto" (default) reads small text and images inline and saves the rest to disk; "inline" always returns the content; "file" always saves it. | |
| mailbox | No | Mailbox (folder) name exactly as returned by list_mailboxes, e.g. "INBOX" or "INBOX/Archive". Defaults to the configured mailbox. | |
| part_id | No | MIME part id from a previous listing call. Omit to list the attachments. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the readOnlyHint annotation by disclosing that small text/images are returned inline, larger payloads are written to the download directory with a path, and executables are refused even if disguised. It also mentions policy constraints on whether fetching is allowed. This gives an agent important behavioral context that annotations alone do not capture.
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 compact and front-loaded: it explains both modes first, then behavior, then the source of part_id, then the safety constraint. Every sentence adds useful information without padding or repetition. It earns its 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?
For a tool with no output schema, the description adequately covers what the agent will receive: attachment metadata when listing, inline content for small text/images, or a file path for larger files. It also covers policy restrictions, executables, and the required provenance of part_id. Nothing essential appears to be 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?
The input schema already documents all four parameters with 100% coverage, so the baseline is 3. The description adds meaningful value by explaining that part_id must originate from the same tool's listing call and by clarifying the mode behavior tied to auto/inline/file. This is helpful context beyond the schema descriptions.
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 clearly distinguishes the tool from siblings by specifying two modes: listing the attachments of a message without part_id and retrieving a single attachment with part_id. It names the resource (attachments of a message) and the verbs (list/returns), and its sibling relationships are obvious from context. This is more specific than the title and leaves no ambiguity about what the tool 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?
The description gives explicit in-tool usage guidance: omit part_id to list, provide part_id to fetch a specific attachment, and part_id must come from a prior listing call of this same tool. It does not explicitly mention alternative tools such as get_message for reading message content, but the mode-based instructions are clear enough for an agent to select and invoke the tool correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_messageGet one messageARead-only
Fetches one message by UID and returns its headers and text body, fenced as untrusted content, together with a server-side security assessment (SPF/DKIM/DMARC verdicts, prompt-injection and homoglyph signals) and the list of its attachments. Does not change the read state. Set include_thread to also list the surrounding conversation.
| Name | Required | Description | Default |
|---|---|---|---|
| uid | Yes | IMAP UID of the message, as returned by the listing tools. | |
| mailbox | No | Mailbox (folder) name exactly as returned by list_mailboxes, e.g. "INBOX" or "INBOX/Archive". Defaults to the configured mailbox. | |
| include_thread | No | true also returns summaries of the other messages in the same conversation. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, the description explicitly states 'Does not change the read state' and discloses that the body is 'fenced as untrusted content' with a server-side security assessment. This adds meaningful 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?
Two tightly written sentences place the core action first, then enrich with behavior and options. 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?
Despite the lack of an output schema, the description enumerates what is returned (headers, text body, security assessment, attachments), notes side effects, and covers the optional thread behavior. Nothing essential is missing for an agent 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?
The input schema covers all three parameters at 100%, so the description is not required to document them. It adds slight value by explaining include_thread as 'listing the surrounding conversation' and tying uid to the listing tools, but this is marginal.
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 and resource: 'Fetches one message by UID' and enumerates the returned content (headers, text body, security assessment, attachments). This clearly differentiates it from list_messages and get_attachments.
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 use case clear: fetch a single message by UID when full content, security assessment, and attachment list are needed. It does not explicitly state when not to use it or name alternatives, but the context is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_server_infoServer and account informationARead-only
Reports what this account and server can do: the configured mailbox, IMAP capabilities, which flags the mailbox stores permanently, whether the new-mail keyword can be used, and which tool groups are enabled. Start here when a call fails for reasons that sound like configuration.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint=true, and the description consistently describes a read-only reporting behavior ('Reports what this account and server can do'). It adds useful behavioral context by framing the tool as a diagnostic starting point and listing the categories of information returned, which goes beyond merely restating the annotation.
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 compact and front-loaded: the first sentence states the core purpose and enumerates specific report contents, and the second sentence provides a practical usage cue. There is no filler or repetition of the tool name 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?
The description is complete enough given the tool's simplicity: no parameters, a read-only annotation, and a clear enumeration of what is reported. It does not describe the exact output format, but for a zero-parameter diagnostic tool this is a minor gap rather than a blocking omission.
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 zero parameters, the schema already fully covers the input surface. The description does not need to add parameter-level detail, and the baseline of 4 for a no-parameter tool is appropriate here.
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 ('Reports') and identifies the resource ('what this account and server can do'), then enumerates concrete information categories such as configured mailbox, IMAP capabilities, stored flags, new-mail keyword support, and enabled tool groups. This clearly distinguishes it from the sibling tools, which focus on mailboxes, messages, and attachments rather than server/account configuration.
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 explicit guidance: 'Start here when a call fails for reasons that sound like configuration.' This is a clear trigger condition. It does not explicitly state when not to use it or name alternatives, but the sibling tools are sufficiently distinct that no exclusion is necessary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_mailboxesList mailboxesARead-only
Lists every folder in the account with its message and unseen counts, its special-use role (drafts, sent, trash, junk) and whether it can hold messages. Use the returned "path" verbatim wherever a tool takes a mailbox.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint annotation already signals safety, and the description adds useful behavioral detail: it returns message counts, unseen counts, special-use roles, and folder writability. This goes beyond the annotation without contradicting it.
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 concise sentences cover purpose, output contents, and a key usage directive with no filler. The essential information is front-loaded and 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?
With no output schema, the description fully enumerates what the agent can expect in the response—counts, roles, writability, and a reusable path. It also explains how to apply the result in later calls, making it complete for a parameterless 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?
The input schema has no parameters, so there is nothing for the description to explain. The baseline of 4 applies, and the description appropriately focuses on output usage instead of parameter details.
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 clearly states the tool lists every folder in the account with counts, special-use roles, and message-holding capability. This distinguishes it from message-focused siblings like list_messages and get_message.
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 instructs that the returned 'path' should be reused verbatim wherever a mailbox is required, giving practical guidance for when to use this tool. It does not explicitly name alternatives, but the zero-parameter scope and mailbox-listing purpose make the use case clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_messagesList and search messagesARead-only
Lists messages newest first, optionally narrowed by sender, recipient, subject, body text, date range or flags. With no criteria it simply pages through the mailbox. Every filter is applied by the mail server, so searching a large folder is cheap. Returns summaries only — use get_message for the body.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | Substring to match in the To header. | |
| body | No | Substring to match in the message body. | |
| from | No | Substring to match in the From header. | |
| seen | No | true for read messages only, false for unread only. | |
| limit | No | Maximum number of messages to return (default from IMAP_MAX_MESSAGES, hard cap 200). | |
| since | No | Only messages received on or after this date (YYYY-MM-DD). | |
| before | No | Only messages received before this date (YYYY-MM-DD). | |
| offset | No | How many messages to skip, newest first, for paging. | |
| flagged | No | true for flagged/starred messages only. | |
| keyword | No | Only messages carrying this custom IMAP keyword. | |
| mailbox | No | Mailbox (folder) name exactly as returned by list_mailboxes, e.g. "INBOX" or "INBOX/Archive". Defaults to the configured mailbox. | |
| subject | No | Substring to match in the subject. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint, so the description must supply behavioral depth. It adds sorting (newest first), output scope (summaries only), and a performance trait (server-side filter execution). This goes well beyond the annotation without contradicting it.
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, no filler, with the core behavior and ordering in the opening line. Every sentence carries a distinct fact: filtering options, no-criteria behavior, server-side performance, and summary-only return. This is appropriately compact for a 12-parameter tool.
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 tool with no required parameters and a fully described schema, the description covers the behavior that matters: ordering, summary output, body alternative, and paging behavior. It doesn't describe exact summary fields or explicitly distinguish all sibling tools, but the schema and the get_message pointer fill most of the gap. Given no output schema, the 'summaries only' statement is sufficient directional guidance.
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 already documents all 12 parameters, so the baseline is 3. The description adds a useful grouping of filter types and clarifies that omitting criteria turns the call into a page-through of the mailbox. It also ties filtering to server-side execution, which is operational context the schema does not provide.
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 opens with a specific verb and resource ('Lists messages newest first') and enumerates the viable filters, including sender, recipient, subject, body, date range, and flags. It also points to get_message for full body, which helps disambiguate from sibling list/get tools. However, it never explicitly contrasts this with list_new_messages, so sibling differentiation is incomplete.
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 when to page without criteria and why: 'With no criteria it simply pages through the mailbox' and 'searching a large folder is cheap' due to server-side filtering. It explicitly routes body retrieval to get_message: 'Returns summaries only — use get_message for the body.' It doesn't mention when to prefer list_new_messages over this tool, so exclusions are partial.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_new_messagesList messages not seen beforeA
Returns messages this server has not handed over yet, newest first, and then marks them with the "AiSeen" keyword so the next call returns only what arrived since. This is separate from the human read/unread state, which is never touched. Use dry_run to preview without marking.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of messages to return (default from IMAP_MAX_MESSAGES, hard cap 200). | |
| dry_run | No | true returns the messages without marking them, so the same set comes back next time. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description fully discloses the side-effecting behavior: messages are marked with the AiSeen keyword, while human read/unread state is 'never touched.' It also presents dry_run as a preview mechanism. This goes well beyond the annotations, which only state readOnlyHint=false and destructiveHint=false.
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 deliver the core behavior, the side effect, the read/unread distinction, and the dry_run option without any filler. The most important information is front-loaded, and every sentence 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?
The description covers ordering, side effects, and preview behavior, which is enough for an agent to invoke the tool correctly. It does not describe the return format, but with no output schema the lack of explicit return-structure details is a minor gap given the tool's straightforward nature.
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 both limit and dry_run are already clearly documented in the schema. The description adds only a brief reminder to use dry_run for previewing, so it does not materially improve parameter understanding beyond 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?
The description uses a specific verb and resource: 'Returns messages this server has not handed over yet, newest first.' It also explains the distinctive AiSeen-marking behavior, clearly separating this tool from the sibling list_messages and the human read/unread state.
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 a polling use case by explaining that marking ensures 'the next call returns only what arrived since,' and it gives a clear dry_run usage instruction. However, it never explicitly states when to choose this tool over alternatives like list_messages, nor does it name exclusions.
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. Dates show when Glama detected each change.
6 tool updates
v0.2.0- First observed
get_attachments - First observed
get_message - First observed
get_server_info - First observed
list_mailboxes - First observed
list_messages - First observed
list_new_messages
TDQS
Most tools map cleanly to distinct resources and actions: server info, mailboxes, messages, new-message queue, message detail, and attachments. The only mild overlap is between list_messages and list_new_messages, and between the attachment list in get_message and get_attachments, but the descriptions clearly separate those cases.
All tools use a consistent verb_noun snake_case pattern: list_* for collections and get_* for individual items or pieces of data. list_new_messages is a clear modifier of list_messages, and get_server_info/get_attachments fit the same predictable scheme.
Six tools is well-scoped for an IMAP retrieval server: one info call, one mailbox enumeration, two message-listing modes, one message fetch, and one attachment handler. Each tool occupies a clear place in the email inspection workflow without unnecessary redundancy.
The core read/inspect workflow is complete: discover capabilities, list mailboxes, search or page messages, consume new messages with the AiSeen marker, fetch full messages, and retrieve attachments. Missing operations like delete, move, or human-visible flag changes appear intentionally out of scope, though they would be expected from a broader IMAP client.
Maintenance
Related MCP Connectors
Read, search, send, organize, draft and schedule email across your inboxes from any MCP client.
Email infrastructure for AI agents — send, receive, search, and reply to email over MCP.
Email inboxes for AI agents: send, receive, reply, search, and manage threaded email over MCP.
Read, send, file and search email in any Gmail, Microsoft 365 or IMAP mailbox, plus its calendar.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceRead-only MCP server for IMAP email access, enabling AI agents to read, search, and monitor email without sending or deleting messages.77MIT
- AlicenseNot gradedqualityBmaintenanceEnables MCP clients to search, read, and inspect Apple Mail on macOS, including conversations and attachments. It can create new, reply, reply-all, or forward drafts, but cannot send or modify existing messages.MIT
- AlicenseAqualityAmaintenanceSafely searches, reads, flags, and drafts email through IMAP, with no send, delete, or move capabilities. Uses a local broker and OS credential store for secure authentication.16Apache 2.0
- AlicenseNot gradedqualityAmaintenanceEnables MCP-compatible AI assistants to securely search multiple mailboxes, reconstruct email threads, and inspect attachments through read-only tools without altering mailbox state.Apache 2.0
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ni-c/imap-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server