M365 Calendar MCP Server
Enables AI assistants to manage Microsoft 365 and Outlook calendars through the Microsoft Graph API. It supports comprehensive event operations including listing, creating, and updating meetings, as well as finding available slots across multiple attendees.
README
M365 Calendar MCP Server
A Model Context Protocol (MCP) server for Microsoft 365 Calendar integration. Enables AI assistants like Claude to manage your Outlook/Microsoft 365 calendar through the Microsoft Graph API.
Features
- List Calendars - View all your calendars with permissions and ownership info
- List Events - Browse events in a date range with full details (supports recurring events)
- Get Event - Retrieve complete event details including body, recurrence, and attachments info
- Create Event - Create events with attendees, Teams meetings, recurrence, reminders, and more
- Update Event - Modify any event property (partial updates supported)
- Delete Event - Remove events with automatic cancellation notices
- Respond to Events - Accept, tentatively accept, or decline meeting invitations
- Find Meeting Times - Find available meeting slots across multiple attendees
Prerequisites
- Node.js >= 18
- A Microsoft 365 account (work, school, or personal)
- An Azure AD app registration
Azure AD App Setup
- Go to the Azure Portal > Azure Active Directory > App registrations
- Click New registration
- Name:
M365 Calendar MCP - Supported account types: Choose based on your needs (single tenant or multi-tenant)
- Redirect URI: Leave blank (we use device code flow)
- Name:
- After creation, note the Application (client) ID and Directory (tenant) ID
- Go to API permissions > Add a permission > Microsoft Graph > Delegated permissions
- Add the following permissions:
Calendars.ReadWriteCalendars.ReadUser.Read
- Go to Authentication > Enable Allow public client flows (required for device code flow)
Installation
npm install
npm run build
Configuration
Set the following environment variables:
# Required: Your Azure AD app client ID
export M365_CLIENT_ID="your-client-id-here"
# Optional: Your Azure AD tenant ID (defaults to "common" for multi-tenant)
export M365_TENANT_ID="your-tenant-id-here"
# Optional: Custom token cache path
export M365_CALENDAR_TOKEN_CACHE_PATH="/path/to/token-cache.json"
Authentication
Before using the MCP server, authenticate with your Microsoft account:
# Login via device code flow
npm run login
# or
node dist/index.js --login
This will display a URL and code. Open the URL in your browser, enter the code, and sign in with your Microsoft account.
Other auth commands:
# Check authentication status
node dist/index.js --check-auth
# Logout and clear cached tokens
npm run logout
Usage with Claude Desktop
Add to your Claude Desktop configuration (claude_desktop_config.json):
{
"mcpServers": {
"m365calendar": {
"command": "node",
"args": ["/path/to/m365calender-mcp/dist/index.js"],
"env": {
"M365_CLIENT_ID": "your-client-id-here",
"M365_TENANT_ID": "your-tenant-id-here"
}
}
}
}
Usage with Claude Code
claude mcp add m365calendar -- node /path/to/m365calender-mcp/dist/index.js
Make sure M365_CLIENT_ID is set in your environment.
Available Tools
list-calendars
Lists all calendars accessible to the authenticated user, including shared calendars. Returns each calendar's name, ID, color, default status, edit/share permissions, and owner information.
This is a good starting point to discover calendar IDs. The id returned here can be passed as the calendarId parameter to any other tool. If you omit calendarId in other tools, they default to the user's primary calendar.
Parameters: None
Returns: Array of calendars with id, name, color, isDefault, canEdit, canShare, and owner.
list-events
Lists calendar events within a date/time range. Uses Microsoft's calendarView endpoint, which automatically expands recurring event series into their individual instances within the range. Results are sorted by start time.
Use this tool to answer questions like "What's on my calendar this week?" or "Do I have any meetings tomorrow afternoon?" Follow up with get-event on any event ID to retrieve full details.
Parameters:
| Param | Required | Type | Description |
|---|---|---|---|
startDateTime |
Yes | string | Start of the time range in ISO 8601 format (e.g., 2025-03-01T00:00:00Z) |
endDateTime |
Yes | string | End of the time range in ISO 8601 format (e.g., 2025-03-31T23:59:59Z) |
calendarId |
No | string | Calendar ID from list-calendars. Defaults to the primary calendar. |
top |
No | number | Maximum number of events to return (default: 25, max: 100) |
Returns: Array of event summaries including subject, start/end times with time zones, location, organizer, attendees with response status, isAllDay, isCancelled, isOnlineMeeting, onlineMeetingUrl, webLink, showAs, importance, isRecurring, and your own myResponse.
Tip: All date/time values should include a timezone offset or use UTC (Z suffix). The response includes time zone information for each event so you can display times correctly.
get-event
Retrieves the full details of a single calendar event by its ID. This returns significantly more data than list-events, including the full HTML body, all locations, online meeting join details, recurrence patterns, categories, attachment indicators, and audit timestamps.
Use this after list-events when you need the complete body content, the Teams join URL, or the recurrence configuration.
Parameters:
| Param | Required | Type | Description |
|---|---|---|---|
eventId |
Yes | string | The event ID (obtained from list-events or create-event) |
calendarId |
No | string | Calendar ID. Defaults to the primary calendar. |
Returns: Full event object including body (HTML), locations[], onlineMeeting (join URL, conference ID, toll numbers), recurrence (pattern + range), categories[], hasAttachments, seriesMasterId, type (singleInstance/occurrence/exception/seriesMaster), createdDateTime, and lastModifiedDateTime.
create-event
Creates a new calendar event with full control over all properties. Supports plain events, all-day events, events with attendees (which automatically send invitations), Teams online meetings, recurring events, and custom reminders.
After creating an event, the full created event object is returned, including the server-assigned id and any auto-generated fields like the Teams meeting URL.
Parameters:
| Param | Required | Type | Default | Description |
|---|---|---|---|---|
subject |
Yes | string | - | Event title |
startDateTime |
Yes | string | - | Start in ISO 8601 (e.g., 2025-03-15T09:00:00) |
endDateTime |
Yes | string | - | End in ISO 8601 (e.g., 2025-03-15T10:00:00) |
body |
No | string | - | Event description (HTML supported) |
startTimeZone |
No | string | UTC |
IANA time zone (e.g., America/New_York, Europe/London) |
endTimeZone |
No | string | UTC |
IANA time zone for end |
location |
No | string | - | Location display name (e.g., "Conference Room A") |
attendees |
No | array | - | List of { email, name?, type? } (type: required/optional/resource) |
isAllDay |
No | boolean | false |
All-day event (start/end should be date-only, e.g., 2025-03-15T00:00:00) |
isOnlineMeeting |
No | boolean | false |
Set true to auto-create a Teams meeting with join link |
showAs |
No | enum | busy |
free, tentative, busy, oof, workingElsewhere, unknown |
importance |
No | enum | normal |
low, normal, high |
sensitivity |
No | enum | normal |
normal, personal, private, confidential |
categories |
No | string[] | - | Color category labels |
reminderMinutesBeforeStart |
No | number | 15 |
Reminder timing in minutes |
calendarId |
No | string | - | Target calendar ID. Defaults to the primary calendar. |
recurrence |
No | object | - | Recurrence pattern and range (see below) |
Recurrence object structure:
{
"pattern": {
"type": "weekly",
"interval": 1,
"daysOfWeek": ["monday", "wednesday", "friday"]
},
"range": {
"type": "endDate",
"startDate": "2025-03-15",
"endDate": "2025-06-15"
}
}
- Pattern types:
daily,weekly,absoluteMonthly,relativeMonthly,absoluteYearly,relativeYearly - Range types:
endDate(withendDate),noEnd(runs forever),numbered(withnumberOfOccurrences) - For
weekly: usedaysOfWeek. ForabsoluteMonthly: usedayOfMonth. ForrelativeMonthly: usedaysOfWeek+index(first,second,third,fourth,last).
Tip: When adding attendees, Microsoft automatically sends invitation emails. Set isOnlineMeeting: true to include a Teams join link in the invitation.
update-event
Updates an existing calendar event using partial update (PATCH) semantics. Only the fields you provide are modified; all other fields remain unchanged. This is safe to use when you only need to change one property (e.g., updating just the subject or moving the time).
If the event has attendees, Microsoft sends update notifications automatically when relevant fields change (time, location, etc.).
Parameters:
| Param | Required | Type | Description |
|---|---|---|---|
eventId |
Yes | string | The ID of the event to update |
calendarId |
No | string | Calendar ID. Defaults to the primary calendar. |
All other parameters are the same as create-event (subject, body, startDateTime, endDateTime, location, attendees, etc.) but all are optional. Only include the fields you want to change.
Returns: The full updated event object.
Tip: To reschedule, provide both startDateTime and endDateTime together. To update attendees, provide the complete attendee list (it replaces the existing list, not appends).
delete-event
Permanently deletes a calendar event. If the authenticated user is the organizer and the event has attendees, Microsoft automatically sends cancellation notices to all attendees.
This action cannot be undone. The event is moved to the Deleted Items folder.
Parameters:
| Param | Required | Type | Description |
|---|---|---|---|
eventId |
Yes | string | The ID of the event to delete |
calendarId |
No | string | Calendar ID. Defaults to the primary calendar. |
Returns: Confirmation message.
respond-event
Responds to a calendar event invitation that someone else organized. You can accept, tentatively accept, or decline. Optionally include a message visible to the organizer, and control whether a response email is actually sent.
Use this after finding an event via list-events where your myResponse is none or notResponded.
Parameters:
| Param | Required | Type | Default | Description |
|---|---|---|---|---|
eventId |
Yes | string | - | The ID of the event to respond to |
response |
Yes | enum | - | accept, tentativelyAccept, or decline |
comment |
No | string | - | Message to include with the response (visible to the organizer) |
sendResponse |
No | boolean | true |
Set false to update your status silently without notifying the organizer |
Returns: Confirmation message.
find-meeting-times
Finds available meeting times for a group of attendees using Microsoft's scheduling intelligence. This queries each attendee's calendar availability and suggests optimal time slots where everyone (or the most people) can meet.
This is particularly useful for scheduling meetings with multiple people without manually checking each person's calendar. Use the suggested time slots with create-event to book the meeting.
Parameters:
| Param | Required | Type | Default | Description |
|---|---|---|---|---|
attendees |
Yes | array | - | List of { email, name?, type? } to check availability for |
startDateTime |
Yes | string | - | Start of the search window in ISO 8601 |
endDateTime |
Yes | string | - | End of the search window in ISO 8601 |
durationMinutes |
No | number | 30 |
Desired meeting length in minutes |
maxCandidates |
No | number | 5 |
Maximum number of time suggestions to return |
isOrganizerOptional |
No | boolean | false |
If true, suggestions may include times when the organizer is busy |
meetingTimeZone |
No | string | UTC |
Time zone for the suggestions (e.g., America/Chicago) |
Returns: Meeting time suggestions from Microsoft's scheduling engine, including the proposed time slots, attendee availability for each slot, and a confidence score.
Tip: The search window should be at least a few days wide to get good results. The attendees must be in the same Microsoft 365 organization (or federated) for availability lookup to work.
Typical Workflow
list-calendars- Discover available calendars and their IDslist-events- Browse events in a date range on a specific calendarget-event- Drill into a specific event for full details (body, Teams link, recurrence)find-meeting-times- Find a slot that works for everyone, then...create-event- Book the meeting with attendees and a Teams linkupdate-event- Reschedule or modify the event laterrespond-event- Accept or decline meetings others have invited you todelete-event- Cancel a meeting you organized
Development
# Install dependencies
npm install
# Build
npm run build
# Run in development mode
npm run dev
License
MIT
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.