Skip to main content
Glama
kharonx
by kharonx

Microsoft 365 Reporting MCP — v1.0

Enterprise MCP server through which ChatGPT, Claude, and other MCP-compatible AI clients get controlled access to Microsoft 365 information sources (Outlook, Calendar, Teams, meeting transcripts, OneNote, SharePoint, OneDrive, Loop, Search, Users).

Principle: read broadly, write narrowly. A broad READ layer within the signed-in user's actual M365 permissions; the only WRITE capability is Outlook email sending (draft / send / reply / forward), and every actual send is gated by a separate confirm=true requirement.

Architecture

ChatGPT / Claude / MCP kliens
        │  MCP over HTTPS (Streamable HTTP) + OAuth bearer token
        ▼
┌──────────────────────────────┐
│  m365-reporting-mcp          │   Tool allowlist (86 tool, 11 WRITE = csak mail)
│  · JWT validálás (Entra)     │   Nincs generikus graph-request / $batch passthrough
│  · On-Behalf-Of tokencsere   │   Audit log (JSONL, tartalom nélkül)
│  · Pagination + 429 retry    │   Forráskövetés (_source blokk minden objektumon)
│  · Admin dashboard (/admin)  │
└──────────────┬───────────────┘
               │  OAuth 2.0 OBO → delegated Graph token
               ▼
    Microsoft Entra ID → Microsoft Graph API (v1.0)

The server never uses app-only permissions: every Graph call runs on behalf of the signed-in user (delegated), so the MCP cannot bypass existing M365 access rules.

Related MCP server: Microsoft Graph MCP Server

Entra ID app registration

  1. Create an App registration (single tenant).

  2. Expose an API: Application ID URI = api://<CLIENT_ID>, scope: access_as_user. Set accessTokenAcceptedVersion to 2 (manifest).

  3. API permissions (Microsoft Graph, Delegated) — the full list is in the docs/tool-matrix.md appendix; in summary:

    • READ: Mail.Read, Mail.Read.Shared, Calendars.Read, Chat.Read, Team.ReadBasic.All, Channel.ReadBasic.All, ChannelMessage.Read.All, TeamMember.Read.All, OnlineMeetings.Read, OnlineMeetingTranscript.Read.All, OnlineMeetingRecording.Read.All, OnlineMeetingArtifact.Read.All, Notes.Read, Notes.Read.All, Sites.Read.All, Files.Read, Files.Read.All, People.Read, User.Read, User.ReadBasic.All, User.Read.All

    • WRITE (mail only): Mail.ReadWrite, Mail.Send, Mail.ReadWrite.Shared, Mail.Send.Shared

    • Admin consent is required for the .All scopes.

  4. For HTTP mode: Certificates & secrets → client secret.

  5. For stdio/dev mode: Authentication → "Allow public client flows" = Yes (device code).

Note to spec point 11: Sites.Selected exists as an application permission; in a delegated (user-context) model, site-level narrowing is provided by the user's own SharePoint permissions — the MCP uses delegated Sites.Read.All, which alone does not give access to a site the user cannot otherwise reach.

Installation and execution

npm install
cp .env.example .env      # töltsd ki: TENANT_ID, CLIENT_ID, CLIENT_SECRET, BASE_URL, ADMIN_KEY
npm run build

# Webapp (remote MCP) mód:
npm run start:http

# Lokális/dev (stdio, device code login):
npm run login             # egyszeri bejelentkezés, token cache-elve
npm start

Endpoints in HTTP mode:

URL

Description

POST /mcp

MCP endpoint (stateless Streamable HTTP), bearer token required

GET /.well-known/oauth-protected-resource

MCP OAuth resource metadata → points to the built-in OAuth proxy

GET /.well-known/oauth-authorization-server

OAuth AS metadata (the proxy)

POST /register, GET /authorize, POST /token, GET /auth/callback

Built-in OAuth proxy in front of Entra ID

GET /admin

Admin dashboard: Settings / Tools / Log (X-Admin-Key)

GET /healthz

Health check

In HTTP mode the server starts even without Entra data: initial configuration can be done on the /admin interface (Tenant ID, Client ID, Client Secret, Base URL, connection test) — the save takes effect immediately, and the settings are stored in data/settings.json and override .env values.

Connecting ChatGPT (and other MCP clients)

The server has a built-in OAuth proxy in front of Entra ID, because the ChatGPT connector expects dynamic client registration per RFC 7591, which Entra does not support. The proxy provides a complete OAuth 2.1 interface (DCR + PKCE) to the client and uses the single registered enterprise app toward Entra; the access token issued to the client is the one Entra itself issues for api://<CLIENT_ID>, so the /mcp validation and the OBO Graph exchange are unchanged — all calls run on behalf of the signed-in user.

Connecting from ChatGPT:

  1. In the Entra app's Authentication section, add as Web redirect URI: https://<BASE_URL>/auth/callback (the exact value is shown on the admin Settings tab).

  2. ChatGPT → Settings → Connectors → join a new Connector, URL: https://<BASE_URL>/mcp.

  3. The login shown is the corporate Entra ID login — the user signs in with their own account and only receives their own M365 permissions.

Claude Desktop / Claude Code: the same URL as remote MCP, or locally in stdio mode (claude large.


Note: The source contains `claude mcp add m365-reporting -- node dist/index.js --stdio`; I must preserve this verbatim.

## Security layer (spec 19-20)

* **No** generic `graph_request(method, url, body)` tool, and **no** `$batch` passthrough — only the 86 allowlisted endpoints are available.
* **No** Calendar/Teams/Files/Sites/OneNote/User/Group write, and no delete anywhere.
* Creating a draft is not sending permission: any send/reply/forward requires `confirm=true`, and the tool description instructs the AI to first ask for explicit user approval.
* With the environment variable `READ_ONLY=true`, all write tools can be disabled; with `ENABLED_TOOLSETS`, the toolset-level profile can be narrowed down (e.g. `mail,calendar,meetings`).

## Audit (spec 21)

Every call is logged in JSONL (`logs/audit-YYYY-MM-DD.jsonl`): `timestamp, user, session, tool, operation (READ, WRITE|, resourceType, graphEndpoint, httpMethod, is, success, durationMs`, and for WRITE `sender, recipients, cc, subject, messageId, result`. **actual content (body, transcript, document, token) is never logged.**

## Fault tolerance (spec 22–23)

* HTTP 429/503/504: automatic retry, honoring `Retry-Afterer` (max. 4 attempts);
* `@odata.nextLink` pagination on all list tools (`max MaxSize` param, marked truncation);
* expired token / permission denied / missing resource: an error message that is user-understandable and actionable;
* file download with size limit (`MAX_MAX_DOWNLOAD_BYTES`), DOCX/XLSX/PPTX/PDF/TXT/CSV → text extraction, other binary → base64.

## Tool matrix (dev appendix)

The complete *MCP tool → Graph endpoint → HTTP method → delegated permission → READ / WRITE → enabled* matrix as a generated document: [docs/tool-matrix.md](docs/tool-matrix.md) (`npm run matrix` updates it from the `src/tools/endpoints/*.ts` definitions).

## Loop-Loop adapter limitations (spec 13)

There is no generally available dedicated Graph Loop workspace API, so the Loop adapter **does not invent fictitious endpoints**: it addresses `.loop`/`.fluid` components via the Search API and SharePoint/OneDrive drives. Loop workspaces stored in SharePoint Embedded storage containers are not necessarily available via delegated Graph — the tool description signals this to the AI, so that the limitation is also pointed out to the user.

## Acceptance test (spec 26)

From a connected client, in natural language: *"Examine my past 30 days' email, calendar, Teams conversations, and meeting transcripts… Make me a summary about project X… Turn it into an email, then after separate approval, send it."* — the expected tool chain is: `get-calendar-view` → `find-online-meeting-by-join-url` → `list-meeting-transcripts` → `get-meeting-transcripts-content` + `list-mail-messages` + `list-chat-messages` + `search-onenote-pages` + `search-m365` → `create-draft-email` → (user approval) → `send-draft-email` tool.
F
license - not found
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • Your memory, everywhere AI goes. Build knowledge once, access it via MCP anywhere.

  • Official Microsoft MCP Server to query Microsoft Entra data using natural language

  • Remote MCP for MCP consent scope receipt, structured receipts, audit logs, and reviewer-ready eviden

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kharonx/mcp_gateway'

If you have feedback or need assistance with the MCP directory API, please join our Discord server