event
cmdhub adapter

Microsoft Calendar CLI
for cmdhub.

Outlook calendars, events, free/busy windows, and open slots through Microsoft Graph.

lock Auth: OAuth2
Quick Install cmdhub get mscal

data_object Agent Contract

Agents should start with auth/status and discovery commands, inspect schemas before composition, and treat commands marked as mutating as state-changing operations.

Output

Use human output for normal reads, `--json` for scripting or complete structured fields, and `--jsonl` for upstream pipe inputs.

Auth

Microsoft OAuth. Used for Outlook calendars, events, and availability.

Refs

Prefer list/search, then short refs or piped JSONL. Use `resolve` to inspect cached refs.

Schemas

Use `mscal schema` and `catalog.json` to inspect fields, flags, examples, and side effects.

Auth scopes

offline_accessUser.ReadCalendars.ReadWrite

terminal Command Reference

Generated from source. Global flags apply to all commands.

Global Flags

--json bool Emit JSON machine output
--jsonl bool Emit JSONL records for piping
--output, -o string Compatibility output mode: json|jsonl. Prefer --json or --jsonl
--view string = summary View mode: summary|full
--profile string = default Config/auth profile
--config string Config path override
--quiet, -q bool Suppress non-essential diagnostics
--debug bool Enable debug diagnostics
--limit int = 50 Maximum items to emit
--page-size int = 50 Requested upstream page size
--cursor string Continuation cursor
--no-paginate bool Fetch only one page
--version, -v bool Print version information
mscal attachment Manage event attachments
#cmd-mscal-attachment discovery safe
$ mscal attachment --help
mscal attachment add Add a file attachment to an event
#cmd-mscal-attachment-add mutates state
--calendar string Optional calendar selector
--content-type string Attachment MIME type
--event string Event ref or provider ID
--file string File to upload
--name string Attachment display name
--yes, -y bool Confirm attachment upload
$ mscal attachment add --event e1 --file agenda.pdf --name "Agenda.pdf" --content-type application/pdf --yes
$ mscal attachment add --event e1 --file agenda.pdf --yes
$ mscal attachment add --help
mscal attachment delete Delete an attachment
#cmd-mscal-attachment-delete mutates state dry-run
--calendar string Optional calendar selector
--dry-run bool Preview attachment deletion without deleting
--event string Event ref or provider ID when not using an attachment local ref
--yes, -y bool Confirm attachment delete
$ mscal attachment delete --event e1 AAMk... --yes
$ mscal attachment delete --help
$ mscal attachment delete a1 --dry-run
$ mscal attachment delete a1 --yes
mscal attachment download Download an attachment
#cmd-mscal-attachment-download discovery safe
--calendar string Optional calendar selector
--event string Event ref or provider ID when not using an attachment local ref
--output-file string Path to write attachment bytes
$ mscal attachment download
$ mscal attachment download --event e1 AAMk... --output-file agenda.pdf
$ mscal attachment download a1 --output-file agenda.pdf
mscal attachment get Get an attachment
#cmd-mscal-attachment-get discovery safe
--calendar string Optional calendar selector
--event string Event ref or provider ID when not using an attachment local ref
$ mscal attachment get
$ mscal attachment get a1
$ mscal attachment get a1 --view full
mscal attachment list List attachments for an event
#cmd-mscal-attachment-list discovery safe
--calendar string Optional calendar selector
--event string Event ref or provider ID
$ mscal attachment list
$ mscal attachment list --event e1
$ mscal attachment list --event e1 --view full
mscal auth Manage Microsoft Outlook Calendar authentication
#cmd-mscal-auth discovery safe

Manage Microsoft Outlook Calendar OAuth credentials for the selected cmdhub profile.

mscal uses Microsoft OAuth device-code login. Login displays https://microsoft.com/devicelogin with a one-time code, waits for Microsoft authorization, and stores the Microsoft Graph refresh/access token in the shared cmdhub credential backend for the selected profile. It never asks for a normal Microsoft account password and never prints tokens.

Use –profile for one command or mscal profile use to change the default profile. Required delegated scopes are offline_access, User.Read, and Calendars.ReadWrite.

Recovery commands: mscal auth status mscal auth login mscal auth whoami mscal doctor

$ mscal auth --help
mscal auth login Authenticate with Microsoft Outlook Calendar
#cmd-mscal-auth-login mutates state

Start Microsoft OAuth device-code login for Microsoft Outlook Calendar.

The command displays https://microsoft.com/devicelogin with a one-time code. Sign in with the intended Microsoft account and approve delegated Microsoft Graph scopes offline_access, User.Read, and Calendars.ReadWrite. Do not paste a normal Microsoft account password, access token, refresh token, client secret, cookie, or private key into mscal.

The packaged CLI embeds a public Microsoft native-client ID. Local development can override it with CMDHUB_MSCAL_CLIENT_ID only when testing a different public/native app registration.

Recovery commands: mscal auth status mscal auth login mscal auth whoami mscal doctor

$ mscal auth login
$ mscal auth login --help
$ mscal auth status
$ mscal auth whoami
mscal auth logout Remove stored Microsoft OAuth device-code credentials
#cmd-mscal-auth-logout mutates state
Remove the selected profile’s stored Microsoft OAuth device-code refresh/access token from the shared cmdhub credential backend.
$ mscal auth login
$ mscal auth logout
$ mscal auth logout --help
mscal auth refresh Refresh stored token
#cmd-mscal-auth-refresh mutates state
Refresh the selected profile’s stored Microsoft OAuth access token from the shared cmdhub credential backend. If refresh fails or required scopes are missing, rerun mscal auth login.
$ mscal auth refresh
$ mscal auth refresh --help
$ mscal auth status
mscal auth status Show auth status
#cmd-mscal-auth-status discovery safe

Report Microsoft Outlook Calendar auth readiness for the selected profile.

Status checks whether the shared cmdhub credential backend has Microsoft OAuth device-code credentials, whether refresh succeeds, whether the required delegated scopes are present, and whether the profile is ready for Microsoft Graph Calendar commands.

If credentials are missing, expired, underscoped, or tied to the wrong Microsoft account, rerun mscal auth login for the same –profile and then mscal doctor.

$ mscal auth status
$ mscal auth status --help
$ mscal auth status --json
$ mscal auth status --view full
mscal auth whoami Show current calendar identity
#cmd-mscal-auth-whoami discovery safe

Show the Microsoft identity bound to the selected mscal profile.

The command verifies the stored Microsoft OAuth token against Microsoft Graph /me and reports the account details available for the selected profile. Use mscal auth status for credential storage, scope, token-refresh, and provider-readiness details.

$ mscal auth whoami
$ mscal auth whoami --help
$ mscal auth whoami --json
mscal calendar Manage calendars
#cmd-mscal-calendar discovery safe
$ mscal calendar --help
mscal calendar get Get a calendar
#cmd-mscal-calendar-get discovery safe
$ mscal calendar get
$ mscal calendar get c1
$ mscal calendar get c1 c2
$ mscal calendar get primary --view full
$ mscal calendar list --jsonl | mscal calendar get
mscal calendar list List calendars
#cmd-mscal-calendar-list discovery safe
$ mscal calendar list
$ mscal calendar list --jsonl | mscal calendar get
$ mscal calendar list --view full
mscal capabilities Describe mscal capabilities, scopes, output modes, and schemas
#cmd-mscal-capabilities discovery safe

Describe mscal capabilities, scopes, schemas, and the command contract.

The default machine output includes the full command contract so help, schemas, guidance, and conformance use the same inventory. Use –section for focused human or JSON views of scopes, schemas, or command paths.

--section string Focused section: scopes, schemas, or commands
$ mscal capabilities
$ mscal capabilities --help
$ mscal capabilities --json
$ mscal capabilities --section scopes
mscal category Inspect Outlook calendar categories
#cmd-mscal-category discovery safe
$ mscal category --help
mscal category get Get a category
#cmd-mscal-category-get discovery safe
$ mscal category get
$ mscal category get "Red category" --view full
$ mscal category get cat1
mscal category list List categories
#cmd-mscal-category-list discovery safe
$ mscal category list
$ mscal category list --view full
mscal config Inspect local configuration
#cmd-mscal-config discovery safe
$ mscal config --help
mscal config explain Explain resolved configuration
#cmd-mscal-config-explain discovery safe
$ mscal config explain --help
mscal doctor Run mscal diagnostics
#cmd-mscal-doctor discovery safe
$ mscal doctor
$ mscal doctor --help
$ mscal doctor --view full
mscal event Manage calendar events
#cmd-mscal-event discovery safe
$ mscal event --help
mscal event accept Respond to an event invitation
#cmd-mscal-event-accept discovery safe
--calendar string Optional calendar selector
--comment string Response comment
--send-response bool Send response message to organizer
$ mscal event accept --help
$ mscal event accept e1 --comment "Thanks" --send-response
mscal event cancel Cancel a meeting and notify attendees
#cmd-mscal-event-cancel discovery safe dry-run
--calendar string Optional calendar selector
--comment string Cancellation message
--dry-run bool Preview event cancellation without notifying attendees
--yes, -y bool Confirm cancellation notification
$ mscal event cancel --help
$ mscal event cancel e1 --comment "No longer needed" --dry-run
$ mscal event cancel e1 --comment "No longer needed" --yes
$ mscal event search --query planning --jsonl | mscal event cancel --comment "No longer needed" --yes
mscal event create Create an event
#cmd-mscal-event-create mutates state

Create a timed or all-day event.

Time fields accept natural values such as “tomorrow 14:00”, relative values such as +1h, or RFC3339 timestamps such as 2026-05-30T14:00:00+02:00. Use –duration with –start for the common RFC3339 + duration + location shape. Timed events without –end or –duration default to 30 minutes.

Adding –attendee or –optional-attendee creates a Microsoft meeting and sends provider invitations. Pass –send-invites to confirm that external effect.

--all-day bool All-day event
--attendee stringArray = [] Required attendee email; repeat for multiple attendees
--calendar string = primary Calendar selector
--category stringArray = [] Existing Outlook category name; repeat for multiple categories
--description string Description
--duration string Duration
--end string Event end
--location string Location
--online-meeting bool Request a provider online meeting link when supported
--optional-attendee stringArray = [] Optional attendee email; repeat for multiple attendees
--recurrence string Provider recurrence payload or rule
--reminder string Reminder before start, for example 15m
--send-invites bool Confirm that attendee flags send Microsoft meeting invitations
--show-as string Show-as state: free, tentative, busy, oof, workingElsewhere
--start string Event start
--timezone string Event time zone
--title string Event title
--transaction-id string Idempotency transaction ID for create
--yes, -y bool Accepted for compatibility; this command is already non-interactive
$ mscal event create --calendar c1 --title "Planning" --start 2026-05-30T14:00:00+02:00 --duration 45m --location "Room 4"
$ mscal event create --help
$ mscal event create --title "Company holiday" --start 2026-05-01 --all-day
$ mscal event create --title "Interview" --start +2h --duration 45m --attendee alex@example.com --send-invites
$ mscal event create --title "Project review" --start "tomorrow 14:00" --duration 45m
mscal event decline Respond to an event invitation
#cmd-mscal-event-decline discovery safe
--calendar string Optional calendar selector
--comment string Response comment
--send-response bool Send response message to organizer
$ mscal event decline --help
$ mscal event decline e1 --comment "Thanks" --send-response
mscal event delete Delete an event
#cmd-mscal-event-delete mutates state dry-run
--all bool Confirm batch event delete
--calendar string Optional calendar selector
--dry-run bool Preview event delete without deleting
--yes, -y bool Confirm destructive batch event delete
$ mscal event delete --all --yes e1 e2
$ mscal event delete --help
$ mscal event delete e1 --dry-run
$ mscal event delete e1 --yes
$ mscal event search --query cmdhub-human-audit --jsonl | mscal event delete --all --yes
mscal event get Get an event
#cmd-mscal-event-get discovery safe

Get event details by local ref, provider ID, or event JSONL from stdin.

When stdin contains event JSONL items from event list/search, event get consumes the item id/provider_id plus calendar_id fields, fetches current provider details, and renders the retrieved event. The get output is already the usable detail view; a second “mscal event get e1” call is only needed if you intentionally want to re-open a new local ref.

--calendar string Optional calendar selector
$ mscal event get
$ mscal event get e1
$ mscal event get e1 --view full
$ mscal event get e1 e2
$ mscal event list --today --jsonl | mscal event get
$ mscal event search --query audit --limit 1 --jsonl | mscal event delete --all --yes
$ mscal event search --query audit --limit 1 --jsonl | mscal event get
$ mscal event search --query audit --limit 1 --jsonl | mscal event update --location "Room 4"
mscal event list List events
#cmd-mscal-event-list discovery safe
--calendar string = primary Calendar selector
--from string Start time
--include-cancelled bool Include cancelled events
--to string End time; relative values such as +4h are relative to --from
--today bool Today window
--tomorrow bool Tomorrow window
--tz string Display time zone
--week bool Week window
$ mscal event list
$ mscal event list --calendar c1 --from now --to +72h
$ mscal event list --today
$ mscal event list --week --view full
mscal event quick-add Create an event from natural text
#cmd-mscal-event-quick-add mutates state
--calendar string = primary Calendar selector
--text string Quick-add text
--yes, -y bool Accepted for compatibility; this command is already non-interactive
$ mscal event quick-add --calendar c1 --text "Planning review today 3pm"
$ mscal event quick-add --help
$ mscal event quick-add --text "Lunch with Sam tomorrow 12pm"
mscal event tentatively-accept Respond to an event invitation
#cmd-mscal-event-tentatively-accept discovery safe
--calendar string Optional calendar selector
--comment string Response comment
--send-response bool Send response message to organizer
$ mscal event tentatively-accept --help
$ mscal event tentatively-accept e1 --comment "Thanks" --send-response
mscal event update Update an event
#cmd-mscal-event-update mutates state

Update event fields.

Adding or changing attendees creates or updates a Microsoft meeting and can send provider invitations or updates. Pass –send-updates all when using attendee or attendee-list flags so the notification behavior is explicit.

--add-attendee stringArray = [] Add required attendee email; repeat for multiple attendees
--all-day bool All-day event
--attendee stringArray = [] Required attendee email; repeat for multiple attendees
--calendar string Optional calendar selector
--cancel-online-meeting bool Remove online meeting state when provider-supported
--category stringArray = [] Existing Outlook category name; repeat for multiple categories
--clear-description bool Clear event description
--clear-location bool Clear event location
--clear-reminder bool Clear event reminder
--description string Description
--duration string Duration
--end string Event end
--location string Location
--online-meeting bool Request a provider online meeting link when supported
--optional-attendee stringArray = [] Optional attendee email; repeat for multiple attendees
--recurrence string Provider recurrence payload or rule
--reminder string Reminder before start, for example 15m
--remove-attendee stringArray = [] Remove attendee email; repeat for multiple attendees
--send-updates string Confirm attendee update notifications: all
--set-optional-attendee stringArray = [] Set optional attendee list; repeat for multiple attendees
--set-required-attendee stringArray = [] Set required attendee list; repeat for multiple attendees
--show-as string Show-as state: free, tentative, busy, oof, workingElsewhere
--start string Event start
--timezone string Event time zone
--title string Event title
--yes, -y bool Accepted for compatibility; this command is already non-interactive
$ mscal event search --query review --jsonl | mscal event update --location "Room 4"
$ mscal event update --help
$ mscal event update e1 --attendee alex@example.com --send-updates all
$ mscal event update e1 --start "tomorrow 15:00" --duration 30m
$ mscal event update e1 --title "Updated title"
mscal freebusy Inspect busy windows
#cmd-mscal-freebusy discovery safe
$ mscal freebusy --help
mscal freebusy get Get busy windows for calendars
#cmd-mscal-freebusy-get discovery safe
--calendar stringSlice = [primary] Calendar selectors
--from string Start time
--schedule stringSlice = [] User or resource schedule email to include; repeat or comma-separate
--to string End time; relative values such as +4h are relative to --from
--tz string Display time zone
$ mscal freebusy get
$ mscal freebusy get --calendar c1 --from today --to tomorrow --tz Africa/Johannesburg
$ mscal freebusy get --from "tomorrow 09:00" --to "tomorrow 17:00" --view full
$ mscal freebusy get --from now --to +4h
$ mscal freebusy get --schedule alex@example.com --from "tomorrow 09:00" --to "tomorrow 17:00"
mscal mcp Run the MCP server
#cmd-mscal-mcp discovery safe

Run a stdio Model Context Protocol server for this adapter.

The server exposes read-only resource commands by default. Mutating commands are listed only when explicitly allowed with –allow and remain gated by the command contract safety class.

--allow stringArray = [] Allow mutating command keys such as gmail.message.archive or gmail.message.label.*
--allow-dangerous bool Allow --allow wildcards to include destructive or sends_external commands
--concurrency int Maximum concurrent MCP subprocesses
--max-output int64 = 0 Maximum stdout/stderr bytes captured per MCP command
--print-config bool Print MCP tool configuration and exit
--timeout duration = 0s Per-command MCP subprocess timeout, for example 45s or 2m
$ mcp
$ mcp --print-config
mscal meeting-time Find Microsoft Graph meeting-time suggestions
#cmd-mscal-meeting-time discovery safe
$ mscal meeting-time --help
mscal meeting-time find Find meeting-time suggestions
#cmd-mscal-meeting-time-find discovery safe

Find Microsoft Graph meeting-time suggestions for attendees.

This uses Microsoft Graph findMeetingTimes. Some personal Microsoft accounts or tenants do not support this scheduling surface; in that case mscal returns a provider-limit recovery screen and suggests free/busy or event list fallbacks.

--attendee stringSlice = [] Required attendee email; repeat or comma-separate
--duration string = 30m Meeting duration
--from string Start time
--location string Preferred meeting location
--max-candidates int Maximum meeting-time candidates
--optional stringSlice = [] Optional attendee email; repeat or comma-separate
--required stringSlice = [] Required attendee email; repeat or comma-separate
--to string End time; relative values such as +4h are relative to --from
--tz string Display time zone
$ mscal meeting-time find
$ mscal meeting-time find --attendee alex@example.com --optional sam@example.com --from now --to +8h --max-candidates 5 --tz Africa/Johannesburg
$ mscal meeting-time find --required alex@example.com --from "tomorrow 09:00" --to "tomorrow 17:00" --duration 30m
mscal profile Manage provider profiles
#cmd-mscal-profile discovery safe
$ mscal profile --help
mscal profile create Create an unauthenticated provider profile
#cmd-mscal-profile-create mutates state
$ mscal profile create --help
mscal profile delete Delete a local provider profile
#cmd-mscal-profile-delete mutates state
$ mscal profile delete --help
mscal profile list List provider profiles
#cmd-mscal-profile-list discovery safe
$ mscal profile list --help
mscal profile rename Rename a local provider profile
#cmd-mscal-profile-rename discovery safe
$ mscal profile rename --help
mscal profile use Set the default provider profile
#cmd-mscal-profile-use mutates state
$ mscal profile use --help
mscal resolve Resolve a marker or short id
#cmd-mscal-resolve discovery safe
$ mscal resolve --help
$ mscal resolve c1
$ mscal resolve e1
$ mscal resolve u1
mscal schema Emit mscal schema hints
#cmd-mscal-schema discovery safe
--in bool Show input schema
--input bool Show input schema
--out bool Show output schema
$ mscal schema
$ mscal schema --help
$ mscal schema event.create --input
$ mscal schema event.create --out
mscal slot Find open slots
#cmd-mscal-slot discovery safe
$ mscal slot --help
mscal slot find Find open slots across calendars
#cmd-mscal-slot-find discovery safe
--calendar stringSlice = [primary] Calendar selectors
--duration string = 30m Minimum slot duration
--from string Start time
--to string End time; relative values such as +4h are relative to --from
--tz string Display time zone
$ mscal slot find
$ mscal slot find --calendar c1 --from today --to tomorrow --duration 1h --tz Africa/Johannesburg
$ mscal slot find --from "tomorrow 09:00" --to "tomorrow 17:00" --view full
$ mscal slot find --from now --to +4h --duration 30m
mscal version Show mscal version information
#cmd-mscal-version discovery safe
$ mscal version
$ mscal version --help
$ mscal version --json

play_circle Live Examples

Output captured from a real workspace. Regenerate with scripts/gen-docs.sh --update.

auth

Check current Microsoft calendar identity
$ mscal auth whoami
Authenticated as kestrelphilip@outlook.com

Next steps:
- Calendars:    mscal calendar list
- Events:       mscal event list --week
- Capabilities: mscal capabilities

diagnostics

Run diagnostics
$ mscal doctor
mscal doctor: WARN
Account: kestrelphilip@outlook.com
Checks: {id} ok, {id} warn, profiles ok, microsoft_oauth ok, token ok, scopes ok, mscal_api ok, local_timezone ok
CHECK                STATUS  DETAIL
{id}   OK      using file
{id}  WARN    credential backend stores local plaintext secrets
profiles             OK      active profile "kestrelphilip@outlook.com"
microsoft_oauth      OK      Microsoft Calendar OAuth client is configured
token                OK      token expires at 2026-06-13T17:56:58Z
scopes               OK      stored token covers required Microsoft Outlook Calendar scopes
mscal_api            OK      calendar API reachable
local_timezone       OK      Local

Next steps:
- Status:       mscal auth status
- Capabilities: mscal capabilities

calendars

List calendars
$ mscal calendar list --limit 5
REF  TITLE                  STATUS
c1   Calendar               primary, writer
c2   Birthdays              selected, reader
c3   South Africa holidays  selected, reader

Next steps:
- Open:      mscal calendar get c1
- Search:    mscal calendar search --query <text>
- Calendars: mscal calendar list
- Events:    mscal event list --week

events

List today's events
$ mscal event list --today --limit 5
Empty state
No event found.

Next steps:
- Search:    mscal event search --query <text>
- Create:    mscal event create
- Status:    mscal auth status
- Calendars: mscal calendar list
Search events
$ mscal event search --query eval --limit 5
Empty state
No event found.

Next steps:
- List:      mscal event list
- Create:    mscal event create
- Status:    mscal auth status
- Calendars: mscal calendar list

freebusy

Inspect busy windows
$ mscal freebusy get --calendar primary --from now --to +8h
Status: free
Busy windows
Field      Value
---------  -----
Window     Sat 13 Jun 18:57-Sun 14 Jun 02:57 Local
Calendars  primary

No busy intervals found.

Next steps:
- Find slots: mscal slot find --calendar primary --from 2026-06-13T16:57:35Z --to 2026-06-14T00:57:35Z --duration 30m
- Events:     mscal event list --calendar primary --from 2026-06-13T16:57:35Z --to 2026-06-14T00:57:35Z
- Calendars:  mscal calendar list

alt_route Composition Patterns

Bridge your ecosystem with zero middleware.

mscal auth login

# Review today's calendar and inspect one event
mscal event list --today --limit 10
mscal event get e1

# Search, inspect, and resolve through short refs
mscal event search --query "project review" --limit 1 --jsonl \
  | mscal event get

mscal resolve e1

# Create and clean up an event
mscal event create --title "Project review" --start "tomorrow 14:00" --duration 1h
mscal event delete e1 --dry-run
mscal event delete e1 --yes