
MCP Microsoft Office
One MCP server. Multiple users. Real Microsoft 365 traffic on your test tenant.
The Problem
Test tenants sit empty. Static test data does not exercise real workflows. When you need agents that send real emails, schedule real meetings, and collaborate in real Teams channels, mocks and stubs fall short.
What This Solves
This project connects any MCP-compatible AI client to Microsoft 365 through the Graph API. Each agent authenticates as a distinct tenant user and performs real operations against real data.
- 117 tools across 12 modules: Mail, Calendar, Files, Excel, Word, PowerPoint, Teams, Contacts, To-Do, Groups, People, Search
- Multi-user: one server supports your entire team, each with isolated data
- Real Graph API calls: every operation hits the actual tenant, not a mock
- Secure: tokens encrypted at rest, no credentials stored on third-party servers
Architecture
┌──────────────────┐
│ MCP Client │
│ (Claude, etc.) │
└────────┬─────────┘
│ JSON-RPC (stdin/stdout)
┌────────▼─────────┐
│ MCP Adapter │
│ (runs locally) │
└────────┬─────────┘
│ HTTP + Bearer Token
┌────────▼─────────┐
│ MCP Server │
│ (local or │
│ remote) │
└────────┬─────────┘
│ Microsoft Graph API
┌────────▼─────────┐
│ Microsoft 365 │
│ (your tenant) │
└──────────────────┘
Three parts:
- MCP Client -- the AI you interact with
- MCP Adapter -- a Node.js process that translates MCP protocol to HTTP requests (runs on the same machine as the client)
- MCP Server -- handles authentication and calls the Microsoft Graph API (runs locally or on a remote server)
Permissions
The server requires 18 Microsoft Graph delegated permissions. Twelve work without admin consent. Six require a tenant administrator to grant consent.
No Admin Consent Required
Requires Admin Consent
Without admin consent, you get Mail, Calendar, Files, Excel workbooks, Word documents, PowerPoint presentations, Contacts, To-Do, Chat, and basic Teams channel operations. With admin consent, you add People directory search, Groups, channel member management, and meeting transcripts.
Quick Start
Prerequisites
- Node.js 18+ (download)
- Claude Desktop (download) or another MCP client
- Microsoft 365 account (work, school, or personal)
Step 1: Azure App Registration
- Go to Azure Portal > Microsoft Entra ID > App registrations > New registration
- Name it
MCP-Microsoft-Office, register with your preferred account type
- Copy the Application (client) ID and Directory (tenant) ID
- Go to API permissions > Add a permission > Microsoft Graph > Delegated permissions
- Add the 18 permissions listed above
- If you are a tenant admin, click Grant admin consent
- Go to Authentication > Add a platform > Web
- Redirect URI:
http://localhost:3000/api/auth/callback
- Enable Allow public client flows
git clone https://github.com/Aanerud/MCP-Microsoft-Office.git
cd MCP-Microsoft-Office
npm install
Copy .env.example to .env and fill in your Azure app details:
MICROSOFT_CLIENT_ID=your-client-id
MICROSOFT_TENANT_ID=your-tenant-id
Step 3: Start the Server and Authenticate
npm run dev:web
Open http://localhost:3000 in your browser. Click Login with Microsoft, sign in, and grant permissions. Then click Generate MCP Token and copy the token.
Edit your Claude Desktop config:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
Claude Desktop has a practical limit of ~55 tools per MCP server. This project exposes 117 tools, so we split them across three servers that share the same adapter and backend:
{
"mcpServers": {
"microsoft-365": {
"command": "node",
"args": ["/path/to/MCP-Microsoft-Office/mcp-adapter.cjs"],
"env": {
"MCP_SERVER_URL": "http://localhost:3000",
"MCP_BEARER_TOKEN": "paste-your-token-here",
"MCP_MODULES": "search,mail,calendar,files,people,contacts,groups,query"
}
},
"microsoft-365-teams": {
"command": "node",
"args": ["/path/to/MCP-Microsoft-Office/mcp-adapter.cjs"],
"env": {
"MCP_SERVER_URL": "http://localhost:3000",
"MCP_BEARER_TOKEN": "paste-your-token-here",
"MCP_MODULES": "teams,todo"
}
},
"microsoft-365-office": {
"command": "node",
"args": ["/path/to/MCP-Microsoft-Office/mcp-adapter.cjs"],
"env": {
"MCP_SERVER_URL": "http://localhost:3000",
"MCP_BEARER_TOKEN": "paste-your-token-here",
"MCP_MODULES": "excel,word,powerpoint,files"
}
}
}
}
MCP_MODULES filters which modules the adapter exposes. Omit it to expose all 117 tools (works with clients that have no tool cap).
Set MCP_DEBUG=1 in the env block to enable diagnostic logging to stderr — useful for troubleshooting tool dispatch issues.
Restart Claude Desktop. Ask: "What's on my calendar today?" or "Create an Excel workbook with a budget table."
Mail (9)
Calendar (13)
Files (10)
Excel (30)
Work directly with Excel workbooks stored in OneDrive or SharePoint — no file download needed. All operations go through Microsoft Graph's workbook API with transparent session management.
Word (5)
Create, read, and convert Word documents. Documents are created from structured JSON and stored in OneDrive. Reading uses a multi-library fallback chain: mammoth (best HTML for .docx) → word-extractor (handles both .doc and .docx) → webUrl fallback. Binary downloads use the Graph beta /contentStream endpoint for reliable binary transfer.
Note: Some SharePoint tenants convert uploaded .docx files to OLE2 binary format within seconds of upload. When this happens, client-side parsing libraries cannot read the file. The server gracefully falls back to returning the webUrl so the user can open the document in the browser.
PowerPoint (4)
Create, read, and convert PowerPoint presentations. Presentations are built from structured slide data and stored in OneDrive. Reading uses Graph HTML conversion with jszip fallback for slide-level text extraction.
Teams (21)
(Note: addChannelMember applies to private channels only. Standard channels auto-include all team members.)
To-Do (11)
Groups (4)
People (3)
Search (1)
Multi-User
Each user authenticates independently. The server isolates all data by user identity.
Alice ([email protected]) Bob ([email protected])
├─ Her own Microsoft tokens ├─ His own Microsoft tokens
├─ Her own session ├─ His own session
└─ Claude Desktop (her laptop) └─ Claude Desktop (his PC)
Complete data isolation.
Alice never sees Bob's data.
For automated testing with multiple agents, use the ROPC (Resource Owner Password Credentials) flow to authenticate programmatically:
# Start the server
npm run dev:web
# Run the E2E test suite (authenticates 3 users via ROPC)
node tests/run-all.cjs
The test suite authenticates multiple users, then exercises all 117 tools across 12 modules plus 5 cross-module workflows. See tests/ for the full implementation.
E2E Test Suite
The project includes a comprehensive test suite covering all 117 tools.
# Run all tests (requires server running)
node tests/run-all.cjs
# Run a single module
node tests/run-all.cjs --bucket mail --buckets-only
# Run only workflows
node tests/run-all.cjs --workflows-only
Test structure:
tests/
lib/ Shared auth, HTTP client, reporter
buckets/ One file per module (12 files, 117 tools)
workflows/ Cross-module tests (5 files)
run-all.cjs Master runner
Tests authenticate via ROPC (no manual token management) and run in ~100 seconds.
Environment Variables
Copy .env.example to .env and configure:
Deployment
Local (Recommended for Getting Started)
npm install
npm run dev:web
Azure App Service
See docs/azure-deployment.md for CI/CD deployment with GitHub Actions.
Security
- Encrypted storage: all Microsoft tokens encrypted at rest with AES-256
- No client secrets: uses public client flow (PKCE) for desktop authentication
- Token isolation: each user's tokens stored separately with different encryption keys
- Rate limiting: built-in rate limiting protects against abuse
- CORS protection: origin allowlist in production
- Session expiry: sessions expire after 24 hours
Production Checklist
- Set
NODE_ENV=production
- Set
DEVICE_REGISTRY_ENCRYPTION_KEY (32 bytes)
- Set
JWT_SECRET (strong random string)
- Set
CORS_ALLOWED_ORIGINS
- Use HTTPS with a valid certificate
Project Structure
MCP-Microsoft-Office/
├── mcp-adapter.cjs MCP protocol adapter (runs locally with Claude Desktop)
├── src/
│ ├── api/ Express routes and controllers
│ ├── auth/ MSAL authentication (OAuth2, ROPC, token exchange)
│ ├── core/ Services (cache, storage, tools, error handling)
│ ├── graph/ Microsoft Graph API services
│ │ ├── graph-client.cjs HTTP client with retry, binary support, sessions
│ │ ├── files-service.cjs OneDrive file operations
│ │ ├── excel-service.cjs Workbook API (sessions, ranges, tables, functions)
│ │ ├── word-service.cjs Word create/read (docx + mammoth + word-extractor)
│ │ └── powerpoint-service.cjs PPT create/read (pptxgenjs + jszip)
│ └── modules/ Feature modules (mail, calendar, excel, word, powerpoint, etc.)
├── public/ Web UI for authentication
└── tests/ E2E test suite (gitignored)
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Submit a pull request
License
MIT License -- see LICENSE file.