npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@jeffreyhaen/msgraph-axi

v0.2.0

Published

Agent-ergonomic TOON wrapper for Microsoft Graph — Outlook mail and calendar on top of the CLI for Microsoft 365

Readme

msgraph-axi (Microsoft Graph axi)

ci npm license node

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:

  1. Automatic setup (quickest): Run m365 setup and choose Create a new app registration. It registers an app with the CLI presets and stores the App ID in your local config.

  2. 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.Read so calendar --timezone can 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>"

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 [email protected] | free/busy via getSchedule, availabilityView plus a code legend | | calendar suggest --attendees [email protected] --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 --execute alone: mail send --execute saves a draft and --send --execute delivers 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/--end accept 2026-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

  1. Move the Unreleased section in CHANGELOG.md under ## [x.y.z] - <date>.
  2. Bump version in package.json and VERSION in src/version.ts.
  3. 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