Skip to main content
Glama

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

  1. Go to the Azure Portal > Azure Active Directory > App registrations

  2. 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)

  3. After creation, note the Application (client) ID and Directory (tenant) ID

  4. Go to API permissions > Add a permission > Microsoft Graph > Delegated permissions

  5. Add the following permissions:

    • Calendars.ReadWrite

    • Calendars.Read

    • User.Read

  6. 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 (with endDate), noEnd (runs forever), numbered (with numberOfOccurrences)

  • For weekly: use daysOfWeek. For absoluteMonthly: use dayOfMonth. For relativeMonthly: use daysOfWeek + 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

  1. list-calendars - Discover available calendars and their IDs

  2. list-events - Browse events in a date range on a specific calendar

  3. get-event - Drill into a specific event for full details (body, Teams link, recurrence)

  4. find-meeting-times - Find a slot that works for everyone, then...

  5. create-event - Book the meeting with attendees and a Teams link

  6. update-event - Reschedule or modify the event later

  7. respond-event - Accept or decline meetings others have invited you to

  8. delete-event - Cancel a meeting you organized

Development

# Install dependencies npm install # Build npm run build # Run in development mode npm run dev

License

MIT

-
security - not tested
F
license - not found
-
quality - not tested

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/dcpurnell/m365calender-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server