Skip to main content
Glama
mpalermiti

outlook-mcp

by mpalermiti

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault

No arguments

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
outlook_auth_statusA

Check authentication status. Run outlook-mcp auth on the host if needed.

outlook_list_inboxA

List messages in one folder with structured filters (read, sender, date, category, Focused).

Use this for folder-scoped browsing; use outlook_search_mail for KQL full-text search across all folders. For polling/recurring agents use outlook_list_inbox_delta (typically 10x cheaper after the first call).

Example: outlook_list_inbox(folder="Junk Email", unread_only=True, count=5) folder accepts display names, well-known names ("inbox", "junkemail"), or Graph IDs — prefer names. Pass concise=True to drop large fields (preview, categories) — ~10x fewer tokens. Pass uncategorized_only=True to return only messages with no categories assigned. after/before take ISO 8601 or a relative offset — 7d is seven days ago, +7d is seven days from now.

outlook_read_messageA

Get one full message by ID or Message-ID (<abc@example.com>).

format is "text", "html", or "full" (both). Pass include_deferred_send=True to also return the scheduled-send time (PR_DEFERRED_SEND_TIME) as deferred_send_datetime — useful when recreating a delayed draft. Pass concise=True to drop large fields (body, body_html) and return a 200-char body_preview — ~10x fewer tokens for triage scans. include_sender_auth=True adds sender_authentication: did Microsoft verify the From domain?

outlook_read_messagesA

Bulk read up to 20 messages by ID via $batch — use NOT N outlook_read_message calls.

Per-message shape in messages matches outlook_read_message byte-for-byte for the same (format, concise, include_deferred_send, include_sender_auth). Ordering follows input message_ids. Returns {messages, failures, requested, succeeded, failed} — 404s on some IDs are surfaced in failures without failing the whole call (partial-failure tolerant).

Example: outlook_read_messages(message_ids=[id1, id2, id3], concise=True) Hard cap of 20 (Graph $batch limit).

outlook_search_mailA

Full-text search mail with KQL across all folders (or one, if folder is set).

Use this for "find emails about X"; use outlook_list_inbox for structured filters scoped to a single folder.

Example: outlook_search_mail(query="from:sarah@acme.com received>=2026-01-01", count=10) query is Microsoft KQL (from:, subject:, received>=, hasattachment:true, AND/OR/NOT). Operators must be UPPERCASE — lowercase and is matched as a literal term. Two terms with no operator between them broaden the search; use AND explicitly to narrow. Pass concise=True to drop large fields (preview, categories) — ~10x fewer tokens.

outlook_list_foldersA

List mail folders with message counts, parent_id, and child count.

Default is top-level only; pass recursive=True to walk the full tree, each folder with the path that folder arguments accept.

outlook_list_inbox_deltaA

List only inbox changes since the last call.

Use this for polling/recurring agents — typically 10x cheaper than outlook_list_inbox after the first call. Use outlook_list_inbox for one-shot snapshots.

Example: first call: outlook_list_inbox_delta(); next: outlook_list_inbox_delta(delta_token=). is_deleted=True items are tombstones (drop cached payload). has_more=True means drain immediately by passing the returned delta_token back.

outlook_send_messageA

Send an email immediately, no human review.

For human-review workflows use outlook_create_draft + outlook_send_draft instead. For replying to an existing message use outlook_reply; for calendar invites use outlook_rsvp. Pass reply_to to route recipient replies to a different address (e.g. a shared team alias).

outlook_replyB

Reply (or reply-all) to an email message.

Use this for email; use outlook_rsvp for calendar meeting invites.

outlook_forwardC

Forward an existing message to new recipients, with optional comment.

outlook_move_messageA

Move a message to another folder (removes from source).

Use outlook_copy_message to duplicate without removing the source. For deletion use outlook_delete_message (not move to "deleteditems"). folder accepts display names, well-known names ("inbox", "archive", "deleteditems"), or Graph IDs — prefer names.

outlook_delete_messageA

Delete a message — soft delete (to Deleted Items) by default; permanent=True to hard-delete.

This is the canonical way to delete a message. Do NOT use outlook_move_message(folder="deleteditems") for deletion.

outlook_flag_messageB

Set the follow-up flag on a message. status is "flagged", "complete", or "notFlagged".

outlook_categorize_messageB

Set categories on a message (replaces the full list).

Example: outlook_categorize_message(message_id=..., categories=["Follow-up", "Pricing"])

outlook_mark_readA

Mark a single message as read or unread (set is_read=True or False).

outlook_reclassify_messageA

Reclassify ONE message's Focused/Other placement. classification is "focused" or "other".

Use this to fix a single message; use outlook_set_inbox_override for a sticky rule that affects future messages from the same sender.

outlook_list_inbox_overridesA

List the user's Focused Inbox per-sender override rules.

Each override forces mail from a given sender into Focused or Other regardless of Graph's inference.

outlook_set_inbox_overrideA

Create or update a sticky Focused/Other rule for a sender (upsert, case-insensitive).

Use this to permanently change classification for FUTURE messages from a sender; use outlook_reclassify_message to fix ONE existing message.

Example: outlook_set_inbox_override(sender_email="marketing@acme.com", classify_as="other") Returns status: "created" or "updated".

outlook_delete_inbox_overrideB

Delete a Focused Inbox per-sender override rule by its ID.

outlook_list_eventsA

List calendar events in a date range (expands recurring instances).

Use for one-shot queries; use outlook_list_events_delta for polling/recurring agents.

Pass concise=True for day-at-a-glance scans: drops organizer, response_status, type and show_as; adds is_organizer and attendees_count; spells is_online as is_online_meeting.

calendar: a display name or an ID from outlook_list_calendars; omit for the default calendar. A cursor continues the listing it came from.

outlook_get_eventA

Read an event by event_id, or an invitation by message_id (exactly one).

Returns your current event: body, attendees with proposed_new_time, organizer, is_organizer, allow_new_time_proposals, is_cancelled, recurrence, type, show_as, key and attachment metadata. start/end are UTC; original_start_time_zone is the anchor zone. recurrence uses the create tool's shape.

outlook_find_event_by_keyA

Find events by the key given to outlook_create_event or outlook_update_event.

Any date. Searches the default calendar, or calendar. Returns events and series masters, not occurrences.

outlook_list_events_deltaA

List only calendar event changes within a window since the last call.

Use this for polling/recurring agents — typically 10x cheaper than outlook_list_events after the first call. Use outlook_list_events for one-shot queries.

Example: first call: outlook_list_events_delta(start="2026-05-22T00:00:00Z", end="2026-05-29T00:00:00Z"); next: outlook_list_events_delta(delta_token=). start/end (ISO 8601) required on first call only; the cursor encodes the window thereafter. is_deleted=True items are tombstones. has_more=True means drain immediately.

outlook_create_eventA

Create a calendar event with optional attendees, recurrence, busy status, online meeting.

Example: outlook_create_event(subject="Q3 review", start="2026-08-15T14:00:00Z", end="2026-08-15T15:00:00Z", attendees=["alice@acme.com"]) is_online is accepted but has no effect on personal accounts — Graph silently ignores isOnlineMeeting for consumer mailboxes (it returns isOnlineMeeting: False, onlineMeetingProvider: "unknown"). Teams meetings require a work/school account. start/end are ISO 8601. Passing recurrence creates a series, not a single event. It takes either a shorthand — "daily", "weekdays", "weekly", "monthly", "yearly", all anchored on start and open-ended — or a full Microsoft Graph recurrence object for anything else, e.g. every other Mon+Fri for 10 occurrences: {"pattern": {"type": "weekly", "interval": 2, "daysOfWeek": ["monday", "friday"]}, "range": {"type": "numbered", "numberOfOccurrences": 10}} range.startDate defaults to the event's start date. Prefer a bounded range ("endDate"/"numbered") when the event has attendees — a "noEnd" series invites them to every future occurrence. timezone is the IANA zone the event is anchored in, which is what a recurring series is expanded against (default: the configured zone). A zone name like America/Los_Angeles, never an abbreviation like PDT. show_as is Outlook's "Show as": "free", "tentative", "busy", "oof" (out of office), "workingElsewhere", or "unknown". Omitted, Graph defaults the event to busy. calendar: name or ID; omit for the default. key: your own reference for the event, e.g. a booking number.

outlook_update_eventA

Update fields on an existing event (partial patch — only provided fields change).

recurrence takes the same shapes as outlook_create_event and converts a single event into a series, or replaces an existing series' pattern. Omit it to leave any recurrence alone; pass remove_recurrence=True to turn a series back into a single event, keeping the first occurrence's time (the two are mutually exclusive). attendees REPLACES the whole guest list (Graph has no add-one operation) and sends invitations to everyone on it plus cancellations to anyone dropped — pass the full intended list; [] removes everyone. is_all_day REQUIRES start and end in the same call, both on midnight boundaries. Patching a time keeps the zone the event is anchored in; pass timezone (with start and end) to re-anchor it somewhere else. A start, end or recurrence patch to a series with edited or deleted occurrences is refused, since Graph would discard them. Omitting an argument leaves it unchanged, so False and [] are instructions, not absences. show_as is Outlook's "Show as" — same values as outlook_create_event — and patches on its own; unlike is_all_day it needs nothing resent alongside it. key patches on its own too.

outlook_delete_eventA

Delete a calendar event by ID (cancels and notifies attendees if you're the organizer).

outlook_rsvpA

RSVP to a calendar meeting invite. response is "accept", "decline", or "tentative".

Use this for meeting invites; use outlook_reply to reply to a regular email message.

outlook_attach_to_eventA

Attach files to an event; auto-switches to upload-session for files >3MB.

attachment_paths resolve inside attachments_dir, as for outlook_attach_to_draft. Attendees get the files with the event's next update. Returns new attachment IDs.

outlook_remove_event_attachmentA

Remove one attachment from an event (IDs from outlook_get_event's attachments).

outlook_list_contactsA

List contacts with cursor pagination.

Use for one-shot queries; use outlook_list_contacts_delta for polling/recurring agents.

outlook_search_contactsA

Search contacts by name or email using KQL query syntax.

phone (instead of query) finds a number written any way, with or without country code.

outlook_get_contactB

Get one full contact by ID.

outlook_create_contactA

Create a new contact with name and optional email, phone, company, job_title, birthday (YYYY-MM-DD).

title is the name prefix ("Dr.", "Ms."), shown in the display name — not the job. phone_type: "mobile", "business" or "home".

outlook_update_contactA

Update an existing contact (partial patch — only provided fields change).

An address takes the shape outlook_get_contact returns — any subset of {"street", "city", "state", "postal_code", "country_or_region"} — and REPLACES that whole address, so pass back every part you want to keep. Omit it to leave it untouched. phone_type ("mobile", "business", "home") picks the field; business/home REPLACE that list. clear_phones empties those types: phone_type="business", clear_phones=["mobile"] moves it. title is the name prefix ("Dr.", "Ms."), shown in the display name — not the job. birthday is a date, YYYY-MM-DD. categories REPLACES the whole list ([] clears it). email REPLACES every address; add_emails/remove_emails change only those (3 at most).

outlook_delete_contactC

Delete a contact by ID.

outlook_list_contacts_deltaA

List only contact changes since the last call.

Use this for polling/recurring agents — typically 10x cheaper than outlook_list_contacts after the first call. Use outlook_list_contacts for one-shot queries.

Example: first call: outlook_list_contacts_delta(); next: outlook_list_contacts_delta(delta_token=). is_deleted=True items are tombstones (drop cached payload). has_more=True means drain immediately by passing the returned delta_token back.

outlook_changes_sinceA

One structured "since last call" digest across mail, events, and contacts.

Use this for recurring agent loops (morning brief, hourly inbox sweep) — one call returns counts, urgent_flagged mail, by-sender rollup, plus new/cancelled events and contacts counts. Use the three individual delta tools (outlook_list_inbox_delta, outlook_list_events_delta, outlook_list_contacts_delta) when you need raw item lists or per-resource control.

Example: first call: outlook_changes_since(); next: outlook_changes_since(delta_tokens=<delta_tokens from prior response>). First call covers the last fallback_window_hours (default 24); later calls (tokens passed back) return only what changed. Replace stored delta_tokens with the returned dict; never merge them. has_more true: a resource stopped early; pass the returned dict back. Each resource's token is independent — drop one stale token without re-syncing the others. If Graph 410s on a token (syncStateNotFound), that resource auto-resyncs and _meta.resync lists which one. urgent_flagged = high-importance OR flagged mail. by_sender = top 5 senders. Calendar modified[] is reserved for future use — modified events surface in new[] today (Graph delta doesn't distinguish them). Calendar organizer_email is also currently empty (the v1.9.0 delta formatter surfaces the organizer name only).

outlook_list_task_listsA

List all Microsoft To Do task lists for the current user.

outlook_list_tasksC

List tasks in a To Do list with optional status filter.

status: "notStarted", "inProgress", or "completed".

outlook_get_taskA

Get full To Do task details: notes (body), checklist items, due, recurrence flag.

Use this for one task's sub-steps and notes; use outlook_list_tasks for overviews. checklist_items are ordered unchecked-first, matching the To Do client. list_id is only needed when the task lives in a non-default list.

outlook_create_taskA

Create a Microsoft To Do task with optional due date, importance, body, and recurrence.

Example: outlook_create_task(title="Send invoice", due="2026-09-01", importance="high") reminder=True requires due and sets the reminder to the due time — Graph silently drops a reminder that has no time. due takes ISO 8601 or a relative offset — note +7d is seven days from now, while a bare 7d means seven days ago. importance is "low", "normal", or "high". Defaults to the user's default list when list_id is omitted.

outlook_update_taskB

Update fields on a To Do task (partial patch — only provided fields change).

outlook_complete_taskC

Mark a To Do task as completed.

outlook_delete_taskC

Delete a task from a Microsoft To Do list.

outlook_add_checklist_itemC

Add a checklist item (sub-step) to a To Do task.

outlook_update_checklist_itemA

Update a checklist item (partial patch — only provided fields change).

is_checked=True marks a sub-step done; Graph maintains the checked timestamp from it. Renaming passes display_name.

outlook_delete_checklist_itemB

Delete a checklist item from a To Do task.

outlook_list_task_attachmentsA

List attachments on a To Do task (id, name, size, content_type) with pagination.

Use outlook_download_task_attachment with an id from here to save the content. has_more=True means pass next_cursor back for the next page.

outlook_download_task_attachmentA

Download a To Do task attachment to a local file, or return it with as_content=True.

save_path resolves inside the configured attachments directory; the write is atomic (temp file + replace), so a failed download never truncates a file already staged there. as_content writes nothing; 10 MB at most.

outlook_upload_task_attachmentA

Attach a local file to a To Do task via inline base64 POST (1 byte – 20 MiB).

file_path resolves inside the configured attachments directory. Larger files are refused up front: Graph caps the request body at 30 MB and base64 inflates the file 4/3, so 20 MiB is the honest ceiling.

outlook_delete_task_attachmentC

Remove an attachment from a To Do task.

outlook_list_draftsB

List messages in the Drafts folder with cursor pagination.

outlook_create_draftA

Create a draft email for later review/send (pair with outlook_send_draft).

Use this when a human should review before sending; use outlook_send_message to send immediately without review. reply_to_message_id (reply_all=True for all) or forward_message_id drafts in that thread, quoting the original; on a reply, Graph fills to/cc/subject, so pass [] for a recipient you want cleared and omit the argument to keep Graph's choice. Pass deferred_send_datetime (ISO 8601, e.g. "2026-05-06T08:00:00Z") to schedule delayed delivery — Exchange holds the message server-side after outlook_send_draft. Pass reply_to to pre-populate the Reply-To header.

outlook_update_draftA

Update an existing draft (partial patch).

Pass is_html=True when body is HTML — required when overwriting a draft originally composed as HTML (consumer Outlook rejects Text-over-HTML PATCH). Pass reply_to=[...] to overwrite Reply-To; reply_to=[] to clear it. Pass deferred_send_datetime (ISO 8601) to set the scheduled-send time; empty string clears it.

outlook_send_draftA

Send an existing draft (pair with outlook_create_draft for human-review send flow).

outlook_delete_draftC

Delete a draft message by ID.

outlook_list_attachmentsB

List attachments on a message — returns IDs, names, sizes, and content types.

outlook_download_attachmentA

Download an attachment to save_path on the host, or return it with as_content=True.

save_path is resolved inside the configured attachments directory (attachments_dir, an attachments folder in the settings directory by default) — a bare filename lands there; a path outside it is refused. Same directory for reads and writes. as_content writes nothing; 10 MB at most.

outlook_send_with_attachmentsA

Send an email with file attachments; auto-switches to upload-session for files >3MB.

attachment_paths resolve inside the configured attachments directory (attachments_dir, an attachments folder in the settings directory by default) — a bare filename is looked up there, and a path outside it is refused. attachments: inline files [{name, content_base64, content_type?}], up to 3MB each. Pass reply_to to route replies to a different address.

outlook_attach_to_draftA

Add attachments to an existing draft; auto-switches to upload-session for files >3MB.

attachment_paths resolve inside the configured attachments directory (attachments_dir, an attachments folder in the settings directory by default) — a bare filename is looked up there, and a path outside it is refused. attachments: inline files [{name, content_base64, content_type?}], up to 3MB each. Returns new attachment IDs for later removal via outlook_remove_draft_attachment.

outlook_remove_draft_attachmentA

Remove a single attachment from a draft message by attachment ID.

outlook_create_folderB

Create a mail folder; pass parent_folder (name, path or ID) to nest it under that one.

outlook_rename_folderA

Rename a user-created mail folder by ID.

outlook_delete_folderA

Delete a user-created mail folder by ID; refuses well-known folders (inbox, sentitems).

outlook_list_threadA

List all messages in a conversation thread, chronological order.

Needs conversation_id from a message's metadata. Pass concise=True to drop large fields (quoted prior-message text in each preview) — ~10x fewer tokens on long reply chains.

outlook_copy_messageA

Copy a message to another folder (duplicates; source is unchanged).

Use outlook_move_message to remove from source. folder accepts display names, well-known names, or Graph IDs — prefer names.

outlook_batch_triageA

Triage up to 20 messages in one $batch call.

action is "move", "flag", "categorize", or "mark_read".

Example: outlook_batch_triage(message_ids=[id1, id2], action="move", value="Archive") value is the action target (folder name for move, status for flag/mark_read, category name for categorize). Hard cap of 20.

outlook_whoamiA

Get the authenticated user's profile (display name, email, ID).

outlook_list_calendarsA

List all calendars available to the authenticated user (primary + secondary).

outlook_list_categoriesA

List the user's master category definitions (names + colors).

Provides the valid values for outlook_categorize_message.

outlook_get_mail_tipsB

Pre-send check for recipients: out-of-office, delivery limits, mailbox-full warnings.

Prompts

Interactive templates invoked by user choice

NameDescription
morning_briefToday's calendar, unread mail and tasks due, in one pass.
triage_folderScan one folder cheaply and act on it in a single batch.
catch_upWhat changed in mail, calendar and contacts since a point in time.

Resources

Contextual data attached and managed by the client

NameDescription

No resources

TDQS

B3.4/5.0

Scored across 71 tools

Disambiguation4/5

Descriptions actively differentiate near-pairs (list_inbox vs search_mail, list vs *_delta, reclassify_message vs set_inbox_override, reply vs rsvp, move vs copy vs delete, read_message vs read_messages), which is unusually good given the surface size. Remaining confusion risk comes from the volume of similarly shaped attachment/draft/event tools and the singular/plural read pair, but boundaries are stated explicitly.

Naming Consistency5/5

Every tool uses the same outlook_ prefix and snake_case verb_noun form (list_, get_, create_, update_, delete_, send_, remove_). Resource qualifiers (task_attachment, event_attachment, draft) consistently keep parallel tools distinguishable without breaking the pattern.

Tool Count1/5

At 71 tools the surface is far beyond a tractable set for an agent to select from reliably, even though the underlying domain (mail, calendar, contacts, To Do, attachments) is genuinely broad. Many capabilities (drafts, folders, overrides, checklist items, attachments across four resource types, three delta tools plus a combined digest) are niche enough that they inflate the menu rather than each earning a slot.

Completeness5/5

Lifecycle coverage is thorough: full CRUD on messages, drafts, folders, events, contacts, tasks and attachments, plus send/reply/forward, RSVP, categorization, flagging, focused-inbox overrides, bulk read/triage, and delta/polling sync. No obvious dead ends for the stated mail/calendar/contacts/tasks purpose.

Maintenance

ActivityActive
ResponsivenessResponsive