archive-imap-message Archive IMAP Messagecopy-imap-attachment Copy IMAP Attachmentcreate-draft Create Email Draftcreate-reply-draft Create Email Reply Draftget-compose Get Compose Emailget-imap-headers Get IMAP Headersget-imap-message Get IMAP Messageget-imap-quota Get IMAP Quotalist-composes List Compose Emailslist-imap-connections List IMAP Connectionslist-imap-folders List IMAP Folderslist-imap-messages List IMAP Messagessearch-imap-messages Search IMAP Messagessearch-messages Search Sent Messagesset-gmail-labels Set Gmail Labelsset-imap-flags Set IMAP Flagsupdate-draft Update Email DraftArchives IMAP messages, taking them out of the inbox without deleting them, and reports their state before and after. This is how a handled email is marked resolved. On Gmail it removes the Inbox label, as Gmail's own Archive and Done do: the message stays in All Mail with its other labels, read state and star, and is read and changed there, so each result gives state_folder and state_uid in All Mail (the inbox UID no longer exists once archived; use those to address the message again). On other hosts it moves the message to the archive folder: archive_folder if given, else the server's special-use Archive folder, else "Archive" (filter lh_email_imap_archive_folder); the folder must already exist. The move is UID MOVE, or with UIDPLUS a copy then a delete and expunge of that one UID; a server with neither is refused, and nothing is ever deleted outright. after_folder and after_uid say where the message ended up. Repeating the call is harmless: a message already archived is reported unchanged. Takes uid, uids (up to 50) or both; one message failing does not stop the rest. Does not mark the message read; use set-imap-flags for that. Requires edit_posts. Pass site_id to act on another site you belong to.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
slug | string | Yes | IMAP connection slug, from list-imap-connections. | |
folder | string | No | Folder the UIDs belong to, as list-imap-messages and search-imap-messages give it. Default: INBOX. | |
uid | integer | No | UID of one message. Pass this, uids, or both. | |
uids | array of integer | No | UIDs of several messages in the folder, at most 50. | |
archive_folder | string | No | Non-Gmail hosts only: folder to move messages to. Default: the server's Archive folder, else "Archive". Ignored on Gmail. | |
task_id | integer | No | Optional. The lh-tasks task this call is working on. Pass with claim_token: the call is refused unless you hold that claim, and a successful call renews it. | |
claim_token | string | No | Optional. The claim_token from claim-next-task for task_id. Required when task_id is given. | |
site_id | integer | No | Optional. ID of another site in the network to act on; list-my-sites gives the sites you belong to. Permissions are checked on that site. Omit for this site. |
Copies one IMAP attachment out of the mailbox onto this server and returns a source reference for lh-mcp-file-abilities, which for an attachment includes the site ID so it reads the right media library from any connector. The copy is made server-side, so the file never passes through the response, and every lh-mcp-file-abilities ability accepts the reference as its source input: follow with get-file-text, describe-file, get-file-rows or get-file-image to read it. destination chooses where the copy goes. private (the default) files it into this site's media library through LH Private Uploads: the file is written straight into its private directory and served only through the access-checked proxy URL, and the copy is refused if LH Private Uploads is not active. media files it into normal public uploads; a copy attached to a private parent still ends up private, and is_private reports what actually happened. Both check the file type as the normal uploader does, refuse anything WordPress would refuse, and are idempotent: the origin (connection, folder, UID, part, Message-ID, sender, date, subject) is recorded in attachment meta, and a repeat call for the same message and part returns the existing attachment with newly_saved false. sandbox writes the file to your own lh-mcp-sandbox directory under lh-email/, for reading a document without keeping it: no attachment is created, the copy counts against your sandbox quota, a repeat call replaces it, and you remove it with lh-mcp-sandbox/delete-staged-path once read. Attachments over the configured limit (default 5MB) are refused rather than truncated. The message is not marked as seen. Use the part number from get-imap-message's attachment list. Requires edit_posts, plus upload_files for private and media, or the lh-mcp-sandbox capability (install_plugins by default) for sandbox. Pass site_id to act on another site you belong to.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
slug | string | Yes | IMAP connection slug. | |
folder | string | Yes | Folder name. | |
uid | integer | Yes | Message UID. | |
part | integer | Yes | Attachment part number, as returned in the part field of get-imap-message's attachment list (1-based). | |
destination | string | No | "private" | private (default): a private media attachment. media: a public media attachment. sandbox: a file in your own lh-mcp-sandbox directory, for reading without keeping. One of: private, media, sandbox. |
title | string | No | Attachment title, for private and media. Optional – defaults to the file name without its extension. | |
parent_id | integer | No | ID of a post to attach the file to, for private and media. Optional. You must be able to edit it. | |
task_id | integer | No | Optional. The lh-tasks task this call is working on. Pass with claim_token: the call is refused unless you hold that claim, and a successful call renews it. | |
claim_token | string | No | Optional. The claim_token from claim-next-task for task_id. Required when task_id is given. | |
site_id | integer | No | Optional. ID of another site in the network to act on; list-my-sites gives the sites you belong to. Permissions are checked on that site. Omit for this site. |
Creates a new lh_email_compose post as a draft. Cannot publish or dispatch — use the WordPress editor to send when ready. attachments takes the IDs of private media items on this site (make one with lh-private-uploads/create-private-media); the files are read from disk when the email is sent, never linked. Requires edit_posts. Pass site_id to act on another site you belong to.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
subject | string | Yes | Email subject line. | |
body | string | No | Email body as HTML, plain text or block markup. HTML and plain text are converted to block markup before saving; block markup is stored as given. | |
mode | string | No | Compose mode: single (one message, multiple recipients share the same body) or broadcast (one personalised message per recipient). Defaults to single. One of: single, broadcast. | |
to | string | No | Comma-separated To email addresses. | |
cc | string | No | Comma-separated CC email addresses. Optional. | |
bcc | string | No | Comma-separated BCC email addresses. Optional. | |
expand_aliases | boolean | No | Broadcast only: send each member one message addressed to their primary email and every verified alias (LH User Identity), merging any of their addresses entered more than once. Unverified aliases are never added. Defaults to true; false sends only to the addresses entered, still one message per member. | |
attachments | array of integer | No | Attachment IDs of private media items on this site to send with the email, in order. Only private files held by LH Private Uploads that you can open are accepted; at most 10, 10 MB in all. In broadcast mode every recipient gets the same files. Optional. | |
task_id | integer | No | Optional. The lh-tasks task this call is working on. Pass with claim_token: the call is refused unless you hold that claim, and a successful call renews it. | |
claim_token | string | No | Optional. The claim_token from claim-next-task for task_id. Required when task_id is given. | |
site_id | integer | No | Optional. ID of another site in the network to act on; list-my-sites gives the sites you belong to. Permissions are checked on that site. Omit for this site. |
Creates a new lh_email_compose post as a draft that threads into an existing email conversation via In-Reply-To/References headers. Fetches the source message internally via its IMAP UID to auto-populate the subject and threading headers — the source message must be real; there is no way to fabricate threading against a message that does not exist. Single mode only, with no mode param — a reply targets exactly one prior message, which does not fit broadcast's one-personalised-message-per-recipient model. Cannot publish or dispatch — use the WordPress editor to send when ready. Requires edit_posts. Pass site_id to act on another site you belong to.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
reply_to_imap_uid | integer | Yes | UID of the IMAP message being replied to, as returned by get-imap-message, search-imap-messages, or list-imap-messages. | |
slug | string | Yes | IMAP connection slug the source message lives on. | |
folder | string | Yes | IMAP folder the source message lives in. | |
body | string | No | Reply body as HTML, plain text or block markup. HTML and plain text are converted to block markup before saving; block markup is stored as given. This is the primary reply content — individually-worded per recipient is left to the caller, not templated here. | |
to | string | No | Comma-separated To email addresses. Optional — defaults to the source message's sender. | |
cc | string | No | Comma-separated CC email addresses. Optional. | |
bcc | string | No | Comma-separated BCC email addresses. Optional. | |
quote_original | boolean | No | Whether to append a quoted "On {date}, {sender} wrote:" block with the original message below the reply body. Defaults to false so the reply text stays the primary content. | |
task_id | integer | No | Optional. The lh-tasks task this call is working on. Pass with claim_token: the call is refused unless you hold that claim, and a successful call renews it. | |
claim_token | string | No | Optional. The claim_token from claim-next-task for task_id. Required when task_id is given. | |
site_id | integer | No | Optional. ID of another site in the network to act on; list-my-sites gives the sites you belong to. Permissions are checked on that site. Omit for this site. |
Retrieves a compose email post by ID. Returns subject, mode, envelope fields, status, raw post_content, rendered body HTML, attachments, and dispatch meta. Useful for reading sent emails as templates. Requires edit_posts. Pass site_id to act on another site you belong to.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
post_id | integer | Yes | ID of the lh_email_compose post to retrieve. | |
site_id | integer | No | Optional. ID of another site in the network to act on; list-my-sites gives the sites you belong to. Permissions are checked on that site. Omit for this site. |
Fetches headers only for a single IMAP message by UID — no body fetch. Useful for quick threading lookups. Includes sent_match check against the outbound email log. Read-only — does not mark as seen. Requires edit_posts. Pass site_id to act on another site you belong to.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
slug | string | Yes | IMAP connection slug. | |
folder | string | Yes | Folder name. | |
uid | integer | Yes | Message UID. | |
site_id | integer | No | Optional. ID of another site in the network to act on; list-my-sites gives the sites you belong to. Permissions are checked on that site. Omit for this site. |
Fetches a single IMAP message by UID. Returns full headers, plain text body, HTML body, attachment list (metadata only, no content — pass an attachment's part number to copy-imap-attachment to copy it onto the server, then read it with the lh-mcp-file-abilities abilities), In-Reply-To, References, and a sent_match if the message is a reply to a record in the outbound email log. Read-only — does not mark as seen. Requires edit_posts. Pass site_id to act on another site you belong to.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
slug | string | Yes | IMAP connection slug. | |
folder | string | Yes | Folder name. | |
uid | integer | Yes | Message UID. | |
site_id | integer | No | Optional. ID of another site in the network to act on; list-my-sites gives the sites you belong to. Permissions are checked on that site. Omit for this site. |
Returns mailbox quota and usage if the IMAP server supports it (QUOTAROOT). Fails with a message when the server does not report a quota. Each entry says whether its figures are reliable: Gmail always answers with a placeholder, and a limit over 1 TB is taken to mean unlimited, so those entries have reliable false, no percent, and a note explains why. Requires edit_posts. Pass site_id to act on another site you belong to.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
slug | string | Yes | IMAP connection slug. | |
site_id | integer | No | Optional. ID of another site in the network to act on; list-my-sites gives the sites you belong to. Permissions are checked on that site. Omit for this site. |
Lists compose email posts. Optionally filter by status (draft, publish) and/or mode (single, broadcast). Supports keyword search on subject and pagination. Sent emails are useful as templates for new compositions. Requires edit_posts. Pass site_id to act on another site you belong to.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
status | string | No | Filter by post status: draft, publish, or any (default: any). One of: draft, publish, any. | |
mode | string | No | Filter by compose mode: single or broadcast. Optional — omit for all modes. One of: single, broadcast. | |
search | string | No | Keyword to search in the subject (post title). Optional. | |
per_page | integer | No | Results per page. Default 20, max 100. | |
page | integer | No | Page number. Default 1. | |
site_id | integer | No | Optional. ID of another site in the network to act on; list-my-sites gives the sites you belong to. Permissions are checked on that site. Omit for this site. |
Lists all configured IMAP connections for the current site. Returns slug, label, host and port for each, never credentials, plus whether IMAP is available on this server. Use a slug from here with the other IMAP abilities. Requires edit_posts. Pass site_id to act on another site you belong to.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
_ | string | No | "" | Unused; takes no input. |
site_id | integer | No | Optional. ID of another site in the network to act on; list-my-sites gives the sites you belong to. Permissions are checked on that site. Omit for this site. |
Lists all folders/mailboxes available on an IMAP connection, sorted by path. Requires edit_posts. Pass site_id to act on another site you belong to.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
slug | string | Yes | IMAP connection slug. | |
site_id | integer | No | Optional. ID of another site in the network to act on; list-my-sites gives the sites you belong to. Permissions are checked on that site. Omit for this site. |
Lists messages in an IMAP folder with sorting and pagination. Returns message summaries including unseen status. Sorting by date is done by the server across the whole folder; sorting by from, subject or size only orders the page that was fetched. Only headers are fetched. If the request runs short of time it returns the summaries it has, with partial true. Read-only — does not mark messages as seen. Requires edit_posts. Pass site_id to act on another site you belong to.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
slug | string | Yes | IMAP connection slug. | |
folder | string | No | Folder name. Default: INBOX. | |
limit | integer | No | Messages per page. Default 20, max 100. | |
page | integer | No | Page number. Default 1. | |
sort | string | No | Sort field: date, from, subject, size. Default: date. One of: date, from, subject, size. | |
order | string | No | Sort order: asc or desc. Default: desc. One of: asc, desc. | |
site_id | integer | No | Optional. ID of another site in the network to act on; list-my-sites gives the sites you belong to. Permissions are checked on that site. Omit for this site. |
Search messages using IMAP search criteria or Gmail search syntax. Standard IMAP examples: FROM "peter@", SINCE "1-Jan-2026", SUBJECT "invoice", UNSEEN, ALL. Gmail: pass gmail_search for full Gmail search syntax. Only headers are fetched. If the request runs short of time it returns the summaries it has, with partial true. Read-only — does not mark messages as seen. Requires edit_posts. Pass site_id to act on another site you belong to.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
slug | string | Yes | IMAP connection slug. | |
folder | string | No | Folder name. Default: INBOX. | |
query | string | No | Standard IMAP search string. Default: ALL. | |
gmail_search | string | No | Gmail search query (only used when host is imap.gmail.com). Overrides query. | |
limit | integer | No | Results per page. Default 20, max 100. | |
page | integer | No | Page number. Default 1. | |
site_id | integer | No | Optional. ID of another site in the network to act on; list-my-sites gives the sites you belong to. Permissions are checked on that site. Omit for this site. |
Searches the outbound email log for every site you can see. Supports filtering by site, subject keyword, recipient email, and delivery status, and each result names its site. Requires manage_options on each site searched, or install_plugins to see every site.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
site_id | integer | No | Only messages sent from this site. Optional; omit to search every site you can see. | |
search | string | No | Keyword to search in the subject field. Optional. | |
email | string | No | Filter by recipient email address (exact match against actors table). Optional. | |
status | string | No | Filter by delivery status: lh_email_queued, lh_email_sending, lh_email_sent, lh_email_failed, lh_email_skipped. Optional. One of: lh_email_queued, lh_email_sending, lh_email_sent, lh_email_failed, lh_email_skipped. | |
per_page | integer | No | Results per page. Default 20, max 100. | |
page | integer | No | Page number. Default 1. |
Adds and removes Gmail labels on messages, such as a Resolved label, and reports their labels before and after. Gmail connections only. Labels are the names Gmail shows, nested ones as Parent/Child; system labels take a leading backslash (\Important, \Starred), and Inbox means \Inbox, so removing it archives. \Trash and \Spam cannot be added. A user label that does not exist is refused, and nothing changed, unless create_missing is true, when it is created first; the result lists created_labels. The message is changed in All Mail, so state_folder and state_uid point there. Repeating the call is harmless: a message already labelled that way is reported unchanged. Takes uid, uids (up to 50) or both; one message failing does not stop the rest. To archive, prefer archive-imap-message, which also works off Gmail. Requires edit_posts. Pass site_id to act on another site you belong to.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
slug | string | Yes | IMAP connection slug, from list-imap-connections. | |
folder | string | No | Folder the UIDs belong to, as list-imap-messages and search-imap-messages give it. Default: INBOX. | |
uid | integer | No | UID of one message. Pass this, uids, or both. | |
uids | array of integer | No | UIDs of several messages in the folder, at most 50. | |
add | array of string | No | Labels to add. | |
remove | array of string | No | Labels to remove. | |
create_missing | boolean | No | false | Create a label in add that does not exist yet. Default false: a missing label is refused. |
task_id | integer | No | Optional. The lh-tasks task this call is working on. Pass with claim_token: the call is refused unless you hold that claim, and a successful call renews it. | |
claim_token | string | No | Optional. The claim_token from claim-next-task for task_id. Required when task_id is given. | |
site_id | integer | No | Optional. ID of another site in the network to act on; list-my-sites gives the sites you belong to. Permissions are checked on that site. Omit for this site. |
Marks IMAP messages read or unread and starred or unstarred, and reports their flags before and after. add and remove each take seen (read) and flagged (starred in Gmail); a flag may not be in both. On Gmail the message is changed in All Mail, so the result's state_folder and state_uid point there; elsewhere it is changed where it is. Repeating the call is harmless: a message already in that state is reported unchanged. Takes uid, uids (up to 50) or both; one message failing does not stop the rest. Does not archive: use archive-imap-message to take a handled message out of the inbox. Requires edit_posts. Pass site_id to act on another site you belong to.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
slug | string | Yes | IMAP connection slug, from list-imap-connections. | |
folder | string | No | Folder the UIDs belong to, as list-imap-messages and search-imap-messages give it. Default: INBOX. | |
uid | integer | No | UID of one message. Pass this, uids, or both. | |
uids | array of integer | No | UIDs of several messages in the folder, at most 50. | |
add | array of string | No | Flags to add: seen, flagged. | |
remove | array of string | No | Flags to remove: seen, flagged. | |
task_id | integer | No | Optional. The lh-tasks task this call is working on. Pass with claim_token: the call is refused unless you hold that claim, and a successful call renews it. | |
claim_token | string | No | Optional. The claim_token from claim-next-task for task_id. Required when task_id is given. | |
site_id | integer | No | Optional. ID of another site in the network to act on; list-my-sites gives the sites you belong to. Permissions are checked on that site. Omit for this site. |
Updates an existing lh_email_compose draft. Patch semantics — only supplied fields are changed, and each supplied field replaces the stored value; attachments replaces the whole list, and an empty array removes them all. Refuses if the compose post has already been dispatched. Requires edit_posts. Pass site_id to act on another site you belong to.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
post_id | integer | Yes | ID of the lh_email_compose draft to update. | |
subject | string | No | New subject line. Optional — omit to keep existing. | |
body | string | No | New body as HTML, plain text or block markup; HTML and plain text are converted to block markup before saving. Optional — omit to keep existing. | |
mode | string | No | Compose mode: single or broadcast. Optional — omit to keep existing. One of: single, broadcast. | |
to | string | No | Comma-separated To addresses. Optional — omit to keep existing. | |
cc | string | No | Comma-separated CC addresses. Optional — omit to keep existing. | |
bcc | string | No | Comma-separated BCC addresses. Optional — omit to keep existing. | |
expand_aliases | boolean | No | Broadcast only: send each member one message addressed to their primary email and every verified alias (LH User Identity), merging any of their addresses entered more than once. Unverified aliases are never added. Defaults to true; false sends only to the addresses entered, still one message per member. Optional — omit to keep existing. | |
attachments | array of integer | No | Attachment IDs of private media items on this site, replacing the draft's current attachments; an empty array removes them all. Only private files held by LH Private Uploads that you can open are accepted; at most 10, 10 MB in all. Optional — omit to keep existing. | |
task_id | integer | No | Optional. The lh-tasks task this call is working on. Pass with claim_token: the call is refused unless you hold that claim, and a successful call renews it. | |
claim_token | string | No | Optional. The claim_token from claim-next-task for task_id. Required when task_id is given. | |
site_id | integer | No | Optional. ID of another site in the network to act on; list-my-sites gives the sites you belong to. Permissions are checked on that site. Omit for this site. |