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-runon 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:
mgsships its own registered multi-tenant Entra app ("mgs CLI"), somgs auth loginneeds no setup. Organizations can bring their own app viaMGS_CLIENT_ID. For unattended/server/CI use, setMGS_AUTHfor 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)
| File | Size | Uploaded | |
|---|---|---|---|
| mgs_cli-0.8.3.tar.gz | 100.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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}
|