Skip to content
Development
Skill

/calendar

Exchange Online calendars through Microsoft Graph: event retrieval and date-range queries, free/busy and availability lookup, meeting and Teams-meeting creation, room and equipment resource bookings, calendar permissions, and the Graph scopes and error causes involved.

From plugin
msp-claude-plugins
52200 skills146 agents200 commands4 MCP

Claude Code

$ npx -y skills add wyre-ai/msp-claude-plugins --skill calendar --agent claude-code

SKILL.md

calendar.SKILL.md
name: "Microsoft 365 Calendar"
description: >
  Exchange Online calendars through Microsoft Graph: event retrieval and
  date-range queries, free/busy and availability lookup, meeting and Teams-meeting
  creation, room and equipment resource bookings, calendar permissions, and the
  Graph scopes and error causes involved.
when_to_use: >-
  When viewing events, finding free/busy times, creating meetings, managing room bookings, or
  checking a user's schedule. Use when: m365 calendar, outlook calendar, calendar events m365,
  meeting schedule m365, find availability m365, room booking m365, m365 free busy, teams meeting
  create, or calendar permissions.

Microsoft 365 Calendar Management

Overview

Microsoft 365 calendar is powered by Exchange Online and surfaced through Microsoft Graph. For MSPs, calendar tasks include troubleshooting scheduling issues, creating meetings on behalf of users, managing room resources, and checking user availability during support incidents.

Anti-triggers

"Schedule a meeting" routes three different ways depending on who picks the time. Here, *you* pick it and write the event straight into a mailbox:

  • **The customer picks the slot from a booking link** — a self-service

scheduling request tied to a PSA ticket is what TimeZest is for; use the `timezest` plugin (`timezest-scheduling`). Writing the event directly here bypasses the PSA workflow and the customer's choice.

  • **Dispatching a technician to a job** — an onsite visit or service

window is a PSA service call, which carries the billing and dispatch record a calendar event does not; use the `autotask` plugin (`autotask-service-calls`) or the equivalent PSA plugin.

  • **The same calendar work across many tenants** — use the `cipp`

plugin.

Note also that a TimeZest "resource" is a technician or team, while a resource here is a room or equipment mailbox — they are not the same object.

Graph API Patterns

Get a User's Calendar Events

GET /v1.0/users/{userId}/calendar/events?$select=id,subject,start,end,organizer,attendees,isOnlineMeeting,location&$orderby=start/dateTime&$top=10

Get Events in a Date Range

GET /v1.0/users/{userId}/calendarView?startDateTime=2024-01-15T00:00:00Z&endDateTime=2024-01-22T00:00:00Z&$select=subject,start,end,organizer,attendees,isOnlineMeeting

> Use `calendarView` (not `/events`) for date-range queries — it correctly expands recurring events.

Check Free/Busy Time

Get availability for a set of users:

POST /v1.0/users/{userId}/calendar/getSchedule
Content-Type: application/json

{
  "schedules": ["user1@contoso.com", "user2@contoso.com"],
  "startTime": { "dateTime": "2024-01-20T08:00:00", "timeZone": "Eastern Standard Time" },
  "endTime":   { "dateTime": "2024-01-20T17:00:00", "timeZone": "Eastern Standard Time" },
  "availabilityViewInterval": 30
}

**Response:**

{
  "value": [
    {
      "scheduleId": "user1@contoso.com",
      "availabilityView": "000022220000",
      "scheduleItems": [
        {
          "status": "busy",
          "start": { "dateTime": "2024-01-20T10:00:00" },
          "end":   { "dateTime": "2024-01-20T11:00:00" }
        }
      ]
    }
  ]
}

`availabilityView` is a string where each character represents a 30-min slot: `0`=free, `1`=tentative, `2`=busy, `3`=out-of-office, `4`=working elsewhere.

Create a Meeting (with Teams Link)

POST /v1.0/users/{organizerId}/events
Content-Type: application/json

{
  "subject": "IT Onboarding — Jane Smith",
  "start": { "dateTime": "2024-01-20T10:00:00", "timeZone": "Eastern Standard Time" },
  "end":   { "dateTime": "2024-01-20T11:00:00", "timeZone": "Eastern Standard Time" },
  "attendees": [
    { "emailAddress": { "address": "jsmith@contoso.com" }, "type": "required" },
    { "emailAddress": { "address": "itadmin@contoso.com" }, "type": "required" }
  ],
  "isOnlineMeeting": true,
  "onlineMeetingProvider": "teamsForBusiness",
  "body": { "contentType": "HTML", "content": "<p>IT onboarding session agenda...</p>" }
}

Get Room Resources

GET /v1.0/places/microsoft.graph.room?$select=id,displayName,emailAddress,capacity,building,floorNumber

Check Room Availability

Use `getSchedule` with the room's email address as a schedule ID (same as users above).

Cancel an Event

POST /v1.0/users/{userId}/events/{eventId}/cancel
Content-Type: application/json

{
  "comment": "Meeting has been rescheduled. New invite to follow."
}

Update an Event

PATCH /v1.0/users/{userId}/events/{eventId}
Content-Type: application/json

{
  "subject": "Updated: IT Onboarding — Jane Smith",
  "start": { "dateTime": "2024-01-21T14:00:00", "timeZone": "Eastern Standard Time" },
  "end":   { "dateTime": "2024-01-21T15:00:00", "timeZone": "Eastern Standard Time" }
}

Common MSP Workflows

Find Available Meeting Time

1. Get list of required attendees 2. Call `getSchedule` for all attendees + desired room 3. Parse `availabilityView` strings to find overlapping free slots 4. Return top 3 options within the user's working hours

Out-of-Office and Calendar Coordination

When setting OOO (via mailbox settings), also check if the user has events during their absence:

1. Get events in the OOO date range 2. List events with other attendees — these may need cancellation or reassignment 3. Cancel/update events as needed 4. Set OOO via mailbox settings

Recurring Event Management

Recurring events are expanded in `calendarView` results. Each instance has:

  • `seriesMasterId` — the master recurring event ID
  • `type: "occurrence"` — individual instance
  • `type: "seriesMaster"` — the template

To update all future instances: `PATCH` the series master. To update only one instance: `PATCH` the specific occurrence.

Error Handling

| Error | Cause | Resolution | |-------|-------|------------| | `ErrorCalendarNotFound` | User has no calendar (no Exchange license) | Assign Excha

Read more
@wyre-technology
Ships withmsp-claude-plugins

One command to supercharge Claude Code for MSP workflows. Then restart Claude Code. That's it. Documentation: mcp.wyre.ai

52200 skills146 agents4 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
52
Star history of wyre-technology/msp-claude-plugins on GitHub, a chart by star-history.com

Other skills on msp-claude-plugins.

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills13d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react4d252k
@facebook@facebookInstall Skill

Questions about calendar.

Which coding agents can use calendar?
calendar installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.