Control scopes & safety rails
An agent that can call Primail can read and send mail the same way the CLI can. The checks below are the ones Core actually runs.
Layer 1: Shared local profile
Section titled “Layer 1: Shared local profile”primail-mcp uses the same data-directory resolver as the app and
CLI (PRIMAIL_DATA_DIR, then runtime-profile.json, then the
platform default). There is no MCP/REST token and no read /
draft / send / manage scope on a token.
Whoever can spawn the binary against that profile can call every registered tool. Limit that by OS user, file permissions, and which profile path you pass.
Layer 2: Account control scope
Section titled “Layer 2: Account control scope”Stored on the account: all, ui_only, or mcp_only.
On send, Core’s check_send_allowed rejects the wrong
interface with send_blocked_scope:
ui_only— UI may send; MCP and CLI may not.mcp_only— MCP and CLI may send; UI may not.
List and read still see the account. Scope is not invisibility.
Change it with primail account settings-update ACCOUNT_ID --control-scope ui-only
or MCP account_settings_update. The GUI only shows a notice.
Layer 3: Account role
Section titled “Layer 3: Account role”| Role | Send |
|---|---|
personal | Allowed (then scope applies) |
managed | Allowed today; no confirmation queue |
receive-only | Blocked (send_blocked_receive_only) |
See Account roles.
Layer 4: Provider and input limits
Section titled “Layer 4: Provider and input limits”There is no Primail 20-sends-per-minute or 300-reads-per-minute cap, and no HTTP 429 from a local REST server.
What does exist:
- Provider IMAP/SMTP throttles (
provider_rate_limited,smtp_rate_limit). - Batch add/remove/group UTF-8 and item budgets (50 items / 16384 bytes) on those account tools.
- Validation, missing account, and missing-message errors
(
validation_error,account_not_found,message_not_found).
Successful and failed work is recorded in the shared rotating log
and, for Command-bus verbs, the local command_log table. Open
Settings → Support → Activity Log or run primail logs.
Nothing is uploaded.
There is no Settings → AI Agents → Tokens list and no
primail-mcp token revoke --all.
Undo Send
Section titled “Undo Send”The GUI compose Undo Send timer is a Settings hold on the
composer path. Direct MCP email_send is not that timer. Optional
send_at schedules a local Core send on this device.
Models and injection
Section titled “Models and injection”Tool arguments come from the client. Role and scope checks run
inside Core on send. That is not blanket prompt-injection immunity:
a client with a writable profile can still send from any
personal/managed account whose scope allows MCP.
Separately, optional Core Gemini tools
(ai_summarize_message and siblings) upload message text to Gemini
when a key is configured. Your MCP client may also send tool
results to its own provider. Neither is a Primail hosted consumer
AI in the GUI.