m365-reporting-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| BASE_URL | Yes | Public base URL of the MCP server, used for OAuth redirect URIs and endpoint configuration. | |
| ADMIN_KEY | Yes | API key for accessing the admin dashboard and protected administrative endpoints. | |
| CLIENT_ID | Yes | Microsoft Entra app registration client ID. | |
| READ_ONLY | No | When set to 'true', disables all write tools. | |
| TENANT_ID | Yes | Microsoft Entra tenant ID used for OAuth and Graph OBO. | |
| CLIENT_SECRET | Yes | Client secret for the Entra app registration. | |
| ENABLED_TOOLSETS | No | Comma-separated list of toolset profles to enable (e.g. 'mail, calendar, meetings'). | |
| MAX_DOWNLOad_BYTES | No | Maximum download size in bytes for file attachments and content. |
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 |
|---|---|
| list-mail-messagesA | List/search messages in the signed-in user's mailbox. Supports full-text KQL search (sender, recipient, cc, subject, keyword, attachment, read/unread, importance) and time ranges. |
| get-mail-messageB | Get a single message including its full body. |
| list-mail-foldersA | List top-level mail folders of the signed-in user's mailbox. |
| list-mail-child-foldersB | List child folders of a mail folder. |
| list-mail-folder-messagesA | List/search messages inside a specific mail folder. |
| list-mail-attachmentsA | List attachments of a message (metadata only: name, contentType, size). |
| get-mail-attachment-contentA | Download an attachment and return its content. DOCX/XLSX/PPTX/PDF/TXT/CSV are converted to text; other binaries (images) come back as base64. |
| list-shared-mailbox-foldersA | List mail folders of a shared mailbox the user has access to. |
| list-shared-mailbox-messagesA | List/search messages of a shared mailbox the signed-in user has access to. |
| list-shared-mailbox-folder-messagesB | List/search messages inside a folder of a shared mailbox. |
| get-shared-mailbox-messageA | Get a single shared-mailbox message including its full body. |
| get-shared-mailbox-attachment-contentA | Download an attachment from a shared-mailbox message (text extraction like get-mail-attachment-content). |
| create-draft-emailA | Create a DRAFT email in the signed-in user's Drafts folder. Does NOT send anything - use send-draft-email (with explicit user approval) to send it. |
| send-draft-emailA | SEND a previously created draft. WRITE operation - requires confirm=true and explicit user approval. |
| send-mailA | Compose and SEND an email in one step as the signed-in user. WRITE operation - requires confirm=true and explicit user approval. Prefer create-draft-email + user review for report emails. |
| reply-mailA | Reply to a message as the signed-in user. Requires confirm=true. |
| reply-all-mailA | Reply-all to a message as the signed-in user. Requires confirm=true. |
| forward-mailA | Forward a message as the signed-in user. Requires confirm=true. |
| create-shared-mailbox-draftA | Create a DRAFT in a shared mailbox. Does NOT send. |
| send-shared-mailbox-mailB | Compose and SEND an email from a shared mailbox. Requires confirm=true and explicit user approval. |
| reply-shared-mailbox-mailB | Reply to a shared-mailbox message. Requires confirm=true. |
| reply-all-shared-mailbox-mailB | Reply-all to a shared-mailbox message. Requires confirm=true. |
| forward-shared-mailbox-mailA | Forward a shared-mailbox message. Requires confirm=true. |
| list-calendarsB | List the signed-in user's calendars. |
| get-calendarA | Get a single calendar by id. |
| get-calendar-viewA | PRIMARY meeting-lookup tool: list all calendar events (including recurring occurrences) within a time range. Requires timeRange or from/to. Returns organizer, participants, start/end, location, onlineMeeting join URL, recurrence. |
| list-calendar-eventsA | List events of the default calendar (series masters + single events). For time-ranged queries prefer get-calendar-view which expands recurrences. |
| get-calendar-eventA | Get a single event with full body/description, attendees, online meeting info and recurrence. |
| list-event-attachmentsA | List attachments of a calendar event (metadata). |
| get-people-availabilityA | Free/busy availability (getSchedule) of one or more colleagues' calendars for a time window. Returns availabilityView (0=free, 1=tentative, 2=busy, 3=out of office) and busy time slots - event details stay hidden unless their calendar is shared with the user. |
| find-meeting-timesA | Suggest meeting time slots that work for the signed-in user and the given attendees (findMeetingTimes), based on free/busy data and working hours. |
| create-calendar-eventA | CREATE a calendar event in the signed-in user's default calendar (optionally as a Teams online meeting; attendees get invitations). WRITE operation - requires confirm=true after explicit user approval. |
| update-calendar-eventA | UPDATE an existing calendar event (only the provided fields change; attendees are notified of changes). WRITE operation - requires confirm=true. |
| respond-to-calendar-eventA | Respond to a meeting invitation (accept / decline / tentativelyAccept); the organizer is notified. WRITE operation - requires confirm=true. |
| list-chatsA | List the signed-in user's Teams chats (1:1, group, meeting chats). |
| get-chatA | Get a single chat including its members. |
| list-chat-messagesA | List messages of a chat, newest first. Supports a time range (lastModifiedDateTime filter). Keyword filtering must be done client-side or via search-m365 with entityTypes=["chatMessage"]. |
| get-chat-messageB | Get a single chat message. |
| list-joined-teamsA | List the Microsoft Teams teams the signed-in user is a member of. |
| get-teamB | Get a team's properties. |
| list-team-channelsC | List channels of a team. |
| get-team-channelB | Get a single channel of a team. |
| list-channel-messagesA | List messages of a team channel, newest first (Graph does not support server-side filtering here; use search-m365 for keyword search). |
| get-channel-messageB | Get a single channel message. |
| list-channel-message-repliesA | List replies (thread) of a channel message. |
| list-team-membersA | List members of a team (name, email, roles). |
| send-chat-messageA | SEND a message to a Teams chat (1:1 or group) as the signed-in user. WRITE operation - requires confirm=true after explicit user approval. |
| send-channel-messageA | POST a new message to a team channel as the signed-in user. WRITE operation - requires confirm=true after explicit user approval. |
| reply-to-channel-messageA | REPLY to an existing channel message (thread) as the signed-in user. WRITE operation - requires confirm=true. |
| find-online-meeting-by-join-urlA | Resolve an onlineMeeting from a Teams join URL (calendar event -> onlineMeeting.joinUrl -> this tool). This is how a calendar event is connected to its transcripts/recordings/attendance. |
| get-online-meetingA | Get an online meeting by its onlineMeeting id (subject, organizer, participants, join URL, start/end). |
| list-meeting-transcriptsB | List transcripts available for an online meeting (metadata: id, created date). |
| get-meeting-transcript-contentA | Get the FULL TEXT of a meeting transcript in WebVTT format (speaker, timestamp, text preserved). Use for meeting summaries, decisions and commitments extraction. |
| list-meeting-recordingsA | List recordings of an online meeting (metadata + content URL; the recording itself stays in OneDrive/SharePoint). |
| list-meeting-attendance-reportsC | List attendance reports of an online meeting. |
| list-meeting-attendance-recordsA | List attendance records (who joined, when, for how long) of an attendance report. |
| list-onenote-notebooksA | List the signed-in user's OneNote notebooks. |
| get-onenote-notebookA | Get a single OneNote notebook. |
| list-onenote-notebook-sectionsA | List sections of a OneNote notebook (newest-modified first; paginates past 100 sections automatically). |
| list-onenote-sectionsA | List all OneNote sections across the user's notebooks (newest-modified first; paginates past 100 automatically). |
| list-onenote-notebook-section-groupsA | List section groups of a OneNote notebook (sections nested in groups are NOT returned by list-onenote-notebook-sections). |
| list-onenote-section-group-sectionsA | List sections inside a OneNote section group (newest-modified first; paginates past 100 automatically). |
| list-onenote-section-pagesC | List pages of a OneNote section. |
| search-onenote-pagesA | List OneNote pages across all personal notebooks, newest first (time filter on lastModifiedDateTime; filter e.g. "contains(title,'x')"). Full-text |
| get-onenote-pageA | Get metadata of a OneNote page. Use get-onenote-page-content for the actual body. |
| get-onenote-page-contentA | Get the FULL HTML content of a OneNote page (the actual note body, not just metadata). |
| list-site-onenote-notebooksA | List OneNote notebooks hosted on a SharePoint site. |
| list-site-onenote-notebook-sectionsA | List sections of a SharePoint-hosted OneNote notebook (newest-modified first; paginates past 100 sections automatically). |
| list-site-onenote-sectionsA | List ALL sections of a SharePoint site's OneNote notebooks regardless of section-group nesting (newest-modified first; paginates past 100 automatically). Each item carries parentNotebook and parentSectionGroup. Best entry point for large notebooks. |
| list-site-onenote-notebook-section-groupsA | List section groups of a SharePoint-hosted OneNote notebook. |
| list-site-onenote-section-group-sectionsA | List sections inside a section group of a SharePoint-hosted OneNote notebook (newest-modified first). |
| list-site-onenote-section-pagesA | List pages of a section in a SharePoint-hosted OneNote notebook. |
| list-site-onenote-pagesB | List/search OneNote pages of a SharePoint site's notebooks. |
| get-site-onenote-page-contentA | Get the FULL HTML content of a SharePoint-hosted OneNote page. |
| search-sitesA | Search SharePoint sites the signed-in user can access, by keyword. |
| get-siteA | Get a SharePoint site by id (or 'hostname:/sites/path' form). |
| list-site-drivesA | List document libraries (drives) of a SharePoint site. |
| get-driveA | Get a drive (document library) by id. |
| list-drive-root-itemsB | List files/folders in the root of a drive (document library). |
| list-drive-folder-itemsB | List files/folders inside a folder of a drive. |
| get-drive-itemA | Get file/folder metadata (includes @microsoft.graph.downloadUrl for files). |
| search-drive-itemsA | Search files by keyword within one drive (document library). |
| download-drive-itemA | Download a file's content from SharePoint. DOCX/XLSX/PPTX/PDF/TXT/CSV are converted to text; other binaries come back as base64. Size-limited by MAX_DOWNLOAD_BYTES. |
| list-site-listsB | List SharePoint lists of a site. |
| get-site-listA | Get a SharePoint list by id. |
| list-site-list-itemsB | List items of a SharePoint list including their field values. |
| get-site-list-itemA | Get a single SharePoint list item including field values. |
| get-my-driveA | Get the signed-in user's OneDrive (drive id, quota, owner). |
| list-my-drive-root-itemsA | List files/folders in the root of the user's OneDrive. |
| list-my-drive-folder-itemsB | List files/folders inside a OneDrive folder. |
| get-my-drive-itemB | Get OneDrive file/folder metadata (includes @microsoft.graph.downloadUrl for files). |
| get-my-drive-item-download-urlA | Get a short-lived direct download URL for a OneDrive file without fetching its content. |
| search-my-driveA | Search the user's OneDrive (and items shared with them) by keyword. |
| download-my-drive-itemA | Download a OneDrive file's content. DOCX/XLSX/PPTX/PDF/TXT/CSV are converted to text; other binaries come back as base64. Size-limited by MAX_DOWNLOAD_BYTES. |
| search-loop-componentsA | Search Microsoft Loop components (.loop/.fluid files stored in SharePoint/OneDrive) by keyword. Note: Loop workspaces in SharePoint Embedded containers are not exposed via delegated Graph and may be missing from results. |
| get-loop-component-contentA | Download a Loop component's raw content by driveId + itemId (from search-loop-components hit resource.parentReference). Content is Fluid/JSON-like text. |
| search-m365A | Cross-source Microsoft 365 search (Mail, Calendar, Teams messages, SharePoint, OneDrive). KQL supported. Restriction from Graph: driveItem/drive/site/list/listItem can be combined in one call; message, event and chatMessage must each be searched in a SEPARATE call. Use the returned pointers with dedicated tools to fetch full content. |
| search-peopleA | Search people relevant to the signed-in user (colleagues, frequent contacts). Good first step for fuzzy name resolution. |
| list-usersA | List ALL users of the organization including disabled accounts (accountEnabled=false) and guests. Paged: for directories larger than maxItems follow nextCursor. Supports $filter (e.g. "accountEnabled eq false") and advanced $search. |
| get-userA | Get a user by object id or userPrincipalName (email). |
| get-user-account-status-historyA | When was a user DISABLED (or re-enabled), by whom, with what result? Reads the Entra directory audit log (category UserManagement) for the given user and returns only the events that changed accountEnabled: 'Disable account' / 'Enable account' activities and 'Update user' events whose modifiedProperties contain AccountEnabled (true -> false = disabled). Other user updates are excluded. Newest first. RETENTION: Entra keeps directory audits 30 days (P1/P2; 7 days Free) - if the change is older the result is explicitly 'not available in audit log'; no date is estimated. Read-only; needs delegated AuditLog.Read.All + Directory.Read.All with admin consent and a reader role (Reports Reader / Security Reader / Global Reader). |
| list-directory-auditsA | Entra directory audit log (who changed what, when): user/group/app changes, password resets, role assignments. Time filter on activityDateTime; $filter e.g. "category eq 'UserManagement' and activityDisplayName eq 'Update user'" or "targetResources/any(t:t/id eq '')". Retention: 30 days (P1/P2). Read-only; needs AuditLog.Read.All + Directory.Read.All (admin consent). |
| search-usersA | Resolve a person by (partial) display name or email, e.g. "Móré Attila" -> Entra user with email + id. Use search-people first for fuzzy matches among the user's contacts. |
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 103 tools
The toolset is organized by domain and descriptions are highly detailed, but with 103 tools there are several near-overlapping pairs (list-calendar-events vs get-calendar-view, search-drive-items vs search-my-drive, search-people vs search-users/list-users) that create selection risk. The explicit 'primary' and 'prefer' notes reduce ambiguity somewhat, but the sheer number of similar retrieval variants makes it hard for an agent to always pick the right one.
Tool names consistently use kebab-case verb-noun phrasing, and domain prefixes like mail-, calendar-, team-, onenote-, and site- make the hierarchy fairly predictable. Minor inconsistencies exist such as get-calendar-view vs list-calendar-events, search-drive-items vs search-my-drive, and the long shared-mailbox variants, but there is no chaotic mixing of naming conventions.
103 tools is an extreme count, especially for a server named m365-reporting-mcp, which implies a reporting focus rather than a full Microsoft Graph client surface. This exceeds the '50+ tools' threshold for extreme mismatch, even though each tool maps to a real Graph operation.
The server covers a remarkably broad set of M365 data sources: mail including shared mailboxes, calendar, Teams chats/channels/meetings/transcripts/recordings, OneNote, SharePoint/OneDrive, Loop, people, users, and audit logs. Minor gaps exist, such as no event-attachment content download, no shared-mailbox draft sending, and no direct channel keyword search, but these are documented with workarounds and the core reporting/read workflows are well covered.