Microsoft 365

Live

OAUTH 2.0

PRODUCTIVITY

Productivity

Give your agent per-user access to email, calendar, files, and Teams — with every call scoped and audited to the real user.

  • Acts as the user. Reads mail, events, and files with the signed-in user's delegated permissions — no shared service account.
  • Credentials stay vaulted. OAuth tokens stored AES-256, resolved at request time, never exposed in context or logs.
  • Scoped before every call. Graph API scopes enforced per tool — your agent can't read mail if it only needs calendar.
Microsoft 365
agent · Acme Q3
Run
What meetings do I have tomorrow and are there any unread emails about the Q3 review?
S
microsoft365_calendar_events_list
85ms
Microsoft 365 agent
You have 3 meetings tomorrow: standup at 9 AM, design review at 1 PM, and a 1:1 at 4 PM. Found 2 unread emails about Q3 review — one from Sarah Chen (Jun 19) and one from the finance team (Jun 20).
Sources: 3 calendar events, 2 mail threads
microsoft365mcp
2 tools, 5 items
18:29
Message Claude...

Tools your productivity agent reaches for on Microsoft 365, scoped per user.

CALL ANY TOOL
Each tool maps to a specific Microsoft Graph API endpoint and enforces the minimal OAuth scope required for that operation.
microsoft365_excel_add_table_column
Excel Add Table Column
Add a new column to an existing Excel table in OneDrive. Optionally specify the column name, its zero-based insertion index (null = append at end), and initial cell values as a 2D array (first row is the header). Returns the created column object.
Parameters
Name
Type
Required
Description
item_id
string
Required
OneDrive item ID of the Excel (.xlsx) file. Example: '01BYE5RZ6QN3ZWBTUFOFD3GSPGOHDJD36K'.
table_id
string
Required
Name or ID of the table to add the column to. Example: 'Table1' or the GUID assigned by Excel.
index
integer
Optional
Zero-based index position at which to insert the column. Null or omitted means append the column at the right end of the table. Example: 0 inserts as the first column.
name
string
Optional
Display name for the new column header. If omitted, Excel auto-generates a name (e.g., 'Column1'). Example: 'Revenue'.
session_id
string
Optional
Optional workbook session ID from createSession. When provided, sent as the workbook-session-id header. Example: 'cluster=SN2&session=...'.
values
array
Optional
2D array of initial cell values for the column, including the header row in the first element. Example: [["Header"],["row1val"],["row2val"]]. Each inner array is one row. If omitted, the column is created empty.
microsoft365_excel_add_table_row
Excel Add Table Row
microsoft365_excel_clear_range
Excel Clear Range
microsoft365_excel_close_session
Excel Close Session
microsoft365_excel_create_chart
Excel Create Chart
microsoft365_excel_create_session
Excel Create Session
microsoft365_excel_create_table
Excel Create Table
microsoft365_excel_create_worksheet
Excel Create Worksheet
microsoft365_excel_delete_chart
Excel Delete Chart
microsoft365_excel_delete_table
Excel Delete Table
microsoft365_excel_delete_table_column
Excel Delete Table Column
microsoft365_excel_delete_table_row
Excel Delete Table Row
microsoft365_excel_delete_worksheet
Excel Delete Worksheet
microsoft365_excel_export_to_pdf
Excel Export To Pdf
microsoft365_excel_filter_table
Excel Filter Table
microsoft365_excel_get_range
Excel Get Range
microsoft365_excel_get_table
Excel Get Table
microsoft365_excel_get_worksheet
Excel Get Worksheet
microsoft365_excel_list_charts
Excel List Charts
microsoft365_excel_list_comments
Excel List Comments
microsoft365_excel_list_named_items
Excel List Named Items
microsoft365_excel_list_table_columns
Excel List Table Columns
microsoft365_excel_list_table_rows
Excel List Table Rows
microsoft365_excel_list_tables
Excel List Tables
microsoft365_excel_list_worksheets
Excel List Worksheets
microsoft365_excel_merge_range
Excel Merge Range
microsoft365_excel_protect_worksheet
Excel Protect Worksheet
microsoft365_excel_sort_range
Excel Sort Range
microsoft365_excel_sort_table
Excel Sort Table
microsoft365_excel_unmerge_range
Excel Unmerge Range

For more tools, view docs.

Build your Agent
One token vault, one scope check, one audit trail — same pattern whether your agent runs on LangChain, the OpenAI SDK, Anthropic, or Google ADK.
Python · LlamaIndex
Try these prompts
Drop any of these into your agent to see per-user Microsoft 365 access in action.
Email & communication
Copy the prompt
Copied
Summarize my unread emails from the last 24 hours.
Copy the prompt
Copied
Draft a reply to the latest email from [name] and send it when I approve.
Copy the prompt
Copied
Find all emails about the Q3 budget and pull out the key numbers.
Copy the prompt
Copied
Who emailed me most this week?
Calendar & scheduling
Copy the prompt
Copied
What does my week look like? Flag any double-bookings.
Copy the prompt
Copied
Find a 30-minute slot tomorrow where both me and [colleague] are free.
Copy the prompt
Copied
Summarize the agenda and attendees for my next meeting.
Copy the prompt
Copied
How many hours am I in meetings this week?
Files & docs
Copy the prompt
Copied
Find the latest version of the Q3 review deck in my OneDrive.
Copy the prompt
Copied
Summarize the document [file name] and pull out all action items.
Copy the prompt
Copied
List everything in my Documents folder modified in the last 7 days.
SEE HOW AUTH WORKS
User authorizes once via OAuth 2.0; Scalekit vaults the token, refreshes it automatically, and enforces scope on every subsequent tool call.
1
Authorize
Your user connects
Microsoft 365
once. We tie it to their identity and the meetings they approved — no shared bot account, no org-wide access
Who:
user ‘A’
when:
Once per user
access:
Limited to user
2
Store
Their
Microsoft 365
token lives in a vault scoped to them. User A's meetings are never reachable by an agent acting for user B, even on the same connection
vault:
encrypted
scope:
per-user
tokens:
auto-refreshed
3
Resolve
When your agent calls a
Microsoft 365
tool, we fetch the right token server-side. It never touches your agent, never appears in the LLM context, never shows up in your logs
speed:
~40ms
check:
before every call
seen by:
nobody
4
Audit
Every
Microsoft 365
tool call is logged — who triggered it, which meeting was fetched, what came back. 90 days of history, tied to the user who authorized it
history:
90 days
export:
SIEM-ready
logged:
every call
Test other agents
The same per-user OAuth vault works across every connector — swap Microsoft 365 for Slack, Google Calendar, or any other service with zero new auth code.
OPS
Email-to-calendar scheduling agent
Parse scheduling intent from Gmail threads and create Google Calendar events with the right attendees and timezone.
ENGINEERING
Engineering standup agent
Aggregate GitHub and GitLab activity, link to Jira, and post a daily standup digest to Slack. No async updates.
Why Scalekit
Secure your agent's access. Connectors ship in minutes
The Microsoft Graph API has 60+ scopes and per-user token semantics that break every shortcut.
01.
Shared tokens break per-user analytics
A shared service account token looks fine in a demo. In production every Graph API call is attributed to the service account — not the real user who triggered the agent. Scalekit resolves the delegated credential so audit logs say the right name.
// shared token
audit → bot_service_account
mail.read → all users' inboxes

// scalekit
audit → alice@company.com ✓
mail.read → alice's inbox only ✓
02.
Authentication is not authorization
03.
Multi-tenancy is architectural
04.
Microsoft 365 today. Others tomorrow.
“Our agents act across Salesforce, Gong, Google Drive, and more, on behalf of every customer. Scalekit behind the scenes meant we can keep adding tools without ever rebuilding how credentials or tool calling work.”
Venu Madhav Kattagoni
Head of Engineering / Von
FAQs
Frequently Asked Questions
Does each user need their own OAuth token, or can I use a shared service account?
Each user authorizes individually via OAuth 2.0 delegated flow. Scalekit stores and resolves a separate token per user, so every Microsoft Graph API call is attributed to the real user — not a service account. This is required for accurate audit logs and correct permission enforcement across tenants.
How are OAuth tokens stored and protected?
Tokens are encrypted at rest with AES-256 and resolved at request time inside Scalekit's vault. They are never written to agent context, logs, or LLM prompts. Refresh is handled automatically before expiry so your agent never surfaces an expired-token error to users.
Can I limit which Microsoft Graph API scopes my agent is allowed to use?
Yes. Use listScopedTools to declare the exact set of tools — and therefore the exact set of Graph scopes — available to a given agent or tenant. Scalekit enforces this allowlist at call time; tools not in scope return a 403 before the Graph API is ever contacted.
What happens when a user revokes consent or their Microsoft 365 subscription lapses?
Scalekit detects token invalidation on the next refresh attempt and marks the credential as revoked in the vault. Subsequent tool calls return an actionable error that your agent can surface to the user prompting them to re-authorize — no stale tokens silently failing in the background.
Does the connector support Microsoft 365 Business and Enterprise tenants, or only personal accounts?
The connector works with both personal Microsoft accounts and Azure AD-backed organizational (work/school) tenants. For enterprise deployments, admin consent may be required for certain Graph API scopes — Scalekit surfaces this in the OAuth flow and documents the required scopes per tool so your IT admin can grant consent in advance.
Start in your coding agent
Up and running in one command
Install the Scalekit skill in your editor of choice. Connector, auth, tools, prompt, all wired up
Claude Code REPL
/plugin marketplace add scalekit-inc/claude-code-authstack
/plugin install agentkit@scalekit-auth-stack
Cursor Code REPL
# ~/.cursor/mcp.json
{
""mcpServers"": {
""microsoft365"": {
""url"": ""https://mcp.scalekit.com/microsoft365"",
""headers"": { ""Authorization"": ""Bearer $SCALEKIT_TOKEN"" }
}
}
}
Codex Code REPL
# ~/.codex/config.toml
[mcp_servers.microsoft365]
url = ""https://mcp.scalekit.com/microsoft365""
auth_env = ""SCALEKIT_TOKEN""
Copilot Code REPL
# .vscode/mcp.json
{
""servers"": {
""microsoft365"": {
""url"": ""https://mcp.scalekit.com/microsoft365"",
""type"": ""http""
}
}
}