@monolithia/microsoft-365-mcp
v1.0.0
Published
Model Context Protocol server for Microsoft 365 — Outlook (email, calendar, folders, rules), OneDrive (files, sharing), Microsoft Teams (chats, channels, messages, attachments, mentions), and Power Automate — via Microsoft Graph API with delegated OAuth.
Maintainers
Readme
@monolithia/microsoft-365-mcp
A comprehensive MCP (Model Context Protocol) server that connects Claude with Microsoft 365 services through the Microsoft Graph API and Power Automate API.
Forked from
ryaker/outlook-mcp(MIT). This Monolithia distribution adds a full Microsoft Teams module (chats, channels, meeting chats, send/edit/delete, attachments, rich text, @mentions) and hardens the OAuth scope set. See LICENSE for upstream attribution.
Supported Services
- Outlook - Email, calendar, folders, and rules
- OneDrive - Files, folders, search, and sharing
- Power Automate - Flows, environments, and run history
- Microsoft Teams - Chats (1:1, group, meeting), channels, send / edit / delete messages, attachments, rich text, @mentions
Directory Structure
├── index.js # Main entry point
├── config.js # Configuration settings
├── auth/ # Authentication modules
│ ├── index.js # Authentication exports
│ ├── token-manager.js # Token storage and refresh (Graph + Flow)
│ └── tools.js # Auth-related tools
├── calendar/ # Calendar functionality
│ ├── index.js # Calendar exports
│ ├── list.js # List events
│ ├── create.js # Create event
│ ├── delete.js # Delete event
│ ├── cancel.js # Cancel event
│ ├── accept.js # Accept event
│ └── decline.js # Decline event
├── email/ # Email functionality
│ ├── index.js # Email exports
│ ├── list.js # List emails
│ ├── search.js # Search emails
│ ├── read.js # Read email
│ ├── send.js # Send email
│ └── mark-as-read.js # Mark email read/unread
├── folder/ # Folder functionality
│ ├── index.js # Folder exports
│ ├── list.js # List folders
│ ├── create.js # Create folder
│ └── move.js # Move emails
├── rules/ # Email rules functionality
│ ├── index.js # Rules exports
│ ├── list.js # List rules
│ └── create.js # Create rule
├── onedrive/ # OneDrive functionality
│ ├── index.js # OneDrive exports
│ ├── list.js # List files/folders
│ ├── search.js # Search files
│ ├── download.js # Get download URL
│ ├── upload.js # Simple upload (<4MB)
│ ├── upload-large.js # Chunked upload (>4MB)
│ ├── share.js # Create sharing link
│ └── folder.js # Create/delete folders
├── power-automate/ # Power Automate functionality
│ ├── index.js # Power Automate exports
│ ├── flow-api.js # Flow API client
│ ├── list-environments.js # List environments
│ ├── list-flows.js # List flows
│ ├── run-flow.js # Trigger flow
│ ├── list-runs.js # Run history
│ └── toggle-flow.js # Enable/disable flow
├── teams/ # Microsoft Teams messaging
│ ├── index.js # Teams exports + tool definitions
│ ├── message-builder.js # Shared payload builder (HTML, mentions, attachments, inline images)
│ ├── list-chats.js # List 1:1/group/meeting chats
│ ├── list-joined-teams.js # List joined teams
│ ├── list-channels.js # List channels in a team
│ ├── list-chat-messages.js # List messages in a chat
│ ├── list-channel-messages.js# List channel messages (+replies)
│ ├── send-chat-message.js # Send to chat
│ ├── send-channel-message.js # Send to channel (top-level)
│ ├── reply-channel-message.js# Reply to a channel message
│ ├── edit-message.js # PATCH chat/channel message (own messages only)
│ ├── delete-message.js # softDelete / undoSoftDelete (own messages only)
│ ├── create-chat.js # Create or resolve 1:1/group chat
│ ├── resolve-meeting-chat.js # Map online meeting → chatId
│ └── attach-onedrive-file.js # Build Teams attachment ref from OneDrive item
└── utils/ # Utility functions
├── graph-api.js # Microsoft Graph API helper
├── odata-helpers.js # OData query building
└── mock-data.js # Test mode dataFeatures
- Authentication: OAuth 2.0 authentication with Microsoft Graph API (+ Flow API for Power Automate)
- Email Management: List, search, read, send, and organize emails
- Calendar Management: List, create, accept, decline, and delete calendar events
- OneDrive Integration: List, search, upload, download, and share files
- Power Automate: List environments/flows, trigger flows, view run history
- Microsoft Teams: Send / edit / delete messages in 1:1, group, and meeting chats and team channels; file attachments via OneDrive; inline images; @mentions (user / channel / team); HTML rich text
- Modular Structure: Clean separation of concerns for maintainability
- Test Mode: Simulated responses for testing without real API calls
Available Tools
Outlook (Email & Calendar)
| Tool | Description |
|------|-------------|
| list-emails | List recent emails from inbox |
| search-emails | Search emails with filters |
| read-email | Read email content |
| send-email | Send a new email |
| mark-as-read | Mark email as read/unread |
| list-events | List calendar events |
| create-event | Create calendar event |
| accept-event | Accept event invitation |
| decline-event | Decline event invitation |
| delete-event | Delete calendar event |
| list-folders | List mail folders |
| create-folder | Create mail folder |
| move-emails | Move emails between folders |
| list-rules | List inbox rules |
| create-rule | Create inbox rule |
OneDrive
| Tool | Description |
|------|-------------|
| onedrive-list | List files in a path |
| onedrive-search | Search files by query |
| onedrive-download | Get download URL |
| onedrive-upload | Upload small file (<4MB) |
| onedrive-upload-large | Chunked upload (>4MB) |
| onedrive-share | Create sharing link |
| onedrive-create-folder | Create folder |
| onedrive-delete | Delete file or folder |
Power Automate
| Tool | Description |
|------|-------------|
| flow-list-environments | List Power Platform environments |
| flow-list | List flows in environment |
| flow-run | Trigger a manual flow |
| flow-list-runs | Get flow run history |
| flow-toggle | Enable/disable a flow |
Microsoft Teams
| Tool | Description |
|------|-------------|
| list-teams-chats | List your chats (1:1 / group / meeting) |
| list-joined-teams | List teams you belong to |
| list-team-channels | List channels in a team |
| list-chat-messages | List messages in a chat |
| list-channel-messages | List channel messages (with optional replies) |
| send-teams-chat-message | Send a message to a chat (text / HTML / attachments / mentions / inline images) |
| send-teams-channel-message | Post a top-level message to a channel (supports subject) |
| reply-teams-channel-message | Post a threaded reply in a channel |
| edit-teams-message | Edit your own chat or channel message |
| delete-teams-message | Soft-delete (or restore with undo=true) your own message |
| create-teams-chat | Create or resolve a 1:1 / group chat |
| resolve-teams-meeting-chat | Get the chatId for a Teams meeting (by joinWebUrl or meetingId) |
| attach-onedrive-file-to-teams | Turn a OneDrive file into a Teams attachment reference |
Quick Start
Option A — install from npm (recommended)
npm install -g @monolithia/microsoft-365-mcpOr run on-demand with npx (no global install):
npx @monolithia/microsoft-365-mcpThen:
- Azure setup: Register an app in Azure Portal (see detailed steps below)
- Set env vars:
OUTLOOK_CLIENT_IDandOUTLOOK_CLIENT_SECRET(orMS_CLIENT_ID/MS_CLIENT_SECRETwhen using a.envfile) - Configure Claude Desktop: see "Claude Desktop Configuration" below
- Start the auth server:
m365-mcp-auth(installed as a CLI when younpm install -g) - Authenticate: call the
authenticatetool in Claude and open the returned URL - Start using: Access your M365 data through Claude!
Option B — clone and run from source
- Install dependencies:
npm install - Azure setup: Register app in Azure Portal (see detailed steps below)
- Configure environment: Copy
.env.exampleto.envand add your Azure credentials - Configure Claude: Update your Claude Desktop config with the server path
- Start auth server:
npm run auth-server - Authenticate: Use the
authenticatetool in Claude to get the OAuth URL - Start using: Access your M365 data through Claude!
Installation
Prerequisites
- Node.js 14.0.0 or higher
- npm or yarn package manager
- Azure account for app registration
Install Dependencies
npm installAzure App Registration & Configuration
App Registration
- Open Azure Portal
- Search for "App registrations"
- Click "New registration"
- Name: "M365 MCP Server"
- Account type: "Accounts in any organizational directory and personal Microsoft accounts"
- Redirect URI: Web →
http://localhost:3333/auth/callback - Click "Register"
- Copy the "Application (client) ID" for your
.envfile
App Permissions
- Go to "API permissions" under Manage
- Click "Add a permission" → "Microsoft Graph" → "Delegated permissions"
- Add these permissions:
offline_accessUser.Read,User.ReadBasic.All(admin consent)Mail.Read,Mail.ReadWrite,Mail.SendCalendars.Read,Calendars.ReadWriteFiles.Read,Files.ReadWrite- Microsoft Teams (see notes below):
Chat.ReadWrite(user-consentable)ChannelMessage.Send(user-consentable)ChannelMessage.ReadWrite(admin consent — needed only for channel edit / delete)Channel.ReadBasic.All(admin consent)Team.ReadBasic.All(admin consent)OnlineMeetings.Read(admin consent — needed forresolve-teams-meeting-chat)
- Click "Add permissions"
- For any scope marked "admin consent", click Grant admin consent for <tenant> (requires Global Admin / Privileged Role Admin). Alternatively hand out an admin-consent URL:
https://login.microsoftonline.com/{tenantId}/adminconsent?client_id={clientId}
For Power Automate (optional):
- Requires additional Azure AD configuration with Flow API scope
- See Power Automate section below for details
Microsoft Teams notes:
- Only work / school accounts are supported (personal
@outlook.comaccounts will fail — this is a Graph API restriction, not a bug). - Messages are sent as the authenticated user (delegated token). No bot / "via app" badge.
- You can only edit or delete your own messages (server-enforced).
- Tenant Teams Messaging Policy can disable editing or deletion org-wide; in that case you'll get
403even with correct scopes. - Teams throttles message sends at roughly 1 per second per user per chat/channel. Graph returns
429with aRetry-Afterheader when you hit the limit. - Sending / editing / deleting are not metered — no Azure billing configuration required (Microsoft removed Teams API metering for these operations in Aug 2025).
Client Secret
- Go to "Certificates & secrets" → "Client secrets"
- Click "New client secret"
- Add description and select expiration
- Copy the VALUE (not the Secret ID)
Configuration
1. Environment Variables
cp .env.example .envEdit .env:
# Get these values from Azure Portal > App Registrations > Your App
MS_CLIENT_ID=your-application-client-id-here
MS_CLIENT_SECRET=your-client-secret-VALUE-here
MS_TENANT_ID=your-tenant-id-here
USE_TEST_MODE=falseImportant Notes:
- Use
MS_CLIENT_IDandMS_CLIENT_SECRETin the.envfile - Set
MS_TENANT_IDfor single-tenant apps to avoid/commonendpoint errors - For Claude Desktop config, you'll use
OUTLOOK_CLIENT_IDandOUTLOOK_CLIENT_SECRET - Always use the client secret VALUE, never the Secret ID
2. Claude Desktop Configuration
Add to your Claude Desktop config:
If installed globally from npm:
{
"mcpServers": {
"m365-assistant": {
"command": "m365-mcp",
"env": {
"USE_TEST_MODE": "false",
"OUTLOOK_CLIENT_ID": "your-client-id",
"OUTLOOK_CLIENT_SECRET": "your-client-secret"
}
}
}
}Or via npx (no install):
{
"mcpServers": {
"m365-assistant": {
"command": "npx",
"args": ["-y", "@monolithia/microsoft-365-mcp"],
"env": {
"USE_TEST_MODE": "false",
"OUTLOOK_CLIENT_ID": "your-client-id",
"OUTLOOK_CLIENT_SECRET": "your-client-secret"
}
}
}
}Or from a local clone:
{
"mcpServers": {
"m365-assistant": {
"command": "node",
"args": ["/path/to/m365-mcp/index.js"],
"env": {
"USE_TEST_MODE": "false",
"OUTLOOK_CLIENT_ID": "your-client-id",
"OUTLOOK_CLIENT_SECRET": "your-client-secret"
}
}
}
}Authentication
Graph API (Outlook + OneDrive)
- Start auth server:
npm run auth-server - Use the
authenticatetool in Claude - Visit the provided URL and sign in
- Tokens saved to
~/.outlook-mcp-tokens.json
Power Automate (Optional)
Power Automate requires a separate token with the Flow API scope. Configure additional Azure AD permissions for https://service.flow.microsoft.com//.default scope.
Limitations:
- Only solution-aware flows are accessible
- Only manual trigger flows can be run via API
- Requires environment ID for most operations
Microsoft Teams — Usage
The Teams module uses the same delegated Graph token as Outlook and OneDrive. After adding the Teams scopes in Azure (see above), re-run authenticate so the new token carries those scopes.
Sending a simple message
// Tool: send-teams-chat-message
{
"chatId": "19:[email protected]",
"body": "Hey team, quick update — build is green."
}Rich text + @mention + file attachment
The body uses placeholder tokens (default {{@Name}} for mentions, {{@attach:filename}} for attachments, {{@image:tempId}} for inline images). The module splices these into the correct Teams tags and builds the mentions / attachments / hostedContents arrays for you.
// Step 1: resolve a OneDrive file into a Teams attachment reference
// Tool: attach-onedrive-file-to-teams
{ "path": "/Documents/Q4-plan.docx" }
// Returns an attachment object { id, contentType, contentUrl, name }
// Step 2: send the message
// Tool: send-teams-channel-message
{
"teamId": "team-engineering",
"channelId": "19:[email protected]",
"subject": "Q4 Planning",
"body": "<p>Heads up {{@Alice}} — please skim {{@attach:Q4-plan.docx}} before Friday.</p><ul><li>Goals locked</li><li>Risks TBD</li></ul>",
"isHtml": true,
"mentions": [{ "name": "Alice", "userId": "aad-user-id-for-alice" }],
"attachments": [{
"id": "11111111-2222-3333-4444-555555555555",
"contentType": "reference",
"contentUrl": "https://tenant.sharepoint.com/.../Q4-plan.docx",
"name": "Q4-plan.docx"
}]
}Messaging a meeting chat
// Step 1: resolve the meeting's chat thread
// Tool: resolve-teams-meeting-chat
{ "joinWebUrl": "https://teams.microsoft.com/l/meetup-join/..." }
// Returns chatId (e.g. 19:[email protected])
// Step 2: post into that chat with send-teams-chat-message using the returned chatIdEditing / deleting your own message
// Tool: edit-teams-message
{ "chatId": "19:...", "messageId": "1733...", "body": "Updated: build is green *and* deployed." }
// Tool: delete-teams-message
{ "chatId": "19:...", "messageId": "1733..." }
// Pass undo=true to restore.Rich-text notes
Teams supports a restricted HTML subset: <b>/<i>/<u>/<s>, <p>, <br>, <ul>/<ol>/<li>, <h1>-<h3>, <a href>, <blockquote>, <img>, basic <table>, and the Teams-specific tags <at id="...">, <attachment id="...">, <emoji>, <codeblock class="Python"><code>...</code></codeblock>. CSS is often stripped. Practical message size limit is ~25 KB of HTML.
Inline images
Pass base64 bytes in inlineImages and reference them in the body with {{@image:1}} (or a custom placeholder). The module builds the hostedContents array and rewrites the tokens into <img src="../hostedContents/1/$value">.
Troubleshooting
Common Issues
"Cannot find module"
npm install"Port 3333 in use"
npx kill-port 3333
npm run auth-server"Invalid client secret" (AADSTS7000215)
- Use the secret VALUE, not the Secret ID
"Authentication required"
- Delete
~/.outlook-mcp-tokens.jsonand re-authenticate
Teams tool returns 403 / "Access denied"
- Missing scope — make sure the Teams scopes (see above) are added AND admin-consented for those marked
(admin consent). - Tenant Teams Messaging Policy may disable edit/delete globally.
- For channel edit/delete,
ChannelMessage.ReadWrite(admin consent) is required. - The chat includes a federated / Skype participant — edit is blocked by Graph in that case.
Teams tool returns 429 (Throttled)
- You're sending too fast. Teams caps at ~1 send/sec per user per chat. Respect the
Retry-Afterheader.
Teams attachment shows up blank in the client
- The
<attachment id="..."/>body marker is missing. The module auto-appends it if yourbodydidn't include the{{@attach:name}}placeholder — but if you passed a pre-built HTML body without the marker AND disabled auto-append, nothing will render. KeepautoAppendAttachmentson (the default) or include the placeholder yourself.
Testing
# Run with MCP Inspector
npm run inspect
# Run in test mode (mock data)
npm run test-mode
# Run Jest tests
npm testExtending the Server
- Create new module directory
- Implement tool handlers in separate files
- Export tool definitions from module index
- Import and add to
TOOLSarray inindex.js
