Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Outlook OAuth MCP Serverlist my upcoming calendar events for today"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
useful-outlook-mcp
A remote MCP server for Microsoft Outlook with proper OAuth2 and agent-optimized tools.
Features
Spec Compliant: RFC 9728/8414 OAuth metadata, RFC 7591 dynamic client registration
Stateless OAuth: Tokens managed by client, not server—as OAuth intended
Agent-Optimized Tools: Extensive prompt engineering in tool descriptions
Dynamic Scopes: OAuth scopes auto-adjust to enabled tools
Production Ready: Docker, rate limiting, read-only mode, tool filtering
Quick Start
npm install
npm run build
npm start # Server at http://localhost:3000Required environment:
MS365_MCP_CLIENT_ID=your-azure-ad-client-id
MS365_MCP_CLIENT_SECRET=your-azure-ad-client-secret
MS365_MCP_TENANT_ID=your-tenant-id # or 'common'Azure AD Setup
Azure Portal → Microsoft Entra ID → App registrations → New
Add delegated permissions:
User.Read,Mail.Read,Mail.ReadWrite,Mail.Send,Calendars.Read,Calendars.ReadWrite,Calendars.Read.Shared,Place.Read.All,People.Read,offline_accessAdd redirect URI:
http://localhost:6274/oauth/callback(for MCP Inspector)Certificates & secrets → New client secret → Copy the value
Copy Client ID, Client Secret, and Tenant ID to your
.env
Tools
list-mail-folders · list-mail-messages · search-mail · get-mail-message · send-mail · create-draft-mail · reply-mail · reply-all-mail · create-reply-draft · create-reply-all-draft · delete-mail-message · move-mail-message
Calendar
list-calendars · list-calendar-events · search-calendar-events · find-meeting-times · get-calendar-event · get-calendar-view · create-calendar-event · update-calendar-event · delete-calendar-event
People
lookup-contact-email
Room Search
For in-person meetings, find-meeting-times automatically:
Fetches all available meeting rooms across your organization
Includes them in availability checks alongside attendees
Groups free rooms by location (city/building)
Returns only available rooms with email addresses for booking
Set isOnlineMeeting: false to enable room search. For online meetings (default: true), Teams meeting links are automatically generated.
Required scope: Place.Read.All (add to Azure AD app permissions)
Configuration
Variable | Default | Description |
| required | Azure AD client ID |
| - | Client secret (optional) |
|
| Tenant ID |
|
| Server port |
|
| Disable write operations |
| all | Comma-separated tool allowlist |
|
| CORS origins |
|
| Requests per window |
|
| Window size (ms) |
| - | Restrict to specific tenants |
Docker
From GitHub Container Registry:
docker run -p 3000:3000 \
-e MS365_MCP_CLIENT_ID=xxx \
-e MS365_MCP_CLIENT_SECRET=xxx \
-e MS365_MCP_TENANT_ID=xxx \
ghcr.io/Leonine-Studios/useful-outlook-mcp:latestOr build locally:
docker build -t useful-outlook-mcp .
docker run -p 3000:3000 \
-e MS365_MCP_CLIENT_ID=xxx \
-e MS365_MCP_CLIENT_SECRET=xxx \
-e MS365_MCP_TENANT_ID=xxx \
useful-outlook-mcpEndpoints
Endpoint | Description |
| MCP protocol |
| Health check |
| RFC 9728 |
| RFC 8414 |
| OAuth (proxies to Microsoft) |
| Token exchange (proxies to Microsoft) |
| Dynamic client registration |
Testing
npm run dev
npx @modelcontextprotocol/inspector # Connect to http://localhost:3000/mcpDesign Notes
Problems with existing servers
Legacy architecture: Built as stdio with HTTP bolted on. This is HTTP-native.
OAuth done wrong: Most servers store tokens server-side. This server is stateless—tokens passed per-request via Authorization header, never stored.
Tools without thought: Typical servers map API endpoints 1:1 without guidance. Agents fail in practical use because they don't know API quirks or multi-step workflows.
What's different
Every tool includes:
When to use it vs alternatives
Known Graph API quirks (there are many)
Workflow guidance for multi-step tasks
Parameter combinations that fail
Example: find-meeting-times explains that email addresses are required (names don't work), how to find emails from names using search-mail, what OrganizerUnavailable means, and that isOrganizerOptional=true needs user confirmation.
Known Graph API quirks
Mail sender filtering:
eqonfrom/emailAddress/addressis unreliable—usesstartswith()Mail recipient filtering: Can't filter to/cc/bcc with
$filter—must use$searchCalendar organizer filtering:
$filteron organizer email returns 500—filtered client-sideConcurrency: Parallel calls can return
MailboxConcurrencyerrorsSearch + sort:
$searchcan't combine with$orderby
License
MIT
This server cannot be installed
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.