Open Source·AI Agent Infrastructure

Microsoft 365 in Your Terminal.

Mail. Calendar. OneDrive. Contacts. 25 commands. Every one doubles as an MCP tool.

Google shipped their Workspace CLI. Half the enterprise world runs Microsoft. So we built ms365-cli — the missing CLI for agents on the Microsoft stack.

Install from npm
25
Commands
4
Microsoft Services
CLI
+ MCP Native
OpenClaw
OpenClaw
CLI / MCP
Microsoft 365
mail · calendar · onedrive · contacts

Why ms365-cli Exists

Without ms365-cli

  • Agent needs a browser to check Outlook — impossible
  • Microsoft Graph API requires OAuth boilerplate every time
  • No way to wire M365 into an autonomous agent loop
  • Google has a CLI. Microsoft doesn’t. Until now.
  • Agents can’t send emails, book meetings, or search files

With ms365-cli

  • 25 commands covering Mail, Calendar, OneDrive, Contacts
  • MSAL device code auth — login once, tokens refresh silently
  • Every command is also an MCP tool — plug into any AI agent
  • JSON-first output — pipe to jq, save to files, feed to agents
  • 5-minute setup, MIT licensed, zero dependencies beyond MSAL

Quick Start

1. Install

Terminal
npm install -g ms365-cli

2. Register an Azure AD App (one-time)

1. Go to portal.azure.com → App registrations → New registration

2. Redirect URI: Mobile and desktophttp://localhost

3. API permissions: Mail.ReadWrite, Mail.Send, Calendars.ReadWrite, Files.ReadWrite, Contacts.ReadWrite, User.Read

4. Authentication → Allow public client flows → Yes

3. Login

Terminal
m365 login --client-id <your-app-id> --tenant-id <your-tenant-id>

Opens a device code flow — sign in once, tokens are cached and silently refreshed.

4. Verify

Terminal
m365 status --pretty
# {"authenticated":true,"account":"you@example.com"}

m365 mail unread-count
# {"folder":"Inbox","unread":4,"total":12}

What ms365-cli Gives Your Agent

8 cmds

Mail Management

List inbox, read messages, send email, reply, search with KQL, move, delete, and track unread counts.

5 cmds

Calendar & Meetings

List events, create meetings with Teams links, update, delete, and filter by date range. Full scheduling control.

5 cmds

OneDrive Access

Browse files, search across drives, download documents, get metadata, and delete items. Full file system control.

4 cmds

Contacts

List, search, get, and create Outlook contacts programmatically. Perfect for CRM sync workflows.

3 cmds

Attachments

Send emails with file attachments, list attachments on messages, and download any attachment type to disk.

MCP Server

Every command is exposed as an MCP tool. Claude, Cursor, OpenClaw, and any MCP client can call all 25 commands.

Agent Workflows

Real prompts agents use to manage Microsoft 365 end-to-end.

Morning Inbox Triage

Agent Prompt

Check my email for anything unread. Summarize the important ones, reply to the meeting request from Sarah, and archive the newsletters.

Agent checks unread count, pulls unread messages, classifies by priority, replies to actionable items, and moves low-priority mail — fully autonomous inbox management.

1
m365 mail unread-count

Check if new mail exists

2
m365 mail list --unread --top 20 --pretty

Pull all unread messages

3
m365 mail get $MESSAGE_ID

Read full message content

4
m365 mail reply $MESSAGE_ID --body "Confirmed, see you at 2pm."

Reply to the meeting request

5
m365 mail move $NEWSLETTER_ID --destination "Archive"

Archive low-priority mail

Schedule a Discovery Call

Agent Prompt

Schedule a discovery call with prospect@acme.com next Tuesday at 2pm EST. Include a Teams link and send a confirmation email.

Agent creates a calendar event with Teams meeting, adds the attendee, then sends a personalized confirmation email — booking + outreach in one autonomous flow.

1
m365 calendar create --subject "Discovery Call" --start 2026-03-10T14:00:00 --end 2026-03-10T15:00:00 --timezone "America/New_York" --attendees "prospect@acme.com" --online-meeting

Create meeting with Teams link

2
m365 mail send --to prospect@acme.com --subject "Discovery Call Confirmed" --body "Looking forward to connecting Tuesday at 2pm EST. Teams link: ..." --content-type html

Send confirmation email

Find and Download a Document

Agent Prompt

Search OneDrive for the Q1 quarterly report, download it, and email it to the finance team.

Agent searches OneDrive, identifies the right file, downloads it locally, and sends it as an email attachment — document retrieval + distribution automated.

1
m365 drive search "Q1 quarterly report"

Search OneDrive for the file

2
m365 drive download --id $FILE_ID --output-file ./q1-report.pdf

Download to local disk

3
m365 mail send --to finance@company.com --subject "Q1 Report" --body "Attached." --attachment ./q1-report.pdf

Email with attachment

Weekly Calendar Prep

Agent Prompt

Pull my calendar for next week. Identify any double-bookings or gaps. List all external meetings with attendees.

Agent pulls the full week of events, analyzes for conflicts, identifies external vs. internal meetings, and delivers a structured briefing — your weekly prep, automated.

1
m365 calendar list --start 2026-03-09T00:00:00Z --end 2026-03-13T23:59:59Z --pretty

Pull all events for the week

2
m365 calendar get $EVENT_ID

Get details on flagged events

3
m365 contacts search "Sarah Johnson"

Look up attendee details

Reply to Client Thread

Agent Prompt

Find the latest email from client@bigco.com, read the full thread, and draft a reply addressing their pricing question.

Agent searches mail by sender, reads the full conversation thread for context, and composes a contextual reply — your agent handles client communication.

1
m365 mail search "from:client@bigco.com"

Find messages from this sender

2
m365 mail get $MESSAGE_ID

Read the full thread

3
m365 mail reply $MESSAGE_ID --body "Thanks for your question on pricing..."

Send contextual reply

New Contact from LinkedIn

Agent Prompt

I just connected with Jane Smith, VP Sales at Acme Corp on LinkedIn. Add her to my Outlook contacts and send an intro email.

Agent creates a structured contact record in Outlook and sends a personalized introduction email — LinkedIn connection to CRM pipeline in one step.

1
m365 contacts create --given "Jane" --surname "Smith" --email "jane.smith@acme.com" --company "Acme Corp" --phone "+1-555-0123"

Create Outlook contact

2
m365 mail send --to jane.smith@acme.com --subject "Great connecting!" --body "Hi Jane, enjoyed connecting on LinkedIn..."

Send intro email

Commands Reference

Auth
m365 auth login [--client-id <id>] [--tenant-id <id>]Authenticate via device code flow
m365 auth logoutClear cached tokens
m365 auth statusShow authentication state
Mail (8 commands)
m365 mail list [--top <n>] [--folder <name>] [--filter <odata>] [--unread]List inbox messages
m365 mail get <id>Read a specific message
m365 mail send --to <emails> --subject <text> --body <text> [--attachment <files>]Send email with optional attachments
m365 mail reply <id> --body <text> [--reply-all]Reply to a message thread
m365 mail search <query>Search with KQL syntax
m365 mail move <id> --destination <folder>Move message between folders
m365 mail delete <id>Delete a message
m365 mail unread-count [--folder <name>]Get unread message count
Calendar (5 commands)
m365 calendar list [--start <iso>] [--end <iso>] [--top <n>]List events in a date range
m365 calendar get <id>Get event details
m365 calendar create --subject <text> --start <iso> --end <iso> [--attendees] [--online-meeting]Create event with optional Teams link
m365 calendar update <id> [--subject] [--start] [--end]Update an existing event
m365 calendar delete <id>Delete an event
OneDrive (5 commands)
m365 drive list [--folder-id <id>] [--top <n>]Browse files and folders
m365 drive get <id> | --path <path>Get file metadata
m365 drive search <query>Search across OneDrive
m365 drive download [id] [--path] [--output-file]Download file to disk
m365 drive delete <id>Delete a file or folder
Contacts (4 commands)
m365 contacts list [--top <n>] [--filter <odata>]List Outlook contacts
m365 contacts get <id>Get contact details
m365 contacts search <query>Search contacts
m365 contacts create --given <name> [--surname] [--email] [--phone] [--company]Create a new contact

MCP Server Setup

Every command is available as an MCP tool. Configure once and your agent has full Microsoft 365 access.

Claude Desktop / Cursor (~/.cursor/mcp.json or claude_desktop_config.json)
{
  "mcpServers": {
    "m365": {
      "command": "npx",
      "args": ["ms365-cli", "mcp"],
      "env": {
        "M365_CLIENT_ID": "your-azure-app-client-id"
      }
    }
  }
}

MCP tools registered:

mail_listmail_getmail_sendmail_replymail_searchmail_movemail_deletemail_unread_countcalendar_listcalendar_getcalendar_createcalendar_updatecalendar_deletedrive_listdrive_getdrive_searchdrive_downloaddrive_deletecontacts_listcontacts_getcontacts_searchcontacts_createauth_loginauth_logoutauth_status

OpenClaw Agent Setup

Give any OpenClaw agent full Microsoft 365 access. Install once, authenticate, and the agent handles everything via exec.

1
Install on the agent's server
npm install -g ms365-cli
2
Authenticate as the agent's email
m365 login --client-id <id> --tenant-id <id> — follow device code flow
3
Install skills into OpenClaw
ln -s /path/to/ms365-cli/skills/m365-* ~/.openclaw/skills/
4
Add email instructions to SOUL.md
Tell the agent how to check inbox, send mail, book meetings via m365 commands
5
Test from Slack
"Check my email and tell me what's unread" — agent calls m365 mail list via exec

Architecture

Every API endpoint is a CommandDefinition — one source of truth powering both the CLI subcommand and the MCP tool. Adding a new endpoint is one new file.

src/
├── core/
│   ├── types.ts      # CommandDefinition, GraphClient interfaces
│   ├── client.ts     # Graph API HTTP client (retry, rate limit, pagination)
│   ├── auth.ts       # MSAL device code flow + silent refresh
│   ├── config.ts     # ~/.m365/ config and token cache
│   ├── errors.ts     # Typed error classes
│   ├── output.ts     # JSON output + field filtering
│   └── handler.ts    # executeCommand (path/query/odata/body mapping)
├── commands/
│   ├── mail/         # 8 commands
│   ├── calendar/     # 5 commands
│   ├── drive/        # 5 commands
│   └── contacts/     # 4 commands
└── mcp/
    └── server.ts     # MCP server (auto-registers all commands as tools)

Same pattern as instantly-cli + clay-gtm-cli

The CommandDefinition architecture is shared across all TOFU CLIs. One schema definition generates the Commander.js subcommand, the Zod schema, and the MCP tool — zero duplication.

MSAL authentication

Device code flow for initial login. Tokens cached at ~/.m365/token-cache.json and silently refreshed via MSAL’s acquireTokenSilent. No browser needed after first auth.

Ready to give your agent Microsoft 365 superpowers?

Install ms365-cli, authenticate in 5 minutes, and your agent can read email, book meetings, search OneDrive, and manage contacts.

Need agents wired into your Microsoft 365 stack? We deploy and manage the full setup.