A powerful Model Context Protocol (MCP) server that enables seamless Microsoft 365 email integration through natural language interactions. Built for SIYA Desktop, LLMs, and any MCP-compatible application with production-ready security.
- 🎯 Optimized Tool Architecture - Only 6 unified tools (67% reduction from 18 tools)
- 📧 Complete Email Management - Send, read, search, organize, and manage attachments
- 🔐 Bulletproof Authentication - Proactive token refresh prevents chat interruptions
- 🤖 AI-First Design - Intuitive action-based tools perfect for LLM interactions
- 🔒 Enterprise Security - OAuth2 with secure keychain storage and automatic refresh
- 📁 Smart Contact Management - Search and retrieve your Microsoft 365 contacts
- 🌐 Cross-Platform - Works on macOS, Linux, and Windows
For detailed technical documentation, enhancement reports, and guides, see the docs/ directory:
- Enhancement Reports - Recent fixes and improvements
- Technical Guides - Batch operations and Graph API implementation guides
-
send_email
- Send emails with attachments and rich formatting -
manage_email
- UNIFIED: Read, search, list, mark, move, delete, or draft emails -
get_attachment
- Download email attachments with metadata -
list_folders
- Browse mailbox folders with item counts
-
manage_contacts
- UNIFIED: List all contacts or search by name/email -
authenticate
- UNIFIED: Complete authentication management (login, status, logout)
Option A: Global Installation
# Install globally
npm install -g ms365-mcp-server
# Authenticate (no Azure setup needed!)
ms365-mcp-server --login
# Start the server
ms365-mcp-server
# Start with custom server URL
ms365-mcp-server --server-url https://your-domain.com
Option B: Run with npx (no installation needed)
# Authenticate
npx ms365-mcp-server --login
# Start the server
npx ms365-mcp-server
# Start with custom server URL
npx ms365-mcp-server --server-url https://your-domain.com
For Global Installation:
{
"mcpServers": {
"ms365": {
"command": "ms365-mcp-server",
"args": ["--server-url", "https://your-domain.com"]
}
}
}
For npx Usage:
{
"mcpServers": {
"ms365": {
"command": "npx",
"args": ["ms365-mcp-server", "--server-url", "https://your-domain.com"]
}
}
}
Chat with SIYA and ask it to help with your emails! The tools are designed for natural language interaction.
# One-command authentication
ms365-mcp-server --login
# Authentication with custom server URL
ms365-mcp-server --login --server-url https://your-domain.com
# Set server URL via environment variable
export SERVER_URL=https://your-domain.com
ms365-mcp-server
// Check authentication status
{
"tool": "authenticate",
"arguments": {
"action": "status"
}
}
// Login with device code
{
"tool": "authenticate",
"arguments": {
"action": "login"
}
}
// Logout
{
"tool": "authenticate",
"arguments": {
"action": "logout"
}
}
// Send an email with attachment
{
"tool": "send_email",
"arguments": {
"to": ["colleague@company.com"],
"subject": "Project Update",
"body": "<h2>Status Report</h2><p>Project is on track!</p>",
"bodyType": "html",
"attachments": [{
"name": "report.pdf",
"contentBytes": "base64_encoded_content"
}]
}
}
// Search emails with smart name matching
{
"tool": "manage_email",
"arguments": {
"action": "search",
"from": "John Smith", // Works with names or emails
"after": "2024-01-01",
"hasAttachment": true
}
}
// List recent inbox emails
{
"tool": "manage_email",
"arguments": {
"action": "list",
"folderId": "inbox",
"maxResults": 10
}
}
// Find emails sent to you (TO or CC)
{
"tool": "manage_email",
"arguments": {
"action": "search_to_me",
"from": "boss@company.com",
"isUnread": true
}
}
// Read a specific email
{
"tool": "manage_email",
"arguments": {
"action": "read",
"messageId": "email_id_here"
}
}
// Mark email as read
{
"tool": "manage_email",
"arguments": {
"action": "mark",
"messageId": "email_id",
"isRead": true
}
}
// Move email to folder
{
"tool": "manage_email",
"arguments": {
"action": "move",
"messageId": "email_id",
"destinationFolderId": "archive"
}
}
// Delete email
{
"tool": "manage_email",
"arguments": {
"action": "delete",
"messageId": "email_id"
}
}
// Create draft email
{
"tool": "manage_email",
"arguments": {
"action": "draft",
"draftTo": ["colleague@company.com"],
"draftSubject": "Draft: Project Update",
"draftBody": "<h2>Status Report</h2><p>Project is on track!</p>",
"draftBodyType": "html",
"draftCc": ["manager@company.com"],
"draftImportance": "normal"
}
}
// List all contacts
{
"tool": "manage_contacts",
"arguments": {
"action": "list",
"maxResults": 100
}
}
// Search contacts by name
{
"tool": "manage_contacts",
"arguments": {
"action": "search",
"query": "John"
}
}
// Get attachment from email
{
"tool": "get_attachment",
"arguments": {
"messageId": "email_id",
"attachmentId": "attachment_id"
}
}
// List mailbox folders
{
"tool": "list_folders",
"arguments": {}
}
// Download a specific attachment
{
"tool": "get_attachment",
"arguments": {
"messageId": "email_id",
"attachmentId": "attachment_id"
}
}
// Download all attachments from an email
{
"tool": "get_attachment",
"arguments": {
"messageId": "email_id"
}
}
The server automatically serves downloaded attachments. By default, files are served at http://localhost:55000/attachments/
. For production environments, configure the server URL using the SERVER_URL
environment variable:
# Local development (default)
SERVER_URL=http://localhost:55000 ms365-mcp-server
# Production environment
SERVER_URL=https://your-domain.com ms365-mcp-server
Files are:
- Stored with unique names to prevent collisions
- Available for 24 hours
- Served with proper content types
- Accessible via the configured server URL
Attachments are automatically cleaned up after 24 hours. You can also manually delete files from the public/attachments
directory.
// Create a basic draft
{
"tool": "manage_email",
"arguments": {
"action": "draft",
"draftTo": ["colleague@company.com"],
"draftSubject": "Project Update",
"draftBody": "Draft content here...",
"draftBodyType": "text"
}
}
// Create a threaded reply draft (automatically appears in email thread)
{
"tool": "manage_email",
"arguments": {
"action": "reply_draft",
"originalMessageId": "original_email_id",
"draftBody": "My reply content...", // Optional comment
"replyToAll": false
}
}
// Create a forward draft (automatically includes original content)
{
"tool": "manage_email",
"arguments": {
"action": "forward_draft",
"originalMessageId": "original_email_id",
"draftBody": "Forwarding this for your review..." // Optional comment
}
}
// Update an existing draft
{
"tool": "manage_email",
"arguments": {
"action": "update_draft",
"draftId": "draft_email_id",
"draftSubject": "Updated Subject",
"draftBody": "Updated content..."
}
}
// Send a saved draft
{
"tool": "manage_email",
"arguments": {
"action": "send_draft",
"draftId": "draft_email_id"
}
}
// List all draft emails
{
"tool": "manage_email",
"arguments": {
"action": "list_drafts",
"maxResults": 20
}
}
// List all folders including subfolders with hierarchy
{
"tool": "list_folders"
}
// List only child folders of a specific parent folder
{
"tool": "list_folders",
"arguments": {
"parentFolderId": "inbox_folder_id"
}
}
// Search for folders by name (case-insensitive)
{
"tool": "list_folders",
"arguments": {
"searchName": "projects"
}
}
# Authentication
ms365-mcp-server --login # Authenticate using device code
ms365-mcp-server --logout # Clear stored tokens
ms365-mcp-server --verify-login # Check authentication status
# Management
ms365-mcp-server --setup-auth # Interactive credential setup
ms365-mcp-server --reset-auth # Clear all authentication data
ms365-mcp-server --debug # Enable detailed logging
- 🔄 Proactive Token Refresh - Prevents authentication interruptions during long conversations
- 🔐 Secure Storage - OS keychain integration with encrypted fallback
- 🛡️ OAuth2 Compliance - Microsoft MSAL library with enterprise-grade security
- 🏠 Privacy First - All processing happens locally, no data sent to third parties
- 🔒 Single-User Model - Simplified security without account enumeration risks
# Check current status
ms365-mcp-server --verify-login
# Reset and re-authenticate
ms365-mcp-server --logout
ms365-mcp-server --login
# Enable detailed logging
ms365-mcp-server --debug
# Logs location: /tmp/ms365-mcp-server.log
-
"Credentials not configured" → Run
--login
-
"Token expired" → Authentication auto-refreshes, or run
--login
-
Device code timeout → Codes expire in 15 minutes, try
--login
again
- 📞 Natural Language Interface - Ask SIYA to "check my emails from John today"
- 🤖 Smart Email Processing - Let AI help organize, respond, and analyze emails
- ⚡ Optimized for LLMs - Unified tools reduce context switching and improve performance
- 🔄 Reliable Sessions - Proactive authentication prevents chat interruptions
- 📊 Email Analytics - Extract insights and patterns from your email data
# Local development
npm run dev
# Build and test
npm run build
npm test
# Version management
npm run version-bump [patch|minor|major]
- 🎯 67% Fewer Tools - Consolidated 18 tools into 6 unified tools
- 🔄 Bulletproof Auth - Proactive token refresh prevents interruptions
- ⚡ Better Performance - Optimized tool architecture for faster responses
- 🧠 AI-Optimized - Action-based design perfect for LLM interactions
- 🛡️ Enhanced Security - Improved error handling and retry logic
MIT License - see LICENSE file for details.
Contributions welcome! Please submit issues and pull requests.
Built with 🔒 Security and ❤️ for the AI community
Production-ready Microsoft 365 integration for SIYA Desktop and MCP applications
-
--server-url URL
: Set custom server URL for attachments and authentication (default: http://localhost:55000) -
SERVER_URL
: Environment variable to set server URL
-
--setup-auth
: Set up MS365 API credentials -
--reset-auth
: Clear stored authentication tokens -
--multi-user
: Enable multi-user authentication mode -
--login
: Login to MS365 -
--logout
: Logout from MS365 -
--verify-login
: Verify login status
-
--debug
: Enable debug output -
--non-interactive
,-n
: Run in non-interactive mode (no prompt) -
--help
,-h
: Show help message
- The server URL is used for:
- Serving email attachments
- Generating attachment URLs
- OAuth redirect URIs
- Authentication callbacks
- Attachments are served for 24 hours before automatic cleanup
- Default server port is 55000
- For production use, set a custom server URL with HTTPS