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

@sam2kb/m365-mcp

v1.0.6

Published

Production-grade Microsoft 365 MCP server — email, calendar, contacts, OneDrive, Teams, tasks, and users via delegated OAuth

Readme

m365-mcp

npm ClawHub

Production-grade Microsoft 365 MCP server — Email, Calendar, Contacts, OneDrive, Teams, Tasks, and Users via delegated OAuth.

Built from the best of both office365-connector (delegated OAuth, multi-account) and mcp-microsoft365 (MCP protocol, full scope), with all the gaps fixed: pagination, rate limiting, retry logic, proper timezone handling, and TypeScript throughout.

Why this exists

This comparison reflects the code shipped in mcp-microsoft365 v1.0.0 and office365-connector v2.0.0 as reviewed on July 18, 2026.

| Feature | mcp-microsoft365 | office365-connector | m365-mcp | |---|---|---|---| | Auth flow | Client credentials (app-only) | Device code + client secret | Public-client device code | | Access model | Application permissions (tenant-wide) | Delegated (signed-in user) | Delegated (signed-in user) | | Client secret | Required | Required and stored locally | None ✅ | | MCP server | ✅ | ❌ (CLI scripts) | ✅ | | Multi-account | ❌ | ✅ | ✅ | | Pagination | ❌ | ❌ | ✅ | | Graph 429 retries | ❌ | ❌ (not implemented in shipped code) | ✅ | | Read-only mode | ❌ | ❌ | ✅ | | Email | ✅ | ✅ | ✅ | | Calendar | ✅ | ✅ | ✅ | | Contacts | ❌ | ❌ (documented, not shipped) | ✅ | | OneDrive | ✅ | ❌ | ✅ | | Teams | ✅ | ❌ | ✅ | | Tasks | ✅ | ❌ | ✅ | | Users | ✅ | ❌ | ✅ | | Implementation | TypeScript | JavaScript CLI | TypeScript | | Interface coverage | 19 MCP tools | CLI scripts | 43 MCP tools |

m365-mcp does not store a client secret or password. Tenant and client IDs are non-secret identifiers; sensitive OAuth access and refresh tokens are stored locally as permission-restricted plaintext files. See Security for the storage and revocation details.

Scope

Delegated permissions — the app acts AS YOU, not as the tenant. It can only access YOUR data:

  • Mail.Read / Mail.ReadWrite / Mail.Send
  • Calendars.Read / Calendars.ReadWrite
  • Contacts.Read / Contacts.ReadWrite
  • Files.Read.All (your OneDrive)
  • Tasks.ReadWrite (To Do)
  • Chat.Read / Chat.ReadWrite (Teams)
  • User.Read + offline_access

These are delegated scopes, not tenant-wide application permissions. Set M365_MCP_READ_ONLY=true before authentication and when running the server to request only the read variants and disable mutating MCP tools.

Organization-wide mail application permissions such as Mail.Read.All are not used.

Setup

1. Create Azure Entra ID App Registration

  1. Go to Azure Portal → App registrations
  2. New registration
    • Name: m365-mcp
    • Supported account types: Single tenant (or multi-tenant if you manage your own tenant)
    • Redirect URI: leave this blank; device-code flow does not use one
  3. Click Register
  4. Go to AuthenticationAdvanced settings
  5. Set "Allow public client flows" to Yes, then click Save

This is required for device-code OAuth. Do not create or configure a client secret; m365-mcp is a public client.

2. Add API Permissions

Under API PermissionsAdd a permissionMicrosoft GraphDelegated permissions:

offline_access
User.Read
Mail.Read
Mail.ReadWrite
Mail.Send
Calendars.Read
Calendars.ReadWrite
Contacts.Read
Contacts.ReadWrite
Files.Read.All
Tasks.ReadWrite
Chat.Read
Chat.ReadWrite

Click Grant admin consent (or each user will consent individually during login).

Organization-wide user listing and lookup additionally requires delegated User.Read.All with admin consent. This broader scope is not requested by default.

3. Install

Install the published command-line tools:

npm install --global @sam2kb/m365-mcp

Or build from source:

# Clone
git clone https://github.com/sam2kb/m365-mcp.git
cd m365-mcp

# Install dependencies
npm install

# Build
npm run build

4. Add Your Account & Authenticate

m365-mcp-auth add work <tenant-id> <client-id> [email protected] "Work account"
m365-mcp-auth login --account=work

AADSTS7000218 or a missing client_secret / client_assertion error: Microsoft is treating the registration as a confidential client. Confirm that the configured Application (client) ID belongs to the registration you edited, then return to Authentication and verify Allow public client flows is saved as Yes. Do not work around this error by adding a client secret.

When running from a source checkout, use node dist/auth-cli.js instead of m365-mcp-auth.

Follow the on-screen URL + code to sign in. Access and refresh tokens are stored as plaintext JSON in ~/.m365-mcp/auth/ by default, protected with directory mode 0700 and file mode 0600 where supported. Set M365_MCP_AUTH_DIR to use another protected location.

5. Configure an MCP Client

The server uses standard MCP over stdio and works with any MCP client (Claude Desktop, Cursor, Continue, etc.).

OpenClaw

For the global npm installation, add this to your mcporter config at ~/.openclaw/mcporter.json:

{
  "mcpServers": {
    "m365": {
      "command": "m365-mcp",
      "args": [],
      "env": {
        "M365_ACCOUNT": "work",
        "M365_TIMEZONE": "America/Chicago"
      }
    }
  }
}

Or via mcporter CLI:

mcporter config add m365 --stdio "m365-mcp" \
  --env M365_ACCOUNT=work \
  --env M365_TIMEZONE=America/Chicago

For a source checkout, use "command": "node" with "args": ["/absolute/path/to/m365-mcp/dist/index.js"].

Then restart OpenClaw for the server to load.

Other MCP Clients

Use the same JSON config in your client's MCP server configuration — m365-mcp is a standard stdio MCP server with no client-specific requirements.

Multi-Account

# Add more accounts
node dist/auth-cli.js add personal <tenant2> <client2> [email protected] "Personal"
node dist/auth-cli.js add client <tenant3> <client3> [email protected] "Consulting"

# Authenticate each
node dist/auth-cli.js login --account=personal
node dist/auth-cli.js login --account=client

# Set default
node dist/auth-cli.js default work

# List
node dist/auth-cli.js list

Each account needs its own App Registration in its respective tenant. Tokens are isolated per account.

Available Tools (43)

📧 Mail (9 tools)

| Tool | Description | |---|---| | m365_mail_list | List emails (folder, filter, search, paginated) | | m365_mail_read | Read full email by ID | | m365_mail_send | Send email (to/cc/bcc, HTML or plain) | | m365_mail_reply | Reply / reply-all to an email | | m365_mail_search | Search emails across folders | | m365_mail_move | Move email to another folder | | m365_mail_delete | Delete email | | m365_mail_mark_read | Mark as read/unread | | m365_mail_folders | List all mail folders with counts |

📅 Calendar (7 tools)

| Tool | Description | |---|---| | m365_calendar_list | Events in a date range (paginated) | | m365_calendar_today | Today's events, nicely formatted | | m365_calendar_week | Week view grouped by day | | m365_calendar_create | Create event (optional Teams meeting) | | m365_calendar_update | Update event | | m365_calendar_delete | Cancel event with message | | m365_calendar_availability | Free/busy lookup |

👤 Contacts (11 tools)

| Tool | Description | |---|---| | m365_contacts_list | List by folder and filter by one or more exact categories (any/all) | | m365_contacts_search | Search by name, email, or company | | m365_contacts_read | Full contact details | | m365_contacts_create | Create with multiple emails, phones, categories, addresses, and work or personal details | | m365_contacts_update | Update or clear contact fields and category assignments | | m365_contacts_delete | Move a contact to Deleted Items | | m365_contacts_categories_list | List unique categories in the default or selected folder with usage counts | | m365_contacts_folders_list | List top-level or child contact folders | | m365_contacts_folder_create | Create a child contact folder | | m365_contacts_folder_update | Rename or move a contact folder | | m365_contacts_folder_delete | Delete a non-default contact folder |

Outlook categories are tags stored on each contact; contact folders are containers. Category filtering is exact and case-insensitive, supports any/all matching, and can be combined with folder selection. Folder tools manage top-level folders and one direct child level, keeping the interface predictable.

📁 OneDrive (5 tools)

| Tool | Description | |---|---| | m365_files_list | List files/folders (paginated) | | m365_files_search | Search files | | m365_files_read | Read text file content | | m365_files_info | File/folder metadata | | m365_files_create_folder | Create folder |

💬 Teams (3 tools)

| Tool | Description | |---|---| | m365_teams_chats | List your chats | | m365_teams_messages | Get chat messages | | m365_teams_send | Send chat message |

✅ Tasks (5 tools)

| Tool | Description | |---|---| | m365_tasks_lists | List To Do lists | | m365_tasks_list | List tasks in a list | | m365_tasks_create | Create task | | m365_tasks_update | Update task | | m365_tasks_delete | Delete task |

👥 Users (3 tools)

| Tool | Description | |---|---| | m365_users_list | List org users | | m365_users_profile | Get user profile | | m365_users_manager | Get user's manager |

Development

npm install
npm run dev    # tsx watch mode
npm run build  # compile TypeScript

Security

  • Delegated OAuth — the app acts as the authenticated user; it does not use application credentials or tenant-wide mail permissions.
  • Device code flow — you never type your password into anything but Microsoft's login page.
  • Sensitive reads — mail, files, calendar entries, contacts, Teams messages, tasks, and user profiles can enter the MCP client's model context.
  • Real side effects — send, reply, move, create, update, and delete tools change Microsoft 365 data. Configure your MCP client to require explicit user approval before it invokes them.
  • MCP safety annotations — every tool declares read-only, destructive, idempotent, and open-world hints for clients that enforce tool policies.
  • Enforced read-only mode — set M365_MCP_READ_ONLY=true both when authenticating and running the server. The auth flow requests read-only Graph scopes, mutating tools are omitted from discovery, and direct calls are blocked.
  • Local token storage — access and refresh tokens are plaintext JSON protected by 0700 directories and 0600 files where supported. Protect ~/.m365-mcp/auth/ or your configured M365_MCP_AUTH_DIR.
  • Auto-refresh — tokens refreshed before expiry, expired refresh tokens trigger re-auth.
  • No telemetry, no analytics, no third-party calls besides login.microsoftonline.com and graph.microsoft.com.

To delete a local token, remove its account:

m365-mcp-auth remove work

If a token or device may be compromised, also revoke the application's consent from the Microsoft account or Entra ID portal. Re-authenticate after changing M365_MCP_READ_ONLY so the stored token reflects the intended scope set.

License

MIT