m365-mcp-server
m365-mcp-server
A production-ready MCP (Model Context Protocol) server for Microsoft 365, providing secure access to Email, SharePoint, and OneDrive through Azure AD/Entra ID authentication with OAuth 2.1 + PKCE.
Features
Email Access: List folders, search messages, read email content (including shared mailboxes)
Calendar Access: List calendars, browse events, expand recurring events with date ranges
SharePoint/OneDrive: Browse sites, drives, folders, and read file content
Document Parsing: Extracts readable text from PDF, Word, Excel, PowerPoint, CSV, and HTML files
OAuth 2.1 + PKCE: Secure authentication via Azure AD/Entra ID
Delegated Permissions: Users access only their authorized content
Open WebUI Compatible: Works with native MCP or MCPO proxy
Production Ready: Docker support, security hardening, structured audit logging
Token Revocation: RFC 7009 compliant token revocation endpoint
Quick Start
1. Azure AD Setup
Follow docs/entra-app-registration.md to create an Azure AD app registration with these permissions:
openid,offline_access(OIDC)User.Read,Mail.Read,Mail.Read.Shared,Files.Read,Sites.Read.All,Calendars.Read(Microsoft Graph)
2. Configuration
Create a .env file:
# Azure AD / Entra ID (required)
AZURE_CLIENT_ID=your-client-id
AZURE_CLIENT_SECRET=your-client-secret
AZURE_TENANT_ID=your-tenant-id
# Server
MCP_SERVER_PORT=3000
MCP_SERVER_BASE_URL=http://localhost:3000
SESSION_SECRET=$(openssl rand -hex 32)
# Optional
LOG_LEVEL=info
REDIS_URL=redis://localhost:6379
# OAuth signing keys (required in production)
# OAUTH_SIGNING_KEY_PRIVATE=<base64-encoded PEM>
# OAUTH_SIGNING_KEY_PUBLIC=<base64-encoded PEM>3. Run Locally
# Install dependencies
npm install
# Development mode
npm run dev
# Production build
npm run build
npm start4. Authenticate
Open
http://localhost:3000/auth/loginin a browserSign in with your Microsoft 365 account
Note the session ID returned after login
Docker Deployment
Basic
cd docker
docker-compose up -d m365-mcp-server redisWith Open WebUI
cd docker
docker-compose --profile with-webui up -dWith MCPO Proxy
cd docker
docker-compose --profile with-mcpo up -dOpen WebUI Integration
Option A: Native MCP (Recommended)
In Open WebUI, go to Admin Settings > Tools
Add MCP Server:
{ "url": "http://localhost:3000/mcp", "transport": "streamable-http" }Complete OAuth login when prompted
Option B: Via MCPO Proxy
Start MCPO with the provided config:
mcpo --config docker/mcpo-config.json --port 8000In Open WebUI, add as OpenAPI Tool:
http://localhost:8000/openapi.json
MCP Tools
Email Tools
Tool | Description |
| List messages with optional filters (supports shared mailboxes) |
| Get full message details with body (HTML→text), CC/BCC, and attachment metadata |
| List mail folders or subfolders (supports shared mailboxes) |
| Read and parse email attachments (PDF, Word, Excel, PowerPoint, CSV, HTML→text). Max 20MB |
All email tools accept an optional mailbox parameter (email address or user ID) to access shared mailboxes. Omit to use your personal mailbox. Requires Mail.Read.Shared permission with admin consent.
mail_list_messages, mail_get_message, and mail_get_attachment return a short reference id (e.g. m_a1b2c3d4e5f6) instead of the raw Graph id. Pass this id back verbatim when calling subsequent mail tools. A reference id stays resolvable for HANDLE_TTL_SECONDS after it is issued (default 86400 = 24h).
SharePoint/OneDrive Tools
Tool | Description |
| Search and list SharePoint sites |
| List drives (OneDrive/document libraries) |
| List folder contents |
| Get file content with automatic document parsing (PDF, Word, Excel, PowerPoint → text). Max 20MB |
OneDrive Tools
Tool | Description |
| Get personal OneDrive info including drive ID and storage quota |
| List files and folders in personal OneDrive (root or subfolder) |
| Get file content by item_id with automatic document parsing (PDF, Word, Excel, PowerPoint). Max 20MB |
| Search for files in personal OneDrive only |
| List recently accessed files |
| List files shared with you by others |
Calendar Tools
Tool | Description |
| List all calendars with metadata |
| List events with optional date range (expands recurring events) |
| Get full event details including body/description |
Requires Calendars.Read permission (no admin consent needed). Provide start_date and end_date to expand recurring events into individual occurrences.
API Endpoints
Endpoint | Method | Description |
| GET | Health check |
| GET | Initiate OAuth login |
| GET | OAuth callback |
| GET | Logout and revoke session |
| GET | Check authentication status |
| POST | Token revocation (RFC 7009) |
| POST | MCP JSON-RPC endpoint |
| GET | MCP SSE stream endpoint |
| DELETE | Terminate MCP session |
Security
OAuth 2.1 + PKCE: Required for all authentication flows
Delegated Permissions Only: No app-only access, read-only Graph scopes (
Mail.Read.Sharedrequires admin consent)Token Encryption: AES-256-GCM encryption for session tokens at rest
PII Redaction: Sensitive data (tokens, emails, secrets) filtered from logs
Structured Audit Logging: Security events logged with correlation IDs
Rate Limiting: 100 req/min general, 5/hour for client registration
Security Headers: HSTS, CSP (no unsafe-inline), Permissions-Policy, X-Frame-Options via Helmet
Input Validation: Zod schemas + regex validation for all Graph API resource IDs
DCR Protection: Redirect URI pattern whitelist, rate limiting, audit logging
Production Enforcement: Config validation requires Redis, HTTPS, persistent signing keys
See docs/security/threat-model.md for full security analysis.
Architecture
┌─────────────────────────────────────────────────────────────┐
│ Open WebUI / Client │
└─────────────────────────────┬───────────────────────────────┘
│ MCP Protocol (Streamable HTTP)
▼
┌─────────────────────────────────────────────────────────────┐
│ m365-mcp-server │
│ ┌─────────────┐ ┌─────────────┐ ┌──────────────────────┐ │
│ │ OAuth 2.1 │ │ MCP Handler │ │ Microsoft Graph │ │
│ │ + PKCE │ │ (JSON-RPC) │ │ Client │ │
│ └──────┬──────┘ └─────────────┘ └──────────┬───────────┘ │
└─────────│────────────────────────────────────│──────────────┘
│ │
▼ ▼
┌──────────────────────┐ ┌─────────────────────────┐
│ Azure AD / Entra ID │ │ Microsoft Graph API │
│ (Authorization) │ │ (Data Access) │
└──────────────────────┘ └─────────────────────────┘Environment Variables
Variable | Required | Default | Description |
| Yes | - | Azure AD app client ID |
| Yes | - | Azure AD app client secret |
| Yes | - | Azure AD tenant ID |
| Yes | - | Session encryption key (32+ chars) |
| No | 3000 | Server port |
| No | Public URL (HTTPS required in production) | |
| Prod | - | Redis URL (required in production) |
| Prod | - | RSA private key PEM (required in production) |
| Prod | - | RSA public key PEM (required in production) |
| No | - | Comma-separated URI patterns for DCR |
| No | info | Log level (trace/debug/info/warn/error) |
| No | development | Environment mode |
| No | 30000 | Document parsing timeout |
| No | 500 | Max parsed text output size |
| No | 86400 | How long a mail reference id stays resolvable |
Development
# Install dependencies
npm install
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Lint
npm run lint
# Type check
npm run typecheck
# Build
npm run buildMCP Registry
This server is published to the MCP Registry. Add to your MCP client:
{
"mcpServers": {
"m365": {
"command": "npx",
"args": ["-y", "@anthropic/m365-mcp-server"],
"env": {
"AZURE_CLIENT_ID": "your-client-id",
"AZURE_CLIENT_SECRET": "your-client-secret",
"AZURE_TENANT_ID": "your-tenant-id",
"SESSION_SECRET": "your-session-secret"
}
}
}
}Documentation
Supported Document Formats
sp_get_file automatically extracts readable text from these formats:
Format | Extensions | Library |
| pdf-parse | |
Word |
| mammoth |
Excel |
| exceljs |
PowerPoint |
| Built-in ZIP/XML |
CSV |
| Built-in |
HTML |
| Built-in |
Other binary formats are returned as base64. Parsed text output is limited to 500KB by default.
Known Limitations
Maximum file download size: 20MB
Parsed text output capped at 500KB (configurable via
FILE_PARSE_MAX_OUTPUT_KB)SharePoint site listing requires search query (Graph API limitation)
Refresh tokens limited to 24 hours for SPA scenarios
No write operations (read-only by design)
Access tokens (JWTs) are stateless and cannot be directly revoked (expire naturally)
License
MIT
Contributing
Fork the repository
Create a feature branch
Submit a pull request
Please ensure all tests pass and the code follows the existing style.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/SwamiRama/m365-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server