multi-mail-mcp
A local-first MCP server for managing multiple Gmail and Microsoft 365 email accounts through a single unified interface. All operations run locally with encrypted token storage — no cloud token storage.
list_accounts: View all configured local email account aliases (e.g.,work,personal) without exposing secrets or tokens.search_mail: Search one or all accounts simultaneously using provider-specific syntax (Gmail search or Microsoft Graph). Optional filtering by account alias or provider (gmail/m365), with up to 25 results per account.get_thread: Fetch a full Gmail thread bythreadIdor a Microsoft 365 conversation byconversationId, using IDs returned from search results.create_draft: Compose and save a draft email with support forto,cc,bcc,subject,body(plain text or HTML), and reply threading viainReplyTo.send_draft: Send a previously created draft bydraftId. Requires explicitconfirm: "SEND"to prevent accidental sends.send_mail: Send a new email immediately with full recipient and body support. Also requiresconfirm: "SEND"as a safety guard.
Notable constraints: No tools for deleting, archiving, or labeling mail are available.
Allows reading, searching, drafting, and sending emails from Gmail accounts, supporting multiple accounts via local aliases.
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., "@multi-mail-mcpSearch all my mail accounts for 'invoice from Stripe' and show the newest 10 hits."
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.
multi-mail-mcp
Local-first MCP server for agents that need to work across multiple Gmail and Microsoft 365 accounts without cloud token storage.
This is an alpha built for the exact pain in the thread: work Gmail, personal Gmail, side-project Gmail, and Microsoft 365 should all be available to an agent by alias.
Beta site: https://multi-mail-mcp.netlify.app
What It Does
Stores multiple accounts as local aliases:
work,personal,side,m365, etc.Encrypts OAuth profiles and tokens on the machine.
Exposes one MCP server over stdio.
Supports Gmail and Microsoft 365 / Outlook.
Searches one account or all accounts.
Fetches Gmail threads or Microsoft 365 conversations.
Creates drafts.
Sends drafts or new emails only when the tool call includes
confirm: "SEND".
Related MCP server: Agent Email
Tools
list_accountssearch_mailget_threadcreate_draftsend_draftsend_mail
Install
npm install -g https://github.com/claygeo/multi-mail-mcp/archive/refs/heads/main.tar.gz
mailmcp initAdd Gmail
In Google Cloud Console:
Enable the Gmail API.
Configure the OAuth consent screen. While the app is in testing, add the Gmail account as a test user.
Create an OAuth client with application type
Desktop app.
Then run:
mailmcp add-gmail `
--alias personal `
--credentials-json "C:\Users\you\Downloads\client_secret_....apps.googleusercontent.com.json"The local callback is http://127.0.0.1:41577.
Default Gmail scopes:
https://www.googleapis.com/auth/gmail.readonlyhttps://www.googleapis.com/auth/gmail.compose
That means read/search plus draft/send support. There is no delete/archive/label mutation tool in this alpha.
Add Microsoft 365
In Microsoft Entra:
Register an app.
Add a
Mobile and desktop applicationsplatform redirect URI:http://127.0.0.1:41578/oauth/callback.Enable public client/native flows for the app registration.
Then run:
mailmcp add-m365 `
--alias work `
--client-id "<MICROSOFT_CLIENT_ID>" `
--tenant commonDefault Microsoft scopes:
offline_accessUser.ReadMail.ReadMail.ReadWriteMail.Send
Some work/school tenants require admin consent before delegated mail scopes work.
Verify The Full Loop
After at least one account is added:
mailmcp list
mailmcp verify --account personal --max-results 3
mailmcp verify --account personal --max-results 3 --draft-to you@example.comverify checks the local vault, confirms the send guard refuses sends without confirm: "SEND", searches real mail, fetches the first returned thread/conversation, and optionally creates an unsent draft. It does not send email.
If you added both providers:
mailmcp verify --provider gmail --max-results 3
mailmcp verify --provider m365 --max-results 3To prove the MCP layer itself is responding:
npx @modelcontextprotocol/inspector --cli mailmcp server --method tools/list
npx @modelcontextprotocol/inspector --cli mailmcp server --method tools/call --tool-name list_accountsMCP Client Config
Use this server as a stdio MCP command:
{
"mcpServers": {
"multi-mail": {
"command": "node",
"args": ["C:\\Users\\clayg\\Documents\\Codex\\2026-05-27\\caleb-baskin-calebbaskin-6m-i-ll\\dist\\cli.js", "server"]
}
}
}If installed globally later, this can become:
{
"mcpServers": {
"multi-mail": {
"command": "mailmcp",
"args": ["server"]
}
}
}Example Agent Prompts
List my configured mail accounts.Search all my mail accounts for "invoice from Stripe" and show the newest 10 hits.Use my work account to draft a reply to this thread. Do not send it.Send the draft from my personal account only if it matches the body we just approved.Security Shape
The alpha is intentionally local-first:
Tokens are encrypted in
profiles.vault.json.The vault key is generated locally as
master.key, or derived fromMAILMCP_MASTER_KEYif set.On Windows,
initand vault writes try to remove inherited ACLs from the config directory, vault, and key so only the current user, Administrators, and SYSTEM can read them.No email contents or tokens are sent to this package's servers because there are no package servers.
Send operations require
confirm: "SEND".Delete/archive/label mutation tools are intentionally absent.
For a production public release, replace the local key-file fallback with OS keychain storage and complete the relevant Google/Microsoft verification work.
Verification
npm run checkThis runs the TypeScript build and local smoke tests. OAuth/API calls require real client credentials and user login.
Available Tools
6 toolscreate_draftCreate Draft EmailA
Create a draft in Gmail or Microsoft 365. This is the preferred write path before sending.
| Name | Required | Description | Default |
|---|---|---|---|
| account | Yes | Local account alias. | |
| to | Yes | Recipient email or list of recipient emails. | |
| cc | No | ||
| bcc | No | ||
| subject | Yes | ||
| body | Yes | ||
| html | No | Set true when body is HTML. | |
| inReplyTo | No | Optional Gmail Message-ID header for reply threading. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must carry the full burden. It does not disclose behavioral traits such as authentication requirements, limitations on drafts, or side effects beyond creating the draft. It lacks details on what happens if the account is invalid or if parameters are malformed.
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 two sentences long, front-loads the core purpose, and contains no extraneous information. Every word 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?
Given the complexity (8 parameters, no output schema), the description is insufficient. It does not explain the return value (e.g., draft ID), error handling, or interaction with sibling tools. The tool requires more contextual 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?
The schema description coverage is 50% (4 of 8 parameters described). The description adds general context but does not detail each parameter beyond what the schema provides. It does not compensate for the undocumented parameters (cc, bcc, subject, body).
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 verb 'Create' and the resource 'a draft' and specifies the platform 'Gmail or Microsoft 365'. It also distinguishes itself as a write path before sending, differentiating from sibling tools like send_draft or send_mail.
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 says 'preferred write path before sending', implying it should be used to prepare an email before sending. However, it does not explicitly state when not to use it or mention specific alternatives like send_draft or send_mail.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_threadGet Mail ThreadA
Fetch a Gmail thread by threadId or a Microsoft 365 conversation by conversationId. Use ids from search_mail results.
| Name | Required | Description | Default |
|---|---|---|---|
| account | Yes | Local account alias. | |
| threadId | Yes | Gmail threadId or Microsoft 365 conversationId. |
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. It discloses the core behavior (fetching a thread by ID) but does not elaborate on any side effects, authentication requirements, rate limits, or response characteristics. For a simple fetch, this is adequate but minimal.
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 sentence that efficiently communicates the tool's purpose and key usage hint. There is no redundancy, and the most important information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (2 parameters, no output schema), the description covers the essential aspects: what it fetches and how to obtain the required ID. It does not describe the return value, but for a straightforward fetch the agent can infer that. A complete description might add output details, but it is not severely lacking.
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 100% schema description coverage, the baseline is 3. The description adds value by explaining that threadId values come from search_mail results, which provides practical context beyond the schema's definitions. This slight improvement raises the score to 4.
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 specifies the action ('Fetch'), the resource (Gmail thread or Microsoft 365 conversation), and the identifier types (threadId/conversationId). It also distinguishes this tool from siblings by noting that IDs come from search_mail results.
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 provides explicit guidance on when to use this tool: after search_mail, since it says 'Use ids from search_mail results.' This implies the prerequisite step. However, it does not explicitly name alternatives or state when not to use this tool, though the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_accountsList Mail AccountsA
List local Gmail and Microsoft 365 account aliases available to this MCP server. No secrets are returned.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden of behavioral disclosure. It adds value by stating 'No secrets are returned' and specifying the scope (local accounts). However, it does not cover other behavioral aspects like idempotency, rate limits, or what happens if no accounts are configured.
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 extremely concise: two sentences that are front-loaded with the primary action and include a critical caveat. Every word serves a purpose, and there is no fluff.
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 parameterless list tool, the description is largely complete. It specifies what is listed (account aliases) and what is not returned (secrets). However, it does not describe the output format or structure, which would be expected given no output schema. Still, it provides sufficient context for an agent to understand the tool's purpose.
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 are zero parameters, so the baseline is 4 per guidelines. The description does not need to explain parameters, and it adds no parameter information beyond what the schema provides.
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 action (list), the resources (local Gmail and Microsoft 365 account aliases), and adds a clarifying note about secrets not being returned. It effectively distinguishes from sibling tools which all involve different operations like creating drafts or sending mail.
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?
No explicit guidance is provided about when to use this tool versus alternatives. However, the usage is implied: before using email-related tools, one might list available accounts. No exclusion criteria or alternatives are mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_mailSearch MailA
Search one account or all configured accounts. Gmail uses Gmail search syntax. Microsoft 365 uses Graph message search syntax.
| Name | Required | Description | Default |
|---|---|---|---|
| account | No | Optional local account alias. | |
| provider | No | Optional provider filter. | |
| query | No | Search query. If omitted, returns recent messages. | |
| maxResults | No | Maximum results per account. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It mentions that omitting query returns recent messages, which is helpful. However, it does not disclose rate limits, result ordering, pagination, or whether the operation modifies data.
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 two sentences, front-loading the main purpose (search mail) and adding concise details about syntax. No 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?
The description omits details about the output format or fields returned. Given that output schema is absent and sibling tools like get_thread suggest structured results, more information about return values would improve completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description adds meaning beyond schema by clarifying that the 'account' parameter can be omitted to search all accounts and by explaining provider-specific syntax for 'query'.
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 searches mail across one or all accounts, specifying syntax differences for Gmail and Microsoft 365. This distinguishes it from sibling tools like send_mail or create_draft.
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 provides context on when to use the tool (searching mail) and mentions provider-specific syntax. It does not explicitly state when not to use it or list alternatives, but the purpose is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_draftSend Draft EmailA
Send an existing draft. Requires confirm: "SEND" to reduce accidental sends.
| Name | Required | Description | Default |
|---|---|---|---|
| account | Yes | Local account alias. | |
| draftId | Yes | Draft id returned by create_draft. | |
| confirm | No | Must equal "SEND". |
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. It discloses that sending requires a confirmation to prevent accidents, but does not explain other behaviors like whether the action is irreversible, what happens if the draft is already sent, or any side effects.
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 short, focused sentences. The first states the purpose, the second adds a critical usage detail. Every word contributes, no 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?
Given the tool's simplicity (3 flat parameters, no output schema), the description covers the core purpose and a key behavioral note. However, it lacks information on return values, potential errors, or idempotency, which would be helpful for a destructive action like sending.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% (all three parameters described). The description adds value by explaining the confirm parameter's purpose (reduce accidental sends) beyond the schema's note that it 'must equal "SEND"'. Account and draftId are adequately described in 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 clearly states the tool sends an existing draft, using specific verb+resource ('Send an existing draft'). This distinguishes it from siblings like send_mail (sends new email) and create_draft (creates draft).
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 mentions the confirm requirement ('Requires confirm: "SEND" to reduce accidental sends.'), providing a usage constraint, but does not explicitly guide when to use this tool versus alternatives (e.g., send_mail) or provide context for when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_mailSend New EmailA
Send a new email immediately. Requires confirm: "SEND". Prefer create_draft unless the user explicitly asks to send now.
| Name | Required | Description | Default |
|---|---|---|---|
| account | Yes | Local account alias. | |
| to | Yes | Recipient email or list of recipient emails. | |
| cc | No | ||
| bcc | No | ||
| subject | Yes | ||
| body | Yes | ||
| html | No | Set true when body is HTML. | |
| confirm | No | Must equal "SEND". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, but description discloses the immediate send behavior and the required confirm parameter guard. Lacks details on side effects, error handling, or authentication, but the core behavioral constraint is clear.
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, front-loaded with key action and usage guidance. No redundant or unnecessary 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?
No output schema, no annotations, and 8 parameters. The description omits return behavior, error conditions, and parameter details like account format or body type. Adequate but minimal for a send tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50% (4 of 8 parameters described), but the description adds no new parameter information beyond stating the confirm requirement (already in schema). Does not compensate for low coverage.
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?
Description clearly states 'Send a new email immediately' with a specific verb and resource. It distinguishes from sibling create_draft by mentioning preference for that tool.
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 advises to prefer create_draft unless the user explicitly asks to send now, providing clear when-to-use and when-not-to-use guidance with an alternative named.
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.1.0-alpha.0- First observed
create_draft - First observed
get_thread - First observed
list_accounts - First observed
search_mail - First observed
send_draft - First observed
send_mail
TDQS
Each tool has a clearly distinct purpose: create_draft for writing, send_mail for immediate send, send_draft for sending existing drafts, get_thread for retrieving threads, search_mail for searching, and list_accounts for configuration. No overlap in functionality.
All tool names follow a consistent verb_noun pattern using snake_case (e.g., create_draft, search_mail). No deviations in style or convention.
With 6 tools, the set is well-scoped for an email server supporting two providers. It covers the core operations without being too sparse or excessive.
The tool surface covers essential email lifecycle (create, send, search, retrieve threads) and account listing. Minor gaps exist, such as no tool for updating or deleting drafts, but core workflows are supported.
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
MCP server connecting AI agents to 100+ apps (Gmail, Slack, Notion, GitHub) via one-click OAuth.
Email infrastructure for AI agents — send, receive, search, and reply to email over MCP.
Hosted MCP server with managed OAuth for 15+ toolkits: Google Workspace, Fitbit, Oura, Kalshi, etc.
Private-by-default, local-first memory/context/task orchestrator for MCP apps and agents.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceA locally-hosted MCP server that integrates Gmail, Google Calendar, and Google Drive to provide AI-powered management of emails, events, and files. It enables tool-based interactions like sending emails, creating calendar events, and searching Drive files through clients like Cursor and Claude Desktop.-
- AlicenseNot gradedqualityAmaintenanceAn open-source MCP server that provides AI agents with secure access to read, search, and manage emails via Microsoft 365 and Gmail. It features security-first defaults like recipient allowlists and markdown content conversion to facilitate safe agent interaction with mailboxes.6Apache 2.0
- AlicenseBqualityDmaintenanceA local MCP server that provides LLM clients with read/write access to email and calendar data from Gmail, iCloud, and generic IMAP providers. It runs entirely on your machine, keeping data private while enabling email management, calendar operations, and task handling through natural language.39MIT
- AlicenseNot gradedqualityDmaintenanceA local MCP server that connects Codex to Microsoft Graph and Gmail for reading and managing personal mail and calendar accounts.MIT
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/claygeo/multi-mail-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server