Skip to content
Agentmart
Submit a tool

ms365-connect

Connect to Microsoft 365 (OneDrive, Outlook mail, Calendar, Teams) via Microsoft Graph using the open-source python-o365 (O365) library.

Skill by sonichi

IndexedMIT★ 400
Write a review

Chalk Labs

Need help deploying ms365-connect?

Chalk Labs sets up agents like this inside real teams: connected to your tools, tested on your data, with a human in the loop where it matters.

Book a call

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/sonichi-ms365-connect

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Connect to Microsoft 365 (OneDrive, Outlook mail, Calendar, Teams) via Microsoft Graph using the open-source python-o365 (O365) library. Use when the user wants to list/download OneDrive files, read or send Outlook email, list calendar events, or post a message to a Teams channel from a Sutando workflow.

Use cases: productivity

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found
Runs as
Python package

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/ms365-connect

What's inside

Skill name
ms365-connect
Description
Connect to Microsoft 365 (OneDrive, Outlook mail, Calendar, Teams) via Microsoft Graph using the open-source python-o365 (O365) library. Use when the user wants to list/download OneDrive files, read or send Outlook email, list calendar events, or post a message to a Teams channel from a Sutando workflow.
License
MIT
Instructions
122 lines in SKILL.md · view on GitHub

Before installing

  • Ships executable scripts

Files (4)

  • SKILL.md
  • manifest.json
  • requirements.txt
  • ms365.py · scripts/

SKILL.md (first lines)

# ms365-connect

Microsoft 365 connectivity for Sutando, built on the Apache-2.0
[`python-o365`](https://github.com/O365/python-o365) library (`O365` on PyPI),
which is a thin wrapper over Microsoft Graph.

## What it does

All operations go through Microsoft Graph via python-o365:

- **OneDrive** — list a folder's contents (`onedrive-list`) and download a file
  to a local path (`onedrive-get`).
- **Outlook mail** — list recent inbox messages (`outlook-list`) and send an
  email (`outlook-send`).
- **Calendar** — list upcoming events over a window of days (`calendar-list`).
- **Teams** — post a message to a channel in a team (`teams-post`).

Authentication is a one-time delegated OAuth2 consent flow (`auth`); the refresh
token is cached on disk so subsequent commands run non-interactively.

## Usage

Run the CLI with `python3 scripts/ms365.py <subcommand>`:

```bash
# One-time: run the OAuth consent flow and cache the token
python3 scripts/ms365.py auth

# OneDrive
python3 scripts/ms365.py onedrive-list                 # list root
python3 scripts/ms365.py onedrive-list "/Projects/Q3"  # list a folder by path
python3 scripts/ms365.py onedrive-get "/Reports/x.pdf" ./x.pdf

# Outlook mail
python3 scripts/ms365.py outlook-list --n 10
python3 scripts/ms365.py outlook-send --to a@b.com --subject "Hi" --body "Hello"

# Calendar
python3 scripts/ms365.py calendar-list --days 7

# Teams
python3 scripts/ms365.py teams-post --team "Engineering" --channel "General" \
  --message "Deploy is green"
```

Every subcommand except `auth` requires that `auth` has already been run and a
cached token exists.

## Configuration

Secrets are read from the environment (populate them from the Sutando vault;
**never hardcode**):

| Variable | Purpose |
|----------|---------|
| `MS365_CLIENT_ID` | Azure AD application (client) ID |
| `MS365_CLIENT_SECRET` | Azure AD client secret value |
| `MS365_TENANT_ID` | Directory (tenant) ID, or `common` / `organizations` |
| `MS365_AUTH_FLOW` | `credentials` (default; confidential client, id+secret) or `public` (native client, id only — required when the app's redirect is registered under "Mobile and desktop applications"; symptom of the mismatch: `AADSTS700025` on token exchange). In `public` flow `MS365_CLIENT_SECRET` is not required. |

If any is unset, the CLI exits with a clear message naming the missing variable.

**Token cache:** the OAuth token is stored under the workspace state dir at
`state/ms365-token/o365_token.txt` via python-o365's `FileSystemTokenBackend`.
Override the base with `MS365_STATE_DIR` if the workspace state dir is elsewhere.
Treat this file as a live credential (owner-only permissions).

## Azure AD app registration (one-time, owner does this)

Delegated Graph access requires an app registration. The owner performs this
once in the Azure Portal:

1. **Register the app** — Azure Portal → **Microsoft Entra ID** (Azure AD) →
   **App registrations** → **New registration**. Name it (e.g. `Sutando M365`).
   For "Supported account types", pick single-tenant unless multi-tenant is
   required. Copy the **Application (client) ID** and **Directory (tenant) ID**.

2. **Add a redirect URI** — in the app's **Authentication** blade →
   **Add a platform** → **Mobile and desktop applications**, add python-o365's
   default native-client redirect:
   `https://login.microsoftonline.com/common/oauth2/nativeclient`
   (A `http://localhost` redirect also works if you prefer a loopback flow.)

3. **Grant delegated Microsoft Graph scopes** — **API permissions** → **Add a
   permission** → **Microsoft Graph** → **Delegated permissions**, add:

   | Scope | Why |
   |-------|-----|
   | `offline_access` | Issue a refresh token so the token cache survives |
   | `User.Read` | Read the signed-in user's basic profile |
   | `Files.ReadWrite.All` | List and download (and write) OneDrive files |
   | `Mail.Read` | Read Outlook inbox messages |
   | `Mail.Send` | Send Outlook email as the user |
   | `Calendars.ReadWrite` | Read (and create) calendar events |
   | `Team.ReadBasic.All` | Look up the team by name (`GET /me/joinedTeams`) — required before posting |
   | `Channel.ReadBasic.All` | Look up the channel by name (`GET /teams/{id}/channels`) — required before posting |
   | `ChannelMessage.Send` | Post messages to Teams channels |
   | `Chat.Read` | Read Teams chat/channel context |

   > `teams-post` resolves the team and channel **by display name** before it
   > can send, so the two `*.ReadBasic.All` lookup scopes are mandatory — without
   > them the lookups return empty and the CLI reports `Team not found` even
   > though the team exists.

   Click **Grant admin consent** for the tenant if your org requires it.

4. **Create a client secret** — **Certificates & secrets** → **New client
   secret**. Copy the secret **Value** immediately (shown once).

5. **Store the 3 credentials in the vault, not in code** — put the
   Application (client) ID, the client secret Value, and the Directory (tenant)
   ID in the Sutando vault, exposed to this skill as `MS365_CLIENT_ID`,
   `MS365_CLIENT_SECRET`, and `MS365_TENANT_ID`.

Then run `python3 scripts/ms365.py auth` once to complete the consent flow and
cache the token.

## Requirements

From sonichi/sutando, MIT.

More from sonichi/sutando

Signals

Stars
400
Forks
98
Open issues
1,202
Last commit (this folder)
Aug 7, 2026 (2 months ago)
Last release
Aug 20, 2026 (2 months ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
Website
sutando.ai
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from sonichi

Done for you

Rather not set it up yourself?

Chalk Labs scopes, builds and runs agents for your team: the task audit, the eval harness, the integrations and the weekly ops report. Fixed scope, priced before we start.

See how we build AI agents →Read the case studies

Chalk Labs is a two-founder AI and growth studio. We build AI agents, CRMs and MVPs for Web3 and AI companies, and have shipped 50+ product and token launches.

launches shipped
50+
launches shipped
media placements
500+
media placements
founders on every account
2
founders on every account

Press we've placed: Forbes · CoinDesk · Decrypt · Cointelegraph · The Block

Rahil Jain, Co-founder, Chalk Labs. Ex-Goldman Sachs engineer. You talk to the person who builds it.

Get ms365-connect running in your business

Tell us what you want to automate. A founder replies within one working day with a plan, not a pitch deck.

Goes to the Chalk Labs founders, not the newsletter. Privacy

Need help deploying ms365-connect?

CallGet help
Cite this page

ms365-connect skill. Agent Mart. https://agentmart.dev/skills/sonichi-ms365-connect (last updated 2026-10-24)