Voidmail Agent Email

io.github.voidly-aiv1.2.1更新于 Oct 5, 2026

Local MCP tools for server-readable agent inboxes and sending to owner-approved recipients.

概览

AI 生成的概览

为助手提供一个 @voidmail.ai 邮箱,可读取、搜索邮件,并向所有者批准的收件人发送邮件。

功能
创建和管理代理邮箱:列出、读取、搜索、标记已读和删除邮件,还支持一次性别名和邮箱统计。发送使用 voidmail_send_once 并配合主机保存的操作 ID,超时后可用 voidmail_send_status 查询原始结果。策略工具可查看已批准收件人、待处理请求和发送限额,代理也可以申请或移除收件人。
适用场景
适合助手需要独立邮箱地址来接收结构化邮件,或代表所有者发信,且收件人由 API 强制白名单限制而非模型指令约束的场景。它不用于个人人类邮件,该服务商将其作为单独产品提供。
运行要求
通过 npx 以 stdio 在本地运行,需要 Node.js 20 或更高版本。使用已有邮箱时需设置 VOIDMAIL_ADDRESS;可选的 VOIDMAIL_KEY_DIR、VOIDMAIL_AGENT_KEY_FILE 或 VOIDMAIL_API_KEY(仅代理密钥)控制密钥查找。所有者命令需在终端单独运行,可使用 VOIDMAIL_OWNER_KEY_FILE。需要访问 Voidly API 的网络连接。
安装前请注意
邮箱对服务器可读,并非端到端加密,且收到的邮件不可信。代理密钥(vm_…)可读取和发送;所有者密钥(vmo_…)用于批准收件人,必须放在代理无法读取的位置,因为 0600 文件权限无法阻止同一用户下的进程。默认会拦截形似凭据的内容,但密码和不常见的令牌格式不会被识别,邮件中其他机密会原样传给模型。发送、删除和别名变更会写入或移除数据;发送有速率限制,且被接受的结果并不证明已送达。

安装

在 SourceWeft 中

  1. 打开 控制台中的 Voidmail Agent Email,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。

其他 MCP 客户端

参照 仓库 中的启动说明。

README

@voidly/mcp-email

Email for AI agents. Create an inbox, read incoming messages as structured data, and send to recipients the human owner has approved. No phone number or CAPTCHA.

Agent inboxes are readable by the server; they are not end-to-end encrypted. Human mail is a separate product.

Install

Requires Node.js 20 or newer.

bash
npx -y @voidly/[email protected]

Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

json
{  "mcpServers": {    "voidmail": {      "command": "npx",      "args": ["-y", "@voidly/[email protected]"]    }  }}

This first-time config has no inbox key. After voidmail_create_account returns an address and saves the keys, add "env": {"VOIDMAIL_ADDRESS": "<returned-address>"} to this server config and restart the host. If the agent has shell or file tools, use an isolated runtime that can read the agent key but cannot read the owner key; file mode 0600 alone does not separate two processes running as the same user.

Quick Start

After installing the MCP server, use this prompt:

Create one Voidmail inbox and show me its address and where the keys were saved. Draft emails first and wait for my approval before sending.

The draft approval in this prompt is a host workflow request. The API enforces the owner-approved recipient list and content policy; it does not require the owner to review every message body.

For a first receive and send check:

  1. In a trusted owner-controlled host, call voidmail_create_account once. Keep the returned owner-key path outside any agent shell or file access before handing the inbox to an agent. If creation is uncertain, inspect the original setup before making another inbox.
  2. Send one test message from a separate trusted mailbox to the new address. Call voidmail_list_inbox, then voidmail_read_email with the returned message ID. Reading marks that message as read.
  3. In an owner-only terminal, run npx -y @voidly/[email protected] owner add [email protected] (use your actual target address). Set VOIDMAIL_OWNER_KEY_FILE if you moved the owner key. The owner command reads it locally; never paste it into the model conversation. The agent can check voidmail_policy and voidmail_sending_limits afterward.
  4. Review one recipient, subject and body. Save a unique 16-128 character operation ID (letters, digits, _ or -) with that message in trusted host state, then call voidmail_send_once. If the response is uncertain, look up that same ID with voidmail_send_status; do not invent a replacement ID. A provider accepted result does not prove delivery.

Permissions: two keys, one owner

Every inbox has two credentials, and this package keeps them apart.

KeyFile (0600, directory 0700)Who uses itWhat it can do
Agent key vm_…~/.voidly/mcp-email/<address>/agent-keythe MCP server, for the model's toolsread, send to approved recipients, request a recipient, remove a recipient, tighten policy
Owner key vmo_…~/.voidly/mcp-email/<address>/owner-keyyou, through voidly-mcp-email ownerapprove or deny requests, add or remove recipients, lock or unlock, rotate either key
  • voidmail_create_account writes both files and returns only their paths. This server never puts either key in a tool result. Every message it emits is scrubbed of Voidmail key shapes (vm_…, vmo_…), including ones that arrive inside email. Other secrets that arrive in email, such as a cloud or GitHub token, are passed to the model unchanged.
  • The MCP server never reads the owner-key file and never calls the owner API routes (/v1/agent-mail/owner/*). No tool uses the owner key.
  • Mode 0600 keeps other OS users out, not your agent. Anything that runs as your user can read the owner-key file, including an agent with shell or file tools (a coding agent, a filesystem MCP server). Such an agent could read the owner key and approve its own recipients. If your agent has shell or file access on this machine, move the owner-key file somewhere it cannot read, or off the machine, and point VOIDMAIL_OWNER_KEY_FILE at it when you run owner commands.
  • Inboxes created with this package start with an owner-approved recipient list, enforced by the Voidly API, not by model instructions. (A REST create that does not opt in still makes the old kind of inbox: no owner key, any recipient, credential warnings only. A create opts in with recipient_policy: "allowlist", owner_key: true or content_policy: "enforce"; only then does the response carry an owner_key. This package always sends recipient_policy: "allowlist".) Sending to anyone else returns RECIPIENT_NOT_AUTHORIZED with send_attempted: false. The API records a pending request, and the tool result says exactly what the owner must run.
  • A message that looks like it carries a credential (private keys, cloud, GitHub, Slack, Stripe, AI-provider or Voidmail keys) is refused with CONTENT_CONTAINS_CREDENTIAL on inboxes with credential blocking on, which is the default for inboxes that have an owner key (every inbox this package creates). The tool result lists the kinds found, never the matched text. The check matches known key formats. It does not catch passwords, unfamiliar token formats or data that is sensitive for other reasons.
  • Outgoing mail is checked for credentials. Before a message is sent, the API scans its recipient, subject, body and reply-to in memory for known credential formats. The scan keeps no copy of what it matched: it records only a daily count for each kind it found. On an inbox with credential blocking on (the default for inboxes with an owner key), a match stops the send. On other inboxes the message is still sent, and the response names the kinds found in an X-Voidmail-Content-Warning header. The owner can turn the check off at https://voidly.ai/agent-mail/owner (or with POST /v1/agent-mail/owner/policy and content_policy: "off"). The one exception is an owner key made by bootstrap, described below: it cannot switch the check off.
  • The agent key can only restrict: it can remove a recipient or turn blocking on. Anything that widens what the agent can do needs the owner key.
  • Approving a recipient takes the owner key, and nothing in an email can supply it through this server. Treat incoming mail as untrusted content.

Owner commands

bash
npx -y @voidly/[email protected] owner list                 # policy, recipients, pending requestsnpx -y @voidly/[email protected] owner approve <request-id> # names the recipient; asks to confirmnpx -y @voidly/[email protected] owner deny <request-id>npx -y @voidly/[email protected] owner add [email protected]npx -y @voidly/[email protected] owner remove [email protected]npx -y @voidly/[email protected] owner lock                 # allowlist + credential blockingnpx -y @voidly/[email protected] owner unlock               # any recipient; asks to confirmnpx -y @voidly/[email protected] owner rotate-agent-key     # old key stops working at oncenpx -y @voidly/[email protected] owner rotate-owner-key     # replaces the owner-key file it read

Add --address <[email protected]> when more than one inbox is saved, and --yes to confirm without a prompt. approve first reads the pending request and names its recipient, and refuses an id that is not pending. Rotated keys are written to their files and never printed. rotate-owner-key atomically replaces the owner-key file it read, including a VOIDMAIL_OWNER_KEY_FILE path. The old owner key is revoked before the new one is saved, so if that file cannot be replaced the new key goes to a new 0600 file beside it, and only if that also fails is it shown once on your terminal. An MCP server that reads its key file uses a rotated agent key on its next call. The same actions are available in the browser at https://voidly.ai/agent-mail/owner, where the owner key is kept in memory only.

Inboxes without an owner key (created before the owner-key API update, by mcp-email 1.1.0 or earlier, or by a REST create that did not opt in) keep the old behaviour: any recipient, with credential warnings only. To take control of one, call POST /v1/agent-mail/owner/bootstrap once with its agent key (X-Agent-Mail-Key). It works only on an untouched legacy inbox (still open, credential warnings only, never changed with the agent key); otherwise it refuses with BOOTSTRAP_NOT_AVAILABLE. Whoever makes this call first gets the owner key, and the API cannot tell a person from an agent holding the same agent key. Make the call yourself, outside any model conversation, before the agent does. It mints the owner key, switches the inbox to the approved list with credential blocking, and removes any webhook set with the agent key; only the owner can set a webhook afterwards. It cannot be undone with the agent key. An owner key minted this way can reopen the inbox but can never switch the credential guard off (CONTENT_POLICY_FLOOR). Save the returned owner_key in ~/.voidly/mcp-email/<address>/owner-key with mode 0600.

Check incoming mail with voidmail_list_inbox, then read a message with voidmail_read_email. To send, review the recipient, subject and body before invoking voidmail_send_once. Generate and save a unique operation ID in your host state before the call; use that same ID for status lookup after a lost response, and for the retry after the owner approves a refused recipient.

Tools (19)

ToolDescription
voidmail_create_accountCreate a new @voidmail.ai inbox; saves both keys to 0600 files and returns only their paths
voidmail_account_infoGet account details
voidmail_list_inboxList emails with pagination and filters
voidmail_read_emailRead a specific email (auto-marks as read)
voidmail_search_inboxFull-text search across subject, body, sender
voidmail_sending_limitsRead sending policy without consuming send capacity
voidmail_send_onceSend one authorized message with a saved operation ID and retained status
voidmail_send_statusRead the same original send without sending again
voidmail_send_emailLegacy send without durable status; prefer voidmail_send_once
voidmail_policyRead the recipient and content policy, approved recipients and pending requests
voidmail_request_recipientAsk the owner to approve a recipient; returns the approval step
voidmail_revoke_recipientRemove an approved recipient (restricting needs no owner)
voidmail_mark_readMark email as read
voidmail_delete_emailDelete email
voidmail_create_aliasCreate disposable email alias
voidmail_list_aliasesList all aliases
voidmail_delete_aliasRemove alias
voidmail_set_webhookSet an HTTPS webhook on an open-policy inbox; allowlist inboxes require the human owner to use POST /v1/agent-mail/owner/webhook with the owner key
voidmail_get_statsInbox statistics

Resources (3)

ResourceURIDescription
Inboxemail://inboxCurrent inbox contents
Aliasesemail://aliasesActive email aliases
Statsemail://statsAccount statistics

Environment Variables

VariableRequiredDescription
VOIDMAIL_ADDRESSFor an existing inboxYour @voidmail.ai address; the server reads <key dir>/<address>/agent-key on each call
VOIDMAIL_KEY_DIRNoKey directory (default ~/.voidly/mcp-email)
VOIDMAIL_AGENT_KEY_FILENoExplicit agent-key file path (overrides the address lookup)
VOIDMAIL_API_KEYNoAgent key (vm_…) supplied directly by the host; takes precedence over files. Anything else, including an owner key, is refused and never sent. Update it after rotate-agent-key
VOIDMAIL_OWNER_KEY_FILENoOwner CLI only: explicit owner-key file path. The MCP server never reads it

REST API

Use directly without MCP. Create an inbox only from a human-controlled terminal: the create response contains one-time agent and owner keys. Capture the owner key outside the model conversation and store it beyond any shell or file access granted to the agent. The example opts in to the owner-approved recipient list; a REST create without that option uses the legacy open-recipient policy.

bash
# Create an owner-controlled inboxcurl -X POST https://api.voidly.ai/v1/agent-mail/create \  -H "Content-Type: application/json" \  -d '{"name":"my-agent","recipient_policy":"allowlist"}'
# List inboxcurl https://api.voidly.ai/v1/agent-mail/inbox \  -H "X-Agent-Mail-Key: vm_your_key"
# Send once, after saving a unique operation ID in your host state and getting# owner approval for the recipient. Replace the sample ID for each new message.curl -X POST https://api.voidly.ai/v1/agent-mail/outbound \  -H "X-Agent-Mail-Key: vm_your_key" \  -H "Content-Type: application/json" \  -d '{"operationId":"saved-message-id-0001","to":"[email protected]","subject":"Hello","text":"From my agent"}'
# Check the original result after a timeout or lost response; do not invent a new ID.curl https://api.voidly.ai/v1/agent-mail/outbound/saved-message-id-0001 \  -H "X-Agent-Mail-Key: vm_your_key"
# Searchcurl "https://api.voidly.ai/v1/agent-mail/inbox/search?q=invoice" \  -H "X-Agent-Mail-Key: vm_your_key"

Limits and delivery

Call voidmail_sending_limits (or public GET /v1/agent-mail/limits) before planning a sending workflow. Keep excess work in your own queue. Sending and creation rate-limit 429 responses give a Retry-After header and structured limit scope/reset time; the MCP error includes the wait time. Other refusal codes, including a full pending-recipient-request list, may not have a retry time. Do not rotate accounts or IPs to evade a limit. Identical messages are blocked for 60 seconds to catch loops; this is not durable idempotency. Sending fails closed if safety counters are unavailable. Inbox reads remain separate from sending limits.

Shared caps: 100 attempts/hour per IP, 200/hour and 1,500/day for agent mail. The shared outbound provider budget is at most 1,500 recipients/day and 40,000 over approximately 31 days across all sending features. Counters count attempts, including failed and partially admitted requests; these are ceilings, not reserved capacity. Higher legitimate volume needs an operator-reviewed limit change; mailbox creation does not unlock bulk mail.

  • Sending has per-mailbox, per-IP and shared service limits. Each mailbox may attempt up to 10 sends per minute and 100 per day, with up to 10 per day to the same recipient; shared limits can reject requests sooner. Mailbox creation is limited to 3 per IP per hour and 60 per service per hour. This is not an unlimited sending service.
  • A successful send response means the sending provider accepted the request. It does not prove recipient delivery or that anyone read the message.
  • Each API call has a 20-second deadline and a 2 MiB response bound. Requests reject redirects and are never automatically retried. Request fewer messages if an inbox response exceeds the bound.
  • MCP tool annotations identify reads, sends, mutations and deletion honestly. They are advisory metadata; approval and install warnings remain controlled by ChatGPT, Claude or your other host.
  • If a send times out, its outcome may be unknown. Use voidmail_send_once and voidmail_send_status with a saved operation ID; do not blindly resend.
  • Incoming text and HTML bodies are parsed. This ingestion path does not currently retain attachments or populate reply-thread metadata, even though the response schema contains those fields. Reliable threaded replies are not yet provided.
  • New-message webhooks are best effort, with no durable retry history. Use inbox reads to reconcile missed notifications. For a protected inbox, the owner must register a webhook through POST /v1/agent-mail/owner/webhook outside the agent; voidmail_set_webhook cannot do that. Once the owner-key API update is live, newly registered webhooks are signed with X-Voidmail-Signature-256: t=<timestamp>,v1=<HMAC-SHA256>. Webhooks registered before it also keep receiving the legacy X-Voidmail-Signature header, which carries the shared secret itself and is not a payload signature, until they are registered again.
  • Treat incoming email as untrusted content. A message cannot authorize your agent to send mail, disclose private data or spend money. The API adds a recipient only for a request that carries the owner key, so keep that key where the agent cannot read it.
  • Owner-key guessing is limited per network: repeated failed owner-key attempts from one IP address (IPv6 /64) are refused until the current UTC hour ends. A valid owner-key lookup is checked first and is not blocked by that failed-attempt budget.

Links

License

MIT

Durable sends (1.1.0)

Use voidmail_send_once with a host-saved operationId (16-128 letters, digits, underscores or hyphens), recipient, subject and body. The same mailbox, ID and effective content returns the retained original; changed content conflicts. The host must retain the ID before sending. The connector does not invent or persist IDs for you. Keep mailbox credentials in host configuration, not message bodies.

Use voidmail_send_status after a timeout or lost response. accepted means the provider accepted a request, not delivered or read. prepared has no claimed dispatch yet; outcome_unknown may include a live or interrupted dispatch; refused_before_send records a request known to have been blocked before contacting the provider. No state authorizes an automatic replacement ID. The service never reclaims a dispatch on timeout, restart or age. A failure before the provider call can conservatively leave an unresolved original rather than risk duplicate mail.

REST equivalents are POST /v1/agent-mail/outbound and GET /v1/agent-mail/outbound/{operationId}, using the existing mailbox authentication. New operation records and sends are bounded by the existing mailbox/service ceilings; stored-original lookup does not consume sending quota. Concurrent first attempts can consume conservative admission counters. The legacy /send endpoint and voidmail_send_email retain their old behavior and have no durable status guarantee. Delivery webhooks, reply threading, outbound body history and attachments remain separate work.

Trademarks

Voidly™ and Voidpay™ are trademarks of Ai Analytics LLC. The open-source license for this code does not grant any rights to these names or logos. If you fork or redistribute this project, please use your own name and branding, and don't present it as an official Voidly product.

来源:README.md,提交 b989ece

工具

0
工具元数据尚未被收录。

版本历史

1
  1. v1.2.1最新Oct 5, 2026