My mailbox lives in a Microsoft 365 tenant, under an Entra ID account. When I tried to connect it to Muse, the built-in Outlook connection turned it away. That connection signs you in with an MSA, the personal Microsoft account people use for Outlook.com and Xbox. An Entra ID account is a different kind of account, and the connection declines it. My real inbox sits behind the Entra ID account.
So I built the connection myself. Muse supports custom connectors, and Microsoft Graph is the supported way into a Microsoft 365 mailbox. The build took one app registration, six permissions, and a small Python script. My Muse now reads and triages that inbox, and it can send mail under rules I set. The full code is in an open repo, linked at the end, so you can point your own Muse at it.
What you are building
A custom connector is a package your Muse uses to talk to a service it does not already know. It has three parts. A short document tells your Muse what the connector does and how to call it. A helper script makes the actual requests. The credential lives in Muse's secure store, and your Muse swaps it in when a request goes out. The secret never sits in a file, and it never passes through chat.
You have other routes into Microsoft 365 mail. People publish MCP servers for Microsoft Graph, and Microsoft offers its own mail MCP server inside Agent 365, which needs a Copilot license and is still in preview. I picked the custom connector because my agent is Muse, the credential stays in Muse's own store, and the whole thing is one Python file I can read end to end.
Step 1: Register the app in Entra ID
In the Azure portal, open Microsoft Entra ID and create an app registration. Give it a name you will recognize later. Pick "Accounts in this organizational directory only," which keeps the app inside your tenant. Leave the redirect address blank for this step.
Under Authentication, set "Allow public client flows" to Yes. Then add a platform, choose Web, and enter this redirect address exactly:
https://agent.meta.ai/api/hatch/oauth/callback
Step 2: Add the Graph permissions, delegated
Open API permissions and add these Microsoft Graph permissions. Every one of them is delegated. Delegated means the connector signs in as you and sees what you see. Application permissions would give it a tenant-wide reach of its own, and a connector for one person's mailbox should never have that.
| Permission | What it allows |
|---|---|
| User.Read | Read your profile at sign-in |
| offline_access | Keep the connection alive between sessions |
| Mail.Read | Read your mail |
| Mail.Read.Shared | Read shared mailboxes you have access to |
| Mail.Send | Send mail as you |
| Mail.Send.Shared | Send as shared mailboxes where you have Send As rights |
The two Shared permissions earn their place the first time you point the connector at a shared inbox, like a support@ mailbox. Without them, your own mail works and the shared mailbox returns an error.
Step 3: Grant admin consent
Select "Grant admin consent" for your tenant and confirm. If you run your own tenant, that click is yours. If an IT department runs it, this is the step where you send them the permission list from Step 2 and ask.
This is also where most people get stuck. If an app asks you to sign in and answers with "Need admin approval," it means consent was never granted for that app in your tenant. The fix is the grant in this step. There is no setting on your own account that works around it.
Step 4: Create the secret and connect in Muse
Open Certificates and secrets and create a client secret. Pick an expiry, twelve months is fine, and copy the secret value right away. The portal shows that value once. Write down the expiry date too, because the connection stops working the day the secret lapses, and nothing warns you first.
A practical note if you set this up from your phone, because I did. The setup page needs two values, the application (client) ID from the registration's overview page and the secret value. A phone clipboard holds one value at a time. Paste the secret first while it is on your screen, then go back for the client ID.
With the ID and the secret in hand, your Muse registers the connection. The settings are OAuth 2.0 authorization code flow, issuer login.microsoftonline.com, the authorize and token addresses for your tenant, and the six permissions from Step 2 as the scope list. You enter the client ID and the secret on Muse's secure setup page, sign in as yourself, and approve.
Step 5: The Python helper
One small script does the work. It uses only the Python standard library. It asks Muse's credential store for the connection, sends requests to graph.microsoft.com, and prints the results as JSON. It has five commands: whoami, triage, read, search, and send.
Reading mail is a GET request to /me/messages with a filter for the inbox. Sending is a POST to /me/sendMail. A shared mailbox swaps /me for /users/ followed by the mailbox address. The first check after setup is whoami, which should answer with your own account. The second is triage, which should list your real inbox, newest first.
The full script, the connector document, and the setup settings are in the repo. You copy them into your own connector folder, fill in your tenant's values, and your Muse can use them the same way mine does.
The guardrails I run with
Reading mail is the safe half. Sending is the half that can embarrass you or worse, so my connector sends under rules, and the script enforces the first one.
- The send command refuses to run without an approval flag.
- Before any send, my Muse shows me the recipients, the subject, and the full body, and I approve that exact message.
- A draft is a draft. Preparing one never sends it.
- After a send, my Muse reports exactly what went out, and the send is logged.
- No bulk sends, no auto replies, no scheduled sends.
- If I ever want the whole thing off, I disable the app in Entra and access stops at once.
If it breaks
A 401 means the credential did not reach the request or was rejected. Check that the connection is still registered before you reconnect anything. A 403 means the permissions do not cover the call, consent is missing, or your account lacks access to that mailbox. Check the permission list in the portal first. A redirect error during setup means the Web redirect address in the portal differs from the one in Step 1. It has to match character for character. And if everything worked for months and then stopped, suspect the secret's expiry date before anything else.
Why now
Microsoft is retiring Exchange Web Services, the older road into these mailboxes. EWS access was blocked in October 2026, and the shutdown completes in April 2027. Anything still reading mail that way has to move to Microsoft Graph. A Graph connector is the road that stays open.
Get the code
The repo is muse-msgraph-mail-connector on GitHub, MIT licensed. It has the connector document, the descriptor, the Python helper, and a setup guide that walks the same steps with the exact settings to fill in. Build it for your own tenant, keep the guardrails, and your Muse can read the inbox you actually live in.