msgraph-mcp
This server gives AI assistants full access to Microsoft Outlook email, calendar, and contacts via 26 tools, supporting authentication, mail management, calendar scheduling, and people search.
Authentication
Device-code flow with multi-account support and caching.
Check status, start authentication, and finish authentication.
Read: List folders and messages (with time filters and threading), search messages, retrieve full details and attachments.
Compose: Send new emails, reply, reply-all, and forward (dry-run by default). Create and manage drafts with attachments.
Organize: Mark read/unread, flag, categorize, move, or soft/hard delete messages.
Bulk Operations: Filtered bulk actions (delete, move, mark read/unread) with dry-run preview and confirmation safety.
Folders & Aliases: Create folders and list send-from addresses.
Calendar
Read: List calendars (including shared via user_id), list events within a time range, and get event details.
Write: Create, update, or delete events with attendees, location, and all-day support (dry-run by default).
Scheduling: Check free/busy status and get meeting time suggestions.
Responses: Accept, decline, or tentatively accept invitations.
Contacts
Search people to resolve display names to email addresses, returning job titles.
Click on "Deploy 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., "@msgraph-mcp show my upcoming events for next week"
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.
msgraph-mcp
A Model Context Protocol (MCP) server that gives AI assistants full access to Microsoft Outlook email and calendar through the Microsoft Graph API. Built on FastMCP, it supports delegated authentication via device-code flow and can run locally or in a framework-managed cloud environment.
Features
26 tools across mail, calendar, contacts, and scheduling:
Read — list folders, messages (with
sincetime filter andconversation_idthreading), search (OData$search), attachments (inline base64 for files under 1.5 MB)Compose — send, reply, reply-all, forward with dry-run preview by default
Drafts — create, update, attach files, then send when ready
Organize — mark read/unread, flag, categorize, move to folder, soft- or hard-delete
Bulk — filtered operations (delete, mark read/unread, move) with dry-run preview; scans the entire folder by default, or pass
limitto cap how many messages are scannedFolders & aliases — create mail folders, list send-from addresses
Calendar
Read — list calendars, events (default window: yesterday through 14 days out), full event details
Write — create, update, delete/cancel events with attendees, body, location, all-day support
Shared calendars — full read/write access to other users' calendars via
user_idparameterScheduling — check free/busy status for multiple users, or let Graph suggest optimal meeting times
Responses — accept, decline, or tentatively accept meeting invitations
Contacts
People search — resolve display names to email addresses using the People API
Authentication
Device-code flow — interactive three-step auth (
start_auth→ user approves →finish_auth)Multi-account — cache and switch between multiple Microsoft accounts
Framework mode — accept pre-authenticated tokens via environment variables for serverless deployments
Related MCP server: m365-mcp-server
Tool reference
Area | Tool | Description |
Auth |
| Show configuration and cached accounts |
Auth |
| Begin device-code flow (returns URL + code) |
Auth |
| Complete device-code flow after user approval |
| List mail folders with item/unread counts | |
| List messages in a folder (limit 1000; | |
| Full message details including body | |
| Delta sync: what changed in a folder since a token, including deletions | |
| Search via OData | |
| List attachment metadata, or download one by | |
| Send a new email (dry-run by default) | |
| Reply or reply-all (dry-run by default) | |
| Forward a message (dry-run by default) | |
| Create a draft without sending | |
| Update or send an existing draft | |
| Attach a file to a draft | |
| Mark read/unread, flag, or categorize | |
| Move to a folder (supports well-known names) | |
| Soft-delete or permanently delete | |
| Bulk filtered actions with dry-run (whole folder by default; | |
| Create a new mail folder | |
| List email aliases / send-from addresses | |
Calendar |
| List calendars (own or shared via |
Calendar |
| List events in a time range (limit 100; needs a |
Calendar |
| Full event details with attendees |
Calendar |
| Create an event or recurring series (dry-run by default; |
Calendar |
| Update an existing event (dry-run by default; needs a |
Calendar |
| Delete or cancel an event (dry-run by default) |
Calendar |
| Accept, decline, or tentatively accept |
Calendar |
| Free/busy lookup or meeting time suggestions (needs a |
Contacts |
| Search contacts by name (limit 50; returns |
Prerequisites
Python 3.11+
An Azure app registration with delegated Microsoft Graph permissions (see below)
uv (recommended) or pip
Azure app registration
Create an app registration in Microsoft Entra admin center (Azure AD).
1. Supported account types
Choose one:
Accounts in this organizational directory only — single tenant
Accounts in any organizational directory — multi-tenant work/school accounts
2. Authentication
Enable Allow public client flows (required for device-code flow)
3. API permissions
Add delegated Microsoft Graph permissions:
Permission | Purpose |
| Read signed-in user profile |
| Read, move, flag, categorize, delete mail |
| Send mail, reply, forward |
| Read and write calendar events |
| Access shared / delegated calendars |
| Search contacts by name |
Calendars.ReadWrite.Sharedis the widest permission here. With it, every calendar tool accepts auser_idand can create, modify, delete, or cancel events on any calendar the signed-in user has been granted access to — cancelling someone else's meeting emails all of its attendees. There is no allowlist of targetable users; authorization rests entirely with Graph. Drop this scope if you don't need it. See SECURITY_REVIEW.md.
For read-only use, replace Mail.ReadWrite and Mail.Send with Mail.Read, and Calendars.ReadWrite / Calendars.ReadWrite.Shared with Calendars.Read, and set MICROSOFT_SCOPES to match.
Scope-based tool registration: tools are exposed to the client only when a scope that satisfies them is present in MICROSOFT_SCOPES. A read-only scope set never advertises delete_message, send_message, create_event, etc. — the model can't attempt actions the token could not perform. With the default (full) scope set, all tools are available. The auth tools (auth_status, start_auth, finish_auth) are always registered so you can authenticate before any scope is granted.
4. Admin consent
Grant admin consent for the tenant if required by your organization's policies.
Configuration
Copy .env.example to .env and fill in your values:
cp .env.example .envVariable | Default | Description |
| (required) | Azure app registration client ID |
|
|
|
|
| Space-separated delegated permissions |
|
| Path to the local MSAL token cache |
|
| Max attachment size (bytes) for inline base64 (default 1.5 MB) |
|
| Max items returned by |
| (unset) |
|
| (unset) | IANA or Windows zone applied to calendar times written without a UTC offset. Unset → such times are refused, not guessed |
Recommended tenant values:
organizations— work/school accounts only (most common for enterprise)A specific tenant GUID — locks authentication to a single organization
common— any Microsoft account (work, school, or personal)
Deployment
Local (stdio)
The default transport is stdio, suitable for desktop MCP clients like Claude Code, Claude Desktop, Cursor, and VS Code.
# Install dependencies
uv sync
# Run the server
uv run msgraph-mcpOr with pip:
pip install -e .
msgraph-mcpMCP client configuration
Add to your MCP client's configuration (e.g. Claude Desktop claude_desktop_config.json, .mcp.json for Claude Code, etc.):
{
"mcpServers": {
"msgraph-mcp": {
"type": "stdio",
"command": "uv",
"args": ["run", "msgraph-mcp"],
"env": {
"MICROSOFT_CLIENT_ID": "your-client-id",
"MICROSOFT_TENANT_ID": "your-tenant-id"
}
}
}
}If you use a .env file in the project directory, the env block can be omitted.
Cloud — AWS Lambda with mcp-lambda-wrappers (ChatGPT, Claude.ai)
For use with remote MCP clients like ChatGPT and Claude.ai, this server can be deployed as a serverless AWS Lambda function using mcp-cloud-wrappers. That framework wraps any stdio-based MCP server behind Amazon Bedrock AgentCore Gateway with full OAuth 2.0 and Dynamic Client Registration (RFC 7591) support — no code changes required in this project.
What the framework provides:
Serverless deployment — runs this MCP server as a Lambda subprocess behind AgentCore Gateway
Per-user OAuth — each user authenticates with their own Microsoft account; tokens are stored in AWS Secrets Manager with automatic refresh
Caller authentication — Cognito JWT validation for all inbound requests
Dynamic Client Registration — MCP clients (ChatGPT, Claude.ai) self-register via a standard
/registerendpointZero idle cost — Lambda functions spin up on demand
How it works:
An MCP client sends a tool call to the AgentCore Gateway endpoint
The framework validates the caller's JWT, extracts their identity, and loads their Microsoft Graph OAuth token from Secrets Manager
The token is injected as
GRAPH_ACCESS_TOKENinto this server's environmentThis server runs as a subprocess, reads the token, and executes the tool against Microsoft Graph
If the user hasn't authenticated yet,
start_authreturns the framework's OAuth URL instead of a device code
This project is used as the reference example service in mcp-lambda-wrappers — see infra/lambda/services/msgraph/ in that repo for the full configuration.
Quick deploy (from the mcp-lambda-wrappers repo):
# One-time: deploy shared infrastructure (Cognito, DCR, OAuth callback)
make deploy-shared
# Create the Azure app secret
aws secretsmanager create-secret \
--name mcp-wrappers-msgraph-service-secrets \
--secret-string '{"MICROSOFT_CLIENT_ID": "your-client-id"}'
# Generate tool definitions and deploy
make gen-tools SERVICE=msgraph
make deploy-service SERVICE=msgraphFramework environment variables
When running inside the framework, this server auto-detects Lambda mode via these injected environment variables:
Variable | Description |
| Pre-authenticated Microsoft Graph access token (per-user) |
| Set to |
| Authenticated user identifier |
| OAuth authorization URL (shown when user needs to authenticate) |
| Service identifier for the framework |
In this mode:
The MSAL device-code flow is bypassed — tokens are injected by the framework
No local token cache is used (compatible with read-only filesystems like Lambda's
/var/task)auth_statusreports the framework-managed token statestart_auth/finish_authreturn guidance to authenticate through the framework's OAuth flow instead
Docker
While no Dockerfile is included, the server can be containerized:
FROM python:3.12-slim
WORKDIR /app
COPY . .
RUN pip install --no-cache-dir .
ENV MICROSOFT_CLIENT_ID=""
ENV MICROSOFT_TENANT_ID="organizations"
EXPOSE 8000
CMD ["msgraph-mcp"]For persistent authentication, mount a volume for the token cache:
docker run -v msgraph-data:/app/.data \
-e MICROSOFT_CLIENT_ID=your-id \
-e MICROSOFT_TENANT_ID=your-tenant \
msgraph-mcpSafety defaults
Write operations default to safe behavior:
Feature | Default | Notes |
|
| Creates a temporary draft for preview, then deletes it |
|
| Preview before sending |
|
| Preview before sending |
|
| Shows matches without executing; |
|
| Moves to Deleted Items (recoverable) |
|
| Graph mails invitations immediately, so preview first |
|
| Preview shows current state next to the proposed changes |
|
| Preview names the event and says whether attendees are notified |
respond_to_event is deliberately not gated — accepting or declining is
reversible by responding again, so a confirmation step would be friction with no
safety payoff.
Calendar times and timezones
Graph's dateTimeTimeZone pairs a naive wall-clock string with a separate zone
name, so how a time is written matters:
Input | Sent to Graph |
|
|
|
|
| Refused |
That last row is deliberate. Reading a bare local time as UTC is how a 2pm
Eastern meeting silently becomes 10:00 EDT, with invitations already sent — and
on an MCP server the caller is usually a model turning "book me 2pm Thursday"
into exactly that string. Set MSGRAPH_DEFAULT_TIMEZONE if you want a
server-side default instead of passing timezone per call.
The same rule applies to reads — list_events refuses an offsetless window
rather than shifting it silently by your offset. One difference: a $filter
compares instants, so an offsetless read time is resolved through its zone to
UTC, whereas a write hands Graph the wall-clock time plus the zone name.
All-day events are a separate contract: Graph wants midnight in the stated
zone, so the calendar date is preserved and the instant is not.
2026-04-01T23:00:00-04:00 with is_all_day=True books April 1, not April 2.
Confirming a bulk delete or move
Destructive bulk actions are two-step. The dry run returns a confirm_token
derived from the ids it actually matched:
// 1. preview
{"action": "delete", "dry_run": true}
// -> {"matched": 42, "confirm_token": "42-b7e2d4a1c3f9", "matches": [...]}
// 2. act
{"action": "delete", "dry_run": false, "confirm_token": "42-b7e2d4a1c3f9"}The live run rescans and re-derives the token from its own results. If the mailbox changed in between, it refuses rather than acting on a set you never saw:
confirm_token does not match the current scan: it described 42 message(s),
this scan matched 43. The mailbox is live, so re-check the preview before
acting. Confirm with the new token: 43-9f1c2ae5b7d0Nothing is stored server-side — the token is recomputed each time — so this works unchanged across a Lambda cold start between the two calls.
Bulk scan semantics
bulk_manage_messages scans newest-first and applies its filters client-side. By
default (limit=None) it scans the entire folder, so "find/act on all messages
matching X" returns a true total. Pass limit=N to scan at most the newest N
messages; the value is honored exactly (paged internally at up to 1000/request),
never silently clamped. The response reports coverage explicitly:
Field | Meaning |
| Distinct messages inspected this run |
| How many passed the filters |
| Folder size, as a scale anchor |
|
|
|
|
| Per-message outcomes of a live (non-dry-run) run |
Follow-up flags and categories
flag_message and categorize_message could always write these; nothing read
them back, so an agent could flag a message and then had no way to report which
messages were flagged. Both are now on every list and detail result
(flag_status, categories) and appear in the generated summary string.
list_messages(flag_status="flagged") filters server-side, so "show me my
flagged mail" is one request. Two constraints worth knowing, both confirmed
against the live API rather than inferred:
Exchange rejects a flag restriction combined with a sort — the pairing returns "The restriction or sort order is too complex for this operation." So
$orderbyis dropped for these queries and the rows are re-sorted client-side to keep the newest-first contract.Because the server chose those rows unsorted,
limitselects an arbitrary subset rather than the newest N. Raiselimitabove your expected flagged count, or narrow withsince/until— a date clause does combine with the flag filter.
Categories behave differently, and better. Exchange accepts a category
restriction with a sort, so category is pushed server-side on both
list_messages and bulk_manage_messages, keeps newest-first ordering, and
imposes none of the limit caveat above. Filtering a 50k-message folder by
category reads only the matching rows — a live check scanned 1 message rather
than the folder.
bulk_manage_messages filters flags client-side, since its cursor pagination
depends on the receivedDateTime sort a flag restriction would force it to drop.
Category names are escaped as OData string literals, so a name containing a
quote (Bob's stuff) is handled rather than breaking the filter.
Date windows
received_after and received_before are applied by Graph, not after the
fetch, so a date-scoped query reads only its window. This is what makes old mail
cheap to reach: without a bound, "what did this sender send me last March" pages
the entire folder to match a handful of rows. On a 50k-message mailbox that is
the difference between ~50 round-trips and one.
The upper bound needs no extra machinery — paging already anchors on
receivedDateTime le, so received_before is the starting cursor and the scan
begins inside the window rather than at the newest message.
When either bound is given, stop_reason is window_exhausted rather than
folder_exhausted. That distinction is deliberate: the scan covered all of what
you asked for, but not all of the folder, and reporting the latter would
overclaim.
The mailbox is live, so counts are a point-in-time snapshot: re-running may
legitimately see a different set. Collection and action are separate phases —
messages moved or deleted (e.g. by a rule) between the two are reported as
already_gone, not errors. truncated=True means matches may exist deeper than
this call reached; it is not safe to read a converged count of 0 as "the folder
is clean."
Security
Path segment validation — all user-supplied IDs are validated against a safe-character pattern before URL interpolation, blocking path traversal
Next-link hardening — pagination only follows HTTPS URLs on the configured Graph host
Search sanitization — double-quotes stripped from OData
$searchqueriesRetry with backoff — automatic retry for HTTP 429 and transient 5xx errors (3 attempts, respects
Retry-After)Error translation — raw Graph API payloads are never exposed to callers
Token cache permissions — cache file
0600, parent directory0700, symlinks rejected
See SECURITY_REVIEW.md for the full threat model and remaining risks.
Development
# Install with dev dependencies
uv sync --dev
# Run tests
uv run pytest
# Or with pip
pip install -e '.[dev]'
pytestCI runs the suite on Python 3.11–3.14 for every push and pull request to main
(.github/workflows/ci.yml).
Two guardrails run as part of the ordinary test suite:
tests/conftest.pyblocks real outbound HTTP. Tests that need it patchGraphClient; anything that reacheshttpxfails loudly. This exists because a test once made a live Graph call against a developer's cached token.tests/test_docs_parity.pyasserts the tool tables inREADME.mdandAGENTS.mdmatch the registered tools exactly, in both directions. Adding a tool without documenting it — or documenting one that does not exist — fails the build.
Smoke test harness
A CLI harness for manual testing without a full MCP client:
# Auth
python3 scripts/smoke_test.py status
python3 scripts/smoke_test.py start-auth
python3 scripts/smoke_test.py finish-auth
python3 scripts/smoke_test.py list-accounts
# Mail
python3 scripts/smoke_test.py list-folders
python3 scripts/smoke_test.py list-messages --folder inbox --limit 5
python3 scripts/smoke_test.py get-message MESSAGE_ID
python3 scripts/smoke_test.py search-messages "search term"
python3 scripts/smoke_test.py mark-message-read MESSAGE_ID
python3 scripts/smoke_test.py move-message MESSAGE_ID archive
python3 scripts/smoke_test.py delete-message MESSAGE_ID
python3 scripts/smoke_test.py bulk-manage-messages --sender-contains "newsletters" --limit 50
# Calendar
python3 scripts/smoke_test.py list-calendars
python3 scripts/smoke_test.py list-events --limit 10
python3 scripts/smoke_test.py get-event EVENT_IDLicense
See LICENSE for details.
Available Tools
29 toolsadd_attachment_to_draftC
Attach a file (base64-encoded) to a draft message.
Inputs: name (required), message_id (required), content_base64 (required), account_id, +1 more. Returns: object
auth_statusA
Show current Microsoft auth configuration and cached accounts.
When running inside the MCP Lambda wrapper framework, reports framework-managed authentication status instead of local MSAL state.
Inputs: no named parameters. Returns: object
bulk_manage_messagesA
Bulk-manage messages with filtering. Supports dry-run, delete, move, and mark-read actions.
By default (limit=None) this scans the entire folder newest-first, so
"find/act on all messages matching X" sees the whole folder, not a window.
Pass limit only to cap how many messages are scanned (e.g. limit=200
scans at most the newest 200); the value is honored exactly, never silently
clamped. Filtering is client-side.
The response reports coverage honestly: truncated is False only when the
scan reached the end of the folder (stop_reason="folder_exhausted"), so a
match count is a true total; if limit cut the scan short it is True. The
mailbox is live, so counts are a point-in-time snapshot. Collection and action
are separate phases; messages moved or deleted between them are reported as
already_gone, not errors.
Inputs: limit, action, folder, dry_run, +6 more. Returns: object
check_availabilityB
Check calendar availability. mode='free_busy': get free/busy schedule. mode='suggest': suggest meeting times.
Inputs: emails (required), end_iso (required), start_iso (required), mode, +2 more. Returns: result
create_draftB
Create a draft email (saved to Drafts folder). Use this when you need to add attachments before sending, or want to build a message over multiple steps. Then use manage_draft to send.
Inputs: to (required), body (required), subject (required), cc, +3 more. Returns: object
create_eventB
Create a new calendar event. Pass user_id for shared calendars.
Inputs: end_iso (required), subject (required), start_iso (required), body, +6 more. Returns: object
create_folderB
Create a new mail folder, optionally under a parent folder.
Inputs: name (required), account_id, parent_folder_id. Returns: object
delete_eventB
Delete or cancel a calendar event. Pass user_id for shared calendars.
Inputs: event_id (required), user_id, account_id, cancel_message. Returns: object
delete_messageC
Delete a message or move it to Deleted Items. Requires Mail.ReadWrite permission.
Inputs: message_id (required), permanent, account_id. Returns: object
finish_authA
Complete Microsoft authentication after user approval.
In Lambda mode, this is not needed — call auth_status instead. In local mode, completes the device-code flow.
Inputs: no named parameters. Returns: object
forward_messageA
Forward a message. Defaults to dry-run (preview only). Set dry_run=False to actually send.
Inputs: to (required), message_id (required), body, dry_run, +2 more. Returns: object
get_attachmentsA
Get attachments for a message. Without attachment_id: list all metadata. With attachment_id: download that attachment (base64 if under 1.5 MB).
Inputs: message_id (required), account_id, attachment_id. Returns: result
get_eventB
Get full details for a specific calendar event. Pass user_id for shared calendars.
Inputs: event_id (required), user_id, account_id. Returns: object
get_messageB
Get a full read-only view of a specific mail message.
Inputs: message_id (required), account_id. Returns: object
list_aliasesC
List email aliases (send-from addresses) for the authenticated user.
Inputs: account_id. Returns: object
list_calendarsB
List readable calendars. Pass user_id for shared calendars (e.g. another user's email or object ID).
Inputs: user_id, account_id. Returns: result
list_eventsC
List events from a calendar in a time range. Pass user_id for shared calendars.
Inputs: limit, end_iso, user_id, start_iso, +2 more. Returns: result
list_foldersA
List mail folders. Pass parent_folder_id to list subfolders (check child_folder_count to know if subfolders exist).
Inputs: account_id, include_hidden, parent_folder_id. Returns: result
list_messagesA
List recent mail messages from a folder, newest first.
Pass since (ISO-8601) to filter server-side to messages received at or
after that time. Pass fields to override the selected columns (id is
always included) for a leaner or extended payload. Each summary includes
conversation_id for threading without a follow-up fetch.
Inputs: limit, since, fields, folder, +1 more. Returns: result
manage_draftA
Update and/or send a previously created draft. Provide fields to update, set send=True to send. Use after create_draft and optionally add_attachment_to_draft.
Inputs: message_id (required), cc, to, bcc, +5 more. Returns: object
move_messageC
Move a message to another folder. Requires Mail.ReadWrite permission.
Inputs: message_id (required), destination (required), account_id. Returns: object
reply_to_messageA
Reply to a message. Defaults to dry-run (preview only). Set dry_run=False to actually send.
Inputs: body (required), message_id (required), dry_run, send_as, +2 more. Returns: object
respond_to_eventC
Respond to a meeting invite. Pass user_id for shared calendars.
Inputs: event_id (required), response (required), message, user_id, +1 more. Returns: object
search_messagesC
Search messages using Microsoft Graph message search.
Inputs: query (required), limit, account_id. Returns: result
search_peopleB
Search for people by name to find their email addresses.
Inputs: query (required), limit, account_id. Returns: result
send_messageA
Compose and send an email (no attachments). Defaults to dry-run (preview only). Set dry_run=False to actually send. To send with attachments, use create_draft + add_attachment_to_draft + manage_draft instead.
Inputs: to (required), body (required), subject (required), cc, +4 more. Returns: object
start_authA
Start Microsoft authentication.
In Lambda mode, returns an OAuth authorization URL. In local mode, starts the device-code flow.
Inputs: no named parameters. Returns: object
update_eventC
Update an existing calendar event. Pass user_id for shared calendars.
Inputs: event_id (required), body, end_iso, subject, +6 more. Returns: object
update_messageB
Update message properties: read/unread, follow-up flag (flagged/complete/notFlagged), or color categories.
Inputs: message_id (required), is_read, account_id, categories, +1 more. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 29 tools
Each tool targets a distinct operation (get vs list vs create vs delete vs reply vs forward, etc.) within clear subdomains (mail, calendar, auth, people). No two tools serve the same purpose, and descriptions clarify subtle differences like send_message vs reply_to_message.
Virtually all tools follow a consistent verb_noun snake_case pattern (e.g., list_messages, create_event, delete_message). The only slight deviation is auth_status (no verb), but it's a common idiom for status checks and does not break the overall pattern.
With 29 tools, the set is slightly large but well-justified by the breadth of the Microsoft Graph API (mail, calendar, people, auth). Each tool fills a specific need, and no tools feel redundant. It's just above the typical well-scoped range (3-15) but still cohesive.
The toolset covers the core CRUD operations for mail and calendar, plus search, bulk actions, and check availability. Minor gaps exist (e.g., sending attachments directly without draft flow, no contact management beyond search), but these are acceptable workarounds for the common use case.
Maintenance
Related MCP Connectors
MCP server connecting AI agents to 100+ apps (Gmail, Slack, Notion, GitHub) via one-click OAuth.
One MCP server for the services your AI needs: memory, files, Microsoft 365, kanban and more.
Give AI agents a real email address, vault, calendar, and task delegation via MCP.
Unified MCP Server is a remote MCP connector for AI agents and vertical AI products that provides access to 22,000+ authorized SaaS tools across 400+ integrations and 24 categories directly inside LLMs (Claude, GPT, Gemini, Cohere). Tools operate only on explicitly authorized customer connections, enabling agents to safely read and write against live third-party systems.
Related MCP Servers
- FlicenseCqualityDmaintenanceA powerful MCP server that enables AI assistants to interact with Microsoft Graph API for managing Outlook emails, Calendar events, OneDrive files, and Contacts through natural language commands.3556-
- AlicenseNot gradedqualityCmaintenanceA production-ready MCP server that provides secure, delegated access to Microsoft 365 services including Email, SharePoint, OneDrive, and Calendar. It enables AI models to search messages, browse files, manage calendar events, and parse document contents using OAuth 2.1 authentication.MIT
- AlicenseAqualityCmaintenanceMCP server for any Microsoft Exchange / OWA deployment. Gives LLM agents access to email, calendar, directory search, folders, availability, and meeting analytics via 30 tools.3043 PyPI12MIT
- AlicenseNot gradedqualityDmaintenanceA secure remote MCP server that integrates Microsoft 365 services with AI assistants, enabling email, calendar, Teams, and contact operations via the Microsoft Graph API.2MIT