Skip to main content
Reference Last updated: 4 October 2026

Tools Reference - Outlook Assistant

Quick reference for all 22 MCP tools across 9 modules. Each tool includes MCP safety annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint).

Nathan Schram
By Nathan Schram Founder, Little Bear Apps

Quick reference for all 22 MCP tools across 9 modules. Each tool includes MCP safety annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint).

Authentication (1 tool)

ToolActionsSafetyKey Parameters
authstatus (default), authenticate, device-code-complete, aboutmoderate writemethod (device-code default, browser), force, clientId (saves your Azure Application (client) ID to ~/.outlook-assistant-config.json for clients that can’t set OUTLOOK_CLIENT_ID; the env var wins). Device code state persists across server restarts (v3.7.2+).

Email (8 tools)

ToolDescriptionSafetyKey Parameters
search-emailsSearch, list, delta sync, conversationsread-onlyquery, from, to, folder (name or nested path), searchAllFolders, searchExpression, deltaMode, conversationId, groupByConversation, internetMessageId, sharedMailbox (alias email), maxResults (delta page size)
read-emailRead content or forensic headersread-onlyid, outputVerbosity (body up to 2,000 characters, or 40,000 at full), headersMode, groupByType, importantOnly, sharedMailbox (alias email)
send-emailSend email with safety controlsdestructiveto, subject, body, dryRun, checkRecipients, acknowledgeWarnings, cc, bcc, importance, saveToSentItems
draftCreate, update, send, delete, reply, forward draftsdestructiveaction (required), id, to, subject, body, comment, dryRun, checkRecipients
get-mail-tipsPre-send recipient validationread-onlyrecipients, tipTypes
update-emailMark read/unread, flag/unflag/completeidempotentaction (required), id, ids, dueDateTime, startDateTime, sharedMailbox (alias email)
attachmentsList, view, or download attachmentsmoderate writeaction (list/view/download), messageId, attachmentId, outputDir (download; absolute or ~/…; default system tmpdir), sharedMailbox (alias email)
exportExport emails to various formatsdestructivetarget (message/messages/conversation/mime), id, emailIds, searchQuery/query, conversationId, format, outputDir (or savePath for a single message; absolute or ~/…), overwrite (replace an existing savePath file; default false), sharedMailbox (alias email)

sharedMailbox is opt-in (work/school only). Set OUTLOOK_SHARED_MAILBOX=read (read: Mail.Read.Shared) or =true (read and organise: adds Mail.ReadWrite.Shared), restart, then run auth action=authenticate force=true. While it’s unset, sharedMailbox calls are refused with these steps, and access-shared-mailbox reads only well-known folder names or folder IDs, as before (listFolders and custom/nested names need the setting).

Downloads and exports stay in allowed folders. Every output path must be absolute (a leading ~ means the home directory; relative paths are refused) and resolve to somewhere inside the system temp directory (the default), ~/Downloads, ~/Documents or OUTLOOK_EXPORT_DIR, with no dot-prefixed name below them; anything else is refused. Server-chosen filenames are sanitised, written with exclusive create (an existing file or symlink is never overwritten or followed; a clash gets a numbered suffix) and confined to the chosen folder. An explicit savePath file is never replaced unless overwrite: true is passed, and never if it is a symlink, has other hard links, or is a dotfile or inside a dot-directory below the allowed folder. Files are created with mode 0600 and new folders 0700; a replaced file keeps its mode. IDs containing . or .. path segments are refused before any Graph request.

sharedMailbox is read/organise only. send-email and draft (create/update/send/delete, reply, reply-all, forward) deliberately take no sharedMailbox parameter — they always act on the signed-in user’s own mailbox, and Mail.Send.Shared is not requested.

search-emails modes

ModeTriggerDescription
ListNo query paramsLists recent emails (like old list-emails)
Searchquery, from, to, etc.Full search with OData filters; searchExpression for a raw Graph $search expression; searchAllFolders: true for cross-folder
DeltadeltaMode: trueIncremental sync, returns deltaToken
Conversation listgroupByConversation: trueGroups by thread
Conversation getconversationIdMessages in a thread, oldest first (up to 100; export target=conversation takes up to 1000)
Message-ID lookupinternetMessageIdFind by RFC Message-ID header

Personal accounts: The query and raw searchExpression (formerly kqlQuery, kept as a deprecated alias) parameters use Microsoft’s $search API, which has limited support on personal Outlook.com accounts. Unscoped expressions work; field-scoped ones (e.g. from:someone@example.com, subject:"…") return nothing from $search there, so since v3.10.0 they are translated into the closest equivalent OData filters and retried, reported as strategy raw-kql-translated (#217) — note a subject: term becomes a substring match, so the translation is close rather than identical. Expressions that cannot be translated exactly — free text, AND/OR, unknown prefixes — still terminate rather than silently falling back to an unfiltered search. query handles the same limitation with progressive fallback (OData filters, boolean filters, recent listing). Structured filters (from, subject, to, receivedAfter, hasAttachments, unreadOnly) remain the most direct route. Cross-folder search (searchAllFolders: true) returns a superset of inbox-only results.

query vs searchExpression: these issue structurally different Graph requests, so they surface different messages. An untranslated searchExpression is answered by $search over the entire message — body included — ranked by relevance with no date ordering, so a term buried in a body can outrank an obvious subject-line match. On personal accounts query falls back to a subject substring match (every word must appear in the subject), which is precise but never reads bodies. Use query for a term you expect in a subject, searchExpression when you need body content.

to scan cap: personal Outlook.com rejects the server-side recipient filter, so to falls back to a local match over the 500 most recent messages (OUTLOOK_SEARCH_SCAN_LIMIT, max 5000). On a large archive that excludes older mail; pair to with receivedAfter/receivedBefore to reach it. The response discloses a truncated scan whether or not it matched.

More results and long bodies: list and search have no page cursor yet (#286). When a result says more emails are available, raise count (max 50) or narrow receivedAfter/receivedBefore. A body cut at 2,000 characters names the read-email call with outputVerbosity: full (up to 40,000); anything longer can be written whole to a file with export target=message. A batch export target=messages takes at most 100 messages per call and says when some were left out.

Search metadata: every search-emails response carries _meta.searchMetadata. finalStrategy names the rung that answered (combined-search, single-term-*, client-side-*, boolean-filters-only, raw-kql-translated, recent-emails); filterApplied says whether every supplied filter was honoured; droppedFilters lists any that were not — it should always be empty, and a non-empty value means the result set is broader than the query (#229). candidatesScanned (with scanLimit and truncated) discloses how many messages a client-side fallback examined, so a bounded scan never reads as a whole-mailbox answer; kqlTranslatedTo records the rewrite when a field-scoped searchExpression was translated. An empty search additionally reports in its guidance text how many messages any local narrowing pass looked at.

Delta sync is designed for inbox monitoring workflows. The first call returns current emails and a deltaToken; subsequent calls with that token return only new, modified, and deleted messages. maxResults (1–200, default 100) sets the page size, sent as Prefer: odata.maxpagesize on every request; when a page returns a continuation token (_meta.tokenType: "continuation"), keep passing it back with the same maxResults until a delta token arrives. See Monitor Inbox with Delta Sync.

update-email actions

ActionDescriptionParams
mark-readMark as readid (single)
mark-unreadMark as unreadid (single)
flagFlag for follow-upid or ids (batch), dueDateTime, startDateTime
unflagClear flagid or ids (batch)
completeMark flag as completeid or ids (batch)

Flag dates: a dueDateTime/startDateTime with Z or a ±hh:mm offset is kept as that exact instant (sent to Graph in UTC); one without a zone is read in the configured timezone (OUTLOOK_DEFAULT_TIMEZONE, default Australia/Melbourne). Date-only or unparseable values are refused before any change. With only dueDateTime, the start defaults to 09:00 on the due date in the configured timezone, or the due time if earlier. The reply shows each date in UTC and in the configured timezone.

draft actions

ActionDescriptionRequired Params
createSave new draft to Drafts folder— (all optional)
updateEdit an existing draft (refuses non-drafts)id
sendSend an existing draft (refuses non-drafts)id
deleteDelete a draft to Recoverable Items (restorable for a limited time, depending on your account), skipping Deleted Items (refuses non-drafts)id
replyCreate reply draft from messageid
reply-allCreate reply-all draft from messageid
forwardCreate forward draft with new recipientsid, to

Draft safety: dryRun: true previews without saving (create only). checkRecipients: true validates recipients via mail-tips before saving. The send action shares rate limits with send-email. Recipient allowlist applies to create, update, forward, reply and reply-all (a reply draft with a recipient outside it is deleted and refused), and send re-checks the draft’s current to/cc/bcc. Reply, reply-all and forward count towards the draft rate limit. update, send and delete check the id first and refuse anything that is not an unsent draft, so a received or sent message is never edited, deleted or re-sent. comment and body are mutually exclusive on reply/forward.

Export formats

FormatUse Case
mime / emlFull MIME with headers — archival and forensics
mboxUnix MBOX archive — batch export conversations
markdownHuman-readable — paste into documents
jsonStructured data — programmatic processing
htmlFormatted — visual archival of threads
csvSpreadsheet-friendly metadata export

Content-type handling: The attachments tool handles text and binary content types. Text attachments (text/*, application/json, application/xml) are displayed inline; binary attachments require download. The contentType field is included in attachment listings.

Calendar (3 tools)

ToolDescriptionSafetyKey Parameters
list-eventsList events: upcoming by default, or past/current/by name with filters (times as canonical UTC ISO-8601 + labelled local)read-onlycount (default 10, max 100), startAfter/startBefore (ISO 8601 with Z or ±hh:mm, normalised to UTC), subject (case-insensitive contains, ≤ 255 chars). Supplying any filter replaces the default start ≥ now bound and filters are AND-ed; backward-looking searches (startBefore alone, or subject alone) return newest first. Invalid values return a tool error before any Graph call
create-eventCreate new eventdestructive (sends invitations)subject, start, end, attendees (email strings are required attendees; {email, type} objects set type to required/optional/resource), body, dryRun (preview who would be invited, with an external count, without creating anything). With OUTLOOK_ALLOWED_RECIPIENTS set, every attendee must be allowed or nothing is created; counts towards OUTLOOK_MAX_CREATE_EVENT_PER_SESSION (else OUTLOOK_MAX_EMAILS_PER_SESSION). Times use configured timezone (default: Australia/Melbourne; override with OUTLOOK_DEFAULT_TIMEZONE env var) — omit Z suffix for local time
manage-eventUpdate, decline, cancel, or delete (delete removes the event and Graph doesn’t document a guaranteed recovery path; deleting a meeting you organised that has attendees emails them a cancellation; use cancel with a comment to control the message)destructiveaction (update/decline/cancel/delete), eventId (or alias id), comment (decline/cancel; omitted if not given), sendResponse (decline only; false declines without notifying the organiser), subject/start/end/attendees/body/location/isOnlineMeeting/sensitivity/showAs/importance/categories/reminderMinutesBeforeStart (update only — only the fields you pass are changed; attendees is a full replacement list of email strings or {email, type} objects, and an entry without a type keeps the type that address already has, new addresses being required; with OUTLOOK_ALLOWED_RECIPIENTS set, every address on the list must be allowed or the update is refused), dryRun (all actions; nothing is changed or sent: decline/cancel/delete read the event and say who would be emailed, with an external count; update previews the PATCH, reading the event first when attendees are untyped so the preview shows the resolved types)

Folder (1 tool)

ToolActionsSafetyKey Parameters
folderslist (default), create, move, stats, deletedestructivename, parentFolder/parentFolderId (create), emailIds, targetFolder/targetFolderId (move), folder/folderId (stats), folderName/folderId (delete), dryRun (delete: preview the items and subfolders that would be lost), outputVerbosity. Folders addressable by nested path (Parent/Child) or ID; list shows full paths + IDs. All actions accept sharedMailbox (alias email)

Rules (1 tool)

ToolActionsSafetyKey Parameters
manage-ruleslist (default), create, update, reorder, deletedestructivename (or alias displayName), fromAddresses, containsSubject, bodyContains, hasAttachments, moveToFolder/copyToFolder (name, nested path like Triage/Delete, or ID), forwardTo/redirectTo (a rule with any address blocked by OUTLOOK_ALLOWED_RECIPIENTS is refused whole), assignCategories, dryRun (create/update; doesn’t count towards the rate limit), except*, ruleName, ruleId, sequence. Create, update, reorder and delete count towards OUTLOOK_MAX_MANAGE_RULES_PER_SESSION

Contacts (2 tools)

ToolDescriptionSafetyKey Parameters
manage-contactFull CRUD: list (default), search, get, create, update, deletedestructiveaction, query, id, displayName, firstName/lastName, email, emails, count, skip (list paging), outputVerbosity, dryRun (delete: preview which contact would be removed)
search-peopleRelevance-based search (People API)read-onlyquery, count

Categories (3 tools)

ToolDescriptionSafetyKey Parameters
manage-categoryCRUD: list (default), create, update/set (alias), deletedestructive (delete)action, displayName, color, id (or deprecated alias categoryId)
apply-categoryApply/add/remove categories on messages. With sharedMailbox, category names must already exist in that mailbox’s master list (manage-category manages the signed-in account only)idempotentmessageId/messageIds, categories, action, sharedMailbox (alias email)
manage-focused-inboxFocused Inbox overrides: list (default), set, deletedestructive (delete)action, emailAddress, name, classifyAs, outputVerbosity

Category colours

preset0-preset24: Red, Orange, Brown, Yellow, Green, Teal, Olive, Blue, Purple, etc.

Settings (1 tool)

ToolActionsSafetyKey Parameters
mailbox-settingsget (default), set-auto-replies, set-working-hoursdestructive (auto-replies reach external senders), idempotentsection, enabled, startDateTime, endDateTime, internalReplyMessage, externalReplyMessage, externalAudience, dryRun (set-auto-replies: preview who would get replies, the schedule and message lengths), startTime, endTime, daysOfWeek, timeZone

Advanced (2 tools)

ToolDescriptionSafetyKey Parameters
access-shared-mailboxRead shared mailbox (incl. custom subfolders) or enumerate its folder tree — no send/draft/reply/forwardread-onlysharedMailbox (or alias email), folder (name/path), folderId, listFolders, count (default 25, max 50), outputVerbosity
find-meeting-roomsSearch meeting roomsread-onlyquery, building, floor, capacity, outputVerbosity

Safety Annotations

All four hints are set explicitly on every tool, and derived from the risk-class map in utils/risk-classes.js, so every tool and action is classified on purpose. Annotations are hints: your MCP client decides whether to prompt, and a client set to auto-approve a tool, or running in a mode that skips prompts, won’t ask. destructiveHint covers deletes, and also anything that reaches other people or keeps acting after the call (sends, invitations, cancellations, inbox rules, automatic replies).

CategoryToolsClient Behaviour
Read-only (7)search-emails, read-email, list-events, search-people, access-shared-mailbox, find-meeting-rooms, get-mail-tipsMay be auto-approved by clients that support annotations
Destructive (11)send-email, draft, create-event, manage-event, manage-rules, mailbox-settings, folders, manage-contact, manage-category, manage-focused-inbox, export (can replace a local file with overwrite: true)Clients that honour the hint prompt for confirmation
Other writes (4)auth, update-email, apply-category, attachmentsYour client’s normal approval settings

idempotentHint: true (repeating the call has no further effect) is set on every read-only tool and on update-email, apply-category and mailbox-settings.

send-email and create-event also carry _meta["anthropic/requiresUserInteraction"], so Claude Code asks before every call to them, dry runs included, even in auto-accept or bypass modes. Other clients ignore it.

Errors: every failed tool call returns isError: true with a message that says what went wrong and, usually, a “Next step”. A call to a tool that doesn’t exist is a JSON-RPC error (-32602), not a tool result. Signed out? The message names auth with action=authenticate.

Plugin skill and safety hook: the Outlook Assistant plugin adds the using-outlook-assistant skill and a hook that asks before calls that reach other people, delete something or keep acting (rules, forwarding, automatic replies), with a plain-English reason. See the plugin README and Supported Clients and Their Limits.

Read-only mode: with OUTLOOK_READ_ONLY=true the server refuses every tool call or action that isn’t a read before it runs, whatever the client’s approval settings. That includes dryRun previews, export and attachments action=download; auth sign-in still works. See the README’s environment variables.

dryRun only where it previews: send-email, draft create, create-event, every manage-event action, manage-rules create/update, mailbox-settings set-auto-replies, and folders and manage-contact delete. dryRun: true on any other call is refused before it runs (dryRun is not supported for …; nothing was changed.), so a preview never makes the change for real.

openWorldHint: true is set on tools that return content authored by external/untrusted parties (search-emails, read-email, list-events, get-mail-tips, search-people, access-shared-mailbox, attachments, export, draft) or that reach other people (send-email, draft, create-event, manage-event, manage-rules, mailbox-settings), signalling MCP clients to apply appropriate caution (e.g. prompt-injection defences).

send-email Safety Controls

ControlConfigDefault
Pre-send mail tipscheckRecipients: true param. Out-of-office, mailbox full, delivery restricted or external recipients refuse the sendDisabled
Send despite mail-tip warningsacknowledgeWarnings: true param (with checkRecipients)false
Dry-run previewdryRun: true paramDisabled
Session rate limitOUTLOOK_MAX_SEND_EMAIL_PER_SESSION env, else OUTLOOK_MAX_EMAILS_PER_SESSION (shared with draft action=send)Unlimited (unset or 0)
Recipient allowlistOUTLOOK_ALLOWED_RECIPIENTS env. Also covers draft, rule forwards, create-event attendees and manage-event update attendees; not cancel/decline messages or mailbox-settings automatic replies. Anything that isn’t a single plain address is refused while it’s setAllow all

get-mail-tips

Check recipients before sending — detects out-of-office, mailbox full, delivery restrictions, moderation, external recipients, group member counts, and max message size. Uses POST /me/getMailTips (existing Mail.Read scope).

Tip TypeWhat It Checks
automaticRepliesOut-of-office messages and schedule
mailboxFullStatusWhether mailbox is full (delivery may fail)
customMailTipAdmin-configured notices
deliveryRestrictionWhether you’re allowed to send to this recipient
moderationStatusWhether messages require approval
recipientScopeInternal vs external recipient
maxMessageSizeMaximum message size limit
totalMemberCountGroup size (total members)
externalMemberCountHow many group members are external

These are the names you pass in tipTypes. Graph’s response uses some different field names (mailboxFull, deliveryRestricted, isModerated), and both forms are recognised. _meta.issues lists each flagged condition per recipient as {address, type}, with type one of outOfOffice, mailboxFull, customTip, deliveryRestricted, moderated, external or externalMembers. Mail tips are Microsoft 365 only; personal accounts return none.

Output Verbosity

LevelDescription
minimalEssential fields only (token efficient)
standardCommon fields (default)
fullAll available fields (read-email body up to 40,000 characters; standard stops at 2,000)

draft Safety Controls

ControlConfigDefault
Dry-run previewdryRun: true param (create only; refused on other actions)Disabled
Pre-save mail tipscheckRecipients: true param (create only; the tips are returned with the saved draft and never stop it)Disabled
Session rate limit (create/update/reply/reply-all/forward)OUTLOOK_MAX_DRAFT_PER_SESSION env, else OUTLOOK_MAX_EMAILS_PER_SESSIONUnlimited (unset or 0)
Session rate limit (send)Counts towards the send-email limit (OUTLOOK_MAX_SEND_EMAIL_PER_SESSION, else OUTLOOK_MAX_EMAILS_PER_SESSION)Unlimited (unset or 0)
Recipient allowlistOUTLOOK_ALLOWED_RECIPIENTS env: create, update, forward, reply and reply-all (a refused reply draft is deleted); send re-checks the draft’s current to/cc/bccAllow all
Drafts-only guard (update/send/delete)Always onNon-drafts refused

Common Patterns

// Create a draft for review
draft(action: "create", to: "sarah@company.com", subject: "Project Update", body: "Hi Sarah...", dryRun: true)

// Save draft, then update it
draft(action: "create", to: "sarah@company.com", subject: "Draft", body: "...")
draft(action: "update", id: "draft-id", subject: "Updated Subject", body: "Better content...")

// Send a draft
draft(action: "send", id: "draft-id")

// Reply to an email as a draft
draft(action: "reply", id: "message-id", comment: "Thanks for the update!")

// Forward as draft with recipients
draft(action: "forward", id: "message-id", to: "colleague@company.com", comment: "FYI")

// List recent emails
search-emails(folder: "inbox", count: 10)

// Search with filters
search-emails(from: "boss@company.com", receivedAfter: "2024-01-01")

// Check recipients before sending
get-mail-tips(recipients: ["sarah@company.com", "team@company.com"])

// Preview email with recipient check
send-email(to: "...", subject: "...", body: "...", dryRun: true, checkRecipients: true)

// Preview email before sending
send-email(to: "...", subject: "...", body: "...", dryRun: true)

// Get forensic headers
read-email(id: "...", headersMode: true, importantOnly: true)

// Export conversation to markdown
export(target: "conversation", conversationId: "...", format: "markdown", outputDir: "~/Downloads")

// Upcoming events (default)
list-events(count: 10)

// Past events in a window (oldest first)
list-events(startAfter: "2026-01-01T00:00:00Z", startBefore: "2026-02-01T00:00:00Z")

// Most recent events with "standup" in the subject (newest first)
list-events(subject: "standup", count: 5)

// Set out-of-office
mailbox-settings(action: "set-auto-replies", enabled: true, internalReplyMessage: "I'm away...")

// Flag email for follow-up (Z/offset = exact instant; no zone = configured timezone)
update-email(action: "flag", id: "...", dueDateTime: "2026-03-01T09:00:00Z")
update-email(action: "flag", id: "...", dueDateTime: "2026-03-01T17:00:00")

// Access shared mailbox (needs OUTLOOK_SHARED_MAILBOX for listFolders / custom names)
access-shared-mailbox(sharedMailbox: "team@company.com", folder: "inbox")

// Discover a shared mailbox's custom subfolders (names, paths, IDs)
access-shared-mailbox(sharedMailbox: "team@company.com", listFolders: true)

// Read a custom subfolder of a shared mailbox by path
access-shared-mailbox(sharedMailbox: "team@company.com", folder: "Inbox/Vendors/Acme")

// List a shared mailbox's folder hierarchy via the folders tool
folders(action: "list", sharedMailbox: "team@company.com", includeChildren: true)

// Search within a shared mailbox's custom folder
search-emails(sharedMailbox: "team@company.com", folder: "Archiv", query: "invoice")

// Delta sync (initial — returns emails + deltaToken)
search-emails(deltaMode: true, maxResults: 50)

// Delta sync paging (continuation token from the previous page, same page size)
search-emails(deltaMode: true, deltaToken: "continuation-token...", maxResults: 50)

// Delta sync (incremental — returns only changes)
search-emails(deltaMode: true, deltaToken: "previous-token...", maxResults: 50)
Was this helpful?

Related Articles