m365-mcp
Manages Microsoft 365 personal account mail, calendar, contacts, OneDrive, searches, accounts, cache, and server info via MCP tools.
Read, list, get, search, and export emails, events, contacts, calendars, mail folders, inbox rules, OneDrive files/folders, and attachments.
Create, update, move, delete, flag, categorize, mark read/unread, archive, send, reply, reply-all, and forward emails.
Create, rename, move, delete, empty, or mark-all-read mail folders; manage inbox rules (create, update, reorder, delete).
Manage calendar events/calendars: create, update, delete, respond, forward, propose new time, check availability/free-busy.
Manage contacts/lists: create, update, delete, export vCard, add contact to list.
Manage OneDrive files/folders: upload, download, copy, move, rename, delete, share, get download URLs, and list folder trees.
Authenticate/list Microsoft accounts via device flow; administer cache (stats, invalidate, tasks, warming); get server version.
Dangerous actions (send, share, delete, forward, empty) require confirm=true; read-only tools are safe.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@m365-mcpshow my calendar for next week"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
M365 MCP
MCP server for Microsoft Graph: 30 intent-based tools that give an AI assistant safe access to Outlook mail, Calendar, Contacts and OneDrive on personal Microsoft accounts (outlook.com, hotmail.com, live.com).
Features
Small tool surface: 30 tools in three tiers (16 core, 7 extended, 7 admin, hidden by default) instead of one tool per Graph endpoint. Eight generic
m365_*tools browse, read, search, create, update, move and delete across eight resource types; dedicated tools cover sending mail, calendar invitations, sharing and file transfer.Safe by design: anything that sends mail, notifies attendees, shares a file or deletes data needs
confirm=true, enforced by the server. Local file access is limited to allowed folders with a deny-list for secrets.Compact, typed results: every tool has an
outputSchema. Lists return previews (not full bodies) with an opaquenext_cursorand a short summary.Multi-account: several personal accounts at once;
account_idis optional when only one is signed in.Whole-mailbox search: email search runs server-side over the entire mailbox, plus events, contacts and OneDrive files in one call.
Free-time finder:
calendar_find_availabilitysuggests free slots inside your working hours.Encrypted caching: AES-256 SQLCipher cache keyed by account and resource; the only model-facing control is
refresh.Hardened transports: stdio by default; Streamable HTTP with bearer token, constant-time comparison and Origin validation.
Audit log and rate limits: one JSON log line per call (no argument values or secrets); per-account limits on sends, shares and deletes.
Only personal Microsoft accounts are supported. Work and school accounts are rejected at sign-in.
Related MCP server: MCP Microsoft Office
Quick Start
See QUICKSTART.md for the complete installation and setup guide.
TL;DR
# 1. Install
git clone https://github.com/robin-collins/m365-mcp.git
cd m365-mcp && uv sync
# 2. Configure (use .env.example template)
cp .env.example .env
# Edit .env with your M365_MCP_CLIENT_ID
# 3. Sign in a personal Microsoft account
uv run authenticate.py
# 4. Run
uv run m365-mcpClaude Desktop
# Add M365 MCP server (replace with your Azure app ID)
claude mcp add m365-mcp -e M365_MCP_CLIENT_ID=your-app-id-here -- uvx --from git+https://github.com/robin-collins/m365-mcp.git m365-mcp
# Start Claude Desktop
claudeUsage Examples
# Email
> show my unread emails from last week
> find the email about the Telstra migration
> reply to Jane saying "Tuesday works" (asks you to confirm before sending)
# Calendar
> what is on my calendar next week?
> when am I free for an hour on Thursday?
> book a dentist appointment on Friday at 9am
# Files
> what is in my OneDrive Documents folder?
> upload budget.xlsx from Downloads to /Documents
> send me a view-only link to budget.xlsx (asks you to confirm)
# Contacts and accounts
> put Jane in my Family contacts folder
> use my second account for thisAvailable Tools
The server exposes 30 tools. M365_MCP_TOOLSETS (default core,extended)
chooses the tiers; see Client Configuration. Every
Microsoft 365 tool takes an optional account_id. The complete input and
output schema of each tool is in
docs/unified-tools/SCHEMA_REFERENCE.md
and MCP_SERVER_TOOLS.md.
Safety: safe = read-only; moderate = changes data; dangerous =
communicates with other people or grants access; critical = destroys data.
"Confirm" means confirm=true is required (conditional = only in some
cases, as described).
Core tier (16, on by default)
Tool | Safety | What it does |
| safe | Browse emails in a folder, events in a time window, calendars, contacts, contact folders, mail folders, inbox rules or OneDrive files (optionally as a tree) |
| safe | Read one item by ID: email with body, event with attendees, contact, folder, rule, calendar, OneDrive item, or the status of a copy ( |
| safe | Find emails, events, contacts or OneDrive files by free text, one type or several at once |
| moderate | Save a OneDrive file or email attachment to a local file, get a temporary download link, or export a contact as a vCard |
| moderate | Create a mail folder, calendar, contact, contact folder or OneDrive folder |
| moderate | Mark read, flag, categorise, set importance, rename folders and files, edit contact details |
| moderate | Move an email, mail folder, contact or OneDrive item (emails and contacts get a new ID) |
| critical, confirm | Delete an email, folder, rule, event, calendar, contact or OneDrive item (OneDrive items go to the recycle bin; deleting a meeting you organise sends cancellations) |
| moderate | Create an unsent draft (sends nothing) |
| dangerous, confirm | Send a new email or a draft |
| dangerous, confirm | Reply to the sender or to everyone |
| dangerous, confirm | Forward an email with an optional note |
| dangerous, conditional | Add an event; confirm required only when attendees would be emailed |
| dangerous, conditional | Change an event; confirm required when attendees are notified |
| dangerous, conditional | Accept, tentatively accept or decline an invitation; confirm required when a response is emailed |
| safe | Show your busy times and suggest free slots inside your working hours (own calendar only) |
Extended tier (7, on by default)
Tool | Safety | What it does |
| moderate | Upload a local file to OneDrive as a new file or replace an existing one |
| moderate | Copy a OneDrive file or folder (asynchronous; returns an |
| dangerous, confirm | Share a file or folder by link or by inviting named people |
| moderate | Mark every unread message in a mail folder as read (bounded per call) |
| critical, confirm | Delete all messages in a mail folder such as Junk Email (bounded per call) |
| dangerous, conditional | Create, change, enable/disable or reorder an inbox rule; confirm required for rules that forward, redirect or delete |
| dangerous, confirm | Forward a meeting invitation to named people |
Admin tier (7, hidden by default; add admin to M365_MCP_TOOLSETS)
Tool | Safety | What it does |
| safe | List the signed-in accounts (needed only with more than one account) |
| moderate | Start a device-code sign-in; returns a URL, a code and an |
| moderate | Finish the sign-in (single non-blocking poll); work or school accounts are rejected |
| safe | Cache statistics, background tasks, one task, or warming progress ( |
| moderate | Clear cached results for one resource type or all, for one account or all |
| safe | Server version, protocol versions, enabled toolsets |
| moderate | Status, install or remove the weekly re-auth job ( |
High-Performance Caching
Reads through m365_list and m365_get use an encrypted local cache, which
cuts repeated Microsoft Graph calls and makes repeated browsing fast.
Key Features
AES-256 encryption: cached data is encrypted at rest using SQLCipher by default
Three-state TTL per resource: fresh (returned immediately), stale (still served until it expires) and expired (refetched); for example
emailis fresh for 2 minutes and expires after 10,drive_item10 and 60 minutesAutomatic compression: entries of 50 KB or more are gzip-compressed
Keys by account and resource: accounts never share entries; entries are keyed by the resolved account, the resource, the normalised request and the cursor
Smart invalidation: every mutating tool clears the affected resources for its own account only
Optional cache warming: set
M365_MCP_CACHE_WARMING=trueto pre-load the folder tree, inbox, upcoming events and contacts at startup and refresh stale entries in the backgroundAutomatic cleanup: kept under 2 GB
The refresh parameter
The model never manages the cache. The only control is refresh on
m365_list and m365_get:
# Served from the cache when fresh (default)
m365_list(resource="drive_item", path="/Documents")
# Bypass the cache and fetch fresh data
m365_list(resource="drive_item", path="/Documents", refresh=True)
m365_get(resource="email", id=email_id, refresh=True)Cache Security
Encryption: AES-256 encryption via SQLCipher. If SQLCipher is missing while encryption is enabled, startup fails instead of silently using plaintext.
Key storage: system keyring (macOS Keychain, Windows Credential Manager, Linux Secret Service)
Fallback: environment variable
M365_MCP_CACHE_KEYfor headless servers; if neither keyring nor the env var is available, a generated ephemeral key is used with a warningPlaintext mode: only used when cache encryption is explicitly disabled by code, primarily for tests and diagnostics
Cache Management (admin tier)
Add admin to M365_MCP_TOOLSETS to enable the cache tools:
# Statistics: entries, size, hits, per-resource breakdown
admin_cache_get(view="stats")
# Background tasks and cache warming progress
admin_cache_get(view="tasks", status="running")
admin_cache_get(view="warming")
# Clear cached emails for one account, or everything
admin_cache_invalidate(scope="email", account_id="me@outlook.com", reason="stale inbox")
admin_cache_invalidate(scope="all")For the cache guides, see docs/cache_user_guide.md, docs/cache_examples.md and docs/cache_security.md; for the architecture, see CLAUDE.md.
Manual Setup
1. Azure App Registration
Go to Azure Portal → Microsoft Entra ID → App registrations
New registration → Name:
m365-mcpSupported account types: Personal Microsoft accounts only
Authentication → Allow public client flows: Yes
API permissions → Add these delegated permissions:
offline_access (required for refresh tokens; the CLI retries against the consumers authority if a personal account flags it as reserved)
Mail.ReadWrite (read, draft, move, delete mail and rules)
Mail.Send (send, reply, forward;
Mail.ReadWritedoes not cover sending)Calendars.ReadWrite
Files.ReadWrite
Contacts.ReadWrite
MailboxSettings.Read (working hours and time zone for
calendar_find_availability)User.Read
Copy Application ID
The server requests the .default scope, so it gets exactly the permissions
granted to the app registration. A missing permission shows up as a
403 error for that tool only. People.Read is not needed.
The default authority is consumers. Set M365_MCP_TENANT_ID only if you
know you need a different value; work and school accounts are still rejected.
2. Installation
git clone https://github.com/robin-collins/m365-mcp.git
cd m365-mcp
uv sync3. Authentication
# Set your Azure app ID
export M365_MCP_CLIENT_ID="your-app-id-here"
# Run authentication script
uv run authenticate.py
# Force-refresh a cached token to verify silent renewal
uv run authenticate.py --re-auth <account-id-or-email>
# Remove an account, its tokens, and its local data cache
uv run authenticate.py --remove <account-id-or-email>
# Follow the prompts to sign in your personal Microsoft accountsAlternatively add the admin tier and let the assistant call
account_auth_begin / account_auth_complete. You enter the displayed code
at the shown URL; the underlying MSAL flow stays on the server and the model
only sees an opaque auth_session_id.
4. Claude Desktop Configuration
Add to your Claude Desktop configuration:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"microsoft": {
"command": "uvx",
"args": ["--from", "git+https://github.com/robin-collins/m365-mcp.git", "m365-mcp"],
"env": {
"M365_MCP_CLIENT_ID": "your-app-id-here"
}
}
}
}Or for local development:
{
"mcpServers": {
"m365-mcp": {
"command": "uv",
"args": ["--directory", "c:\\projects\\m365-mcp", "run", "m365-mcp"],
"env": {
"M365_MCP_CLIENT_ID": "your-app-id-here"
}
}
}
}Keeping Sign-in Alive (weekly re-auth)
A personal account's refresh token expires after 90 days without use. Set
MCP_WEEKLY_RE_AUTH=true and the server installs a weekly job that refreshes
every signed-in account: Windows Task Scheduler on Windows, cron on Linux and
macOS. While the server runs it re-checks the job every
MCP_RE_AUTH_CHECK_HOURS (default 6): a missing or changed job is put back,
and a failed or overdue run (for example, a sign-in that needs renewing) is
logged as a warning. MCP_WEEKLY_RE_AUTH=false removes the job; leaving the
variable unset never touches an existing one.
Variable | Default | Meaning |
| unset |
|
|
| Day the job runs |
|
| Local 24-hour time |
|
| How often the running server checks the job |
With the admin tier enabled, admin_reauth_schedule reports the schedule,
next and last run and any problems (action="status"), and installs or
removes the job (action="install" / "remove", each with confirm=true).
The job itself is python -m m365_mcp.reauth_job; its last result is in
~/.m365_mcp_reauth_state.json and its log in ~/.m365_mcp_reauth.log. If a
run reports that sign-in is required, run uv run authenticate.py.
Client Configuration
The server exposes 30 tools in three tiers: core (16), extended (7) and
admin (7, hidden by default). M365_MCP_TOOLSETS (comma separated, default
core,extended) chooses which tiers the server registers. Cutting the tool
list saves model context: the core tier costs about 9.4k tokens of tool
definitions and the default core,extended about 13.5k. Unknown values fail
at startup.
Client situation | Set | Also |
Client without tool search or deferred loading |
| Users lose |
Client with tool search or deferred loading |
| Load |
Signing in from the client (no terminal) | add |
|
Tier contents:
core: "m365_list", "m365_get", "m365_search", "m365_get_content", "m365_create", "m365_update", "m365_move", "m365_delete", "email_create_draft", "email_send", "email_reply", "email_forward", "calendar_create_event", "calendar_update_event", "calendar_respond", "calendar_find_availability"
extended: "drive_upload", "drive_copy", "drive_share", "email_folder_mark_all_read", "email_folder_empty", "email_rule_manage", "calendar_forward"
admin: "account_list", "account_auth_begin", "account_auth_complete", "admin_cache_get", "admin_cache_invalidate", "admin_server_info", "admin_reauth_schedule"
Claude Desktop and Claude Code (stdio)
Claude Desktop uses the mcpServers block shown under Claude Desktop
Configuration above; add "M365_MCP_TOOLSETS": "core,extended" to env.
Claude Code:
claude mcp add m365 --env M365_MCP_CLIENT_ID=your-app-id \
--env M365_MCP_TOOLSETS=core,extended \
-- uv --directory /path/to/m365-mcp run m365-mcpClaude API MCP connector and Claude Code both support tool search: keep the
core tools loaded and let extended load on demand. Have the host ask for
approval on tools annotated dangerous or critical (send, share and delete
tools). The server's confirm=true gate is a second check, not a substitute.
OpenAI (Responses API, remote MCP)
Run the server with HTTP transport (see Transport Modes), then:
{
"type": "mcp",
"server_label": "m365",
"server_url": "https://your-host.example/mcp",
"authorization": "<bearer token>",
"allowed_tools": ["m365_list", "m365_get", "m365_search", "m365_get_content"],
"require_approval": "always",
"defer_loading": true
}allowed_tools imports only the listed tools; use it to expose the read
tools alone, or the core list above. defer_loading: true keeps the
function definitions out of the prompt until the model searches for them,
which suits the extended tier. Keep require_approval on for tools that
send, share or delete.
Gemini CLI (Streamable HTTP)
{
"mcpServers": {
"m365": {
"httpUrl": "http://127.0.0.1:8000/mcp",
"headers": { "Authorization": "Bearer <token>" },
"timeout": 30000,
"trust": false,
"includeTools": ["m365_list", "m365_get", "m365_search", "m365_get_content"],
"excludeTools": ["m365_delete", "email_folder_empty", "drive_share"]
}
}
}includeTools is an allowlist and excludeTools a blocklist; exclusion wins.
Leave trust false so Gemini CLI asks before running tools.
Choosing what to expose
Prefer restricting on the server (M365_MCP_TOOLSETS) so every client sees
the same surface, and add client-side allowed_tools / includeTools for
per-agent least privilege (for example a read-only agent with only the
m365_list, m365_get, m365_search and m365_get_content tools).
Transport Modes
M365 MCP supports two transport modes for different use cases:
stdio (Default) - For Desktop Apps
Use for: Claude Desktop, local MCP clients
Security: Inherently secure through process isolation (no authentication required)
# Default mode - no configuration needed
export M365_MCP_CLIENT_ID="your-app-id"
uv run m365-mcpStreamable HTTP - For Web/API Access
Use for: Web applications, remote access, multi-client scenarios
Security: ⚠️ Requires authentication (bearer token; MCP_AUTH_METHOD=oauth is not supported). Browser requests must come from an allowed Origin (loopback by default; set MCP_ALLOWED_ORIGINS to change)
Protocol: Uses MCP Streamable HTTP (spec 2025-03-26+)
# Generate secure token
export MCP_AUTH_TOKEN=$(openssl rand -hex 32)
# Configure Streamable HTTP with bearer authentication
export M365_MCP_CLIENT_ID="your-app-id"
export MCP_TRANSPORT="http"
export MCP_AUTH_METHOD="bearer"
export MCP_HOST="127.0.0.1"
export MCP_PORT="8000"
# Start server
uv run m365-mcpClient connection:
from mcp.client.http import http_client
async with http_client(
"http://localhost:8000/mcp",
headers={"Authorization": f"Bearer {your_token}"}
) as (read, write):
# Use the session...📚 See SECURITY.md for complete security guide and authentication options
Multi-Account Support
Every Microsoft 365 tool accepts an optional account_id (the account ID or
its email address).
With one signed-in account, omit it.
With several accounts, omitting it fails with an error that lists each account's ID and email, so the assistant can ask you which one to use.
account_list(admin tier) shows the signed-in accounts.
# One account signed in
m365_list(resource="email", limit=10)
# Several accounts
m365_list(resource="email", account_id="me@outlook.com", limit=10)
m365_list(resource="event", account_id="family@hotmail.com")All accounts must be personal Microsoft accounts. Cache entries, rate limits and cursors are separate per account.
Development
# Run the test suite (no network; live tests are skipped by default)
uv run pytest tests/ -q
# Live read-only tests against a signed-in personal account
M365_MCP_LIVE_TESTS=1 uv run pytest tests/test_integration_unified.py -v
# Type checking
uv run pyright
# Format and lint
uvx ruff format --check .
uvx ruff check .
# Regenerate and verify the tool specs and reference
uv run python scripts/build_unified_tool_specs.py
uv run python scripts/build_unified_tool_specs.py --check
uv run python scripts/generate_tools_doc.py --checkThe tool surface is defined by the generated specs in
docs/unified-tools/; see
CLAUDE.md for the architecture and CHANGELOG.md
for the 1.0.0 migration table from the old tool names.
Example: AI Assistant Scenarios
Smart Email Management
# Newest unread mail (previews only)
page = m365_list(resource="email", email_filter={"unread": True}, limit=10)
# Read one message in full
email = m365_get(resource="email", id=page["items"][0]["id"])
# Draft a reply for review, or reply after the user approves
email_reply(email_id=email["item"]["id"], mode="sender",
body="Thanks, I'll review and get back to you.", confirm=True)
# Save an attachment locally (inside an allowed folder)
m365_get_content(resource="email", id=email["item"]["id"], mode="download",
attachment_id=email["item"]["attachments"][0]["id"],
save_path="C:/Users/you/Downloads/attachment.pdf")
# Archive the message
m365_move(resource="email", id=email["item"]["id"], destination_id="archive")Intelligent Scheduling
# When am I free for an hour on Thursday?
calendar_find_availability(start="2026-10-01T00:00:00+09:30",
end="2026-10-02T00:00:00+09:30",
slot_minutes=60, max_slots=3)
# Private appointment (no attendees, no confirm needed)
calendar_create_event(subject="Dentist", start="2026-10-02T09:00:00+09:30",
end="2026-10-02T10:00:00+09:30", location="City Dental")
# Meeting with attendees emails invitations, so confirm is required
calendar_create_event(subject="Project Review",
start="2026-10-02T14:00:00+09:30",
end="2026-10-02T15:00:00+09:30",
attendees=[{"address": "colleague@example.com"}], confirm=True)Date-times use RFC 3339 with an offset. Availability covers your own calendar only, because Microsoft Graph does not expose other people's free/busy for personal accounts.
OneDrive
# Upload, then share by view-only link (asks the user first)
drive_upload(local_path="C:/Users/you/Downloads/budget.xlsx",
parent_path="/Documents")
drive_share(item_id=item_id, mode="link", link_type="view", confirm=True)
# Copy is asynchronous: check the returned operation_id
drive_copy(item_id=item_id, destination_path="/Backups")
m365_get(resource="operation", id=operation_id)Security Notes
Personal Microsoft accounts only; work and school sign-ins are rejected
Tokens are cached locally in
~/.m365_mcp_token_cache.jsonCache data is encrypted at rest using AES-256 SQLCipher in
~/.m365_mcp_cache.dbEncryption keys are loaded from system keyring or
M365_MCP_CACHE_KEY; generated non-persistent keys produce a warningSQLCipher is required when cache encryption is enabled; plaintext cache mode is only used when explicitly requested by code
Sending, sharing, deleting and notifying other people require
confirm=trueLocal file access is limited to
MCP_FILE_ALLOWED_ROOTSplus, on stdio, the working and temp directories (off over HTTP unlessMCP_FILE_ALLOW_CWD/MCP_FILE_ALLOW_TEMPistrue); hidden and secret-like files are refusedEmail, event, contact and file content is written by other people and is treated as data, never as instructions
Only request permissions your app actually needs
Consider using a dedicated app registration for production
See SECURITY.md for the full security guide.
Troubleshooting
Authentication fails: Check your CLIENT_ID is correct
"Need admin approval" or a work/school account is rejected: only personal accounts are supported; leave
M365_MCP_TENANT_IDunset (defaultconsumers)Missing permissions: Ensure all required API permissions are granted in Azure
Token errors: Delete
~/.m365_mcp_token_cache.jsonand re-authenticate"several accounts are signed in": pass
account_id(the error lists the choices)"Invalid cursor: it does not match this request": repeat the call without
cursor; cursors are valid only for the identical request, for 24 hours, and expire on restart unlessM365_MCP_CURSOR_KEYis setLocal path refused: the path must be inside the working directory, the temp directory or a folder in
MCP_FILE_ALLOWED_ROOTS, and not hidden or secret-likeCache issues: Delete
~/.m365_mcp_cache.dbto reset cache. If the stored key cannot open the database, the cache is recreated automatically.Stale results: call
m365_listorm365_getwithrefresh=trueSlow first requests: Normal on a cold cache. Set
M365_MCP_CACHE_WARMING=trueto enable startup warming and stale-cache background refresh.
License
MIT
Available Tools
23 toolscalendar_create_eventCreate EventA
Add an event to your calendar. With attendees, Outlook emails them an invitation, so confirm=true is then required. Without attendees it is a private appointment and needs no confirmation. Returns the event.
| Name | Required | Description | Default |
|---|---|---|---|
| end | Yes | RFC 3339 date-time with offset, e.g. 2026-10-01T09:00:00+09:30. | |
| body | No | Description. | |
| start | Yes | RFC 3339 date-time with offset, e.g. 2026-10-01T09:00:00+09:30. | |
| confirm | No | Must be true to send invitations to the attendees; set only after the user approves. | |
| show_as | No | How the time shows in your calendar. | |
| subject | Yes | Title. | |
| location | No | Location text. | |
| attendees | No | People to invite. | |
| time_zone | No | IANA time-zone name, e.g. Australia/Adelaide. Defaults to the mailbox time zone. | |
| account_id | No | Account ID or email address. Omit when only one account is signed in. | |
| is_all_day | No | All-day event (start and end at midnight in time_zone). | |
| body_format | No | Format of the body text you supply. | text |
| calendar_id | No | Calendar ID (default: your default calendar). | |
| reminder_minutes | No | Reminder before start, in minutes. |
Output Schema
| Name | Required | Description |
|---|---|---|
| event | Yes | |
| summary | Yes | One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field. |
| invitations_sent | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations flag a non-read-only, open-world operation but say nothing about the external email side effect. The description adds that invitations are emailed to attendees through Outlook, which is exactly the kind of consequence an agent must warn the user about. The confirm-after-approval safety gate is a useful restatement, though it partially duplicates the schema's own confirm description.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, zero waste, and the most important behavioral fact (invitations get emailed when attendees exist) is front-loaded right after the purpose. Every sentence carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 14-parameter creation tool, the description covers the essential decision (attendees → confirm required) and an output schema exists so return values need no explanation. It is adequately complete, though it says nothing about defaults for account_id/calendar_id or idempotency behavior implied by idempotentHint=false.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with all 14 parameters including enums and nested attendee fields documented in the schema itself. The description's only parameter-related content is the attendees/confirm dependency, which the schema already encodes. Baseline 3 applies when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Add an event to your calendar.' An agent immediately knows this creates a calendar entry, and the create-vs-update distinction against calendar_update_event follows from the verb. However, no sibling tool is named, so the differentiation is implicit rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear conditional context: with attendees, an Outlook invitation is emailed and confirm=true becomes required; without attendees, it is a private appointment needing no confirmation. That is real workflow guidance. It stops short of stating when to prefer calendar_update_event or calendar_find_availability, so there is no explicit alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_find_availabilityFind Free TimeARead-onlyIdempotent
Show when you are busy in your own calendar during a time range and, given slot_minutes, suggest free slots of that length within your working hours. Personal accounts cannot see other people's availability, so this covers your calendar only.
| Name | Required | Description | Default |
|---|---|---|---|
| end | Yes | Range end; at most 62 days after start. | |
| start | Yes | RFC 3339 date-time with offset, e.g. 2026-10-01T09:00:00+09:30. | |
| max_slots | No | Most free slots to return. | |
| time_zone | No | IANA time-zone name, e.g. Australia/Adelaide. Defaults to the mailbox time zone. | |
| account_id | No | Account ID or email address. Omit when only one account is signed in. | |
| slot_minutes | No | Length of free slots to suggest. | |
| min_gap_minutes | No | Buffer to keep before and after busy time. | |
| working_hours_only | No | Only suggest slots inside your Outlook working hours. |
Output Schema
| Name | Required | Description |
|---|---|---|
| busy | Yes | |
| summary | Yes | One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field. |
| time_zone | Yes | |
| free_slots | Yes | |
| working_hours | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true and destructiveHint=false, so the safe-read profile is covered. The description adds genuinely useful behavioral context beyond that: it only sees the caller's own calendar in personal accounts, and slot suggestions are constrained to working hours. It does not mention the 62-day range cap or return shape, but the output schema covers results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single well-formed sentence with the core action (show busy time, suggest free slots) front-loaded, followed by the scoping caveat. No waste, though it is dense enough that it could be split for readability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With rich annotations, a full output schema, and 100% schema coverage, the description only needs to add what structured fields cannot: the personal-account visibility limit and the working-hours assumption. It does that, so an agent has enough to call it correctly, though the range cap is left to the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all eight parameters are already documented in the schema, establishing the baseline of 3. The description adds only limited extra meaning, mainly re-explaining slot_minutes and the working-hours constraint, which the schema already conveys.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: it shows busy time in your own calendar and suggests free slots of a given length. The scope note ("this covers your calendar only") clarifies what it queries, though it never names a sibling tool like calendar_create_event to route against.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: an agent can infer it should call this before scheduling a meeting, and the personal-account limitation tells it not to expect others' availability. There is no explicit when-to-use/when-not guidance or named alternative tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_forwardForward InvitationA
Forward a meeting invitation to people the user names, with an optional note. Requires confirm=true after the user approves.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | Recipients. | |
| comment | No | Note to include. | |
| confirm | Yes | Must be true to forward this invitation; set only after the user approves. | |
| event_id | Yes | Event to forward. | |
| account_id | No | Account ID or email address. Omit when only one account is signed in. |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| summary | Yes | One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field. |
| event_id | Yes | |
| recipient_count | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the safety profile (readOnly=false, destructive=false, non-idempotent, openWorld). The description's added behavioral context is the confirm-after-approval gate, but that same instruction is already spelled out in the confirm parameter description, so it repeats structured data. It adds little about side effects, e.g. that forwarding sends an external email that cannot be recalled.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, purpose front-loaded and the confirm requirement second. Every sentence carries information and there is no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a full output schema and 100% parameter coverage, the description does not need to explain returns or field formats. It adequately covers purpose and the approval gate, but omits the external side effect of forwarding to recipients, which is only hinted at by the openWorld annotation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema fully documents all five parameters. The description only loosely references 'people the user names' and 'optional note,' which map to 'to' and 'comment' without adding format, limits, or syntax beyond the schema. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Forward a meeting invitation to people the user names, with an optional note.' This is clear and actionable, but it never distinguishes itself from the sibling email_forward or other calendar tools; the calendar-vs-email distinction is left to the reader.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives one usage constraint ('Requires confirm=true after the user approves'), which is a meaningful prerequisite. However, it offers no when-to-use/when-not guidance relative to alternatives like email_forward or calendar_respond, so selection guidance is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_respondRespond to InvitationA
Accept, tentatively accept or decline a meeting invitation, optionally proposing a new time (with tentative or decline). When a response is emailed to the organiser (the default), confirm=true is required.
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | Your response. | |
| comment | No | Message to the organiser. | |
| confirm | No | Must be true to send this response to the organiser; set only after the user approves. | |
| event_id | Yes | Invitation's event ID. | |
| account_id | No | Account ID or email address. Omit when only one account is signed in. | |
| proposed_end | No | Proposed new end (tentative or decline only). | |
| send_response | No | Email the response to the organiser. | |
| proposed_start | No | Proposed new start (tentative or decline only). |
Output Schema
| Name | Required | Description |
|---|---|---|
| action | Yes | |
| summary | Yes | One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field. |
| event_id | Yes | |
| proposed_end | Yes | |
| response_sent | Yes | |
| proposed_start | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the generic profile (not read-only, not idempotent, open-world, non-destructive). The description adds genuinely useful behavioral detail beyond that: the response is emailed to the organiser by default, and that external side effect is gated behind confirm=true. It stops short of noting reversibility or that a sent email cannot be recalled.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense, front-loaded sentences that carry the action set, the proposed-time restriction, and the confirm gate with no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with an output schema available, the description covers the essentials an agent needs to act correctly, especially the subtle confirm requirement for the default email path. Return values needn't be described since the output schema exists.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all 8 parameters including action enum, confirm, send_response, and the tentative/decline-only constraint on proposed times. The description largely restates these constraints rather than adding new semantics, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific set of verbs (accept, tentatively accept, decline) against a specific resource (a meeting invitation), plus the optional proposed-time variation. This is clearly distinguishable in spirit from calendar_create_event/calendar_update_event, though no sibling is named to make the boundary explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Guidance is embedded and actionable: proposing a new time is only valid with tentative or decline, and confirm=true is required when the response is emailed (the default). It gives clear conditions for use but never explicitly contrasts with competing siblings like calendar_update_event.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_update_eventUpdate EventAIdempotent
Change an event's time, title, location, description, reminder or attendees. If the event has attendees, or you add some, Outlook emails them an update, so confirm=true is then required. Returns the updated event.
| Name | Required | Description | Default |
|---|---|---|---|
| changes | Yes | Fields to change (at least one). | |
| confirm | No | Must be true to send updates to the attendees; set only after the user approves. | |
| event_id | Yes | Event to change. | |
| account_id | No | Account ID or email address. Omit when only one account is signed in. |
Output Schema
| Name | Required | Description |
|---|---|---|
| event | Yes | |
| summary | Yes | One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field. |
| changed_fields | Yes | |
| attendees_notified | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnly=false, idempotent=true, destructive=false, openWorld=true), and the description adds a side effect the annotations cannot express: attendee notification emails, gated by confirm=true. That is exactly the extra context the annotations omit. It still does not state permission requirements or atomicity if a partial change fails.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero filler, and the mutation surface is front-loaded before the confirm-gate caveat. Nothing here is repeated boilerplate.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so explaining return values is unnecessary, and the description correctly spends its words on the confirm/notification behavior an agent must know before calling. It is nearly complete, missing only failure-mode context (e.g. what happens if confirm is false while attendees exist).
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with every field (start/end RFC 3339 format, time_zone IANA name, attendees_add/set/remove, reminder_minutes bounds) documented inline. The description only restates the field families at a high level and adds no syntax or format meaning beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (change) and resource (event) and enumerates the mutable field families: time, title, location, description, reminder, attendees. This clearly distinguishes it from the sibling calendar_create_event without needing to open either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit conditional rule: if the event has attendees (or you add some), Outlook emails them and confirm=true is required. That is genuine when-to-do-what guidance. It stops short of routing the agent away from alternatives (e.g. calendar_respond for RSVPs), but no misleading or missing context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
drive_copyCopy FileA
Copy a OneDrive file or folder to another folder. Copying runs in the background: this returns an operation_id to check with m365_get(resource='operation').
| Name | Required | Description | Default |
|---|---|---|---|
| item_id | Yes | File or folder to copy. | |
| new_name | No | Name for the copy (default: same name). | |
| account_id | No | Account ID or email address. Omit when only one account is signed in. | |
| destination_id | No | Destination folder ID ('root' allowed). | |
| destination_path | No | Destination folder path instead of destination_id. |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| summary | Yes | One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field. |
| operation_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false and destructiveHint=false but say nothing about synchronicity, so the description's disclosure that the copy runs in the background and returns an operation_id is genuinely additive. It still omits whether copying overwrites an existing name or what permissions are required, and does not reinforce the non-idempotent annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with zero filler; the core action is front-loaded and the async follow-up is placed immediately after it.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Because an output schema exists, the return values need no elaboration, and the description usefully clarifies that the immediate result is an operation_id rather than a finished copy. It stops short of noting the destination_id/destination_path trade-off, but that gap is minor.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all five parameters including the item_id/new_name/destination_id/destination_path distinctions are already documented. The description adds only the high-level notion of a destination folder, which the schema covers in more detail — baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb (Copy) plus resource (OneDrive file or folder) and target (another folder), so the agent can distinguish it from generic siblings like m365_update or drive_upload. It does not explicitly contrast with the nearest sibling m365_move, which handles relocation rather than duplication.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It tells the agent what to do after invoking (poll m365_get with resource='operation'), which is useful staging guidance, but it never states when to choose copy over move or upload. Usage is implied by the tool name rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
drive_uploadUpload FileA
Upload a local file to OneDrive, as a new file (parent_id or parent_path) or by replacing an existing file's contents (item_id). Reads from the local disk, inside the allowed folders only. Returns the OneDrive item.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | New file: name in OneDrive (default: local file name). | |
| item_id | No | Replace the contents of this existing file. | |
| if_exists | No | New file: what to do if the name is taken. | fail |
| parent_id | No | New file: destination folder ID ('root' allowed). | |
| account_id | No | Account ID or email address. Omit when only one account is signed in. | |
| local_path | Yes | Local file path inside the server's allowed folders. Hidden and secret files are refused. | |
| parent_path | No | New file: destination folder path, e.g. /Documents. |
Output Schema
| Name | Required | Description |
|---|---|---|
| item | Yes | |
| status | Yes | |
| summary | Yes | One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, idempotentHint=false, and destructiveHint=false. Beyond that, the description adds real context: reads occur from the local disk, only within allowed folders, hidden/secret files are refused, and the OneDrive item is returned. It doesn't cover permissions or rate limits, but it meaningfully augments the annotation profile.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the core action and mode split, then the disk-access constraint, then the return value. No filler; every clause carries information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description needn't detail return values, though it helpfully notes one is returned. For a non-idempotent write tool with seven parameters, it covers the local-path restrictions and mode selection well, but omits any note on auth/account scoping or what a replace-mode failure looks like.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds semantic grouping the schema lacks: it ties parent_id/parent_path to the 'new file' mode and item_id to the 'replace contents' mode, clarifying mutual exclusivity that the flat schema does not express.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (upload) and resource (a local file to OneDrive), and explicitly separates the two operating modes via the parameters that select them (parent_id/parent_path for new files vs item_id for replacement). An agent can distinguish this from drive_copy or drive_share without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly routes the agent to the correct mode by naming the parameters for each (new file vs replace). It does not, however, mention when not to use it or point to an alternative sibling (e.g., drive_copy for server-side copies), leaving some usage inference to the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_create_draftCreate Email DraftA
Create an unsent email draft to review, then send later with email_send(mode='draft'). Sends nothing. Returns the draft ID.
| Name | Required | Description | Default |
|---|---|---|---|
| cc | No | Cc recipients. | |
| to | Yes | Recipients (To). | |
| bcc | No | Bcc recipients. | |
| body | Yes | Message body. | |
| subject | Yes | Subject line. | |
| account_id | No | Account ID or email address. Omit when only one account is signed in. | |
| importance | No | Message importance. | |
| attachments | No | Local files to attach: at most 10, each at most 25 MB. | |
| body_format | No | Format of the body text you supply. | text |
Output Schema
| Name | Required | Description |
|---|---|---|
| cc | Yes | |
| to | Yes | |
| bcc | Yes | |
| subject | Yes | |
| summary | Yes | One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field. |
| draft_id | Yes | |
| web_link | Yes | |
| attachment_count | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false and destructiveHint=false, so the write-but-non-destructive profile is partly covered. The description adds real value beyond them: 'Sends nothing' clarifies no mail is dispatched, and 'Returns the draft ID' signals the response shape. It stops short of noting the draft is idempotent-or-not or attachment/auth constraints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short, front-loaded sentences with zero filler. Each sentence carries distinct information: purpose, non-sending behavior, and the follow-up send path.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 9 params fully documented in schema and an output schema present, the description does not need to explain fields or return values. It covers purpose, the send-nothing guarantee, and the handoff to email_send, which is sufficient for correct invocation; only minor edge contexts (account_id omission, attachment path rules) are left to the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% across all 9 parameters, so the schema already documents to/cc/bcc/body/subject/account_id/importance/attachments/body_format fully. The description adds no parameter-level detail beyond that, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Create an unsent email draft') and immediately clarifies it sends nothing, distinguishing it from email_send. An agent can tell it apart from email_send and email_reply without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names the alternative and the follow-up path explicitly ('then send later with email_send(mode="draft")'), which tells the agent this is the compose-and-review step. It gives clear use context but does not spell out when not to use it (e.g. sending directly).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_folder_emptyEmpty Mail FolderADestructiveIdempotent
Delete all messages in one mail folder, such as Junk Email or Deleted Items, up to max_messages per call. Subfolders are kept. Requires confirm=true after the user approves. Deleted messages cannot be restored with these tools.
| Name | Required | Description | Default |
|---|---|---|---|
| confirm | Yes | Must be true to delete every message in this folder; set only after the user approves. | |
| folder_id | Yes | Mail folder ID, or one of the aliases inbox, sent, drafts, deleted, junk, archive. | |
| account_id | No | Account ID or email address. Omit when only one account is signed in. | |
| max_messages | No | Most messages to delete in this call. |
Output Schema
| Name | Required | Description |
|---|---|---|
| deleted | Yes | |
| summary | Yes | One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field. |
| folder_id | Yes | |
| remaining | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true, but the description adds critical nuance they do not carry: the deletion is irreversible ('Deleted messages cannot be restored with these tools'), subfolders survive the operation, and the action is chunked ('up to max_messages per call'), meaning a single call may not fully empty a large folder. These are exactly the traits that change how an agent sequences the call.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, zero filler, front-loaded with the action and scope, followed by the destructive caveats. Every clause carries distinct information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be described. The description covers the safety profile, the confirm workflow, the batching limit, and the irreversibility, which is everything an agent needs before invoking a destructive bulk operation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds interpretation: 'up to max_messages per call' signals the parameter is a batch cap rather than a total, and the confirm sentence explains the approval gating the schema only states mechanically.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Delete all messages in one mail folder') with illustrative scope ('such as Junk Email or Deleted Items') and a key boundary ('Subfolders are kept'). An agent can distinguish this folder-level bulk purge from single-message deletion siblings without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides an operational precondition ('Requires confirm=true after the user approves') that implies a human-in-the-loop approval flow, which is useful routing context. However, it never contrasts this tool with the message-level delete path or states when emptying a folder is preferable to deleting individual messages.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_folder_mark_all_readMark Folder ReadAIdempotent
Mark every unread message in one mail folder as read, up to max_messages per call. If remaining_unread is above zero, call again. Use m365_update for a single message.
| Name | Required | Description | Default |
|---|---|---|---|
| folder_id | Yes | Mail folder ID, or one of the aliases inbox, sent, drafts, deleted, junk, archive. | |
| account_id | No | Account ID or email address. Omit when only one account is signed in. | |
| max_messages | No | Most messages to change in this call. |
Output Schema
| Name | Required | Description |
|---|---|---|
| marked | Yes | |
| summary | Yes | One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field. |
| folder_id | Yes | |
| remaining_unread | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnlyHint=false, idempotentHint=true, destructiveHint=false), and the description adds genuinely useful behavioral context beyond them: the per-call cap of max_messages, the need to loop while remaining_unread > 0, and the routing hint to m365_update for single messages. It does not spell out permission requirements, but the operational loop semantics are the key disclosure an agent needs here.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the core action and scope, followed by the iteration rule and the sibling routing. No filler or redundant restatement of the name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values (including remaining_unread) need not be explained, and the description references the field that drives the loop. Together with the annotations covering mutation safety and idempotency, an agent has everything needed to invoke and re-invoke this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so folder_id, account_id, and max_messages are all fully documented in the schema. The description only echoes max_messages' role as a per-call cap without adding format or constraint detail beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (mark as read), resource (every unread message in one mail folder), and scope (bulk, folder-wide) in the first clause. It also explicitly distinguishes itself from m365_update for single-message operations, so an agent can differentiate without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear iteration rule ('If remaining_unread is above zero, call again') and names the alternative for single-message edits (m365_update). It lacks explicit when-not-to-use guidance for the tool as a whole (e.g., preferring search-based filtering), but the batching contract is well communicated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_forwardForward EmailA
Forward an email to recipients the user names, with an optional note. Requires confirm=true after the user approves. Never infer recipients from other context.
| Name | Required | Description | Default |
|---|---|---|---|
| cc | No | Cc recipients. | |
| to | Yes | Recipients. | |
| bcc | No | Bcc recipients. | |
| comment | No | Note above the forwarded message. | |
| confirm | Yes | Must be true to forward this email; set only after the user approves. | |
| email_id | Yes | Email to forward. | |
| account_id | No | Account ID or email address. Omit when only one account is signed in. | |
| attachments | No | Local files to attach: at most 10, each at most 25 MB. |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| summary | Yes | One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field. |
| forwarded_id | Yes | |
| recipient_count | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare the write/non-idempotent/open-world profile, and the description adds genuinely non-structured behavior: an approval gate via confirm=true and an explicit prohibition on inferring recipients. Those are safety-relevant traits not derivable from the schema or annotations. It does not describe delivery outcome or failure modes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, each carrying a distinct constraint (action, approval gate, recipient-source prohibition). The core action is front-loaded with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation. For an 8-parameter mutation tool, the description covers the action, the confirmation workflow, and the key safety constraint. An agent has everything needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter (cc, bcc, comment, email_id, account_id, attachments) is already documented. The description only reinforces the confirm semantics, which the schema also states, so it adds little beyond the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb (Forward) plus resource (an email) plus the qualifying detail that recipients are user-named and the note is optional. This cleanly separates it from email_send and email_reply, which an agent can distinguish without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives real usage conditions: confirm=true is required and only after user approval, and recipients must never be inferred from other context. That is a clear when-to-use and a hard when-not rule. It stops short of naming the sibling alternatives (email_send/email_reply) for the non-forward cases.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_replyReply to EmailA
Reply to an email, either to the sender only (mode='sender') or to everyone on it (mode='all'). Requires confirm=true after the user approves the reply. Returns the conversation the reply joined.
| Name | Required | Description | Default |
|---|---|---|---|
| cc | No | Extra Cc recipients. | |
| body | Yes | Reply text. | |
| mode | Yes | sender: reply to the sender. all: reply all. | |
| confirm | Yes | Must be true to send this reply; set only after the user approves. | |
| email_id | Yes | Email to reply to. | |
| account_id | No | Account ID or email address. Omit when only one account is signed in. | |
| attachments | No | Local files to attach: at most 10, each at most 25 MB. | |
| body_format | No | Format of the body text you supply. | text |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| status | Yes | |
| summary | Yes | One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field. |
| in_reply_to | Yes | |
| conversation_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, idempotentHint=false, openWorldHint=true, so the mutation profile is covered. The description adds genuinely new behavior beyond the schema: the confirm-after-user-approval gate and the return of the joined conversation, both of which affect how the agent sequences the call.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the action and mode split, then the approval prerequisite, then the return. Every clause carries information and nothing is padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be explained, and annotations cover the safety profile; the description adds the approval gate that the schema alone only implies. Complete enough for correct invocation, though it omits any note about attachment limits or account selection that a caller might want surfaced.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter including mode, confirm, and attachments is already documented in the schema. The description restates mode and confirm semantics without adding syntax, limits, or resolution behavior beyond what the schema provides; baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (reply) and resource (an email), and splits the scope into the two mode values, so an agent can distinguish it from email_send or email_forward. It stops short of naming those siblings as alternatives, so differentiation is implicit rather than explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives the condition that selects each mode ('sender' vs 'all') and a hard usage gate: 'Requires confirm=true after the user approves the reply.' It does not contrast this tool with email_forward or email_send, so the agent gets clear context but no explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_rule_manageManage Inbox RuleA
Create, change, enable or disable, or reorder an Inbox rule. Rules that forward, redirect or delete mail require confirm=true because they act silently on future mail. Read rules with m365_list or m365_get; delete one with m365_delete. Returns the rule.
| Name | Required | Description | Default |
|---|---|---|---|
| rule | No | Rule definition. create requires display_name, conditions and actions; update applies only the supplied fields. | |
| action | Yes | What to do. | |
| confirm | No | Must be true to save a rule that forwards, redirects or deletes mail; set only after the user approves. | |
| rule_id | No | Existing rule (update, set_enabled, reorder). | |
| position | No | reorder: new position. before/after need relative_to_rule_id. | |
| account_id | No | Account ID or email address. Omit when only one account is signed in. | |
| is_enabled | No | set_enabled: turn the rule on (true) or off (false). | |
| relative_to_rule_id | No | reorder with before/after: the other rule. |
Output Schema
| Name | Required | Description |
|---|---|---|
| rule | Yes | |
| action | Yes | |
| summary | Yes | One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare it is not read-only, not idempotent, open-world, and not destructive; the description adds real behavioral context by disclosing that destructive-effect rules act silently on future mail and therefore require confirm=true, plus that the rule is returned. It doesn't spell out the consequence of confirm=false (rejection vs. silent drop) or auth/permission requirements, so it stops short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, zero filler. The capability statement comes first, the safety gate second, and sibling routing last — well front-loaded and each sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 8-parameter nested mutation tool with an output schema already documenting return values, the description covers all four action modes, the confirm safety requirement, and delegation to sibling tools for read/delete. Nothing needed to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so parameter docs already exist; the description still adds rationale the schema lacks, explaining why confirm is required (silent future-mail action) and that the call returns the rule. It does not, however, clarify action/parameter pairings (e.g., rule_id required for set_enabled/reorder), which the schema only partially implies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource and enumerates the four concrete modes (create, change, enable/disable, reorder), so the agent knows exactly which operations this tool covers. It also implicitly separates itself from read/delete siblings by naming them in the next sentence.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit routing is given: read rules with m365_list or m365_get, delete with m365_delete. It also states a conditional gate ('Rules that forward, redirect or delete mail require confirm=true'), which is exactly the when/when-not guidance an agent needs before invoking.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_sendSend EmailA
Send an email now: a new message (mode='new') or a draft you created earlier (mode='draft'). Requires confirm=true after the user approves the recipients and content. Cannot be undone. Never infer recipients.
| Name | Required | Description | Default |
|---|---|---|---|
| cc | No | Cc recipients. | |
| to | No | Recipients (To). | |
| bcc | No | Bcc recipients. | |
| body | No | Message body. | |
| mode | Yes | Send a new message or an existing draft. | |
| confirm | Yes | Must be true to send this email; set only after the user approves. | |
| subject | No | Subject line. | |
| draft_id | No | mode='draft': draft ID from email_create_draft. | |
| account_id | No | Account ID or email address. Omit when only one account is signed in. | |
| importance | No | Message importance. | |
| attachments | No | Local files to attach: at most 10, each at most 25 MB. | |
| body_format | No | Format of the body text you supply. | text |
| save_to_sent | No | mode='new': keep a copy in Sent Items. |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| status | Yes | |
| sent_at | Yes | |
| summary | Yes | One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field. |
| draft_id | Yes | |
| recipient_count | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare the safety profile (readOnly=false, idempotent=false, openWorld=true), so the bar is lower, and the description still adds the critical non-annotation fact: 'Cannot be undone.' That, plus the confirmation gate, is meaningful behavioral context. It stops short of permission/account requirements or delivery failure behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, no filler, with the action and mode split front-loaded and the irreversible/confinement constraints placed after. Every sentence carries a distinct rule.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the schema itself carries parameter detail. The description covers the irreversibility, the confirmation precondition, and recipient strictness, which are the highest-risk facts for this tool; deeper detail (account scoping, attachment limits) lives in the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all 13 parameters including mode, confirm, and draft_id. The description restates mode semantics and the confirm gate, adding only marginal framing ('a draft you created earlier') beyond what the schema says.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (send) and resource (email) and immediately splits the behavior into the two supported modes, mode='new' vs mode='draft'. This distinguishes it from sibling email_create_draft (which only stages) and from email_reply/email_forward.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a hard precondition (confirm=true only after the user approves recipients and content) and an explicit prohibition ('Never infer recipients'), which is exactly the kind of when-to-use guidance an agent needs. It does not explicitly name the alternative tools (create_draft, reply, forward) for cases where sending is premature.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
m365_createCreate ItemA
Create a mail folder, calendar, contact, contact folder or OneDrive folder. Supply the sub-object that matches resource. Not for emails (email_create_draft), events (calendar_create_event), inbox rules (email_rule_manage) or uploading files (drive_upload). Returns the created item.
| Name | Required | Description | Default |
|---|---|---|---|
| contact | No | Required when resource='contact'. | |
| calendar | No | Required when resource='calendar'. | |
| resource | Yes | Type of item to create. | |
| account_id | No | Account ID or email address. Omit when only one account is signed in. | |
| drive_folder | No | Required when resource='drive_item' (creates a folder). | |
| email_folder | No | Required when resource='email_folder'. | |
| contact_folder | No | Required when resource='contact_folder'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| item | Yes | |
| summary | Yes | One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field. |
| resource | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already disclose the safety profile (not read-only, not idempotent, not destructive, open-world), so the description only needs to add context. It adds that the call returns the created item and that a matching sub-object is required, but says nothing about duplicate-name handling (the schema-level 'if_exists' default of 'fail' is significant for creation) or what happens on partial failure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences: capability first, the key structural rule second, exclusions third. No filler, no restatement of the title, and the highest-value routing information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 7-parameter polymorphic creator with nested objects and an output schema, the description covers capability, dispatch rule, exclusions and return shape adequately. The only gap is behavioral detail on idempotency and name collisions, which the annotations and schema partially cover.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and each nested object is already labelled 'Required when resource=...', so the schema fully documents the polymorphic contract. The description's 'Supply the sub-object that matches resource' restates that relationship at a high level without adding format, default, or edge-case detail, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb ('Create') and enumerates the exact resource types it handles (mail folder, calendar, contact, contact folder, OneDrive folder), then explicitly routes four excluded operations to named siblings. An agent can distinguish this from email_create_draft, calendar_create_event and drive_upload without reading any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-not guidance is given for four adjacent operations, each paired with the sibling that should be used instead. It also gives the positive selection rule: supply the sub-object that matches 'resource'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
m365_deleteDelete ItemADestructive
Delete one email, mail folder, inbox rule, event, calendar, contact, contact folder or OneDrive item. Always requires confirm=true after the user approves. Deleting a meeting you organise sends cancellations to its attendees. OneDrive items go to the recycle bin. Returns what happened and whether it can be recovered.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Item ID. Aliases are not accepted. | |
| confirm | Yes | Must be true to delete this item; set only after the user approves. | |
| resource | Yes | Type of item. | |
| account_id | No | Account ID or email address. Omit when only one account is signed in. | |
| cancellation_message | No | event only: note sent with the cancellation when you organise the meeting. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| status | Yes | |
| summary | Yes | One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field. |
| resource | Yes | |
| recoverable | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=false and readOnlyHint=false, so the safety profile is covered. The description adds genuinely useful context beyond that: meeting deletions trigger attendee cancellations, OneDrive items go to the recycle bin, and the result reports recoverability. It stops short of noting auth/permission requirements or scope limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the resource scope, then the confirm requirement, then the side effects. Every sentence carries distinct information with no padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive multi-resource tool with full schema coverage, an output schema, and complete annotations, the description supplies the missing human-facing context (confirm precondition, cancellation side effect, recycle-bin behavior). Only auth/permission expectations are absent, which is a minor gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter including confirm, id, and cancellation_message is already documented. The description restates the confirm gate and implies the recoverability outcome but adds no new parameter-level syntax or format detail, making the baseline 3 appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Delete) plus an explicit enumeration of the eight supported resource types, so the agent knows exactly what scope of items this applies to. It is clearly distinguishable from sibling mutation tools like m365_update or m365_move.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear precondition ('Always requires confirm=true after the user approves') that governs invocation, and the resource enum tells the agent which target types are valid. It does not name alternatives or explicitly state when not to use it (e.g., prefer move/archive instead of delete), so it falls short of a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
m365_getGet ItemARead-onlyIdempotent
Read one item whose ID you already have: an email with its body, an event with attendees, a contact, a mail or contact folder, an inbox rule, a calendar, a OneDrive item's details, or the status of a copy started with drive_copy (resource='operation'). Use m365_list or m365_search to find IDs. Use m365_get_content to download files or attachments. Returns the item.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Item ID from a previous result (for operation: the operation_id). Aliases are accepted for email_folder, calendar (default) and drive_item (root). | |
| path | No | drive_item only: OneDrive path instead of id. | |
| refresh | No | Bypass the cache and fetch fresh data. | |
| resource | Yes | Type of item. | |
| account_id | No | Account ID or email address. Omit when only one account is signed in. | |
| include_body | No | email and event: include the body text. | |
| body_max_chars | No | email and event: truncate the body after this many characters. |
Output Schema
| Name | Required | Description |
|---|---|---|
| item | Yes | |
| summary | Yes | One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field. |
| resource | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, so the safety profile is covered. The description adds a genuine behavioral precondition (requires an ID you already have) and cross-tool dependency (resource='operation' reflects a drive_copy job), which the structured fields do not convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, zero padding, front-loaded with the core requirement (needs an ID). Each sentence routes to a different sibling or states a precondition, so every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value detail is unnecessary, and the description plus 100%-covered schema plus safety annotations give an agent everything needed to select and invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so id/path/refresh/include_body/body_max_chars are all documented in the schema. The description only adds the mapping of resource='operation' to a drive_copy operation, a marginal gain over the enum schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Read one item') and enumerates the concrete resource types it covers (email with body, event with attendees, contact, folders, inbox rule, calendar, OneDrive item, copy operation status). This lets an agent distinguish it from m365_list, m365_search, and m365_get_content without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the alternatives and the condition for each: use m365_list/m365_search to find IDs, use m365_get_content to download files or attachments, and use this tool only when the ID is already known. No inference required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
m365_get_contentGet ContentAIdempotent
Get the content of an item rather than its details: save a OneDrive file or an email attachment to a local file (mode='download'), get a temporary download link for a OneDrive file (mode='download_url'), or export a contact as a vCard (mode='vcard'). Writes to the local disk only inside the allowed folders. Use m365_get for item details.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | OneDrive item ID, email ID or contact ID. | |
| mode | Yes | download: drive_item file or email attachment to save_path. download_url: drive_item file only. vcard: contact only. | |
| resource | Yes | Type of item. | |
| overwrite | No | Replace save_path if it already exists. | |
| save_path | No | Local file path inside the server's allowed folders. Hidden and secret files are refused. | |
| account_id | No | Account ID or email address. Omit when only one account is signed in. | |
| attachment_id | No | email + download only: attachment ID from m365_get(resource='email'). |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| mode | Yes | |
| size | Yes | |
| vcard | Yes | |
| summary | Yes | One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field. |
| resource | Yes | |
| mime_type | Yes | |
| saved_path | Yes | |
| download_url | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations mark readOnlyHint=false with destructiveHint=false, and the description explains why: it writes to the local disk, but only inside allowed folders, and that hidden/secret files are refused. It does not restate the write nature so much as bound it, which is genuinely additive. Overwrite semantics and the temp-link lifetime are left to the schema/annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three clauses and a routing sentence, with the core distinction (content vs. details) front-loaded and the mode breakdown following. No filler or repetition of the title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return format is covered elsewhere. The description supplies the write-location constraint, the mode map, and the sibling routing needed to call it correctly; nothing an agent needs is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter is already documented in the schema, including the mode enum's resource restrictions and the save_path folder constraint. The description reinforces the mode-to-resource mapping but adds no format or edge-case detail beyond it. Baseline 3 for full schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete verb (get content), the resource classes (OneDrive file, email attachment, contact), and explicitly contrasts itself with the sibling m365_get ('Get the content of an item rather than its details'). An agent can distinguish it from m365_get without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Enumerates each mode and the resource it applies to ('mode=download', 'mode=download_url', 'mode=vcard'), and names the alternative tool plus the condition that selects it ('Use m365_get for item details'). Selection criteria are explicit rather than inferred.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
m365_listList ItemsARead-onlyIdempotent
Browse items of one type in a known place: emails in a mail folder, events in a time window, calendars, contacts, contact folders, mail folders, inbox rules, or files in a OneDrive folder (optionally as a tree). Use this when you know where to look. Use m365_search to find items by text, and m365_get when you already have an ID. Returns compact items plus next_cursor for more.
| Name | Required | Description | Default |
|---|---|---|---|
| end | No | event only: window end (default start + 7 days; at most 366 days after start). | |
| path | No | drive_item only: OneDrive folder path instead of container_id, e.g. /Documents/Tax. | |
| limit | No | Maximum number of items to return. | |
| start | No | event only: window start (default now). RFC 3339 with offset. | |
| cursor | No | next_cursor from the previous page; keep all other arguments the same. | |
| refresh | No | Bypass the cache and fetch fresh data. | |
| resource | Yes | Type of item to list. | |
| item_type | No | drive_item only: which kinds of item to return. | all |
| max_depth | No | Tree depth when recursive=true. | |
| recursive | No | email_folder and drive_item only: return a nested tree of folders instead of one level. | |
| account_id | No | Account ID or email address. Omit when only one account is signed in. | |
| container_id | No | Where to list. email: mail folder ID or alias (default inbox). email_folder: parent folder (default: top level). event: calendar ID (default: your default calendar). contact: contact folder ID (default: all contacts). drive_item: parent folder ID (default: OneDrive root). Not used for calendar, contact_folder and email_rule. | |
| email_filter | No | email only: filters applied by Microsoft 365 (all must match). | |
| include_hidden | No | email_folder only: include hidden folders. |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | Yes | |
| summary | Yes | One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field. |
| has_more | Yes | |
| resource | Yes | |
| next_cursor | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, openWorldHint=true, so the safety profile is covered. The description adds genuinely useful behavioral context beyond that: it returns 'compact items plus next_cursor for more', disclosing pagination and payload shape. It does not discuss caching semantics (left to the refresh param) or per-account behavior, but the added context is real.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the capability and scope, then routing, then return shape. No filler, no repetition of schema content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 14-parameter listing tool with a rich schema and an output schema, the description covers selection, alternatives and pagination adequately; return values are delegated to the output schema as permitted. Minor gap: nothing about multi-account behavior (account_id) or cache staleness, though both are documented in the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% across 14 parameters, so the schema already documents resource enum values, filters, date windows, recursion and cursor reuse. The description only names the resource families and the tree option, adding no syntax or format detail beyond the schema. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource set: 'Browse items of one type in a known place', then enumerates the concrete resource types (emails in a mail folder, events in a time window, calendars, contacts, folders, rules, OneDrive files). It also names the two siblings it is not (m365_search, m365_get), so an agent can distinguish it without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit selection condition ('Use this when you know where to look') and routes the agent to alternatives: m365_search for text lookup, m365_get when an ID is already known. Both when-to-use and when-not-to-use are covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
m365_moveMove ItemA
Move an email, mail folder, contact or OneDrive item to another folder. Moving an email to 'archive' archives it; moving a contact places it in a contact folder. Moved emails and contacts get a new ID, which is returned: use it for later calls.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Item to move. | |
| new_name | No | drive_item only: rename while moving. | |
| resource | Yes | Type of item. | |
| account_id | No | Account ID or email address. Omit when only one account is signed in. | |
| destination_id | No | Destination folder. email: mail folder ID or alias (archive, inbox, junk, deleted, drafts, sent). email_folder: mail folder ID or 'root'. contact: contact folder ID or 'default'. drive_item: folder ID or 'root'. | |
| destination_path | No | drive_item only: destination folder path instead of destination_id. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| status | Yes | |
| summary | Yes | One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field. |
| resource | Yes | |
| previous_id | Yes | |
| destination_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare non-readOnly, non-idempotent, non-destructive, openWorld. The description adds a genuinely useful behavioral fact not in the structured data: moved emails and contacts receive a NEW id that is returned and must be used for later calls. That identity-change side effect is exactly the kind of context an agent needs after a mutation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the action and accepted resources, followed by the per-resource behavior and the id-change consequence. Zero filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With annotations carrying the safety profile and an output schema present, the description needn't explain return values, yet it helpfully flags the returned new id. Coverage is strong; only the absence of usage routing against siblings leaves a small gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and every parameter (id, new_name, resource, account_id, destination_id, destination_path) is already documented in the schema. The description's per-resource destination nuance ('archive' archives) adds only marginal value beyond that baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Move') and enumerates the exact resource types it accepts (email, mail folder, contact, OneDrive item), matching the schema enum. It stops short of distinguishing itself from the sibling m365_update, which an agent might otherwise confuse for relocating items.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides implied usage guidance by explaining what happens per resource type (email to 'archive' archives it, a contact goes into a contact folder), but never states when to choose this over m365_update or drive_copy, nor any prerequisites such as required permissions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
m365_searchSearchARead-onlyIdempotent
Find emails, events, contacts or OneDrive files by free text when you do not know where they are. Search one type or several at once. Do not use it to browse a folder (m365_list) or open a known ID (m365_get). Returns matching items labelled by resource, newest first, plus next_cursor.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of items to return. | |
| query | Yes | Words to search for. Plain text; the server handles quoting. | |
| cursor | No | next_cursor from the previous page; keep all other arguments the same. | |
| event_end | No | Event search window end (default: 365 days ahead). | |
| resources | No | Which item types to search. Default: all four. | |
| account_id | No | Account ID or email address. Omit when only one account is signed in. | |
| event_start | No | Event search window start (default: 90 days ago). | |
| email_folder_id | No | Mail folder ID, or one of the aliases inbox, sent, drafts, deleted, junk, archive. |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | Yes | |
| query | Yes | |
| summary | Yes | One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field. |
| has_more | Yes | |
| next_cursor | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, openWorldHint=true, and destructiveHint=false, so the safety profile is covered. The description adds return ordering ('newest first') and pagination info ('next_cursor'), which are useful behavioral details beyond the annotations. It does not mention rate limits or auth requirements, so not a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tightly written sentences, front-loaded with purpose and followed immediately by routing exclusions and return behavior. Every sentence carries distinct, useful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the rich annotations, 100% schema description coverage, and an output schema, the description covers everything an agent needs to select and invoke the tool correctly: purpose, alternatives, and the return shape including pagination. No critical gaps remain for the agent's decision.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema documents all eight parameters with descriptions, defaults, and constraints. The description only implicitly references query and resources ('by free text', 'one type or several at once'), adding little beyond what the schema already provides, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Find') and enumerates the resource types (emails, events, contacts, OneDrive files), with the key qualifier 'by free text'. It explicitly distinguishes itself from siblings m365_list and m365_get, so an agent can route correctly without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides an explicit when-to-use condition ('when you do not know where they are') and two when-not-to-use conditions with named alternatives: 'Do not use it to browse a folder (m365_list) or open a known ID (m365_get).' This is about as clear as usage guidance gets.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
m365_updateUpdate ItemAIdempotent
Change properties of an existing email, mail folder, contact or OneDrive item: mark read or unread, flag, set importance or categories, Focused/Other, rename folders and files, or edit contact details. Supply the *_changes object that matches resource. Not for events (calendar_update_event), inbox rules (email_rule_manage) or file contents (drive_upload). Returns the changed field names.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Item ID. | |
| resource | Yes | Type of item. | |
| account_id | No | Account ID or email address. Omit when only one account is signed in. | |
| email_changes | No | Required when resource='email'. | |
| contact_changes | No | Required when resource='contact'. Only supplied fields change; lists replace the existing list. | |
| drive_item_changes | No | Required when resource='drive_item'. | |
| email_folder_changes | No | Required when resource='email_folder'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| status | Yes | |
| summary | Yes | One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field. |
| resource | Yes | |
| changed_fields | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, idempotentHint=true and destructiveHint=false, so the safety profile is covered. The description adds some context (the *_changes object must match the resource) but says nothing about permissions, how categories_add/remove/set interact, or partial-update semantics beyond what the schema states.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense but front-loaded: the capability list, then the invocation rule, then the exclusions, then the return summary. Every clause carries distinct information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the resource types, mutation surface, invocation pattern and sibling boundaries, which is enough to call it correctly. Minor gaps remain on authorization needs and field-conflict behavior, and the return-value sentence is largely redundant given an output schema exists.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents every parameter including the per-resource conditional requirements. The description's contribution ('Supply the *_changes object that matches resource') only restates the resource-to-object linkage already encoded in the schema's 'Required when resource=...' descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Change properties) plus the resource set (email, mail folder, contact, OneDrive item) and enumerates the concrete mutations available (read/unread, flag, importance, categories, Focused/Other, rename, contact details). It also distinguishes itself from siblings by naming what it does NOT cover.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-not rules with named alternatives: not for events (calendar_update_event), inbox rules (email_rule_manage), or file contents (drive_upload). It also tells the caller how to invoke it: supply the *_changes object matching the resource.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
102 tool updates
v1.0.0- Removed
account_authenticate - Removed
account_complete_auth - Removed
account_list - Removed
cache_get_stats - Removed
cache_invalidate - Removed
cache_task_get_status - Removed
cache_task_list - Removed
cache_warming_status - Removed
calendar_check_availability - Removed
calendar_create_calendar - Changed
calendar_create_event43 fields changed- added
Input schema / $schemaAdded value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / account_id / descriptionAdded value: +"Account ID or email address. Omit when only one account is signed in." - added
Input schema / properties / account_id / maxLengthAdded value: +320 - added
Input schema / properties / account_id / minLengthAdded value: +1 - removed
Input schema / properties / attendees / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } -] - removed
Input schema / properties / attendees / defaultRemoved value: -null - added
Input schema / properties / attendees / descriptionAdded value: +"People to invite." - added
Input schema / properties / attendees / itemsAdded value: +{ + "additionalProperties": false, + "description": "Meeting attendee.", + "properties": { + "address": { + "description": "Email address, e.g. jane@example.com.", + "format": "email", + "maxLength": 320, + "minLength": 3, + "type": "string" + }, + "name": { + "description": "Display name.", + "maxLength": 255, + "type": "string" + }, + "type": { + "default": "required", + "description": "Attendance type.", + "enum": [ + "required", + "optional" + ], + "type": "string" + } + }, + "required": [ + "address" + ], + "type": "object" +} - added
Input schema / properties / attendees / maxItemsAdded value: +500 - added
Input schema / properties / attendees / typeAdded value: +"array" - removed
Input schema / properties / body / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - removed
Input schema / properties / body / defaultRemoved value: -null - added
Input schema / properties / body / descriptionAdded value: +"Description." - added
Input schema / properties / body / maxLengthAdded value: +100000 - added
Input schema / properties / body / typeAdded value: +"string" - added
Input schema / properties / body_formatAdded value: +{ + "default": "text", + "description": "Format of the body text you supply.", + "enum": [ + "text", + "html" + ], + "type": "string" +} - added
Input schema / properties / calendar_idAdded value: +{ + "description": "Calendar ID (default: your default calendar).", + "maxLength": 1024, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / confirmAdded value: +{ + "default": false, + "description": "Must be true to send invitations to the attendees; set only after the user approves.", + "type": "boolean" +} - added
Input schema / properties / end / descriptionAdded value: +"RFC 3339 date-time with offset, e.g. 2026-10-01T09:00:00+09:30." - added
Input schema / properties / end / formatAdded value: +"date-time" - added
Input schema / properties / is_all_dayAdded value: +{ + "description": "All-day event (start and end at midnight in time_zone).", + "type": "boolean" +} - removed
Input schema / properties / location / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - removed
Input schema / properties / location / defaultRemoved value: -null - added
Input schema / properties / location / descriptionAdded value: +"Location text." - added
Input schema / properties / location / maxLengthAdded value: +255 - added
Input schema / properties / location / typeAdded value: +"string" - added
Input schema / properties / reminder_minutesAdded value: +{ + "description": "Reminder before start, in minutes.", + "maximum": 40320, + "minimum": 0, + "type": "integer" +} - added
Input schema / properties / show_asAdded value: +{ + "description": "How the time shows in your calendar.", + "enum": [ + "free", + "tentative", + "busy", + "oof", + "workingElsewhere" + ], + "type": "string" +} - added
Input schema / properties / start / descriptionAdded value: +"RFC 3339 date-time with offset, e.g. 2026-10-01T09:00:00+09:30." - added
Input schema / properties / start / formatAdded value: +"date-time" - added
Input schema / properties / subject / descriptionAdded value: +"Title." - added
Input schema / properties / subject / maxLengthAdded value: +255 - added
Input schema / properties / subject / minLengthAdded value: +1 - added
Input schema / properties / time_zoneAdded value: +{ + "description": "IANA time-zone name, e.g. Australia/Adelaide. Defaults to the mailbox time zone.", + "maxLength": 64, + "minLength": 1, + "type": "string" +} - removed
Input schema / properties / timezoneRemoved value: -{ - "default": "UTC", - "type": "string" -} - changed
Input schema / requiredPrevious value: -[ - "account_id", - "subject", - "start", - "end" -]New value: +[ + "subject", + "start", + "end" +] - added
Output schema / $defsAdded value: +{ + "attendee": { + "additionalProperties": false, + "description": "Event attendee and their response.", + "properties": { + "address": { + "type": "string" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "response": { + "enum": [ + "none", + "organizer", + "tentativelyAccepted", + "accepted", + "declined", + "notResponded" + ] + }, + "type": { + "enum": [ + "required", + "optional", + "resource" + ] + } + }, + "required": [ + "name", + "address", + "type", + "response" + ], + "type": "object" + }, + "event_detail": { + "additionalProperties": false, + "description": "Event from m365_get. recurrence is a read-only human summary.", + "properties": { + "attendee_count": { + "minimum": 0, + "type": "integer" + }, + "attendees": { + "items": { + "$ref": "#/$defs/attendee" + }, + "type": "array" + }, + "body": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "body_truncated": { + "type": "boolean" + }, + "calendar_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "end": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "is_all_day": { + "type": "boolean" + }, + "is_organizer": { + "type": "boolean" + }, + "location": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "my_response": { + "enum": [ + "none", + "organizer", + "tentativelyAccepted", + "accepted", + "declined", + "notResponded" + ] + }, + "organizer": { + "anyOf": [ + { + "$ref": "#/$defs/recipient" + }, + { + "type": "null" + } + ] + }, + "preview": { + "anyOf": [ + { + "maxLength": 255, + "type": "string" + }, + { + "type": "null" + } + ] + }, + "recurrence": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "show_as": { + "enum": [ + "free", + "tentative", + "busy", + "oof", + "workingElsewhere", + "unknown" + ] + }, + "start": { + "format": "date-time", + "type": "string" + }, + "subject": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "time_zone": { + "type": "string" + }, + "web_link": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "id", + "subject", + "start", + "end", + "time_zone", + "is_all_day", + "location", + "organizer", + "is_organizer", + "my_response", + "show_as", + "attendee_count", + "calendar_id", + "preview", + "body", + "body_truncated", + "attendees", + "web_link", + "recurrence" + ], + "type": "object" + }, + "recipient": { + "additionalProperties": false, + "description": "A person's name and address.", + "properties": { + "address": { + "type": "string" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "name", + "address" + ], + "type": "object" + } +} - added
Output schema / $schemaAdded value: +"https://json-schema.org/draft/2020-12/schema" - changed
Output schema / additionalPropertiesPrevious value: -trueNew value: +false - added
Output schema / descriptionAdded value: +"The created event." - added
Output schema / propertiesAdded value: +{ + "event": { + "$ref": "#/$defs/event_detail" + }, + "invitations_sent": { + "type": "boolean" + }, + "summary": { + "description": "One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field.", + "type": "string" + } +} - added
Output schema / requiredAdded value: +[ + "event", + "invitations_sent", + "summary" +]
- Removed
calendar_delete_calendar - Removed
calendar_delete_event - Added
calendar_find_availability - Added
calendar_forward - Removed
calendar_forward_event - Removed
calendar_get_event - Removed
calendar_get_free_busy - Removed
calendar_list_calendars - Removed
calendar_list_events - Removed
calendar_propose_new_time - Added
calendar_respond - Removed
calendar_respond_event - Changed
calendar_update_event18 fields changed- added
Input schema / $schemaAdded value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / account_id / descriptionAdded value: +"Account ID or email address. Omit when only one account is signed in." - added
Input schema / properties / account_id / maxLengthAdded value: +320 - added
Input schema / properties / account_id / minLengthAdded value: +1 - added
Input schema / properties / changesAdded value: +{ + "additionalProperties": false, + "description": "Fields to change (at least one).", + "minProperties": 1, + "properties": { + "attendees_add": { + "description": "Attendees to add.", + "items": { + "additionalProperties": false, + "description": "Meeting attendee.", + "properties": { + "address": { + "description": "Email address, e.g. jane@example.com.", + "format": "email", + "maxLength": 320, + "minLength": 3, + "type": "string" + }, + "name": { + "description": "Display name.", + "maxLength": 255, + "type": "string" + }, + "type": { + "default": "required", + "description": "Attendance type.", + "enum": [ + "required", + "optional" + ], + "type": "string" + } + }, + "required": [ + "address" + ], + "type": "object" + }, + "maxItems": 500, + "minItems": 1, + "type": "array" + }, + "attendees_remove": { + "description": "Attendee addresses to remove.", + "items": { + "description": "Email address, e.g. jane@example.com.", + "format": "email", + "maxLength": 320, + "minLength": 3, + "type": "string" + }, + "maxItems": 500, + "minItems": 1, + "type": "array", + "uniqueItems": true + }, + "attendees_set": { + "description": "Replace the attendee list.", + "items": { + "additionalProperties": false, + "description": "Meeting attendee.", + "properties": { + "address": { + "description": "Email address, e.g. jane@example.com.", + "format": "email", + "maxLength": 320, + "minLength": 3, + "type": "string" + }, + "name": { + "description": "Display name.", + "maxLength": 255, + "type": "string" + }, + "type": { + "default": "required", + "description": "Attendance type.", + "enum": [ + "required", + "optional" + ], + "type": "string" + } + }, + "required": [ + "address" + ], + "type": "object" + }, + "maxItems": 500, + "type": "array" + }, + "body": { + "description": "Description.", + "maxLength": 100000, + "type": "string" + }, + "body_format": { + "default": "text", + "description": "Format of the body text you supply.", + "enum": [ + "text", + "html" + ], + "type": "string" + }, + "end": { + "description": "RFC 3339 date-time with offset, e.g. 2026-10-01T09:00:00+09:30.", + "format": "date-time", + "type": "string" + }, + "is_all_day": { + "description": "All-day event (start and end at midnight in time_zone).", + "type": "boolean" + }, + "location": { + "description": "Location text.", + "maxLength": 255, + "type": "string" + }, + "reminder_minutes": { + "description": "Reminder before start, in minutes.", + "maximum": 40320, + "minimum": 0, + "type": "integer" + }, + "show_as": { + "description": "How the time shows in your calendar.", + "enum": [ + "free", + "tentative", + "busy", + "oof", + "workingElsewhere" + ], + "type": "string" + }, + "start": { + "description": "RFC 3339 date-time with offset, e.g. 2026-10-01T09:00:00+09:30.", + "format": "date-time", + "type": "string" + }, + "subject": { + "description": "Title.", + "maxLength": 255, + "minLength": 1, + "type": "string" + }, + "time_zone": { + "description": "IANA time-zone name, e.g. Australia/Adelaide. Defaults to the mailbox time zone.", + "maxLength": 64, + "minLength": 1, + "type": "string" + } + }, + "type": "object" +} - added
Input schema / properties / confirmAdded value: +{ + "default": false, + "description": "Must be true to send updates to the attendees; set only after the user approves.", + "type": "boolean" +} - added
Input schema / properties / event_id / descriptionAdded value: +"Event to change." - added
Input schema / properties / event_id / maxLengthAdded value: +1024 - added
Input schema / properties / event_id / minLengthAdded value: +1 - removed
Input schema / properties / updatesRemoved value: -{ - "additionalProperties": true, - "type": "object" -} - changed
Input schema / requiredPrevious value: -[ - "event_id", - "updates", - "account_id" -]New value: +[ + "event_id", + "changes" +] - added
Output schema / $defsAdded value: +{ + "attendee": { + "additionalProperties": false, + "description": "Event attendee and their response.", + "properties": { + "address": { + "type": "string" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "response": { + "enum": [ + "none", + "organizer", + "tentativelyAccepted", + "accepted", + "declined", + "notResponded" + ] + }, + "type": { + "enum": [ + "required", + "optional", + "resource" + ] + } + }, + "required": [ + "name", + "address", + "type", + "response" + ], + "type": "object" + }, + "event_detail": { + "additionalProperties": false, + "description": "Event from m365_get. recurrence is a read-only human summary.", + "properties": { + "attendee_count": { + "minimum": 0, + "type": "integer" + }, + "attendees": { + "items": { + "$ref": "#/$defs/attendee" + }, + "type": "array" + }, + "body": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "body_truncated": { + "type": "boolean" + }, + "calendar_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "end": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "is_all_day": { + "type": "boolean" + }, + "is_organizer": { + "type": "boolean" + }, + "location": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "my_response": { + "enum": [ + "none", + "organizer", + "tentativelyAccepted", + "accepted", + "declined", + "notResponded" + ] + }, + "organizer": { + "anyOf": [ + { + "$ref": "#/$defs/recipient" + }, + { + "type": "null" + } + ] + }, + "preview": { + "anyOf": [ + { + "maxLength": 255, + "type": "string" + }, + { + "type": "null" + } + ] + }, + "recurrence": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "show_as": { + "enum": [ + "free", + "tentative", + "busy", + "oof", + "workingElsewhere", + "unknown" + ] + }, + "start": { + "format": "date-time", + "type": "string" + }, + "subject": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "time_zone": { + "type": "string" + }, + "web_link": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "id", + "subject", + "start", + "end", + "time_zone", + "is_all_day", + "location", + "organizer", + "is_organizer", + "my_response", + "show_as", + "attendee_count", + "calendar_id", + "preview", + "body", + "body_truncated", + "attendees", + "web_link", + "recurrence" + ], + "type": "object" + }, + "recipient": { + "additionalProperties": false, + "description": "A person's name and address.", + "properties": { + "address": { + "type": "string" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "name", + "address" + ], + "type": "object" + } +} - added
Output schema / $schemaAdded value: +"https://json-schema.org/draft/2020-12/schema" - changed
Output schema / additionalPropertiesPrevious value: -trueNew value: +false - added
Output schema / descriptionAdded value: +"The updated event." - added
Output schema / propertiesAdded value: +{ + "attendees_notified": { + "type": "boolean" + }, + "changed_fields": { + "items": { + "type": "string" + }, + "type": "array" + }, + "event": { + "$ref": "#/$defs/event_detail" + }, + "summary": { + "description": "One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field.", + "type": "string" + } +} - added
Output schema / requiredAdded value: +[ + "event", + "attendees_notified", + "changed_fields", + "summary" +]
- Removed
contact_add_to_list - Removed
contact_create - Removed
contact_create_list - Removed
contact_delete - Removed
contact_export - Removed
contact_get - Removed
contact_list - Removed
contact_update - Added
drive_copy - Added
drive_share - Added
drive_upload - Removed
email_add_category - Removed
email_archive - Changed
email_create_draft40 fields changed- added
Input schema / $schemaAdded value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / account_id / descriptionAdded value: +"Account ID or email address. Omit when only one account is signed in." - added
Input schema / properties / account_id / maxLengthAdded value: +320 - added
Input schema / properties / account_id / minLengthAdded value: +1 - removed
Input schema / properties / attachments / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } -] - removed
Input schema / properties / attachments / defaultRemoved value: -null - added
Input schema / properties / attachments / descriptionAdded value: +"Local files to attach: at most 10, each at most 25 MB." - added
Input schema / properties / attachments / itemsAdded value: +{ + "description": "Local file path inside the server's allowed folders. Hidden and secret files are refused.", + "maxLength": 4096, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / attachments / maxItemsAdded value: +10 - added
Input schema / properties / attachments / typeAdded value: +"array" - added
Input schema / properties / attachments / uniqueItemsAdded value: +true - added
Input schema / properties / bccAdded value: +{ + "description": "Bcc recipients.", + "items": { + "description": "Email address, e.g. jane@example.com.", + "format": "email", + "maxLength": 320, + "minLength": 3, + "type": "string" + }, + "maxItems": 500, + "type": "array", + "uniqueItems": true +} - added
Input schema / properties / body / descriptionAdded value: +"Message body." - added
Input schema / properties / body / maxLengthAdded value: +1000000 - added
Input schema / properties / body_formatAdded value: +{ + "default": "text", + "description": "Format of the body text you supply.", + "enum": [ + "text", + "html" + ], + "type": "string" +} - removed
Input schema / properties / cc / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } -] - removed
Input schema / properties / cc / defaultRemoved value: -null - added
Input schema / properties / cc / descriptionAdded value: +"Cc recipients." - added
Input schema / properties / cc / itemsAdded value: +{ + "description": "Email address, e.g. jane@example.com.", + "format": "email", + "maxLength": 320, + "minLength": 3, + "type": "string" +} - added
Input schema / properties / cc / maxItemsAdded value: +500 - added
Input schema / properties / cc / typeAdded value: +"array" - added
Input schema / properties / cc / uniqueItemsAdded value: +true - added
Input schema / properties / importanceAdded value: +{ + "description": "Message importance.", + "enum": [ + "low", + "normal", + "high" + ], + "type": "string" +} - added
Input schema / properties / subject / descriptionAdded value: +"Subject line." - added
Input schema / properties / subject / maxLengthAdded value: +998 - added
Input schema / properties / subject / minLengthAdded value: +1 - removed
Input schema / properties / to / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "items": { - "type": "string" - }, - "type": "array" - } -] - added
Input schema / properties / to / descriptionAdded value: +"Recipients (To)." - added
Input schema / properties / to / itemsAdded value: +{ + "description": "Email address, e.g. jane@example.com.", + "format": "email", + "maxLength": 320, + "minLength": 3, + "type": "string" +} - added
Input schema / properties / to / maxItemsAdded value: +500 - added
Input schema / properties / to / minItemsAdded value: +1 - added
Input schema / properties / to / typeAdded value: +"array" - added
Input schema / properties / to / uniqueItemsAdded value: +true - changed
Input schema / requiredPrevious value: -[ - "account_id", - "to", - "subject", - "body" -]New value: +[ + "to", + "subject", + "body" +] - added
Output schema / $schemaAdded value: +"https://json-schema.org/draft/2020-12/schema" - changed
Output schema / additionalPropertiesPrevious value: -trueNew value: +false - added
Output schema / descriptionAdded value: +"The created draft." - added
Output schema / propertiesAdded value: +{ + "attachment_count": { + "minimum": 0, + "type": "integer" + }, + "bcc": { + "items": { + "type": "string" + }, + "type": "array" + }, + "cc": { + "items": { + "type": "string" + }, + "type": "array" + }, + "draft_id": { + "type": "string" + }, + "subject": { + "type": "string" + }, + "summary": { + "description": "One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field.", + "type": "string" + }, + "to": { + "items": { + "type": "string" + }, + "type": "array" + }, + "web_link": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } +} - added
Output schema / requiredAdded value: +[ + "draft_id", + "subject", + "to", + "cc", + "bcc", + "attachment_count", + "web_link", + "summary" +]
- Removed
email_delete - Removed
email_flag - Added
email_folder_empty - Added
email_folder_mark_all_read - Changed
email_forward33 fields changed- added
Input schema / $schemaAdded value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / account_id / descriptionAdded value: +"Account ID or email address. Omit when only one account is signed in." - added
Input schema / properties / account_id / maxLengthAdded value: +320 - added
Input schema / properties / account_id / minLengthAdded value: +1 - added
Input schema / properties / attachmentsAdded value: +{ + "description": "Local files to attach: at most 10, each at most 25 MB.", + "items": { + "description": "Local file path inside the server's allowed folders. Hidden and secret files are refused.", + "maxLength": 4096, + "minLength": 1, + "type": "string" + }, + "maxItems": 10, + "type": "array", + "uniqueItems": true +} - added
Input schema / properties / bccAdded value: +{ + "description": "Bcc recipients.", + "items": { + "description": "Email address, e.g. jane@example.com.", + "format": "email", + "maxLength": 320, + "minLength": 3, + "type": "string" + }, + "maxItems": 500, + "type": "array", + "uniqueItems": true +} - removed
Input schema / properties / bodyRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null -} - removed
Input schema / properties / cc / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } -] - removed
Input schema / properties / cc / defaultRemoved value: -null - added
Input schema / properties / cc / descriptionAdded value: +"Cc recipients." - added
Input schema / properties / cc / itemsAdded value: +{ + "description": "Email address, e.g. jane@example.com.", + "format": "email", + "maxLength": 320, + "minLength": 3, + "type": "string" +} - added
Input schema / properties / cc / maxItemsAdded value: +500 - added
Input schema / properties / cc / typeAdded value: +"array" - added
Input schema / properties / cc / uniqueItemsAdded value: +true - added
Input schema / properties / commentAdded value: +{ + "description": "Note above the forwarded message.", + "maxLength": 100000, + "type": "string" +} - added
Input schema / properties / confirm / descriptionAdded value: +"Must be true to forward this email; set only after the user approves." - added
Input schema / properties / email_id / descriptionAdded value: +"Email to forward." - added
Input schema / properties / email_id / maxLengthAdded value: +1024 - added
Input schema / properties / email_id / minLengthAdded value: +1 - removed
Input schema / properties / to / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "items": { - "type": "string" - }, - "type": "array" - } -] - added
Input schema / properties / to / descriptionAdded value: +"Recipients." - added
Input schema / properties / to / itemsAdded value: +{ + "description": "Email address, e.g. jane@example.com.", + "format": "email", + "maxLength": 320, + "minLength": 3, + "type": "string" +} - added
Input schema / properties / to / maxItemsAdded value: +500 - added
Input schema / properties / to / minItemsAdded value: +1 - added
Input schema / properties / to / typeAdded value: +"array" - added
Input schema / properties / to / uniqueItemsAdded value: +true - changed
Input schema / requiredPrevious value: -[ - "account_id", - "email_id", - "to" -]New value: +[ + "email_id", + "to", + "confirm" +] - added
Output schema / $schemaAdded value: +"https://json-schema.org/draft/2020-12/schema" - changed
Output schema / additionalPropertiesPrevious value: -{ - "type": "string" -}New value: +false - added
Output schema / descriptionAdded value: +"Forward confirmation." - added
Output schema / propertiesAdded value: +{ + "forwarded_id": { + "type": "string" + }, + "recipient_count": { + "minimum": 0, + "type": "integer" + }, + "status": { + "const": "sent" + }, + "summary": { + "description": "One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field.", + "type": "string" + } +} - added
Output schema / requiredAdded value: +[ + "status", + "forwarded_id", + "recipient_count", + "summary" +]
- Removed
email_get - Removed
email_get_attachment - Removed
email_list - Removed
email_mark_read - Removed
email_move - Changed
email_reply22 fields changed- added
Input schema / $schemaAdded value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / account_id / descriptionAdded value: +"Account ID or email address. Omit when only one account is signed in." - added
Input schema / properties / account_id / maxLengthAdded value: +320 - added
Input schema / properties / account_id / minLengthAdded value: +1 - added
Input schema / properties / attachmentsAdded value: +{ + "description": "Local files to attach: at most 10, each at most 25 MB.", + "items": { + "description": "Local file path inside the server's allowed folders. Hidden and secret files are refused.", + "maxLength": 4096, + "minLength": 1, + "type": "string" + }, + "maxItems": 10, + "type": "array", + "uniqueItems": true +} - added
Input schema / properties / body / descriptionAdded value: +"Reply text." - added
Input schema / properties / body / maxLengthAdded value: +1000000 - added
Input schema / properties / body / minLengthAdded value: +1 - added
Input schema / properties / body_formatAdded value: +{ + "default": "text", + "description": "Format of the body text you supply.", + "enum": [ + "text", + "html" + ], + "type": "string" +} - added
Input schema / properties / ccAdded value: +{ + "description": "Extra Cc recipients.", + "items": { + "description": "Email address, e.g. jane@example.com.", + "format": "email", + "maxLength": 320, + "minLength": 3, + "type": "string" + }, + "maxItems": 500, + "type": "array", + "uniqueItems": true +} - added
Input schema / properties / confirm / descriptionAdded value: +"Must be true to send this reply; set only after the user approves." - added
Input schema / properties / email_id / descriptionAdded value: +"Email to reply to." - added
Input schema / properties / email_id / maxLengthAdded value: +1024 - added
Input schema / properties / email_id / minLengthAdded value: +1 - added
Input schema / properties / modeAdded value: +{ + "description": "sender: reply to the sender. all: reply all.", + "enum": [ + "sender", + "all" + ], + "type": "string" +} - changed
Input schema / requiredPrevious value: -[ - "account_id", - "email_id", - "body" -]New value: +[ + "email_id", + "mode", + "body", + "confirm" +] - added
Output schema / $schemaAdded value: +"https://json-schema.org/draft/2020-12/schema" - changed
Output schema / additionalPropertiesPrevious value: -{ - "type": "string" -}New value: +false - added
Output schema / descriptionAdded value: +"Reply confirmation." - added
Output schema / propertiesAdded value: +{ + "conversation_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "in_reply_to": { + "type": "string" + }, + "mode": { + "enum": [ + "sender", + "all" + ] + }, + "status": { + "const": "sent" + }, + "summary": { + "description": "One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field.", + "type": "string" + } +} - added
Output schema / requiredAdded value: +[ + "status", + "mode", + "in_reply_to", + "conversation_id", + "summary" +]
- Removed
email_reply_all - Added
email_rule_manage - Changed
email_send44 fields changed- added
Input schema / $schemaAdded value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / account_id / descriptionAdded value: +"Account ID or email address. Omit when only one account is signed in." - added
Input schema / properties / account_id / maxLengthAdded value: +320 - added
Input schema / properties / account_id / minLengthAdded value: +1 - removed
Input schema / properties / attachments / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } -] - removed
Input schema / properties / attachments / defaultRemoved value: -null - added
Input schema / properties / attachments / descriptionAdded value: +"Local files to attach: at most 10, each at most 25 MB." - added
Input schema / properties / attachments / itemsAdded value: +{ + "description": "Local file path inside the server's allowed folders. Hidden and secret files are refused.", + "maxLength": 4096, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / attachments / maxItemsAdded value: +10 - added
Input schema / properties / attachments / typeAdded value: +"array" - added
Input schema / properties / attachments / uniqueItemsAdded value: +true - added
Input schema / properties / bccAdded value: +{ + "description": "Bcc recipients.", + "items": { + "description": "Email address, e.g. jane@example.com.", + "format": "email", + "maxLength": 320, + "minLength": 3, + "type": "string" + }, + "maxItems": 500, + "type": "array", + "uniqueItems": true +} - added
Input schema / properties / body / descriptionAdded value: +"Message body." - added
Input schema / properties / body / maxLengthAdded value: +1000000 - added
Input schema / properties / body_formatAdded value: +{ + "default": "text", + "description": "Format of the body text you supply.", + "enum": [ + "text", + "html" + ], + "type": "string" +} - removed
Input schema / properties / cc / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } -] - removed
Input schema / properties / cc / defaultRemoved value: -null - added
Input schema / properties / cc / descriptionAdded value: +"Cc recipients." - added
Input schema / properties / cc / itemsAdded value: +{ + "description": "Email address, e.g. jane@example.com.", + "format": "email", + "maxLength": 320, + "minLength": 3, + "type": "string" +} - added
Input schema / properties / cc / maxItemsAdded value: +500 - added
Input schema / properties / cc / typeAdded value: +"array" - added
Input schema / properties / cc / uniqueItemsAdded value: +true - added
Input schema / properties / confirm / descriptionAdded value: +"Must be true to send this email; set only after the user approves." - added
Input schema / properties / draft_idAdded value: +{ + "description": "mode='draft': draft ID from email_create_draft.", + "maxLength": 1024, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / importanceAdded value: +{ + "description": "Message importance.", + "enum": [ + "low", + "normal", + "high" + ], + "type": "string" +} - added
Input schema / properties / modeAdded value: +{ + "description": "Send a new message or an existing draft.", + "enum": [ + "new", + "draft" + ], + "type": "string" +} - added
Input schema / properties / save_to_sentAdded value: +{ + "default": true, + "description": "mode='new': keep a copy in Sent Items.", + "type": "boolean" +} - added
Input schema / properties / subject / descriptionAdded value: +"Subject line." - added
Input schema / properties / subject / maxLengthAdded value: +998 - added
Input schema / properties / subject / minLengthAdded value: +1 - removed
Input schema / properties / to / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "items": { - "type": "string" - }, - "type": "array" - } -] - added
Input schema / properties / to / descriptionAdded value: +"Recipients (To)." - added
Input schema / properties / to / itemsAdded value: +{ + "description": "Email address, e.g. jane@example.com.", + "format": "email", + "maxLength": 320, + "minLength": 3, + "type": "string" +} - added
Input schema / properties / to / maxItemsAdded value: +500 - added
Input schema / properties / to / minItemsAdded value: +1 - added
Input schema / properties / to / typeAdded value: +"array" - added
Input schema / properties / to / uniqueItemsAdded value: +true - changed
Input schema / requiredPrevious value: -[ - "account_id", - "to", - "subject", - "body" -]New value: +[ + "mode", + "confirm" +] - added
Output schema / $schemaAdded value: +"https://json-schema.org/draft/2020-12/schema" - changed
Output schema / additionalPropertiesPrevious value: -{ - "type": "string" -}New value: +false - added
Output schema / descriptionAdded value: +"Send confirmation." - added
Output schema / propertiesAdded value: +{ + "draft_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "mode": { + "enum": [ + "new", + "draft" + ] + }, + "recipient_count": { + "minimum": 0, + "type": "integer" + }, + "sent_at": { + "format": "date-time", + "type": "string" + }, + "status": { + "const": "sent" + }, + "summary": { + "description": "One-line human summary. The tool's text content is this result serialized as JSON (summary included), so a client that ignores structuredContent still sees every field.", + "type": "string" + } +} - added
Output schema / requiredAdded value: +[ + "status", + "mode", + "draft_id", + "recipient_count", + "sent_at", + "summary" +]
- Removed
email_update - Removed
emailfolders_create - Removed
emailfolders_delete - Removed
emailfolders_empty - Removed
emailfolders_get - Removed
emailfolders_get_tree - Removed
emailfolders_list - Removed
emailfolders_mark_all_as_read - Removed
emailfolders_move - Removed
emailfolders_rename - Removed
emailrules_create - Removed
emailrules_delete - Removed
emailrules_get - Removed
emailrules_list - Removed
emailrules_move_bottom - Removed
emailrules_move_down - Removed
emailrules_move_top - Removed
emailrules_move_up - Removed
emailrules_update - Removed
file_copy - Removed
file_create - Removed
file_delete - Removed
file_download_url - Removed
file_get - Removed
file_list - Removed
file_move - Removed
file_rename - Removed
file_share - Removed
file_update - Removed
folder_create - Removed
folder_delete - Removed
folder_get - Removed
folder_get_tree - Removed
folder_list - Removed
folder_move - Removed
folder_rename - Added
m365_create - Added
m365_delete - Added
m365_get - Added
m365_get_content - Added
m365_list - Added
m365_move - Added
m365_search - Added
m365_update - Removed
search_contacts - Removed
search_emails - Removed
search_events - Removed
search_files - Removed
search_unified - Removed
server_get_version
85 tool updates
v0.2.3- First observed
account_authenticate - First observed
account_complete_auth - First observed
account_list - First observed
cache_get_stats - First observed
cache_invalidate - First observed
cache_task_get_status - First observed
cache_task_list - First observed
cache_warming_status - First observed
calendar_check_availability - First observed
calendar_create_calendar - First observed
calendar_create_event - First observed
calendar_delete_calendar - First observed
calendar_delete_event - First observed
calendar_forward_event - First observed
calendar_get_event - First observed
calendar_get_free_busy - First observed
calendar_list_calendars - First observed
calendar_list_events - First observed
calendar_propose_new_time - First observed
calendar_respond_event - First observed
calendar_update_event - First observed
contact_add_to_list - First observed
contact_create - First observed
contact_create_list - First observed
contact_delete - First observed
contact_export - First observed
contact_get - First observed
contact_list - First observed
contact_update - First observed
email_add_category - First observed
email_archive - First observed
email_create_draft - First observed
email_delete - First observed
email_flag - First observed
email_forward - First observed
email_get - First observed
email_get_attachment - First observed
email_list - First observed
email_mark_read - First observed
email_move - First observed
email_reply - First observed
email_reply_all - First observed
email_send - First observed
email_update - First observed
emailfolders_create - First observed
emailfolders_delete - First observed
emailfolders_empty - First observed
emailfolders_get - First observed
emailfolders_get_tree - First observed
emailfolders_list - First observed
emailfolders_mark_all_as_read - First observed
emailfolders_move - First observed
emailfolders_rename - First observed
emailrules_create - First observed
emailrules_delete - First observed
emailrules_get - First observed
emailrules_list - First observed
emailrules_move_bottom - First observed
emailrules_move_down - First observed
emailrules_move_top - First observed
emailrules_move_up - First observed
emailrules_update - First observed
file_copy - First observed
file_create - First observed
file_delete - First observed
file_download_url - First observed
file_get - First observed
file_list - First observed
file_move - First observed
file_rename - First observed
file_share - First observed
file_update - First observed
folder_create - First observed
folder_delete - First observed
folder_get - First observed
folder_get_tree - First observed
folder_list - First observed
folder_move - First observed
folder_rename - First observed
search_contacts - First observed
search_emails - First observed
search_events - First observed
search_files - First observed
search_unified - First observed
server_get_version
TDQS
Scored across 23 tools
Tools are largely distinct and descriptions explicitly cross-reference each other (e.g. m365_create says 'not for emails... use email_create_draft'). However, resource CRUD is split awkwardly: events are created via calendar_create_event, updated via calendar_update_event, but deleted only through the generic m365_delete, which an agent may not find. Overlaps like m365_get vs m365_get_content and m365_update vs calendar_update_event are clarified in text but still require careful reading.
Consistent resource_action pattern throughout: generic m365_* verbs (list, get, search, create, update, move, delete) plus resource-prefixed families (email_, calendar_, drive_). The dual scheme (generic m365_ for cross-resource CRUD vs resource-prefixed for specialized ops) is a deliberate and readable convention, with only minor variance like m365_get_content.
23 tools is on the heavier side but justified by three distinct domains (email, calendar, Drive) each needing their own specialized operations on top of the shared generic CRUD set. No obvious redundant tools beyond the intentional generic/specific split.
Strong lifecycle coverage across email (send, draft, reply, forward, move, delete, rules, folder ops), calendar (create, update, respond, availability, forward), and OneDrive (upload, copy, share, download, create/move/delete). Minor gaps: no calendar_delete_event (only generic m365_delete) and no dedicated attachment-listing operation, but core workflows are covered.
Maintenance
Related MCP Connectors
Gmail, Outlook, Drive, OneDrive and calendars for AI agents. Many accounts, one endpoint, audit log.
Permissioned access to Outlook, OneDrive and Teams via the user's own Microsoft account
Governed memory and workspace for any AI: tasks, calendar, mail and pages, with per-action consent.
GDPR-compliant calendar access for AI assistants: read, create, edit, RSVP. Google, MS 365, Apple.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to interact with Microsoft Graph API services including Outlook email, Calendar events, OneDrive files, and Contacts. Supports multiple Microsoft accounts with unified search across all services.-
- FlicenseNot gradedqualityDmaintenanceConnects AI assistants to Microsoft 365 accounts to manage emails, calendars, files, and Teams messages. It offers 71 tools and supports multi-user environments through a secure, customizable server architecture.55-
- AlicenseNot gradedqualityFmaintenanceEnables AI assistants to interact with Microsoft 365 services (users, mail, calendar, files) via Microsoft Graph API.70 npm1MIT
- AlicenseAqualityDmaintenanceEnables AI assistants to manage Microsoft 365 email, calendar, and contacts through natural language, with zero Azure setup required.1511MIT