ms-graph-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| MS365_MCP_CLOUD | No | Sovereign cloud: global, usgov, usgovdod, china. Anything but global needs --client-id. | global |
| MS365_MCP_GROUPS | No | Comma-separated tool groups to enable. | |
| MS365_MCP_PRESET | No | Group bundle: personal, work, admin, all. | personal |
| MS365_MCP_VERBOSE | No | Log Graph requests to stderr. | off |
| MS365_MCP_ORG_MODE | No | Enable the groups whose scopes need tenant admin consent. | off |
| MS365_MCP_AUTH_FLOW | No | Interactive sign-in flow: auto, browser, device. | auto |
| MS365_MCP_AUTH_PORT | No | Loopback port for the browser flow's redirect. 0 lets the OS pick. | 0 |
| MS365_MCP_CACHE_DIR | No | Directory holding the token cache. | |
| MS365_MCP_CLIENT_ID | Yes | Entra application (client) ID. Overrides the shipped default, and is required in a build that has none, in a sovereign cloud, or wherever your tenant will not accept the shared app. | |
| MS365_MCP_DISCOVERY | No | Expose discover_tools and call_tool instead of every tool. | off |
| MS365_MCP_READ_ONLY | No | Hide every tool that writes. | off |
| MS365_MCP_TENANT_ID | No | Tenant ID, or common / organizations / consumers. Personal Microsoft accounts need consumers. | common |
| MS365_MCP_ALLOW_BETA | No | Allow requests against the Graph beta endpoint. | off |
| MS365_MCP_MAX_OUTPUT_CHARS | No | Truncate serialised tool output beyond this many characters. | 60000 |
| MS365_MCP_ALLOW_GENERIC_WRITE | No | Let graph_request send POST, PATCH, PUT and DELETE. | off |
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
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| me_get_profileA | Returns the signed-in user's own Entra ID profile from /me: by default id, displayName, mail, userPrincipalName, jobTitle, officeLocation and preferredLanguage. Pass |
| me_get_mailbox_settingsA | Returns the signed-in user's Outlook mailbox configuration: time zone, date and time format, locale, working hours, and the automatic-reply (out-of-office) setting. Automatic-reply bodies are HTML in Graph and come back stripped to plain text and truncated to |
| mail_list_messagesA | Lists Outlook messages newest-first, 10 per call by default (50 max), as a compact projection: id, subject, from, toRecipients, receivedDateTime, isRead, hasAttachments, bodyPreview and webLink. Bodies are never included — bodyPreview is Graph's first 255 characters, and mail_get_message returns the rest. Page with |
| mail_search_messagesA | Finds messages by text, returning the same compact projection as mail_list_messages, 10 per call by default (50 max). Two modes, because Graph will not combine them: with no date range it uses $search, a relevance-ranked KQL search over subject, body and participants (results are NOT in date order, and $search supports no date syntax). Passing |
| mail_get_messageA | Returns one message with its body plus sender, recipients, timestamps, importance, conversationId and webLink. The body defaults to plain text and is capped at 8000 characters; raise maxBodyChars for a long thread, or pass format:"preview" to skip the body when you only need to identify the message. Attachment contents are never included — use mail_list_attachments. Reading a message here does not mark it read; use mail_mark_read for that. |
| mail_list_foldersA | Lists the top-level Outlook mail folders with their ids, unread counts and total counts, 50 per call by default. Pass includeChildren to also get one level of subfolders. Only top-level folders are returned otherwise, so a nested folder needs a second call. Use an id from here as folderId in mail_list_messages, though the well-known names (inbox, archive, sentitems) work there without looking anything up. |
| mail_list_attachmentsA | Lists attachment metadata for one message — id, name, contentType, size in bytes, whether it is inline, and its kind (file, item, or reference) — 20 per call by default. File contents are deliberately never returned: a single attachment would exceed the output budget many times over. Check hasAttachments on the message first; inline images count as attachments, so a message with no visible attachment can still list several. |
| mail_sendA | Sends a message immediately from the signed-in mailbox — there is no undo and no confirmation step, so confirm the recipients and text with the user first. Graph returns no message id for a send: if you need one, use mail_create_draft instead. A copy lands in Sent Items unless saveToSentItems is false. Sending needs the Mail.Send permission, which is separate from read/write access. |
| mail_create_draftA | Creates an unsent draft in the Drafts folder and returns its id and webLink. Nothing is transmitted — this tool cannot send, and there is no companion tool that sends an existing draft, so the user must send it from Outlook (or you can use mail_send instead). Recipients are optional on a draft. |
| mail_replyA | Sends a reply to an existing message immediately — it does not create a draft, and there is no undo, so confirm the text with the user first. Your comment is placed above the quoted original as plain text; Graph builds the subject and recipients itself. replyAll includes every original recipient. Sending needs the Mail.Send permission, which is separate from read/write access. |
| mail_forwardA | Forwards an existing message immediately, attachments included — it does not create a draft and there is no undo, so confirm the recipients with the user first. Your comment, if any, is placed above the forwarded content. Sending needs the Mail.Send permission, which is separate from read/write access. |
| mail_move_messageA | Moves a message to another mail folder. The move assigns the message a NEW id — the old one stops resolving, so use the id returned here for any follow-up call. destinationId accepts a folder id from mail_list_folders or a well-known name such as archive or deleteditems; moving to deleteditems is how you soft-delete without mail_delete_message. |
| mail_mark_readA | Sets the read flag on one message. Defaults to marking it read; pass isRead:false to mark it unread again. Reading a message with mail_get_message does not change this flag, so unread counts stay accurate until you call this. |
| mail_delete_messageA | Deletes a message. This is a soft delete: the message moves to Deleted Items and the user can restore it from Outlook, but this server has no tool to undo it, so confirm with the user first. Deleting a message already in Deleted Items removes it permanently. |
| calendar_list_eventsA | Lists events with subject, start, end, location, organizer and attendee count, plus a nextLink when more pages exist. Returns 25 events by default. Passing both start and end switches to calendarView, which expands recurring meetings into their individual occurrences; without them the raw event list is returned, where a recurring series appears once as its series master. Times without an explicit offset in start/end are read as UTC — pass a timeZone to control how returned times are rendered. |
| calendar_get_eventA | Returns one event in full: subject, start, end, location, organizer, the attendee list with each response, the description body (HTML converted to text and capped), recurrence summary, and the Outlook web link. Use calendar_list_events first to find the id. |
| calendar_list_calendarsA | Lists the signed-in user's calendars with id, name, colour, owner and whether they can be edited or shared. Returns 50 by default. Use the returned id as calendarId in calendar_list_events. |
| calendar_get_scheduleA | Returns free/busy availability for up to 20 people or rooms over a time window, as an availabilityView string where each character covers one interval (0 free, 1 tentative, 2 busy, 3 out of office, 4 working elsewhere), plus working hours and any visible busy blocks. Read-only despite being an HTTP POST. Subject and location are only returned for people who share those details with you; everything else comes back as a bare busy block. |
| calendar_find_meeting_timesA | Suggests meeting slots that work for the signed-in user and the given attendees, ranked by confidence, with the attendees who are unavailable in each slot. Returns 10 suggestions by default. Read-only despite being an HTTP POST. All attendees are treated as required, and an empty result comes back with emptySuggestionsReason explaining why (commonly "AttendeesUnavailable" or a window that is too narrow). |
| calendar_create_eventA | Creates an event on the primary calendar and returns the created event. Listing attendees sends them a meeting invitation immediately, so confirm the details with the user first. A start or end without an explicit UTC offset is treated as local time in |
| calendar_update_eventA | Patches the given fields on an event and returns the updated event; omitted fields are left alone. Two traps: sending |
| calendar_delete_eventA | Deletes an event, moving it to Deleted Items. If the signed-in user organized a meeting, every attendee is sent a cancellation; if they were only invited, this removes it from their calendar without telling the organizer — use calendar_respond_event with decline for that. Deleting a series master deletes every occurrence. |
| calendar_respond_eventA | Accepts, declines, or tentatively accepts a meeting invitation, optionally with a comment to the organizer. Graph returns no content on success. Only works on events where the signed-in user is an attendee — responding to an event they organized fails. Proposing a new time is not supported. |
| files_list_childrenA | Lists the direct children of a folder in the signed-in user's OneDrive, returning id, name, kind (file or folder), size, mime type, child count, last-modified time and webUrl per entry, plus count and nextLink when more pages exist. Address the folder by itemId or by path; omit both for the drive root. Page size defaults to 50. This is not recursive: use files_search to look through the whole drive. |
| files_get_itemA | Reads the metadata of one OneDrive file or folder: name, kind, size, mime type, created and last-modified times and authors, parent folder path and ids, and webUrl. Address it by itemId or by path, not both. The pre-authenticated download URL is deliberately not returned; use files_read_text for text contents or files_create_link to share the item. |
| files_searchA | Searches the whole of the signed-in user's OneDrive for free text, matching file names and indexed file contents, and returns the same compact fields as files_list_children plus count and nextLink. Page size defaults to 25. This endpoint accepts only a search term: it supports no date range, no file-type filter and no sort order, so narrow the results yourself or list a folder with files_list_children instead. Recently uploaded files are missing until the service has indexed them. |
| files_list_recentA | Lists files the signed-in user recently opened or edited, most recent first, with count and nextLink. Defaults to 25 items. Entries can come from other people's drives or from SharePoint; those carry remoteDriveId and remoteItemId, and their plain id will not resolve against your own drive. |
| files_list_sharedA | Lists files and folders other people have shared with the signed-in user, with count and nextLink. Defaults to 25 items. These entries are stubs pointing into the owner's drive: use remoteDriveId together with remoteItemId to identify one, or open its webUrl. The other files_* tools address only your own OneDrive, so they cannot read these items by id. Needs the Files.Read.All scope, which a user can consent to without an administrator. |
| files_read_textA | Returns the contents of a text-like OneDrive file (plain text, Markdown, CSV, JSON, XML, source code, config) as a string, truncated to maxChars, which defaults to 20000. Reads the file metadata first and refuses binary formats — PDFs, images, Office documents, archives, media — with an explanation, because their bytes are not readable as text. Word, Excel and PowerPoint files are zip containers and cannot be read here. |
| files_create_folderA | Creates a folder in the signed-in user's OneDrive and returns the created item. Give the parent as parentItemId or parentPath, or omit both for the drive root. A name collision does not fail: Graph renames the new folder with a numeric suffix, so read the returned name rather than assuming it. |
| files_upload_textA | Writes a text file to the given path in the signed-in user's OneDrive and returns the stored item. Missing parent folders are created automatically. An existing file at that path is REPLACED, not merged or appended, so read it with files_read_text first if you mean to edit it. Text only, up to 4 MB; larger or binary uploads need a resumable upload session, which this server does not expose. |
| files_deleteA | Deletes a file or folder from the signed-in user's OneDrive. Deleting a folder deletes everything inside it. The item goes to the OneDrive recycle bin rather than being destroyed, but this server has no tool to restore it, so confirm the id with files_get_item first. |
| files_create_linkA | Creates a sharing link for a OneDrive file or folder and returns its URL, permission type and scope. Defaults to a view link scoped to the organization. Anonymous links are blocked by policy in many tenants, which surfaces as a 403: retry with scope organization. Calling this twice with the same type and scope returns the existing link rather than creating a second one. |
| todo_list_listsA | Lists the signed-in user's Microsoft To Do lists with their id, display name and well-known name (for example defaultList for the built-in Tasks list). Follows up to three pages, which covers any realistic number of lists. Use the returned id as listId for every other todo tool; To Do is delegated-only, so these are always the caller's own lists. |
| todo_list_tasksA | Lists tasks in one To Do list, returning id, title, status, importance, due and reminder times and a short body preview per task, plus count and nextLink when more pages exist. Page size defaults to 50. Completed tasks are excluded unless includeCompleted is true. To Do tasks do not support $search: narrow with filter instead, and note that dueDateTime is a complex type, so a date filter reads dueDateTime/dateTime ge '2026-01-01T00:00:00'. |
| todo_get_taskA | Reads one To Do task in full: title, status, importance, reminder state, start/due/completed times, categories and the notes body (truncated). Needs both the list id and the task id, which come from todo_list_lists and todo_list_tasks. |
| todo_create_taskA | Creates a task in a To Do list and returns the created task. Only title is required. Due and reminder values are sent as Graph dateTimeTimeZone objects using the timeZone argument (default UTC), and a date-only dueDateTime becomes midnight, matching how the To Do apps store all-day due dates. Supplying reminderDateTime also switches the reminder on, since Graph leaves isReminderOn false otherwise. |
| todo_update_taskA | Patches an existing To Do task and returns the updated task. Only the supplied fields change; omitting dueDateTime or reminderDateTime leaves the existing value alone, so use clearDueDateTime or clearReminderDateTime to remove one. Due and reminder values are sent as Graph dateTimeTimeZone objects using the timeZone argument (default UTC). |
| todo_complete_taskA | Marks a To Do task completed by patching its status to 'completed', and returns the updated task including the completedDateTime Graph stamps on it. Recurring tasks are rolled forward by the service rather than closed outright. |
| todo_delete_taskA | Deletes a To Do task permanently and returns a confirmation. There is no recycle bin for To Do tasks, so prefer todo_complete_task when the user only wants it out of the way. |
| todo_create_listA | Creates a new To Do list and returns its id and display name. Display names are not required to be unique, so check todo_list_lists first if the user expects one list per name. |
| contacts_listA | Lists personal contacts from the signed-in user's default Outlook Contacts folder, 25 per page by default (max 100). Each row carries id, displayName, given/surname, company, job title, email addresses and phone numbers; pass |
| contacts_getA | Returns one personal contact by id, with names, company, job title, department, every email address, phone numbers, postal addresses, birthday, categories and timestamps. Personal notes are truncated to 1000 characters. Properties Graph reports as empty are omitted, so a missing key means the field is not set. An id from a different mailbox or a deleted contact fails with 404 ErrorItemNotFound. |
| contacts_searchA | Full-text search over the default Contacts folder using Outlook |
| contacts_createA | Creates a personal contact in the signed-in user's default Contacts folder and returns the stored contact, including the new id. Outlook builds displayName from givenName and surname. Outlook holds at most 3 email addresses per contact. Graph does not de-duplicate: calling this twice creates two contacts, so search first when the contact may already exist. |
| contacts_updateA | Updates the given fields of one personal contact and returns the stored result. Omitted fields are left alone, but |
| contacts_deleteA | Deletes one personal contact. The contact moves to the Deleted Items folder, so it is recoverable from Outlook but not through these tools, and Graph returns no body — only a confirmation of the id. Deleting an id that is already gone fails with 404 ErrorItemNotFound. |
| search_queryA | Runs a relevance-ranked Microsoft Search query across Microsoft 365 and returns a flattened list of hits, each with its rank, a text summary and the resource's id, name or subject, web URL and last-modified time. Defaults to 10 hits per entity-type group over ['message','driveItem']; page with |
| graph_requestA | Sends an arbitrary request to Microsoft Graph and returns the raw JSON response. Use this only when no purpose-built tool covers the endpoint: the dedicated tools project and trim their results, while this one returns everything Graph sends, which is often far more text. The host is fixed to this tenant's Graph endpoint and |
| graph_schemaA | Fetches one item from a Graph path ($top=1) and reports the property names it carries with their JSON types, plus the @odata.context that names the resource type. Use it before graph_request to learn what $select and $filter can reference. It reports the shape of one real item, so properties that happen to be null on that item are absent from the list, and an empty collection yields no properties at all. Read-only. |
| graph_list_permissionsA | Reports how this server is configured: which tool groups are enabled, the delegated Microsoft Graph scopes each one uses, which of them need a tenant administrator to consent, whether write tools are suppressed, and the signed-in account. Call it when a request fails with 403 or "insufficient privileges" to see whether the needed area is switched on at all. Reads only the signed-in account from Graph. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 51 tools
The 51 tools are organized into clear domains (todo, mail, files, calendar, contacts, me, graph) with each tool addressing a distinct resource-action pair. Even within rich domains like mail, tools like mail_list_messages, mail_search_messages, and mail_get_message have clearly separated purposes (listing, searching, and fetching full content). The only generic tool, graph_request, is explicitly positioned as a fallback for uncovered endpoints, and its description clarifies its distinct role.
Every tool follows a strict domain_verb_noun (or domain_noun_verb) snake_case pattern, consistently using the domain prefix (todo_, mail_, files_, calendar_, contacts_, me_, graph_, search_). Verbs are uniform across similar operations (list_, get_, create_, update_, delete_, send_, etc.). This creates a highly predictable naming convention that lets an agent infer tool purposes without reading descriptions.
51 tools is a large surface, but the scope is a broad Microsoft Graph integration covering mail, calendar, files, contacts, To Do, user profile, and search. Each domain has a focused, manageable set (3–10 tools per area) that justifies the total count. It is slightly on the heavy side, but the breadth of the domain makes it reasonable rather than excessive.
The tool surface provides full CRUD coverage for contacts, To Do tasks, calendar events, and basic file operations, plus send/reply/forward/move for mail. Notable gaps exist: no way to send an existing draft, no file rename/move/copy, no todo list deletion or update, and no binary file download. These are acknowledged in descriptions as deliberate limitations, so agents can work around them, but they prevent a perfect score.