search_emails using mailbox: "Drafts", and read it back with get_draft before sending something the agent did not write.
A send is only ever reachable from a draft that already exists, which means there is always a state the user could have inspected between composing and sending. Clients that gate irreversible calls can key off this tool’s MCP annotations rather than its name: it is marked destructiveHint: true and openWorldHint: true, while create_draft is marked false for both.
On success the message moves out of Drafts into Sent and loses its $draft marker — in the same server call as the submission, so a send can never half-commit into “delivered but still a draft”. The message keeps its id, so the returned messageId is what get_email reads back.
Parameters
string
required
The draft to send, as returned by the most recent
create_draft or update_draft call. Editing a draft changes its id.string
Client-chosen key that makes the call safe to retry: a repeat with the same key returns the first call’s answer instead of sending the message again. Pass one whenever the call might be retried. Keys are scoped to the account and to this tool — reusing a
create_draft key here is not a retry, so each call needs its own key or none. Remembered for 15 minutes.Example
Call
Result
get_draft does — this is the record of what actually went out, so it names every file, each with the blobId it was sent as. A file the server exposes without a retrieval handle appears too, marked as one that could not be re-attached: it was delivered with the message, and saying nothing about it would understate what the recipient just received.
Sending twice
Three independent guards stop a duplicate delivery, because each closes a window the others leave open.- Structural, and needs no cooperation from the client. A successful send clears the message’s
$draftmarker, so a second call finds a non-draft and refuses. This holds whether or not anidempotencyKeywas passed, because the state lives on the server — and the marker is cleared even on an account with no Sent folder, where the message stays in Drafts. - A reservation, for the retry that arrives while the first call is still running. That is exactly the case a key alone cannot catch: neither call has recorded an answer yet, and the draft still reads as a draft because the server has not applied the follow-up patch. The second call is told a send is already in progress. The reservation is keyed on the draft rather than on the caller’s key, so a client retrying with no key at all is covered too.
idempotencyKey, for the retry that arrives after the first call finished but whose response the client never saw. It replays the first answer verbatim.
Errors
Draft not found: <id>. Nothing was sent.— usually a stale id from before anupdate_draft.<id> is no longer a draft — it has already been sent. Nothing was sent again.A send of <id> is already in progress. Nothing was sent by this call.An earlier send of <id> failed without saying whether the message went out, so it was NOT sent again.This account cannot send as …— the draft’s sender is no longer one of the account’s identities.Draft <id> has no sender address, so it cannot be sent.Draft <id> has no recipients, so it cannot be sent.— reachable for a draft the user started in Langmail and left unaddressed, since this tool sends drafts it did not stage. Add them withupdate_draftand send the id it returns; an attached draft is no obstacle, since the edit carries its files across.