MCP Microsoft Office
Connect Claude (or any AI) to your Microsoft 365 account
Give AI assistants the ability to read your emails, manage your calendar, access your files, send Teams messages, and more - all through a secure, multi-user server that you control.
What Does This Project Do?
This project creates a bridge between AI assistants (like Claude) and Microsoft 365. When you ask Claude "What meetings do I have tomorrow?" or "Send an email to John about the project update" - this system makes it happen.
Key Benefits:
- 71 Tools - Email, Calendar, Files, Teams, Contacts, To-Do, Search, and more
- Multi-User - One server can support your entire team, each with their own data
- Your Control - Run locally on your computer or deploy to your own server
- Secure - All tokens encrypted, no data stored on third-party servers
- Works with Any MCP Client - Claude Desktop, or any other MCP-compatible AI
How It Works (The Simple Version)
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ │ "Send email" │ │ "Here's the │ │
│ Claude Desktop │ ◄────────────────► │ MCP Adapter │ email data" │ MCP Server │
│ (Your AI) │ │ (On Your PC) │ ◄───────────────► │ (Local or │
│ │ │ │ │ Remote) │
└─────────────────┘ └─────────────────┘ └────────┬────────┘
│
│ Talks to
│ Microsoft
▼
┌─────────────────┐
│ Microsoft 365 │
│ (Your Account) │
└─────────────────┘
Three Parts:
- Claude Desktop - The AI you chat with
- MCP Adapter - A small program that runs on your computer (translates what Claude asks into web requests)
- MCP Server - Handles security and talks to Microsoft 365 (can run on your PC or a remote server)
Why This Architecture?
Q: Why not connect Claude directly to Microsoft?
A: The Model Context Protocol (MCP) requires a local adapter to translate between Claude and any service. By separating the adapter from the server, you get:
- Flexibility: Run the server locally for personal use, or deploy it for your whole team
- Security: Your Microsoft credentials never leave your server
- Multi-User: Multiple people can authenticate separately and use the same server
- Any AI Client: The adapter pattern works with any MCP-compatible AI, not just Claude
Quick Start Guide
Prerequisites
Before you begin, you'll need:
- Node.js 18+ - Download here
- Claude Desktop - Download here
- Azure App Registration - Free, instructions below
- Microsoft 365 Account - Work, school, or personal
Step 1: Create Azure App Registration
This tells Microsoft that your server is allowed to access your data.
- Go to Azure Portal
- Navigate to Microsoft Entra ID → App registrations
- Click + New registration
- Fill in:
- Name:
MCP-Microsoft-Office(or whatever you like) - Supported account types: Choose based on your needs
- Redirect URI: Leave blank for now
- Name:
- Click Register
- Copy these values (you'll need them later):
- Application (client) ID
- Directory (tenant) ID
Add API Permissions
- Go to API permissions → + Add a permission
- Select Microsoft Graph → Delegated permissions
- Add these permissions:
| Permission | What It's For |
|---|---|
User.Read | Read your profile |
Mail.ReadWrite | Read and send emails |
Mail.Send | Send emails |
Calendars.ReadWrite | Manage calendar |
Files.ReadWrite | Access OneDrive files |
People.Read | Find contacts |
Tasks.ReadWrite | Manage To-Do lists |
Contacts.ReadWrite | Manage contacts |
Group.Read.All | Read groups |
Chat.ReadWrite | Teams chat access |
ChannelMessage.Send | Send Teams messages |
- If you're an admin, click Grant admin consent
Configure Authentication
- Go to Authentication → + Add a platform
- Select Web
- Add Redirect URI:
- For local:
http://localhost:3000/api/auth/callback - For remote:
https://your-server.example.com/api/auth/callback
- For local:
- Under Advanced settings, set Allow public client flows to Yes
- Click Save
Step 2: Set Up the Server
Option A: Run Locally (Recommended for Getting Started)
# Clone the project
git clone https://github.com/Aanerud/MCP-Microsoft-Office.git
cd MCP-Microsoft-Office
# Install dependencies (this also sets up the database)
npm install
# Edit the .env file with your Azure app details
# Open .env and add:
# MICROSOFT_CLIENT_ID=your-client-id-here
# MICROSOFT_TENANT_ID=your-tenant-id-here
# Start the server
npm run dev:web
Your server is now running at http://localhost:3000
Option B: Use a Remote Server
If someone has deployed an MCP server for your team, you just need:
- The server URL (e.g.,
https://your-server.example.com) - Skip to Step 3
Step 3: Authenticate with Microsoft
- Open your browser and go to your server:
- Local:
http://localhost:3000 - Remote:
https://your-server.example.com
- Local:
- Click Login with Microsoft
- Sign in with your Microsoft account
- Grant the requested permissions
- You'll be redirected back to the server
Step 4: Get Your MCP Token
After logging in:
- Click Generate MCP Token (or find it in the setup section)
- Copy the token - it looks like a long string starting with
eyJ... - Keep this token safe - it's your key to accessing the server
Step 5: Configure Claude Desktop
The adapter runs from the project folder (it needs node_modules for dependencies).
On macOS
Edit: ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"microsoft365": {
"command": "node",
"args": ["/Users/YOUR_USERNAME/MCP-Microsoft-Office/mcp-adapter.cjs"],
"env": {
"MCP_SERVER_URL": "http://localhost:3000",
"MCP_BEARER_TOKEN": "paste-your-token-here"
}
}
}
}
Replace:
YOUR_USERNAMEwith your macOS username (or use full path to where you cloned the project)paste-your-token-herewith the token from Step 4- Change
MCP_SERVER_URLif using a remote server
On Windows
Edit: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"microsoft365": {
"command": "node",
"args": ["C:\\Users\\YOUR_USERNAME\\MCP-Microsoft-Office\\mcp-adapter.cjs"],
"env": {
"MCP_SERVER_URL": "http://localhost:3000",
"MCP_BEARER_TOKEN": "paste-your-token-here"
}
}
}
}
Step 6: Restart Claude Desktop
- Quit Claude Desktop completely
- Start it again
- You should see the Microsoft 365 tools available
Test it: Ask Claude "What emails do I have?" or "What's on my calendar today?"
Understanding the Token System
This project uses two different tokens for security:
┌─────────────────────────────────────────────────────────────────────────────┐
│ TOKEN TYPES │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────┐ ┌─────────────────────────┐ │
│ │ MCP Bearer Token │ │ Microsoft Graph Token │ │
│ │ (You manage this) │ │ (Server manages this) │ │
│ ├─────────────────────────┤ ├─────────────────────────┤ │
│ │ • Lasts 24h to 30 days │ │ • Lasts 1 hour │ │
│ │ • Goes in Claude config │ │ • Auto-refreshed │ │
│ │ • Identifies YOU │ │ • Talks to Microsoft │ │
│ └───────────┬─────────────┘ └───────────┬─────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ Claude ←→ Adapter ←→ Server Server ←→ Microsoft 365 │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
MCP Bearer Token (the one you copied):
- Proves to the server that requests are from you
- You put this in Claude's configuration
- If it expires, generate a new one from the web UI
Microsoft Graph Token (handled automatically):
- The server uses this to talk to Microsoft
- Automatically refreshed - you never see it
- Stored encrypted on the server
Multi-User Support
This server can support multiple users at once, each with completely separate data:
┌─────────────────────────────────────────────────────────────────────────────┐
│ ONE SERVER, MANY USERS │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Alice (alice@company.com) │ Bob (bob@company.com) │
│ ├─ Her own Microsoft tokens │ ├─ His own Microsoft tokens │
│ ├─ Her own session │ ├─ His own session │
│ ├─ Her own activity logs │ ├─ His own activity logs │
│ │ │ │ │
│ └─ Claude Desktop (her laptop) │ └─ Claude Desktop (his PC) │
│ │
│ ═══════════════════════════════════════════════════════════════════════ │
│ COMPLETE DATA ISOLATION │
│ Alice can NEVER see Bob's data │
│ Bob can NEVER see Alice's data │
└─────────────────────────────────────────────────────────────────────────────┘
How it works:
- Each user logs in with their own Microsoft account
- Each user gets their own MCP token
- All data is tagged with the user's identity
- The database enforces isolation at every query
Available Tools (71 Total)
Email (9 tools)
| Tool | Description |
|---|---|
getInbox | Read your inbox messages |
sendEmail | Send an email |
searchEmails | Search for specific emails |
flagEmail | Flag/unflag an email |
getEmailDetails | Get full email content |
markAsRead | Mark email as read/unread |
getMailAttachments | Get email attachments |
addMailAttachment | Add attachment to email |
removeMailAttachment | Remove attachment from email |
Calendar (13 tools)
| Tool | Description |
|---|---|
getEvents | Get calendar events |
createEvent | Create a new meeting |
updateEvent | Modify an existing event |
cancelEvent | Cancel/delete an event |
getAvailability | Check free/busy times |
findMeetingTimes | Find optimal meeting slots |
acceptEvent | Accept a meeting invite |
declineEvent | Decline a meeting invite |
tentativelyAcceptEvent | Tentatively accept |
getCalendars | List all calendars |
getRooms | Find meeting rooms |
addAttachment | Add attachment to event |
removeAttachment | Remove event attachment |
Files (11 tools)
| Tool | Description |
|---|---|
listFiles | List OneDrive files |
searchFiles | Search for files |
downloadFile | Download a file |
uploadFile | Upload a new file |
getFileMetadata | Get file info |
getFileContent | Read file contents |
setFileContent | Write file contents |
updateFileContent | Update existing file |
createSharingLink | Create share link |
getSharingLinks | List share links |
removeSharingPermission | Remove sharing |
Teams (12 tools)
| Tool | Description |
|---|---|
listChats | List Teams chats |
getChat | Get chat details |
listChatMessages | Read chat messages |
sendChatMessage | Send a chat message |
listTeams | List your teams |
getTeam | Get team details |
listChannels | List team channels |
getChannel | Get channel details |
listChannelMessages | Read channel messages |
sendChannelMessage | Post to a channel |
createOnlineMeeting | Create Teams meeting |
getOnlineMeeting | Get meeting details |
People (3 tools)
| Tool | Description |
|---|---|
findPeople | Find people by name in directory |
getRelevantPeople | Get frequent contacts |
getPersonById | Get detailed person information |
Search (1 tool)
| Tool | Description |
|---|---|
search | Unified search across Microsoft 365 (emails, files, events, people) |
To-Do (11 tools)
| Tool | Description |
|---|---|
listTaskLists | List all task lists |
getTaskList | Get a specific list |
createTaskList | Create new list |
updateTaskList | Rename a list |
deleteTaskList | Delete a list |
listTasks | List tasks in a list |
getTask | Get task details |
createTask | Create a new task |
updateTask | Update a task |
deleteTask | Delete a task |
completeTask | Mark task complete |
Contacts (6 tools)
| Tool | Description |
|---|---|
listContacts | List your contacts |
getContact | Get contact details |
createContact | Add new contact |
updateContact | Update contact info |
deleteContact | Remove a contact |
searchContacts | Search contacts |
Groups (4 tools)
| Tool | Description |
|---|---|
listGroups | List Microsoft 365 groups |
getGroup | Get group details |
listGroupMembers | List group members |
listMyGroups | List groups you're in |
Environment Variables
Configure these in your .env file:
Required Variables
| Variable | Required | Description | Default |
|---|---|---|---|
MICROSOFT_CLIENT_ID | Yes | Azure App Client ID | - |
MICROSOFT_TENANT_ID | Yes | Azure Tenant ID | common |
Security Variables (Required in Production)
| Variable | Required | Description | Default |
|---|---|---|---|
DEVICE_REGISTRY_ENCRYPTION_KEY | Prod | 32-byte key for encrypting tokens | Dev fallback |
JWT_SECRET | Prod | Secret for signing JWT tokens | Random (tokens invalid after restart) |
CORS_ALLOWED_ORIGINS | Prod | Comma-separated allowed origins | * in dev only |
Optional Variables
| Variable | Required | Description | Default |
|---|---|---|---|
MICROSOFT_REDIRECT_URI | No | OAuth callback URL | http://localhost:3000/api/auth/callback |
PORT | No | Server port | 3000 |
NODE_ENV | No | Environment mode | development |
MCP_TOKEN_SECRET | No | Secret for MCP tokens | Auto-generated |
MCP_TOKEN_EXPIRY | No | Token expiry in seconds | 2592000 (30 days) |
DATABASE_TYPE | No | Database type | sqlite |
RATE_LIMIT_WINDOW_MS | No | Rate limit window in ms | 900000 (15 min) |
RATE_LIMIT_MAX | No | Max requests per window | 100 |
RATE_LIMIT_AUTH_MAX | No | Max auth attempts per window | 20 |
Troubleshooting
"AADSTS7000218: client_assertion or client_secret required"
Problem: Azure thinks you need a client secret.
Fix:
- Go to Azure Portal → Your App → Authentication
- Under "Advanced settings", set Allow public client flows to Yes
- Click Save
"Needs administrator approval"
Problem: Your organization requires admin consent for the permissions.
Fix:
- Ask your IT admin to grant consent, OR
- Use a personal Microsoft account for testing
"Invalid redirect URI"
Problem: The callback URL doesn't match exactly.
Fix:
- Go to Azure Portal → Your App → Authentication
- Check that the Redirect URI matches exactly:
- Local:
http://localhost:3000/api/auth/callback - Remote:
https://your-server.example.com/api/auth/callback
- Local:
"Connection refused" or "ECONNREFUSED"
Problem: The server isn't running.
Fix:
- Make sure you started the server:
npm run dev:web - Check the server is on the correct port
- Check firewall settings
"401 Unauthorized"
Problem: Your MCP token expired.
Fix:
- Go to the web UI
- Log in again if needed
- Generate a new MCP token
- Update Claude Desktop's config with the new token
- Restart Claude Desktop
Claude doesn't show Microsoft 365 tools
Fix:
- Make sure the config file is valid JSON (no trailing commas!)
- Check the adapter path is correct for your OS
- Make sure Node.js is installed:
node --version - Restart Claude Desktop completely
Security
- Encrypted Storage: All Microsoft tokens are encrypted at rest using AES-256
- No Client Secrets: Uses public client flow (safer for desktop apps)
- Token Isolation: Each user's tokens are stored separately and encrypted with different keys
- Session Expiry: Sessions automatically expire after 24 hours
- HTTPS: Use HTTPS for production deployments
- Rate Limiting: Built-in rate limiting protects against brute-force attacks (configurable)
- CORS Protection: Origin allowlist prevents unauthorized cross-origin requests in production
- Production Secrets: Encryption keys and JWT secrets must be explicitly set in production
Production Security Checklist
Before deploying to production, ensure you have:
- Set
NODE_ENV=production - Set
DEVICE_REGISTRY_ENCRYPTION_KEY(exactly 32 bytes) - Set
JWT_SECRET(strong random string) - Set
CORS_ALLOWED_ORIGINS(e.g.,https://yourdomain.com) - Use HTTPS with valid SSL certificate
- Review rate limit settings for your use case
For Developers
Project Structure
MCP-Microsoft-Office/
├── mcp-adapter.cjs # The adapter that runs locally
├── src/
│ ├── api/ # Express routes and controllers
│ ├── auth/ # MSAL authentication
│ ├── core/ # Services (cache, events, storage)
│ ├── graph/ # Microsoft Graph API services
│ └── modules/ # Feature modules (mail, calendar, etc.)
├── public/ # Web UI
└── data/ # SQLite database (created on first run)
Running Tests
npm test
Development Mode
npm run dev:web # Start server with hot reload
Deploying to Azure
For production deployments to Azure App Service, see the Azure Deployment Guide.
Key points:
- Uses GitHub Actions for CI/CD
- Requires custom startup script for proper Node.js initialization
- Supports automatic deployments on push to
main
Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Submit a pull request
License
MIT License - see LICENSE file for details.
Acknowledgments
- Microsoft Graph API - The API that powers this integration
- Model Context Protocol - The protocol that enables AI tool integration
- Claude - The AI assistant this was built for
