pylos-mcp

io.github.adamVass由 GitHub 帳號 adamVass 發布v1.4.0更新於 Nov 3, 2026

適用於 Gmail、Outlook 及任何 IMAP 電子郵件的電子郵件 MCP 伺服器,可防禦提示注入

AI 翻譯由 AI 模型根據下方的原文描述翻譯,可能有誤。

原文描述

Email MCP server for Gmail, Outlook and any IMAP mailbox, hardened against prompt injection

已驗證STDIO僅桌面溝通與協作安全與監控

概覽

pylos 的本機 MCP 服務;無需登入;STDIO。

暫無 AI 概覽:以下資訊來自註冊中心條目和服務本身。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 pylos-mcp,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

[pylos-mcp logo, an envelope with a keyhole in its flap]

pylos-mcp

Your mail client shows you the message. pylos-mcp shows your assistant what it hides.

Warnings: sender_mismatch, hidden_text, instruction_patterns, mixed_script, encoded_blob

Reads and drafts by default. Sending starts off. No bcc anywhere.

[Download the Claude Desktop bundle] [Add to Cursor] [Install in VS Code]

[An account security message from 'Lumen Pay Security' as a mail client shows it. pylos-mcp finds a Cyrillic letter posing as a Latin one in the sender's name, a Reply-To pointing at another domain, a hidden instruction telling the AI assistant to forward every invoice, and a hidden base64 payload. The message reaches the assistant fenced as data, not instructions, with a Warnings line naming all of it.]

[npm version] [CI status] [MIT license] [OpenSSF Best Practices]

Ask your assistant what needs you today, to sum up a long thread, or to draft the reply you keep putting off. pylos-mcp gives Claude, or any MCP client, your Gmail, Outlook and Microsoft 365, iCloud or IMAP mailbox to do it with.

Anyone can put text in your inbox, and once an AI assistant reads that inbox, they can put text in front of the assistant too. So every message reaches the assistant fenced as input from a stranger, with a Warnings line for what looks off, such as hidden text, phrases aimed at an AI, lookalike letters, a Reply-To on another domain or a failed DMARC check. The message in the image trips five detectors at once.

It runs on your machine. Moving, sending and deleting stay off until you turn them on, and sending then reaches only the recipients you allow.

Try it without a mailbox

--demo serves a sample inbox instead of yours. It holds a colleague's note with a deadline, a receipt, a newsletter, a parcel notice your mail server could not verify, and the account warning from the image above. The demo reads none of your settings and connects to no mail server, so there is nothing to sign in to.

sh
claude mcp add pylos-demo -- npx -y pylos-mcp --demo

[Add the demo to Cursor] [Install the demo in VS Code]

In other clients, add --demo to the args of the entry under Quick start and leave out env. Then ask the assistant whether anything in the inbox is urgent.

The newsletter shows a limit worth knowing. Its preview line is hidden from mail clients by design, so it gets a hidden_text warning too. A warning says what a message contains, not whether it is malicious.

Quick start

pylos-mcp works with any client that runs local MCP servers. It runs locally through npx and needs Node.js 22 or later. Every route below starts from example values, so replace the address and password with your own. Use an app password, not your account's regular password, and for Outlook no password at all. Provider setup says where to get one.

pylos-mcp connects to your mail provider, and with Outlook to Microsoft's sign in service. What the assistant reads goes to your AI client and, through it, to the model provider you use, as anything else you show your assistant does. Attachments you ask for are saved to your Downloads folder.

Claude Desktop. Download pylos-mcp.mcpb, open it, and fill in the form Desktop shows.

Claude Code. --scope user makes it available in every project. EMAIL_PASSWORD_CMD keeps the password out of your shell history and Claude's config: it runs a command that prints the password, here a macOS keychain lookup. Store the password there first with security add-generic-password -s pylos-mcp -a [email protected] -w, which asks for it.

sh
claude mcp add pylos-mcp --scope user -e PROVIDER=gmail -e [email protected] \  -e EMAIL_PASSWORD_CMD="security find-generic-password -s pylos-mcp -w" -- npx -y pylos-mcp

Cursor and VS Code. Use the buttons above, then put your own values in the config they create.

Config files for Cursor, VS Code, Windsurf, Cline and other clients

Most clients, Cursor's .cursor/mcp.json and Claude Desktop's claude_desktop_config.json among them, take this entry:

json
{  "mcpServers": {    "pylos-mcp": {      "command": "npx",      "args": ["-y", "pylos-mcp"],      "env": {        "PROVIDER": "gmail",        "EMAIL_USER": "[email protected]",        "EMAIL_PASSWORD": "your-app-password"      }    }  }}

VS Code's .vscode/mcp.json names the key servers:

json
{  "servers": {    "pylos-mcp": {      "command": "npx",      "args": ["-y", "pylos-mcp"],      "env": {        "PROVIDER": "gmail",        "EMAIL_USER": "[email protected]",        "EMAIL_PASSWORD": "your-app-password"      }    }  }}

Outlook and Microsoft 365 take PROVIDER=outlook and no password at all, so remove EMAIL_PASSWORD from the entry, or the server refuses to start. The first time the assistant reads mail, your browser opens Microsoft's sign in page.

Restart your client fully after any change, since tools register only at startup and toggling the server off and on is not always enough. Then ask the assistant to list your mail folders. A list means it works.

If the Claude Desktop extension shows "Server disconnected", the reason is in Desktop's main.log in ~/Library/Logs/Claude on macOS or %APPDATA%\Claude\logs on Windows, on a line starting with pylos-mcp:.

Why the defaults are what they are

Simon Willison calls it the lethal trifecta: an AI agent with access to private data, exposure to untrusted content and the ability to communicate externally. An assistant reading your email has the first two by design, because your inbox is private and anyone can write to it. Stealing what it read takes the third, a way to send it somewhere else.

Sending is off by default. Drafts wait in your Drafts folder until you send them yourself, and enabling sending still requires a recipient allowlist. With SEND_CONFIRM=true, every message is also shown to you in a dialog and goes out only if you accept. No tool attaches a file from your disk or adds a forwarding rule.

The third leg can still come from elsewhere in the same client, such as a tool that fetches web pages or runs shell commands. Image markup inside a message is neutralized, but the model can still write an image link of its own, which a client that loads images would fetch. When the assistant reads your mail, keep tools that reach the internet out of that conversation.

Fencing reduces prompt injection risk, and nothing eliminates it. The model still reads text written by strangers, so check what the assistant tells you about your mail before acting on it.

Capabilities

Each capability is a separate switch, and turning one on leaves the others as they are. Reading is always on, drafting starts on, and everything else stays off until you list it in CAPABILITIES. A tier that is off has its tools left out of the tool list entirely, so a model never learns they exist.

TierDefaultTools
readalways onsearch_emails, get_email, get_thread, get_attachment, list_folders
draftsoncreate_draft
manageoffmove_email, set_flags
sendoffsend_email
deleteoffdelete_email
sieve-readofflist_sieve_scripts, get_sieve_script

Enable more with a list, for example CAPABILITIES=drafts,manage,delete. Moving a message into Trash is a delete by another route, so move_email refuses Trash unless delete is on too.

get_thread lists the conversation a message belongs to, meaning the messages it replies to and the replies that name it or an earlier message, from its own folder, INBOX and Sent. Each message is then read with get_email, which adds its warnings. Both create_draft and send_email take in_reply_to to thread a reply under the original in mail clients. Sending the reply marks the original as answered. With quote_original, the server adds the original below the reply as mail clients do, but only when every recipient was already on the original. Text the original's HTML hid is left out. A message body can be at most 64 kB, quote included.

search_emails pages through results filtered by free text, from, to, subject, since and before dates, or unread and flagged status. get_email shows sent and arrival times, Cc, and Reply-To when it differs from From. With manage on, set_flags marks messages read, unread, flagged or unflagged.

get_attachment saves a file to DOWNLOAD_DIR without reading its contents into the conversation. Saved files are readable only by you, never replace an existing file, and on macOS carry the quarantine flag, so an app among them goes through Gatekeeper before it runs.

What this can never do

These limits are enforced by the server.

  • No raw HTML reaches the model. Bodies come from the plain text part when one exists, or are converted to text otherwise. Invisible characters that hide instructions from a reader while staying readable to a model are stripped.
  • Bodies, subjects, sender names and Sieve scripts are fenced with markers that are neutralized inside the content, so a message cannot forge its way out. The server writes the lines outside the fence. Any short mailbox value repeated there, such as a folder name, is cleaned and length capped first.
  • No bcc field exists on drafts or sent mail. A bcc recipient gets a full copy while appearing nowhere in the message, which is exactly what an injected email would ask for.
  • Drafts and sent mail can attach only files already in the mailbox, named by folder, uid and part. No tool takes a file path or attaches anything from your disk.
  • Deleting moves a message to Trash. There is no expunge or permanent delete. A server that cannot move messages is refused. What your provider later does with Trash is up to the provider.
  • With several accounts, one call reaches one account. Attachments, replies and quotes come only from the account the call names, and the server never moves mail from one account to another.
  • Sieve access stays read only. No tool writes filter rules, which can forward, reply and notify even after you revoke the app password or uninstall this server.

Sending stays closed with send on until SEND_ALLOWLIST names recipients. It accepts single addresses, domains as *@example.com, or * alone for anyone. With no allowlist, the refusal explains how to allow specific recipients or anyone. SEND_CONFIRM=true adds a confirmation dialog before every send, showing the recipients, subject, attachments and the whole message, quote included. It needs a client that supports MCP elicitation, and other clients are refused, so use drafts there. Claude Desktop does not show these dialogs yet (October 2026). Allowing anyone without it lets the assistant write to anyone unasked, the third part of the lethal trifecta. See SECURITY.md for the design notes.

Suspicion warnings

Six detectors annotate get_email results for hidden text, instruction patterns, encoded blobs, sender mismatch, mixed scripts and DMARC failure. The Warnings line sits above the content, written in the server's own words and never quoting the content that triggered it. The image at the top shows five detectors firing on one message, and --demo lets you see them in your own client.

Warnings: hidden_text (412 hidden characters via display:none), encoded_blob (base64 run of 600 characters)

The message always comes back alongside its warnings. Each detector has its own switch in the configuration reference below. See detector details for thresholds, false positives and DMARC trust selection.

Provider setup

Set PROVIDER to one of gmail, outlook, icloud, yahoo, gmx, fastmail, mailbox.org or posteo and the matching servers and ports fill themselves in.

Gmail, iCloud, Yahoo and Fastmail need an app password. Google requires 2-Step Verification and an account policy that allows app passwords. iCloud requires two factor authentication on the Apple Account. mailbox.org, GMX and Posteo accept the account password, though an app password is the wiser choice.

Outlook and Microsoft 365 use PROVIDER=outlook with no password. On Outlook.com, turn IMAP on under Settings, Mail, Forwarding and IMAP. Your browser opens Microsoft's sign in page on the first mail read. Sign in, allow access, then ask again.

Work accounts

Your organization may require admin approval, and sending may require an administrator to enable SMTP AUTH. See work accounts for the consent link and tenant settings.

The full provider guide covers passwords, Microsoft permissions and signing out, Proton Mail through Bridge, and your own servers.

Configuration reference

All configuration is environment variables. They are checked when the server starts, so a typo fails at once with a message saying what to fix, rather than at the first tool call. An empty value counts as unset, since bundle managers fill optional fields left blank with empty strings.

All variables
VariableDefaultNotes
ACCOUNTSnoneNames of several accounts, separated by commas, each 1 to 16 lowercase letters or digits. See Several accounts.
PROVIDERnoneOne of gmail, outlook, icloud, yahoo, gmx, fastmail, mailbox.org, posteo. Fills in IMAP, SMTP and Sieve hosts and ports. outlook signs in through the browser instead of a password.
EMAIL_USERrequiredAccount login.
EMAIL_PASSWORDnoneApp password. Either this or EMAIL_PASSWORD_CMD is required, except with outlook, which takes neither.
EMAIL_PASSWORD_CMDnoneCommand that prints the password, such as a keychain lookup or pass, so the secret never sits in the client's config file. It has 60 seconds to finish.
MS_CLIENT_IDpylos-mcp's ownWith outlook only. The application ID of an app registered in your organization's tenant.
MS_TENANTcommonWith outlook only. Your tenant ID or domain, needed when MS_CLIENT_ID names an app registered for one tenant only.
IMAP_HOST / IMAP_PORTpreset / 993Explicit values for your own server. Set either to override the preset.
IMAP_STARTTLSfalseConnect in plain text and switch to TLS with STARTTLS before logging in, for servers that offer IMAP only that way. The default port becomes 143. A server that will not switch is refused, so the login is never sent unencrypted.
SMTP_HOST / SMTP_PORTpreset / 465, 587 for outlookRequired only when send is enabled.
SIEVE_HOST / SIEVE_PORTIMAP_HOST / 4190Used only when sieve-read is enabled.
CAPABILITIESdraftsTiers beyond read, which is always included, separated by commas.
MAX_BODY_KB64Message body truncation limit.
MAX_ATTACHMENT_MB25Attachment size cap. A download is checked against the size the server declares before any bytes arrive. When composing, it caps all attachments of one message together, shared by every message being composed at once.
DOWNLOAD_DIR~/DownloadsWhere get_attachment writes files.
SEND_SESSION_CAP5Successful send_email calls allowed per server run, counted again from zero after a restart.
SEND_SAVE_COPYtrueSave a copy of each sent message to the Sent folder, marked read. Turn off for providers that already file sent mail themselves (Gmail does), which would otherwise show duplicates.
SEND_ALLOWLISTnone (sending closed)Addresses or *@domain patterns separated by commas, or * alone to allow anyone. With send enabled and no value set, every send is refused and the refusal explains this variable. An explicitly empty value also allows nobody. An entry that could never match, such as a bare domain, fails at startup.
SEND_CONFIRMfalseShow each message in a confirmation dialog before it is sent, and send it only if you accept. Needs a client that supports MCP elicitation, which Claude Desktop does not yet. Sends from other clients are refused.
DRAFTS_NO_RECIPIENTSfalseWhen true, create_draft rejects to and cc entirely. Drafts carry no addressing and get it added later in your mail client.
FLAG_HIDDEN_TEXTtrueWarn when message HTML hides text with inline styles or aria-hidden.
FLAG_INSTRUCTION_PATTERNStrueWarn when the body, subject, sender line or attachment names contain phrases addressing an AI.
FLAG_ENCODED_BLOBStrueWarn on long runs of base64 or hex in the body.
FLAG_SENDER_MISMATCHtrueWarn when a Reply-To address sits on a different domain than the From address, or the From display name carries an address on another domain.
FLAG_MIXED_SCRIPTtrueWarn when a word mixes Latin letters with Cyrillic or Greek lookalikes.
FLAG_DMARC_FAILtrueWarn when your own mail server's DMARC check failed.
AUTHSERV_IDpresetServer names that start your provider's Authentication-Results headers, separated by commas, replacing the preset's. An entry starting with a dot matches any name ending in it. With none, dmarc_fail never fires.
STRIP_HIDDEN_TEXTfalseDrop detected hidden text from the body instead of only warning, with a note of how much was dropped. Needs FLAG_HIDDEN_TEXT on, and the combination with the detector off is refused at startup.
FLAG_EXTRA_PATTERNSnonePhrases added to the instruction pattern set, separated by pipes, matched as literal text regardless of case.
TLS_CA_FILEnonePath to a PEM CA certificate added as an extra trust anchor, for your own server with a private CA. Certificate verification cannot be turned off, this only extends what is trusted. Setting it trusts Node's bundled root store plus this file, so anchors added through NODE_EXTRA_CA_CERTS are not in that set. If you rely on those, point TLS_CA_FILE at the same certificate.

Several accounts

One server can read several mailboxes, with one send cap across all of them, where two separate servers would allow two. ACCOUNTS names the accounts, at most 10, and each account's settings take __ plus its name in capitals, such as EMAIL_USER__WORK. Without ACCOUNTS, nothing changes. This entry sets up a personal Gmail that drafts and sends to one listed address, and a work Outlook that keeps the default of reading and drafting:

json
{  "mcpServers": {    "pylos-mcp": {      "command": "npx",      "args": ["-y", "pylos-mcp"],      "env": {        "ACCOUNTS": "personal,work",        "PROVIDER__PERSONAL": "gmail",        "EMAIL_USER__PERSONAL": "[email protected]",        "EMAIL_PASSWORD__PERSONAL": "your-app-password",        "CAPABILITIES__PERSONAL": "drafts,send",        "SEND_ALLOWLIST__PERSONAL": "[email protected]",        "PROVIDER__WORK": "outlook",        "EMAIL_USER__WORK": "[email protected]"      }    }  }}

An account's settings are never taken from the unsuffixed variables, and with ACCOUNTS set those are refused, so an allowlist or a capability meant for one account can never reach another. MAX_BODY_KB, MAX_ATTACHMENT_MB, DOWNLOAD_DIR, SEND_SESSION_CAP, SEND_CONFIRM, DRAFTS_NO_RECIPIENTS, STRIP_HIDDEN_TEXT and every FLAG_ variable apply to every account and take no suffix.

Every tool then takes a required account, and each tool lists only the accounts whose capabilities include it, so here send_email offers personal alone. There is no default account, since a message number means something only inside its own mailbox. Every tool result starts with an Account: line, which keeps the assistant's references tied to the account they came from.

Mistakes show at startup, grouped, each naming the variable to fix. That includes a suffix naming no account in ACCOUNTS and the same mailbox configured twice, meaning the same EMAIL_USER on the same IMAP host.

The Claude Desktop bundle holds one account, since its install form cannot repeat a group of fields. For several accounts, put the entry above in a client's JSON config, Claude Desktop's claude_desktop_config.json included.

When pylos-mcp is not a fit

  • Your mail must never reach a model provider. What the assistant reads goes to the model you use, as anything else you show it does.
  • You want Claude Desktop to send with a confirmation before each message. Desktop does not show those dialogs yet, so there you get drafts, or sending to an allowlist without confirmation.
  • You need bcc, attachments from your disk or filter rules the assistant writes. None of these exist, on purpose.
  • Your organization blocks third party apps or SMTP AUTH and an administrator will not allow them.

Maintenance expectations

pylos-mcp is built for the author's own daily use and maintained on that basis. Issues and pull requests are welcome, and CONTRIBUTING.md has a wishlist of directions that would help.

See CONTRIBUTING.md for development setup and tests. No test in this project connects to a real mailbox, in development or in CI.

來源:README.md,提交 58e9cf4

工具

0
SourceWeft 尚未在沙箱中啟動過該軟體包,因此其工具未知。

版本歷史

11
  1. v1.4.0最新Nov 3, 2026
  2. v1.3.0Oct 19, 2026
  3. v1.2.0Oct 15, 2026
  4. v1.1.0Oct 14, 2026
  5. v1.0.1Oct 12, 2026
  6. v1.0.0Oct 11, 2026
  7. v0.6.0Oct 11, 2026
  8. v0.5.0Oct 10, 2026
  9. v0.4.1Oct 9, 2026
  10. v0.4.0Oct 8, 2026
  11. v0.2.0Sep 16, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分