msgraph-axi (Microsoft Graph axi)
September 13, 2026 · View on GitHub
Agent-ergonomic TOON wrapper for Microsoft Graph — Outlook mail and
calendar first, with a raw Graph bridge for everything else. Built on the
CLI for Microsoft 365 (m365) as a single
backend, following the AXI design principles.
Why AXI: CLI vs MCP vs AXI
Across extensive AXI benchmark studies (over 900 runs), agent-first CLIs achieve 100% task success at ~50% fewer turns and 50–66% lower cost than MCP:
| Interface | Context (Turn 0) | Output | Measured Payload | Write Safety | Guidance |
|---|---|---|---|---|---|
msgraph-axi | ~55 tokens (on-demand) | TOON | -62.0% avg (up to -77.8% on mail listings) | ✅ Dry-run by default; --execute / --confirm | Structured hints (help[]) |
Raw CLI (m365) | ~0 tokens | JSON / ASCII | Baseline (huge Graph OData payloads) | ❌ Direct mutations | Human text / exit codes |
| Graph MCP | ~25k–35k tokens (100+ schemas) | JSON-RPC | Highest overhead (full schemas resent every turn) | Varies | Schema validation errors |
Install & Setup
Install globally (recommended for repeated use):
npm install -g @jeffreyhaen/msgraph-axi @pnp/cli-microsoft365
For a one-off invocation without installing:
npx -y @jeffreyhaen/msgraph-axi --help
Agent integration
Install the skill globally so an agent loads the usage guide on demand:
npx skills add jeffreyhaen/msgraph-axi --skill msgraph-axi -g
Omit -g to install the skill for the current project only.
Initial Entra ID / M365 Setup
The underlying CLI for Microsoft 365 requires an Entra ID application registration in your tenant:
-
Automatic setup (quickest): Run
m365 setupand choose Create a new app registration. It registers an app with the CLI presets and stores the App ID in your local config. -
Existing or manual App Registration: If your organization already has an Entra app registered for CLI / developer use (or you create one manually):
- Set redirect URI (Public client/mobile & desktop):
https://login.microsoftonline.com/common/oauth2/nativeclient - Grant Delegated Microsoft Graph permissions:
Mail.ReadWrite,Mail.Send,Calendars.ReadWrite,User.Read(optional:MailboxSettings.Readsocalendar --timezonecan default to your mailbox time zone instead of this machine's) - Save the App ID and Tenant in your CLI config:
m365 cli config set --key clientId --value "<your-app-id>" m365 cli config set --key tenantId --value "<your-tenant-id>"
- Set redirect URI (Public client/mobile & desktop):
Then log in:
msgraph-axi auth login
msgraph-axi # dashboard
See docs/authentication.md for headless / CI flows and details.
Commands
| Command | Purpose |
|---|---|
auth status|login|logout | m365 sign-in state; device-code and headless logins (see Authentication) |
mail list [--folder] [--start] [--end] | messages with compact defaults |
mail read <id> [--full] | snippet by default, body with --full |
mail send ... [--execute] | dry-run without --execute; --execute saves a draft, --send --execute delivers it |
mail send --draft <id> [--execute] | deliver a saved draft |
mail delete <id> [--execute --confirm <id>] | destructive, double-gated |
mail search --search "..." | Graph message search |
mail draft --to ... [--execute] | save a draft, review, then mail send --draft |
mail thread <conversationId> | the whole conversation, oldest first |
mail attachment get <id> --message <id> [--out <path>] | download an attachment |
calendar list | calendars of the signed-in (or --user) account |
calendar agenda [--start] [--end] [--calendar] | events, default today..+7d |
calendar create | update [--execute] | events via the Graph REST bridge; --show-as free|tentative|busy|oof|workingElsewhere |
calendar cancel | delete [--execute --confirm <id>] | destructive, double-gated |
calendar availability --schedules a@x.com | free/busy via getSchedule, availabilityView plus a code legend |
calendar suggest --attendees a@x.com --duration 60 | meeting slot search via findMeetingTimes; confirm a slot with availability |
user get <upn> | profile plus manager lookup |
user search <term> | directory lookup by name, mail or upn prefix |
raw <path> [--method] [--body] [--execute] | any Graph endpoint through m365 request |
Conventions
- TOON on stdout, structured
{ error, code, help[] }errors on stdout. - Exit codes: 0 success (incl. no-ops), 1 runtime error, 2 usage error.
- Unknown flags rejected by name; lists take
--limit/--fields a,b; detail views truncate at 200 chars and lift with--full. - Read-only by default; writes require
--execute, destructive writes also--confirm <id>. - Mail is never delivered by
--executealone:mail send --executesaves a draft and--send --executedelivers it, so a wrong recipient or body stays fixable. - Long or multi-line payloads travel as JSON (through a temp file when needed): on
Windows the backend is spawned via
cmd.exe, which silently cuts an argument at a line break, so the CLI refuses such an argument instead of sending corrupt data. - Calendar reads and writes work in your mailbox time zone by default (Graph
mailboxSettings, then this machine's zone, then UTC); pass--timezone <tz>to override.--start/--endaccept2026-03-15, a wall clock in that zone (2026-03-15T13:00:00) or an offset (2026-03-15T13:00:00+02:00).
Development
pnpm install
pnpm test # vitest against a fake m365 fixture
pnpm typecheck
pnpm build
pnpm dev -- mail list # run against a real m365 login
Tests run against test/fixtures/m365-cli.js — no Microsoft 365 tenant required. Live
smoke tests need m365 login; the fixture can be pointed at with
MSGRAPH_AXI_M365_BIN.
Releasing
- Move the
Unreleasedsection inCHANGELOG.mdunder## [x.y.z] - <date>. - Bump
versioninpackage.jsonandVERSIONinsrc/version.ts. - Commit as
chore: release vX.Y.Z, then tag and push:
git tag -a vX.Y.Z -m "Release vX.Y.Z"
git push --follow-tags
Pushing the tag runs .github/workflows/release.yml: it builds, tests, publishes to
npm with provenance, and creates the GitHub release with the matching CHANGELOG.md
section as its body (scripts/release-notes.mjs). An existing release is left as is,
so the workflow can be re-run safely.
See also
- docs/authentication.md — every login flow with concrete commands
- AXI — agent eXperience interface · kunchenguid/axi
- TOON — token-optimized object notation · toonformat/toon
- CLI for Microsoft 365 — the backend
- Microsoft Graph — the platform