A Python-based Model Context Protocol (MCP) server for Microsoft 365 Outlook email operations. This server uses OAuth 2.0 Client Credentials Flow for authentication, making it ideal for autonomous agents and server-to-server scenarios.
Built with FastMCP for simplified server implementation, following the pattern used by AWS API MCP Server.
This MCP server provides the following email operations:
- list-mail-messages - List mail messages from inbox or a specific folder
- list-mail-folders - List all mail folders
- list-mail-folder-messages - List messages from a specific folder
- get-mail-message - Get a specific mail message by ID
- send-mail - Send an email
- delete-mail-message - Delete a mail message
- create-draft-email - Create a draft email
- move-mail-message - Move a mail message to another folder
This server uses OAuth 2.0 Client Credentials Flow (app-only authentication), which is perfect for autonomous agents and background services. No user interaction is required.
Reference: Microsoft Graph - Get access without a user
You need to register an application in Azure AD with Application permissions (not Delegated):
- Go to Azure Portal → Azure Active Directory → App registrations
- Create a new registration
- Note down:
- Application (client) ID
- Directory (tenant) ID
- Create a client secret:
- Go to Certificates & secrets → New client secret
- Copy the secret value immediately (it won't be shown again)
- Configure API permissions:
- Go to API permissions → Add a permission → Microsoft Graph
- Select Application permissions (not Delegated)
- Add the following permissions:
Mail.Read- Read user mailMail.ReadWrite- Read and write user mailMail.Send- Send mail as user
- Grant admin consent (required for application permissions)
Important: Application permissions require administrator consent. The app must be granted consent before it can use these permissions.
Reference: Microsoft Graph - Configure permissions
MS365_CLIENT_ID=your-azure-ad-client-id
MS365_CLIENT_SECRET=your-azure-ad-client-secret
MS365_TENANT_ID=your-tenant-id
# Optional: For Government Cloud
MS365_CLOUD_TYPE=gov # Options: "commercial" (default), "gov", "government", "usgov"
# Optional: For shared mailboxes (required for Client Credentials Flow)
MS365_USER_IDENTIFIER=user@domain.com # UserPrincipalName or Graph ID of the shared mailboxImportant for Shared Mailboxes: When using Client Credentials Flow (app-only authentication), you must provide MS365_USER_IDENTIFIER because /me/ endpoints don't work without a signed-in user. Use the UserPrincipalName (e.g., shared-mailbox@domain.com) or the Graph ID of the shared mailbox.
This project uses UV for dependency management, similar to the AWS API MCP Server.
# Install UV using pip
pip install uv
# Or using Homebrew (macOS)
brew install uv
# Or using the official installer
curl -LsSf https://astral.sh/uv/install.sh | sh# Install project dependencies
uv sync
# Or install in development mode with dev dependencies
uv sync --devexport MS365_CLIENT_ID="your-client-id"
export MS365_CLIENT_SECRET="your-client-secret"
export MS365_TENANT_ID="your-tenant-id"
export PORT="8100" # Optional, defaults to 8100
export HOST="0.0.0.0" # Optional, defaults to 0.0.0.0
export LOG_LEVEL="INFO" # Optional, defaults to INFO
export STATELESS_HTTP="true" # Optional, defaults to trueUsing UV (recommended):
# Run using UV
uv run ms365-email-mcp-server
# Or run directly with Python (after uv sync)
python -m ms365_email_mcp_server.serverThe server will start on http://localhost:8100 with:
- SSE endpoint:
http://localhost:8100/message - Health check:
http://localhost:8100/health
The Dockerfile uses UV for dependency management:
docker build -t email-mcp-server .docker run -d \
-p 8100:8100 \
-e MS365_CLIENT_ID="your-client-id" \
-e MS365_CLIENT_SECRET="your-client-secret" \
-e MS365_TENANT_ID="your-tenant-id" \
-e MS365_CLOUD_TYPE="commercial" \
email-mcp-serverCreate a .env file:
MS365_CLIENT_ID=your-client-id
MS365_CLIENT_SECRET=your-client-secret
MS365_TENANT_ID=your-tenant-id
MS365_CLOUD_TYPE=commercialThen run:
docker-compose upOr in detached mode:
docker-compose up -dThe server runs as an HTTP/SSE server. Connect to it using:
- SSE Endpoint:
http://localhost:8100/message - Health Check:
http://localhost:8100/health
For clients that support HTTP/SSE transport, configure:
{
"mcpServers": {
"ms365-email": {
"url": "http://localhost:8100/message",
"transport": "sse"
}
}
}If you want to use UV to run the server (similar to AWS API MCP Server), you can configure:
{
"mcpServers": {
"ms365-email": {
"command": "uvx",
"args": [
"ms365-email-mcp-server@latest"
],
"env": {
"MS365_CLIENT_ID": "your-client-id",
"MS365_CLIENT_SECRET": "your-client-secret",
"MS365_TENANT_ID": "your-tenant-id",
"LOG_LEVEL": "INFO"
}
}
}
}Note: This requires the package to be published to PyPI. For local development, use Option 1 or run the server manually with uv run ms365-email-mcp-server.
- List Messages: GET /me/messages
- Send Mail: POST /me/sendMail
- Get Message:
GET /me/messages/{id} - Delete Message:
DELETE /me/messages/{id} - Create Draft:
POST /me/messages - Move Message:
POST /me/messages/{id}/move - List Folders:
GET /me/mailFolders
For Azure Government Cloud, set:
export MS365_CLOUD_TYPE="gov"This will use:
- Authority:
https://login.microsoftonline.us - Graph API:
https://graph.microsoft.us
- Never commit your client secrets to version control
- Use environment variables or secret management systems
- Rotate client secrets regularly
- Consider using managed identities in Azure for production
- Application permissions require administrator consent
- Verify your
MS365_CLIENT_ID,MS365_CLIENT_SECRET, andMS365_TENANT_IDare correct - Ensure admin consent has been granted for the application permissions
- Check that the client secret hasn't expired
- Verify that admin consent has been granted for all required permissions
- Check that you're using Application permissions (not Delegated permissions)
- Verify your
MS365_TENANT_IDis correct - For Government Cloud, ensure
MS365_CLOUD_TYPEis set to"gov"
MIT