Reference
MCP tools
| Tool | What it does |
|---|---|
list_folders |
Folders with their roles (inbox, sent, trash, …) |
search_messages |
Search a folder by sender, recipient, subject, text, dates, unread or flagged; paged, newest first |
get_message |
Headers, plain-text body (HTML converted when there is no text part) and attachment list; does not mark as read |
send_message |
Send a plain-text message; saves a copy to Sent by default |
reply_to_message |
Reply or reply-all with correct threading headers |
update_flags |
Mark read/unread, flagged/unflagged |
move_message |
Move to another folder |
delete_message |
Move to the trash, or delete permanently on request |
create_folder |
Create a folder |
get_webhook_status |
This account’s new-mail webhook: active, paused, off, unreadable, or not set up, plus the effective outbox limits and the server ceilings. Host only; no URL, secret, auth header, or ciphertext |
set_webhook_enabled |
Turn this account’s new-mail webhook on or off. Enabling retries events kept while it was paused. Turning it back on after it was turned off skips events queued while it was off. Enabling unreadable settings, or an empty or invalid URL, is refused |
set_webhook_outbox_limits |
Set how long this account keeps new-mail events, and how many. Omit a field to leave it. JSON null or default uses the server default for that field; reset true resets both. Lowering a limit deletes the oldest kept events, including ones not delivered yet. Needs a webhook saved on the account page |
Messages are addressed by an opaque id that search_messages returns;
pass it to the other tools unchanged. Earlier versions used folder plus
uid; IMAP accounts still accept that pair, and IMAP results still include
uid, so existing clients keep working. New clients should use id. An
IMAP id stays valid while the message stays in its folder and the folder
keeps the same UIDVALIDITY. After move_message, search the destination
for the new id.
Read-only tools carry readOnlyHint; delete_message,
set_webhook_enabled and set_webhook_outbox_limits carry
destructiveHint. Turning a webhook back on after it was turned off
skips events queued while it was off. Lowering an outbox limit deletes
the oldest kept events, including ones that were not delivered yet.
The tools behave the same for every provider, with these differences:
| IMAP (iCloud, Fastmail, Yahoo, custom) | Outlook | Gmail | |
|---|---|---|---|
| Folders | IMAP folders | Mail folders, including nested ones (Inbox/Receipts) |
Labels: INBOX, Sent, Drafts, Trash, Spam, Starred, Important, All Mail and your own |
| Message ids | imap.…, change when a message moves |
graph.…, stay the same when a message moves |
gmail.…, stay the same |
folder + uid |
Accepted | Not accepted; use id |
Not accepted; use id |
| Sent copy | Saved to Sent unless save_to_sent is false |
Saved by Outlook | Saved by Gmail |
| Permanent delete | Supported | Supported | Refused: postkeep doesn’t request the scope that allows it, so messages go to Trash |
| Search totals | Exact | Exact, or estimated for text searches | Estimated |
Parameter descriptions below are the doc comments on the structs in crates/server/src/tools.rs.
search_messages
| Parameter | Meaning |
|---|---|
folder |
Folder to search. Defaults to INBOX. |
from |
Text that must appear in the From header. |
to |
Text that must appear in the To header. |
subject |
Text that must appear in the subject. |
text |
Text that must appear anywhere in the message, headers or body. |
since |
Only messages on or after this date (YYYY-MM-DD). |
before |
Only messages before this date (YYYY-MM-DD). |
unread_only |
Only unread messages. |
flagged_only |
Only flagged messages. |
offset |
Number of newest matches to skip, for paging. |
limit |
Maximum number of messages to return (default 20, maximum 100). |
get_message
| Parameter | Meaning |
|---|---|
id |
The message id from search_messages. |
folder |
Deprecated: folder of the message, with uid (IMAP accounts only). Use id instead. |
uid |
Deprecated: IMAP UID of the message, with folder. Use id instead. |
max_chars |
Maximum body length in characters (default 20000, maximum 200000). |
send_message
| Parameter | Meaning |
|---|---|
to |
Recipients, as [email protected] or Alice <[email protected]>. |
cc |
Carbon-copy recipients. |
bcc |
Blind carbon-copy recipients. |
subject |
Subject line. |
body |
Plain-text body. |
save_to_sent |
Save a copy in the Sent folder (default true). |
reply_to_message
| Parameter | Meaning |
|---|---|
id |
The message id from search_messages. |
folder |
Deprecated: folder of the message, with uid (IMAP accounts only). Use id instead. |
uid |
Deprecated: IMAP UID of the message, with folder. Use id instead. |
body |
Plain-text reply body. The original is not quoted automatically. |
reply_all |
Reply to all recipients instead of only the sender. |
save_to_sent |
Save a copy in the Sent folder (default true). |
update_flags
| Parameter | Meaning |
|---|---|
id |
The message id from search_messages. |
folder |
Deprecated: folder of the message, with uid (IMAP accounts only). Use id instead. |
uid |
Deprecated: IMAP UID of the message, with folder. Use id instead. |
read |
Mark as read (true) or unread (false). Omit to leave unchanged. |
flagged |
Flag (true) or unflag (false). Omit to leave unchanged. |
move_message
| Parameter | Meaning |
|---|---|
id |
The message id from search_messages. |
folder |
Deprecated: folder of the message, with uid (IMAP accounts only). Use id instead. |
uid |
Deprecated: IMAP UID of the message, with folder. Use id instead. |
destination |
Destination folder name, from list_folders. |
delete_message
| Parameter | Meaning |
|---|---|
id |
The message id from search_messages. |
folder |
Deprecated: folder of the message, with uid (IMAP accounts only). Use id instead. |
uid |
Deprecated: IMAP UID of the message, with folder. Use id instead. |
permanent |
Delete immediately instead of moving to the trash. Cannot be undone. |
create_folder
| Parameter | Meaning |
|---|---|
name |
Name of the new folder. |
list_folders takes no parameters.
get_webhook_status
Takes no parameters. It reports the signed-in account only. The account comes from the connection, never from an argument.
The response never includes the signing secret, the auth header name or value, the full URL, or any stored ciphertext. last_error is a short delivery summary with those values removed, or null when state is unreadable. url_host is only the host, and is also null for unreadable: the host is not returned from a row whose secrets cannot be checked.
| Field | Meaning |
|---|---|
configured |
Whether a webhook has been saved. |
state |
active (enabled, delivering), paused (enabled, backing off after failures), disabled (the user turned it off), unreadable (saved, but no configured key can decrypt it), not_configured, or unavailable when the operator set POSTKEEP_WEBHOOKS=false. unreadable wins over unavailable. |
enabled |
Whether the user has turned delivery on. |
paused |
Whether repeated failures are pausing delivery. |
paused_since |
When the pause began, RFC 3339, or null. |
consecutive_failures |
Failed deliveries in a row. Test events are not included. |
failure_threshold |
Failures in a row after which delivery pauses (10). |
last_error |
The last failure’s summary, with secrets removed, or null. |
last_attempt_at |
When a delivery was last attempted, RFC 3339, or null. |
last_success_at |
When a delivery last succeeded, RFC 3339, or null. |
next_retry_at |
When the next attempt is due, RFC 3339, or null when nothing is scheduled. |
pending_events |
Events still waiting to be delivered. |
retry_interval_seconds |
Seconds between attempts while paused, and the longest wait before a pause. |
url_host |
Host of the endpoint, or null. Never the path or query. Null when state is unreadable. |
message |
When state is unreadable, asks for the URL and auth header to be entered again on the account page (/account). Null otherwise. Never includes the URL, secrets, or ciphertext. |
outbox_retention_seconds |
How long events are kept, in seconds. Counts delivered and undelivered events. |
outbox_retention_source |
default when the account uses the server default, or account when it has its own value. A stored override above a ceiling the operator later lowered is still account, and outbox_retention_seconds is that ceiling. |
outbox_max_events |
How many events are kept. Delivered and undelivered events both count. |
outbox_max_events_source |
default or account, with the same ceiling rule as retention. |
outbox_max_retention_seconds |
Longest retention this server allows an account to set. Present even when no webhook is saved. |
outbox_max_events_limit |
Most events one account may keep. Present even when no webhook is saved. |
set_webhook_enabled
| Parameter | Meaning |
|---|---|
enabled |
Whether new-mail alerts should be delivered. |
Returns the same fields as get_webhook_status, including the outbox limits and the server ceilings. It does not include events_pruned.
Enabling a saved webhook turns delivery on, clears a pause and the failure count, and retries promptly. Events kept while the user had turned it off are dropped, the same as re-enabling on the account page; events kept while it was only paused are kept. That drop is why the tool is marked destructiveHint: turning a webhook back on after it was turned off skips events queued while it was off. If no webhook is saved, the tool returns an error telling you to set it up on the account page (/account). Enabling is also refused when the saved URL is empty or invalid, and the webhook stays off; the error asks you to finish setup on /account and does not include the URL. If the operator set POSTKEEP_WEBHOOKS=false, enabling is refused.
Enabling is also refused when the saved settings can’t be decrypted (state would be unreadable). The watcher and the delivery pump cannot use that row, so turning it on would not deliver anything. Disabling it still works: the row stays off, and the status remains unreadable until the URL and auth header are entered again on the account page. For that state, url_host, last_error and the pause times are null, and the failure counters are not copied from the stored row.
Disabling a readable webhook matches the account-page toggle: it stays off, with no watcher and no automatic recovery.
There is no tool to set or change the webhook URL, the auth header, or the signing secret. An assistant that processes untrusted mail could otherwise be steered into sending new-mail notifications (sender and subject) to an attacker, or into putting those secrets into the model context. Change them on the account page.
set_webhook_outbox_limits
| Parameter | Meaning |
|---|---|
retention |
Optional. A whole number of seconds, or a duration such as 36h, 30d or 90m. Omit to leave the retention unchanged. JSON null or default stores the server default. |
max_events |
Optional. How many events to keep. Omit to leave the cap unchanged. JSON null or default stores the server default. |
reset |
When true, both limits return to the server default and retention and max_events are ignored. |
Returns the same fields as get_webhook_status, plus events_pruned: how many oldest events this call deleted.
Lowering a limit deletes the oldest kept events immediately, including ones that were not delivered yet, which is why the tool is marked destructiveHint. The same call again, once the queue is already within the limit, deletes nothing more (events_pruned is 0). A value below 1 hour or 1 event, or above the server ceiling, is rejected and the error names the allowed range. The stored limits stay as they were. The tool needs a webhook saved on /account. It works while the webhook is paused or turned off, and while POSTKEEP_WEBHOOKS=false, as long as a row is saved. It does not change the endpoint, the secrets, or which events the receiver already accepted (delivered_sequence stays where it is). It does not start a delivery attempt. The response has no URL, signing secret, auth header, or ciphertext.