Skip to main content

mgs — One CLI for Microsoft 365

mgs is a fast Python CLI for Microsoft 365 — built for humans and AI agents. It builds its command surface dynamically from Microsoft Graph's CSDL metadata and covers Outlook mail & calendar, OneDrive/SharePoint files, Teams, Excel, OneNote, and directory users. It is the Microsoft counterpart to the gws Google Workspace CLI.

  • Structured JSON output on every command
  • --dry-run on every write; OData --select/--filter/--top/...; --page-all
  • Zero-setup browser login (Entra ID via MSAL); mgs schema <service> introspection
  • ~33 ms local overhead; one runtime dependency (msal)
  • Generated agent skills (SKILL.md + AGENTS.md) so any agent can drive it

Install

Requires Python 3.10+. The package is mgs-cli; the command it installs is mgs. Easiest via uv or pipx:

uv tool install mgs-cli        # or: pipx install mgs-cli   → provides the `mgs` command

Run without installing: uvx --from mgs-cli mgs --help.

From source:

git clone https://github.com/mr-illu-minati/mgs-cli && cd mgs-cli
uv tool install .                       # installs the `mgs` command globally
# or, for development:
uv sync && uv run mgs --help            # and: uv run pytest

Update with uv tool upgrade mgs-cli, remove with uv tool uninstall mgs-cli.

Quick start

mgs auth login                                   # browser sign-in (Entra ID)
mgs mail +triage --max 5
mgs calendar +agenda --week --timezone America/Toronto
mgs files +upload ./report.pdf --to /Documents
mgs mail +send --to you@example.com --subject Hi --body "It works"
mgs schema mail                                  # introspect a service

Login works out of the box: mgs ships its own registered multi-tenant Entra app ("mgs CLI"), so mgs auth login needs no setup. Organizations can bring their own app via MGS_CLIENT_ID. For unattended/server/CI use, set MGS_AUTH for app-only auth (client secret, workload identity federation, or managed identity). Details, scopes, and admin consent: docs/auth-production.md.

Commands

mail      list get create update delete  +send +read +reply +reply-all +forward +triage +watch +attachments
calendar  list get create update delete  +agenda +insert
files     list get create update delete  +upload +download
teams     list get create update delete  +send +channels +chats
excel     list get create update delete  +read +append
onenote   list get create update delete  +write
users     list get create update delete
auth login|logout|status   ·   schema <service>   ·   skills install   ·   generate-skills

Every service also accepts bound actions (e.g. mgs mail move <id> --json '{...}') and raw bodies via --json / --params. Discover anything with mgs <service> --help and mgs schema <service>.

Target mailbox (--mailbox)

By default commands run against the signed-in user (/me/). The global --mailbox <upn> flag retargets any command to another user's mailbox/drive/calendar (/users/<upn>/):

mgs mail +triage --mailbox assistant@contoso.com          # delegated: shared-mailbox access
MGS_AUTH=secret mgs mail list --mailbox user@contoso.com  # app-only: required (no /me/ context)

In app-only mode /me/ has no meaning, so a mailbox is required: pass --mailbox, or set MGS_DEFAULT_MAILBOX as a fallback. Without either, mgs fails fast with a usage error instead of sending a doomed Graph call. MGS_MAILBOX is the env twin of the flag (flag wins).

Related: mgs mail +send accepts --from <address> to send as a mailbox alias (requires the tenant's SendFromAliasEnabled) or another mailbox (requires Send As rights), and --header 'X-Name: value' (repeatable) for custom internet headers — Graph requires the X- name prefix.

Related: mgs mail +attachments <id> lists a message's attachments and, with --download <dir>, saves file attachments to disk (base64 decoded; only the basename of each attachment name is used, so a crafted name cannot escape the target folder).

Using mgs with AI agents (any platform)

mgs ships a generated, agent-agnostic skill set — no platform lock-in.

Install skills into a project

mgs skills install --dir /path/to/repo   # default targets: claude + agents
mgs skills install --target all          # claude + agents
mgs skills install --target cursor       # Cursor only
mgs skills install --global              # write to global skill dirs (~/.claude/skills etc.)
mgs skills install --prune               # also remove stale mgs-* skills from a previous version

The command is idempotent — re-running it when nothing changed reports added: 0. It never touches skill directories that don't start with mgs-.

Target directories

--target project dir global dir loaded by
claude (default) .claude/skills ~/.claude/skills Claude Code, GitHub Copilot, OpenCode
agents (default) .agents/skills ~/.agents/skills Cursor, OpenCode
cursor .cursor/skills ~/.cursor/skills Cursor
opencode .opencode/skills ~/.config/opencode/skills OpenCode

AGENTS.md

AGENTS.md at the repo root is the single agent-agnostic entry point read automatically by Codex, Cursor, Gemini CLI, Amp, Claude Code, and others. Generate or update it with:

mgs generate-skills --out skills   # writes skills/AGENTS.md; copy or symlink to repo root

The committed AGENTS.md at the root of this repo is kept up to date.

Low-level primitive

mgs generate-skills --out skills   # writes skills/<name>/SKILL.md + SKILLS.md + AGENTS.md

The recipient needs mgs installed and mgs auth login done once.

Performance

The 2.7 MB Graph $metadata is parsed at most once per 24 h and cached as compact per-EntityType JSON, so a typical command loads a few-KB file. MSAL is imported only when a token must be acquired or refreshed; a valid cached token skips it entirely.

Environment variables

Variable Purpose
MGS_TOKEN Pre-obtained Graph access token (highest priority)
MGS_CLIENT_ID / MGS_TENANT_ID Bring-your-own Entra app + tenant (default tenant: common)
MGS_SCOPES Delegated Graph scopes to request at login (space/comma-separated; default: all). Handy with a minimal BYO app.
MGS_CONFIG_DIR Config dir override (default ~/.config/mgs)
MGS_NO_BROWSER Use device-code login instead of the browser (headless/CI)
MGS_AUTH Auth mode: delegated (default), app-only, secret, workload, managed-identity — for unattended/server/CI use (details)
MGS_MAILBOX Target mailbox UPN for /me/-style commands (env twin of the global --mailbox flag)
MGS_DEFAULT_MAILBOX Fallback mailbox in app-only mode when --mailbox/MGS_MAILBOX is not given
AZURE_CLIENT_SECRET / MGS_CLIENT_SECRET App-only client secret (service principal)
AZURE_CLIENT_CERTIFICATE_PATH App-only certificate (PEM)
AZURE_FEDERATED_TOKEN_FILE App-only workload identity federation (OIDC) token file
AZURE_CLIENT_ID / AZURE_TENANT_ID Standard fallbacks

License

MIT — see LICENSE.

Metadata

Release files for mgs-cli 0.8.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mgs-cli 0.8.3
File Size Uploaded
mgs_cli-0.8.3.tar.gz 100.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mgs-cli 0.8.3
File Interpreter ABI Platform
mgs_cli-0.8.3-py3-none-any.whl Python 3 none any Details

Total release size: 148.8 kB

Release files / mgs_cli-0.8.3.tar.gz

Download URL mgs_cli-0.8.3.tar.gz
Size 100.0 kB
Tags Source
SHA-256 checksum
How to use checksums
2c3ccf418759e0218013f432749a95c4530cbe2efab804cb9f22bc4e9377fce3
BLAKE2b-256 checksum
How to use checksums
377a705fa994434f08410ccdeb7b969d38c7ad1280004708a91b9101f4e9d783
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.6 {"installer":{"name":"uv","version":"0.12.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / mgs_cli-0.8.3-py3-none-any.whl

Download URL mgs_cli-0.8.3-py3-none-any.whl
Size 48.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ef663e94e88ae50c0d81eb86a0105b020f5d85d41a2e21047fe0b604b7862287
BLAKE2b-256 checksum
How to use checksums
468be30e1d8da3cdc0b94c2ebc29d7ced0cf05e854622c76fee86da45a49a8e2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.6 {"installer":{"name":"uv","version":"0.12.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.8.3 This release

2 release files

0.8.2

2 release files

0.8.1

2 release files

0.8.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page