Skip to main content
Glama

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 opaque next_cursor and a short summary.

  • Multi-account: several personal accounts at once; account_id is 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_availability suggests 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-mcp

Claude 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
claude

Usage 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 this

Available 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

m365_list

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)

m365_get

safe

Read one item by ID: email with body, event with attendees, contact, folder, rule, calendar, OneDrive item, or the status of a copy (resource="operation")

m365_search

safe

Find emails, events, contacts or OneDrive files by free text, one type or several at once

m365_get_content

moderate

Save a OneDrive file or email attachment to a local file, get a temporary download link, or export a contact as a vCard

m365_create

moderate

Create a mail folder, calendar, contact, contact folder or OneDrive folder

m365_update

moderate

Mark read, flag, categorise, set importance, rename folders and files, edit contact details

m365_move

moderate

Move an email, mail folder, contact or OneDrive item (emails and contacts get a new ID)

m365_delete

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)

email_create_draft

moderate

Create an unsent draft (sends nothing)

email_send

dangerous, confirm

Send a new email or a draft

email_reply

dangerous, confirm

Reply to the sender or to everyone

email_forward

dangerous, confirm

Forward an email with an optional note

calendar_create_event

dangerous, conditional

Add an event; confirm required only when attendees would be emailed

calendar_update_event

dangerous, conditional

Change an event; confirm required when attendees are notified

calendar_respond

dangerous, conditional

Accept, tentatively accept or decline an invitation; confirm required when a response is emailed

calendar_find_availability

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

drive_upload

moderate

Upload a local file to OneDrive as a new file or replace an existing one

drive_copy

moderate

Copy a OneDrive file or folder (asynchronous; returns an operation_id)

drive_share

dangerous, confirm

Share a file or folder by link or by inviting named people

email_folder_mark_all_read

moderate

Mark every unread message in a mail folder as read (bounded per call)

email_folder_empty

critical, confirm

Delete all messages in a mail folder such as Junk Email (bounded per call)

email_rule_manage

dangerous, conditional

Create, change, enable/disable or reorder an inbox rule; confirm required for rules that forward, redirect or delete

calendar_forward

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

account_list

safe

List the signed-in accounts (needed only with more than one account)

account_auth_begin

moderate

Start a device-code sign-in; returns a URL, a code and an auth_session_id

account_auth_complete

moderate

Finish the sign-in (single non-blocking poll); work or school accounts are rejected

admin_cache_get

safe

Cache statistics, background tasks, one task, or warming progress (view)

admin_cache_invalidate

moderate

Clear cached results for one resource type or all, for one account or all

admin_server_info

safe

Server version, protocol versions, enabled toolsets

admin_reauth_schedule

moderate

Status, install or remove the weekly re-auth job (install and remove need confirm=true)

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 email is fresh for 2 minutes and expires after 10, drive_item 10 and 60 minutes

  • Automatic 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=true to pre-load the folder tree, inbox, upcoming events and contacts at startup and refresh stale entries in the background

  • Automatic 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_KEY for headless servers; if neither keyring nor the env var is available, a generated ephemeral key is used with a warning

  • Plaintext 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

  1. Go to Azure Portal → Microsoft Entra ID → App registrations

  2. New registration → Name: m365-mcp

  3. Supported account types: Personal Microsoft accounts only

  4. Authentication → Allow public client flows: Yes

  5. 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.ReadWrite does not cover sending)

  • Calendars.ReadWrite

  • Files.ReadWrite

  • Contacts.ReadWrite

  • MailboxSettings.Read (working hours and time zone for calendar_find_availability)

  • User.Read

  1. 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 sync

3. 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 accounts

Alternatively 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

MCP_WEEKLY_RE_AUTH

unset

true keep installed and repaired, false remove, unset leave alone

MCP_RE_AUTH_DAY

Sunday

Day the job runs

MCP_RE_AUTH_TIME

09:00

Local 24-hour time

MCP_RE_AUTH_CHECK_HOURS

6

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 M365_MCP_TOOLSETS to

Also

Client without tool search or deferred loading

core

Users lose drive_*, bulk mail and rule tools

Client with tool search or deferred loading

core,extended (default)

Load core eagerly, defer extended

Signing in from the client (no terminal)

add admin

uv run authenticate.py remains the primary sign-in path

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-mcp

Claude 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-mcp

Streamable 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-mcp

Client 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 --check

The 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.json

  • Cache data is encrypted at rest using AES-256 SQLCipher in ~/.m365_mcp_cache.db

  • Encryption keys are loaded from system keyring or M365_MCP_CACHE_KEY; generated non-persistent keys produce a warning

  • SQLCipher 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=true

  • Local file access is limited to MCP_FILE_ALLOWED_ROOTS plus, on stdio, the working and temp directories (off over HTTP unless MCP_FILE_ALLOW_CWD / MCP_FILE_ALLOW_TEMP is true); hidden and secret-like files are refused

  • Email, 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_ID unset (default consumers)

  • Missing permissions: Ensure all required API permissions are granted in Azure

  • Token errors: Delete ~/.m365_mcp_token_cache.json and 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 unless M365_MCP_CURSOR_KEY is set

  • Local 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-like

  • Cache issues: Delete ~/.m365_mcp_cache.db to reset cache. If the stored key cannot open the database, the cache is recreated automatically.

  • Stale results: call m365_list or m365_get with refresh=true

  • Slow first requests: Normal on a cold cache. Set M365_MCP_CACHE_WARMING=true to enable startup warming and stale-cache background refresh.

License

MIT

Available Tools

23 tools
calendar_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.

ParametersJSON Schema
NameRequiredDescriptionDefault
endYesRFC 3339 date-time with offset, e.g. 2026-10-01T09:00:00+09:30.
bodyNoDescription.
startYesRFC 3339 date-time with offset, e.g. 2026-10-01T09:00:00+09:30.
confirmNoMust be true to send invitations to the attendees; set only after the user approves.
show_asNoHow the time shows in your calendar.
subjectYesTitle.
locationNoLocation text.
attendeesNoPeople to invite.
time_zoneNoIANA time-zone name, e.g. Australia/Adelaide. Defaults to the mailbox time zone.
account_idNoAccount ID or email address. Omit when only one account is signed in.
is_all_dayNoAll-day event (start and end at midnight in time_zone).
body_formatNoFormat of the body text you supply.text
calendar_idNoCalendar ID (default: your default calendar).
reminder_minutesNoReminder before start, in minutes.

Output Schema

ParametersJSON Schema
NameRequiredDescription
eventYes
summaryYesOne-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_sentYes

TDQS

A4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines4/5

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 TimeA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
endYesRange end; at most 62 days after start.
startYesRFC 3339 date-time with offset, e.g. 2026-10-01T09:00:00+09:30.
max_slotsNoMost free slots to return.
time_zoneNoIANA time-zone name, e.g. Australia/Adelaide. Defaults to the mailbox time zone.
account_idNoAccount ID or email address. Omit when only one account is signed in.
slot_minutesNoLength of free slots to suggest.
min_gap_minutesNoBuffer to keep before and after busy time.
working_hours_onlyNoOnly suggest slots inside your Outlook working hours.

Output Schema

ParametersJSON Schema
NameRequiredDescription
busyYes
summaryYesOne-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_zoneYes
free_slotsYes
working_hoursYes

TDQS

A3.7/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines3/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesRecipients.
commentNoNote to include.
confirmYesMust be true to forward this invitation; set only after the user approves.
event_idYesEvent to forward.
account_idNoAccount ID or email address. Omit when only one account is signed in.

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYes
summaryYesOne-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_idYes
recipient_countYes

TDQS

A3.6/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines3/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
actionYesYour response.
commentNoMessage to the organiser.
confirmNoMust be true to send this response to the organiser; set only after the user approves.
event_idYesInvitation's event ID.
account_idNoAccount ID or email address. Omit when only one account is signed in.
proposed_endNoProposed new end (tentative or decline only).
send_responseNoEmail the response to the organiser.
proposed_startNoProposed new start (tentative or decline only).

Output Schema

ParametersJSON Schema
NameRequiredDescription
actionYes
summaryYesOne-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_idYes
proposed_endYes
response_sentYes
proposed_startYes

TDQS

A4.1/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines4/5

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 EventA
Idempotent

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
changesYesFields to change (at least one).
confirmNoMust be true to send updates to the attendees; set only after the user approves.
event_idYesEvent to change.
account_idNoAccount ID or email address. Omit when only one account is signed in.

Output Schema

ParametersJSON Schema
NameRequiredDescription
eventYes
summaryYesOne-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_fieldsYes
attendees_notifiedYes

TDQS

A4.2/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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').

ParametersJSON Schema
NameRequiredDescriptionDefault
item_idYesFile or folder to copy.
new_nameNoName for the copy (default: same name).
account_idNoAccount ID or email address. Omit when only one account is signed in.
destination_idNoDestination folder ID ('root' allowed).
destination_pathNoDestination folder path instead of destination_id.

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYes
summaryYesOne-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_idYes

TDQS

A3.8/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines3/5

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_shareShare FileA

Share a OneDrive file or folder by link (mode='link') or by inviting named people (mode='invite'). A view or edit link works for anyone who has it. Always requires confirm=true after the user approves who gets access. Returns the link or the invitation results.

ParametersJSON Schema
NameRequiredDescriptionDefault
modeYesShare by link or invite specific people.
roleNoinvite: access level.
confirmYesMust be true to grant this access; set only after the user approves.
item_idYesFile or folder to share (not the OneDrive root).
messageNoinvite: note in the invitation email.
passwordNoOptional password for the link or invitation.
link_typeNolink: view (read-only), edit, or embed (files only).
account_idNoAccount ID or email address. Omit when only one account is signed in.
expires_atNoOptional expiry (invite expiry needs a premium OneDrive).
recipientsNoinvite: people to share with.
require_sign_inNoinvite: recipients must sign in.
send_invitationNoinvite: email the recipients.

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
createdYes
summaryYesOne-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.
link_urlYes
recipientsYes
permission_idsYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover the safety profile (not readOnly, not idempotent, not destructive, openWorld), so the bar is lower. The description adds genuinely useful behavior: that a view/edit link is usable by anyone who holds it, and that confirm=true is mandatory and must follow user approval — an approval-gate workflow the annotations 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences with the core purpose and modes front-loaded, then the mandatory confirm gate, then the return shape. Nothing is padded and no sentence restates the title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 12 parameters fully documented in the schema and an output schema present, the description need not explain return values, and it correctly avoids that. It covers purpose, mode choice, and the approval gate; the only minor gap is that it doesn't flag the OneDrive-root exclusion noted in the item_id schema or account scoping, though the schema handles those.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so every one of the 12 parameters, including enums for mode, role, and link_type, is already documented in the schema. The description restates mode and confirm but adds no syntax or format detail beyond the structured fields, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb (share) and resource (OneDrive file or folder) and distinguishes the two operating modes, link vs invite, telling the agent exactly what capability this tool exposes. It is clearly separable from siblings like drive_copy, drive_upload, and m365_update.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the mode selection rule ('by link' vs 'by inviting named people') and the mandatory confirm=true step after user approval, which is real when-to-use guidance. It does not, however, say when to prefer this over sibling tools such as m365_update for permissions, nor any explicit negative conditions.

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNoNew file: name in OneDrive (default: local file name).
item_idNoReplace the contents of this existing file.
if_existsNoNew file: what to do if the name is taken.fail
parent_idNoNew file: destination folder ID ('root' allowed).
account_idNoAccount ID or email address. Omit when only one account is signed in.
local_pathYesLocal file path inside the server's allowed folders. Hidden and secret files are refused.
parent_pathNoNew file: destination folder path, e.g. /Documents.

Output Schema

ParametersJSON Schema
NameRequiredDescription
itemYes
statusYes
summaryYesOne-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

A4.4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
ccNoCc recipients.
toYesRecipients (To).
bccNoBcc recipients.
bodyYesMessage body.
subjectYesSubject line.
account_idNoAccount ID or email address. Omit when only one account is signed in.
importanceNoMessage importance.
attachmentsNoLocal files to attach: at most 10, each at most 25 MB.
body_formatNoFormat of the body text you supply.text

Output Schema

ParametersJSON Schema
NameRequiredDescription
ccYes
toYes
bccYes
subjectYes
summaryYesOne-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_idYes
web_linkYes
attachment_countYes

TDQS

A4.2/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 FolderA
DestructiveIdempotent

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
confirmYesMust be true to delete every message in this folder; set only after the user approves.
folder_idYesMail folder ID, or one of the aliases inbox, sent, drafts, deleted, junk, archive.
account_idNoAccount ID or email address. Omit when only one account is signed in.
max_messagesNoMost messages to delete in this call.

Output Schema

ParametersJSON Schema
NameRequiredDescription
deletedYes
summaryYesOne-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_idYes
remainingYes

TDQS

A4.5/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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 ReadA
Idempotent

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
folder_idYesMail folder ID, or one of the aliases inbox, sent, drafts, deleted, junk, archive.
account_idNoAccount ID or email address. Omit when only one account is signed in.
max_messagesNoMost messages to change in this call.

Output Schema

ParametersJSON Schema
NameRequiredDescription
markedYes
summaryYesOne-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_idYes
remaining_unreadYes

TDQS

A4.3/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
ccNoCc recipients.
toYesRecipients.
bccNoBcc recipients.
commentNoNote above the forwarded message.
confirmYesMust be true to forward this email; set only after the user approves.
email_idYesEmail to forward.
account_idNoAccount ID or email address. Omit when only one account is signed in.
attachmentsNoLocal files to attach: at most 10, each at most 25 MB.

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYes
summaryYesOne-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_idYes
recipient_countYes

TDQS

A4.3/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
ccNoExtra Cc recipients.
bodyYesReply text.
modeYessender: reply to the sender. all: reply all.
confirmYesMust be true to send this reply; set only after the user approves.
email_idYesEmail to reply to.
account_idNoAccount ID or email address. Omit when only one account is signed in.
attachmentsNoLocal files to attach: at most 10, each at most 25 MB.
body_formatNoFormat of the body text you supply.text

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
statusYes
summaryYesOne-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_toYes
conversation_idYes

TDQS

A4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines4/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
ruleNoRule definition. create requires display_name, conditions and actions; update applies only the supplied fields.
actionYesWhat to do.
confirmNoMust be true to save a rule that forwards, redirects or deletes mail; set only after the user approves.
rule_idNoExisting rule (update, set_enabled, reorder).
positionNoreorder: new position. before/after need relative_to_rule_id.
account_idNoAccount ID or email address. Omit when only one account is signed in.
is_enabledNoset_enabled: turn the rule on (true) or off (false).
relative_to_rule_idNoreorder with before/after: the other rule.

Output Schema

ParametersJSON Schema
NameRequiredDescription
ruleYes
actionYes
summaryYesOne-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

A4.7/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
ccNoCc recipients.
toNoRecipients (To).
bccNoBcc recipients.
bodyNoMessage body.
modeYesSend a new message or an existing draft.
confirmYesMust be true to send this email; set only after the user approves.
subjectNoSubject line.
draft_idNomode='draft': draft ID from email_create_draft.
account_idNoAccount ID or email address. Omit when only one account is signed in.
importanceNoMessage importance.
attachmentsNoLocal files to attach: at most 10, each at most 25 MB.
body_formatNoFormat of the body text you supply.text
save_to_sentNomode='new': keep a copy in Sent Items.

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
statusYes
sent_atYes
summaryYesOne-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_idYes
recipient_countYes

TDQS

A4.2/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
contactNoRequired when resource='contact'.
calendarNoRequired when resource='calendar'.
resourceYesType of item to create.
account_idNoAccount ID or email address. Omit when only one account is signed in.
drive_folderNoRequired when resource='drive_item' (creates a folder).
email_folderNoRequired when resource='email_folder'.
contact_folderNoRequired when resource='contact_folder'.

Output Schema

ParametersJSON Schema
NameRequiredDescription
itemYes
summaryYesOne-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.
resourceYes

TDQS

A4.2/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 ItemA
Destructive

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesItem ID. Aliases are not accepted.
confirmYesMust be true to delete this item; set only after the user approves.
resourceYesType of item.
account_idNoAccount ID or email address. Omit when only one account is signed in.
cancellation_messageNoevent only: note sent with the cancellation when you organise the meeting.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
statusYes
summaryYesOne-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.
resourceYes
recoverableYes

TDQS

A4.2/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 ItemA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoItem ID from a previous result (for operation: the operation_id). Aliases are accepted for email_folder, calendar (default) and drive_item (root).
pathNodrive_item only: OneDrive path instead of id.
refreshNoBypass the cache and fetch fresh data.
resourceYesType of item.
account_idNoAccount ID or email address. Omit when only one account is signed in.
include_bodyNoemail and event: include the body text.
body_max_charsNoemail and event: truncate the body after this many characters.

Output Schema

ParametersJSON Schema
NameRequiredDescription
itemYes
summaryYesOne-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.
resourceYes

TDQS

A4.5/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 ContentA
Idempotent

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesOneDrive item ID, email ID or contact ID.
modeYesdownload: drive_item file or email attachment to save_path. download_url: drive_item file only. vcard: contact only.
resourceYesType of item.
overwriteNoReplace save_path if it already exists.
save_pathNoLocal file path inside the server's allowed folders. Hidden and secret files are refused.
account_idNoAccount ID or email address. Omit when only one account is signed in.
attachment_idNoemail + download only: attachment ID from m365_get(resource='email').

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
modeYes
sizeYes
vcardYes
summaryYesOne-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.
resourceYes
mime_typeYes
saved_pathYes
download_urlYes

TDQS

A4.5/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 ItemsA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
endNoevent only: window end (default start + 7 days; at most 366 days after start).
pathNodrive_item only: OneDrive folder path instead of container_id, e.g. /Documents/Tax.
limitNoMaximum number of items to return.
startNoevent only: window start (default now). RFC 3339 with offset.
cursorNonext_cursor from the previous page; keep all other arguments the same.
refreshNoBypass the cache and fetch fresh data.
resourceYesType of item to list.
item_typeNodrive_item only: which kinds of item to return.all
max_depthNoTree depth when recursive=true.
recursiveNoemail_folder and drive_item only: return a nested tree of folders instead of one level.
account_idNoAccount ID or email address. Omit when only one account is signed in.
container_idNoWhere 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_filterNoemail only: filters applied by Microsoft 365 (all must match).
include_hiddenNoemail_folder only: include hidden folders.

Output Schema

ParametersJSON Schema
NameRequiredDescription
itemsYes
summaryYesOne-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_moreYes
resourceYes
next_cursorYes

TDQS

A4.4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesItem to move.
new_nameNodrive_item only: rename while moving.
resourceYesType of item.
account_idNoAccount ID or email address. Omit when only one account is signed in.
destination_idNoDestination 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_pathNodrive_item only: destination folder path instead of destination_id.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
statusYes
summaryYesOne-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.
resourceYes
previous_idYes
destination_idYes

TDQS

A3.8/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines3/5

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_updateUpdate ItemA
Idempotent

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesItem ID.
resourceYesType of item.
account_idNoAccount ID or email address. Omit when only one account is signed in.
email_changesNoRequired when resource='email'.
contact_changesNoRequired when resource='contact'. Only supplied fields change; lists replace the existing list.
drive_item_changesNoRequired when resource='drive_item'.
email_folder_changesNoRequired when resource='email_folder'.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
statusYes
summaryYesOne-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.
resourceYes
changed_fieldsYes

TDQS

A4.2/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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.

  1. 102 tool updatesv1.0.0
    • Removedaccount_authenticate
    • Removedaccount_complete_auth
    • Removedaccount_list
    • Removedcache_get_stats
    • Removedcache_invalidate
    • Removedcache_task_get_status
    • Removedcache_task_list
    • Removedcache_warming_status
    • Removedcalendar_check_availability
    • Removedcalendar_create_calendar
    • Changedcalendar_create_event43 fields changed
      • addedInput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / account_id / description
        Added value: +"Account ID or email address. Omit when only one account is signed in."
      • addedInput schema / properties / account_id / maxLength
        Added value: +320
      • addedInput schema / properties / account_id / minLength
        Added value: +1
      • removedInput schema / properties / attendees / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "items": {
        -      "type": "string"
        -    },
        -    "type": "array"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / attendees / default
        Removed value: -null
      • addedInput schema / properties / attendees / description
        Added value: +"People to invite."
      • addedInput schema / properties / attendees / items
        Added 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"
        +}
      • addedInput schema / properties / attendees / maxItems
        Added value: +500
      • addedInput schema / properties / attendees / type
        Added value: +"array"
      • removedInput schema / properties / body / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / body / default
        Removed value: -null
      • addedInput schema / properties / body / description
        Added value: +"Description."
      • addedInput schema / properties / body / maxLength
        Added value: +100000
      • addedInput schema / properties / body / type
        Added value: +"string"
      • addedInput schema / properties / body_format
        Added value: +{
        +  "default": "text",
        +  "description": "Format of the body text you supply.",
        +  "enum": [
        +    "text",
        +    "html"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / calendar_id
        Added value: +{
        +  "description": "Calendar ID (default: your default calendar).",
        +  "maxLength": 1024,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / confirm
        Added value: +{
        +  "default": false,
        +  "description": "Must be true to send invitations to the attendees; set only after the user approves.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / end / description
        Added value: +"RFC 3339 date-time with offset, e.g. 2026-10-01T09:00:00+09:30."
      • addedInput schema / properties / end / format
        Added value: +"date-time"
      • addedInput schema / properties / is_all_day
        Added value: +{
        +  "description": "All-day event (start and end at midnight in time_zone).",
        +  "type": "boolean"
        +}
      • removedInput schema / properties / location / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / location / default
        Removed value: -null
      • addedInput schema / properties / location / description
        Added value: +"Location text."
      • addedInput schema / properties / location / maxLength
        Added value: +255
      • addedInput schema / properties / location / type
        Added value: +"string"
      • addedInput schema / properties / reminder_minutes
        Added value: +{
        +  "description": "Reminder before start, in minutes.",
        +  "maximum": 40320,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedInput schema / properties / show_as
        Added value: +{
        +  "description": "How the time shows in your calendar.",
        +  "enum": [
        +    "free",
        +    "tentative",
        +    "busy",
        +    "oof",
        +    "workingElsewhere"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / start / description
        Added value: +"RFC 3339 date-time with offset, e.g. 2026-10-01T09:00:00+09:30."
      • addedInput schema / properties / start / format
        Added value: +"date-time"
      • addedInput schema / properties / subject / description
        Added value: +"Title."
      • addedInput schema / properties / subject / maxLength
        Added value: +255
      • addedInput schema / properties / subject / minLength
        Added value: +1
      • addedInput schema / properties / time_zone
        Added value: +{
        +  "description": "IANA time-zone name, e.g. Australia/Adelaide. Defaults to the mailbox time zone.",
        +  "maxLength": 64,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • removedInput schema / properties / timezone
        Removed value: -{
        -  "default": "UTC",
        -  "type": "string"
        -}
      • changedInput schema / required
        Previous value: -[
        -  "account_id",
        -  "subject",
        -  "start",
        -  "end"
        -]New value: +[
        +  "subject",
        +  "start",
        +  "end"
        +]
      • addedOutput schema / $defs
        Added 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"
        +  }
        +}
      • addedOutput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
      • changedOutput schema / additionalProperties
        Previous value: -trueNew value: +false
      • addedOutput schema / description
        Added value: +"The created event."
      • addedOutput schema / properties
        Added 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"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "event",
        +  "invitations_sent",
        +  "summary"
        +]
    • Removedcalendar_delete_calendar
    • Removedcalendar_delete_event
    • Addedcalendar_find_availability
    • Addedcalendar_forward
    • Removedcalendar_forward_event
    • Removedcalendar_get_event
    • Removedcalendar_get_free_busy
    • Removedcalendar_list_calendars
    • Removedcalendar_list_events
    • Removedcalendar_propose_new_time
    • Addedcalendar_respond
    • Removedcalendar_respond_event
    • Changedcalendar_update_event18 fields changed
      • addedInput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / account_id / description
        Added value: +"Account ID or email address. Omit when only one account is signed in."
      • addedInput schema / properties / account_id / maxLength
        Added value: +320
      • addedInput schema / properties / account_id / minLength
        Added value: +1
      • addedInput schema / properties / changes
        Added 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"
        +}
      • addedInput schema / properties / confirm
        Added value: +{
        +  "default": false,
        +  "description": "Must be true to send updates to the attendees; set only after the user approves.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / event_id / description
        Added value: +"Event to change."
      • addedInput schema / properties / event_id / maxLength
        Added value: +1024
      • addedInput schema / properties / event_id / minLength
        Added value: +1
      • removedInput schema / properties / updates
        Removed value: -{
        -  "additionalProperties": true,
        -  "type": "object"
        -}
      • changedInput schema / required
        Previous value: -[
        -  "event_id",
        -  "updates",
        -  "account_id"
        -]New value: +[
        +  "event_id",
        +  "changes"
        +]
      • addedOutput schema / $defs
        Added 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"
        +  }
        +}
      • addedOutput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
      • changedOutput schema / additionalProperties
        Previous value: -trueNew value: +false
      • addedOutput schema / description
        Added value: +"The updated event."
      • addedOutput schema / properties
        Added 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"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "event",
        +  "attendees_notified",
        +  "changed_fields",
        +  "summary"
        +]
    • Removedcontact_add_to_list
    • Removedcontact_create
    • Removedcontact_create_list
    • Removedcontact_delete
    • Removedcontact_export
    • Removedcontact_get
    • Removedcontact_list
    • Removedcontact_update
    • Addeddrive_copy
    • Addeddrive_share
    • Addeddrive_upload
    • Removedemail_add_category
    • Removedemail_archive
    • Changedemail_create_draft40 fields changed
      • addedInput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / account_id / description
        Added value: +"Account ID or email address. Omit when only one account is signed in."
      • addedInput schema / properties / account_id / maxLength
        Added value: +320
      • addedInput schema / properties / account_id / minLength
        Added value: +1
      • removedInput schema / properties / attachments / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "items": {
        -      "type": "string"
        -    },
        -    "type": "array"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / attachments / default
        Removed value: -null
      • addedInput schema / properties / attachments / description
        Added value: +"Local files to attach: at most 10, each at most 25 MB."
      • addedInput schema / properties / attachments / items
        Added value: +{
        +  "description": "Local file path inside the server's allowed folders. Hidden and secret files are refused.",
        +  "maxLength": 4096,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / attachments / maxItems
        Added value: +10
      • addedInput schema / properties / attachments / type
        Added value: +"array"
      • addedInput schema / properties / attachments / uniqueItems
        Added value: +true
      • addedInput schema / properties / bcc
        Added 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
        +}
      • addedInput schema / properties / body / description
        Added value: +"Message body."
      • addedInput schema / properties / body / maxLength
        Added value: +1000000
      • addedInput schema / properties / body_format
        Added value: +{
        +  "default": "text",
        +  "description": "Format of the body text you supply.",
        +  "enum": [
        +    "text",
        +    "html"
        +  ],
        +  "type": "string"
        +}
      • removedInput schema / properties / cc / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "items": {
        -      "type": "string"
        -    },
        -    "type": "array"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / cc / default
        Removed value: -null
      • addedInput schema / properties / cc / description
        Added value: +"Cc recipients."
      • addedInput schema / properties / cc / items
        Added value: +{
        +  "description": "Email address, e.g. jane@example.com.",
        +  "format": "email",
        +  "maxLength": 320,
        +  "minLength": 3,
        +  "type": "string"
        +}
      • addedInput schema / properties / cc / maxItems
        Added value: +500
      • addedInput schema / properties / cc / type
        Added value: +"array"
      • addedInput schema / properties / cc / uniqueItems
        Added value: +true
      • addedInput schema / properties / importance
        Added value: +{
        +  "description": "Message importance.",
        +  "enum": [
        +    "low",
        +    "normal",
        +    "high"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / subject / description
        Added value: +"Subject line."
      • addedInput schema / properties / subject / maxLength
        Added value: +998
      • addedInput schema / properties / subject / minLength
        Added value: +1
      • removedInput schema / properties / to / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "items": {
        -      "type": "string"
        -    },
        -    "type": "array"
        -  }
        -]
      • addedInput schema / properties / to / description
        Added value: +"Recipients (To)."
      • addedInput schema / properties / to / items
        Added value: +{
        +  "description": "Email address, e.g. jane@example.com.",
        +  "format": "email",
        +  "maxLength": 320,
        +  "minLength": 3,
        +  "type": "string"
        +}
      • addedInput schema / properties / to / maxItems
        Added value: +500
      • addedInput schema / properties / to / minItems
        Added value: +1
      • addedInput schema / properties / to / type
        Added value: +"array"
      • addedInput schema / properties / to / uniqueItems
        Added value: +true
      • changedInput schema / required
        Previous value: -[
        -  "account_id",
        -  "to",
        -  "subject",
        -  "body"
        -]New value: +[
        +  "to",
        +  "subject",
        +  "body"
        +]
      • addedOutput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
      • changedOutput schema / additionalProperties
        Previous value: -trueNew value: +false
      • addedOutput schema / description
        Added value: +"The created draft."
      • addedOutput schema / properties
        Added 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"
        +      }
        +    ]
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "draft_id",
        +  "subject",
        +  "to",
        +  "cc",
        +  "bcc",
        +  "attachment_count",
        +  "web_link",
        +  "summary"
        +]
    • Removedemail_delete
    • Removedemail_flag
    • Addedemail_folder_empty
    • Addedemail_folder_mark_all_read
    • Changedemail_forward33 fields changed
      • addedInput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / account_id / description
        Added value: +"Account ID or email address. Omit when only one account is signed in."
      • addedInput schema / properties / account_id / maxLength
        Added value: +320
      • addedInput schema / properties / account_id / minLength
        Added value: +1
      • addedInput schema / properties / attachments
        Added 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
        +}
      • addedInput schema / properties / bcc
        Added 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
        +}
      • removedInput schema / properties / body
        Removed value: -{
        -  "anyOf": [
        -    {
        -      "type": "string"
        -    },
        -    {
        -      "type": "null"
        -    }
        -  ],
        -  "default": null
        -}
      • removedInput schema / properties / cc / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "items": {
        -      "type": "string"
        -    },
        -    "type": "array"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / cc / default
        Removed value: -null
      • addedInput schema / properties / cc / description
        Added value: +"Cc recipients."
      • addedInput schema / properties / cc / items
        Added value: +{
        +  "description": "Email address, e.g. jane@example.com.",
        +  "format": "email",
        +  "maxLength": 320,
        +  "minLength": 3,
        +  "type": "string"
        +}
      • addedInput schema / properties / cc / maxItems
        Added value: +500
      • addedInput schema / properties / cc / type
        Added value: +"array"
      • addedInput schema / properties / cc / uniqueItems
        Added value: +true
      • addedInput schema / properties / comment
        Added value: +{
        +  "description": "Note above the forwarded message.",
        +  "maxLength": 100000,
        +  "type": "string"
        +}
      • addedInput schema / properties / confirm / description
        Added value: +"Must be true to forward this email; set only after the user approves."
      • addedInput schema / properties / email_id / description
        Added value: +"Email to forward."
      • addedInput schema / properties / email_id / maxLength
        Added value: +1024
      • addedInput schema / properties / email_id / minLength
        Added value: +1
      • removedInput schema / properties / to / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "items": {
        -      "type": "string"
        -    },
        -    "type": "array"
        -  }
        -]
      • addedInput schema / properties / to / description
        Added value: +"Recipients."
      • addedInput schema / properties / to / items
        Added value: +{
        +  "description": "Email address, e.g. jane@example.com.",
        +  "format": "email",
        +  "maxLength": 320,
        +  "minLength": 3,
        +  "type": "string"
        +}
      • addedInput schema / properties / to / maxItems
        Added value: +500
      • addedInput schema / properties / to / minItems
        Added value: +1
      • addedInput schema / properties / to / type
        Added value: +"array"
      • addedInput schema / properties / to / uniqueItems
        Added value: +true
      • changedInput schema / required
        Previous value: -[
        -  "account_id",
        -  "email_id",
        -  "to"
        -]New value: +[
        +  "email_id",
        +  "to",
        +  "confirm"
        +]
      • addedOutput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
      • changedOutput schema / additionalProperties
        Previous value: -{
        -  "type": "string"
        -}New value: +false
      • addedOutput schema / description
        Added value: +"Forward confirmation."
      • addedOutput schema / properties
        Added 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"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "status",
        +  "forwarded_id",
        +  "recipient_count",
        +  "summary"
        +]
    • Removedemail_get
    • Removedemail_get_attachment
    • Removedemail_list
    • Removedemail_mark_read
    • Removedemail_move
    • Changedemail_reply22 fields changed
      • addedInput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / account_id / description
        Added value: +"Account ID or email address. Omit when only one account is signed in."
      • addedInput schema / properties / account_id / maxLength
        Added value: +320
      • addedInput schema / properties / account_id / minLength
        Added value: +1
      • addedInput schema / properties / attachments
        Added 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
        +}
      • addedInput schema / properties / body / description
        Added value: +"Reply text."
      • addedInput schema / properties / body / maxLength
        Added value: +1000000
      • addedInput schema / properties / body / minLength
        Added value: +1
      • addedInput schema / properties / body_format
        Added value: +{
        +  "default": "text",
        +  "description": "Format of the body text you supply.",
        +  "enum": [
        +    "text",
        +    "html"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / cc
        Added 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
        +}
      • addedInput schema / properties / confirm / description
        Added value: +"Must be true to send this reply; set only after the user approves."
      • addedInput schema / properties / email_id / description
        Added value: +"Email to reply to."
      • addedInput schema / properties / email_id / maxLength
        Added value: +1024
      • addedInput schema / properties / email_id / minLength
        Added value: +1
      • addedInput schema / properties / mode
        Added value: +{
        +  "description": "sender: reply to the sender. all: reply all.",
        +  "enum": [
        +    "sender",
        +    "all"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / required
        Previous value: -[
        -  "account_id",
        -  "email_id",
        -  "body"
        -]New value: +[
        +  "email_id",
        +  "mode",
        +  "body",
        +  "confirm"
        +]
      • addedOutput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
      • changedOutput schema / additionalProperties
        Previous value: -{
        -  "type": "string"
        -}New value: +false
      • addedOutput schema / description
        Added value: +"Reply confirmation."
      • addedOutput schema / properties
        Added 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"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "status",
        +  "mode",
        +  "in_reply_to",
        +  "conversation_id",
        +  "summary"
        +]
    • Removedemail_reply_all
    • Addedemail_rule_manage
    • Changedemail_send44 fields changed
      • addedInput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / account_id / description
        Added value: +"Account ID or email address. Omit when only one account is signed in."
      • addedInput schema / properties / account_id / maxLength
        Added value: +320
      • addedInput schema / properties / account_id / minLength
        Added value: +1
      • removedInput schema / properties / attachments / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "items": {
        -      "type": "string"
        -    },
        -    "type": "array"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / attachments / default
        Removed value: -null
      • addedInput schema / properties / attachments / description
        Added value: +"Local files to attach: at most 10, each at most 25 MB."
      • addedInput schema / properties / attachments / items
        Added value: +{
        +  "description": "Local file path inside the server's allowed folders. Hidden and secret files are refused.",
        +  "maxLength": 4096,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / attachments / maxItems
        Added value: +10
      • addedInput schema / properties / attachments / type
        Added value: +"array"
      • addedInput schema / properties / attachments / uniqueItems
        Added value: +true
      • addedInput schema / properties / bcc
        Added 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
        +}
      • addedInput schema / properties / body / description
        Added value: +"Message body."
      • addedInput schema / properties / body / maxLength
        Added value: +1000000
      • addedInput schema / properties / body_format
        Added value: +{
        +  "default": "text",
        +  "description": "Format of the body text you supply.",
        +  "enum": [
        +    "text",
        +    "html"
        +  ],
        +  "type": "string"
        +}
      • removedInput schema / properties / cc / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "items": {
        -      "type": "string"
        -    },
        -    "type": "array"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / cc / default
        Removed value: -null
      • addedInput schema / properties / cc / description
        Added value: +"Cc recipients."
      • addedInput schema / properties / cc / items
        Added value: +{
        +  "description": "Email address, e.g. jane@example.com.",
        +  "format": "email",
        +  "maxLength": 320,
        +  "minLength": 3,
        +  "type": "string"
        +}
      • addedInput schema / properties / cc / maxItems
        Added value: +500
      • addedInput schema / properties / cc / type
        Added value: +"array"
      • addedInput schema / properties / cc / uniqueItems
        Added value: +true
      • addedInput schema / properties / confirm / description
        Added value: +"Must be true to send this email; set only after the user approves."
      • addedInput schema / properties / draft_id
        Added value: +{
        +  "description": "mode='draft': draft ID from email_create_draft.",
        +  "maxLength": 1024,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / importance
        Added value: +{
        +  "description": "Message importance.",
        +  "enum": [
        +    "low",
        +    "normal",
        +    "high"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / mode
        Added value: +{
        +  "description": "Send a new message or an existing draft.",
        +  "enum": [
        +    "new",
        +    "draft"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / save_to_sent
        Added value: +{
        +  "default": true,
        +  "description": "mode='new': keep a copy in Sent Items.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / subject / description
        Added value: +"Subject line."
      • addedInput schema / properties / subject / maxLength
        Added value: +998
      • addedInput schema / properties / subject / minLength
        Added value: +1
      • removedInput schema / properties / to / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "items": {
        -      "type": "string"
        -    },
        -    "type": "array"
        -  }
        -]
      • addedInput schema / properties / to / description
        Added value: +"Recipients (To)."
      • addedInput schema / properties / to / items
        Added value: +{
        +  "description": "Email address, e.g. jane@example.com.",
        +  "format": "email",
        +  "maxLength": 320,
        +  "minLength": 3,
        +  "type": "string"
        +}
      • addedInput schema / properties / to / maxItems
        Added value: +500
      • addedInput schema / properties / to / minItems
        Added value: +1
      • addedInput schema / properties / to / type
        Added value: +"array"
      • addedInput schema / properties / to / uniqueItems
        Added value: +true
      • changedInput schema / required
        Previous value: -[
        -  "account_id",
        -  "to",
        -  "subject",
        -  "body"
        -]New value: +[
        +  "mode",
        +  "confirm"
        +]
      • addedOutput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
      • changedOutput schema / additionalProperties
        Previous value: -{
        -  "type": "string"
        -}New value: +false
      • addedOutput schema / description
        Added value: +"Send confirmation."
      • addedOutput schema / properties
        Added 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"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "status",
        +  "mode",
        +  "draft_id",
        +  "recipient_count",
        +  "sent_at",
        +  "summary"
        +]
    • Removedemail_update
    • Removedemailfolders_create
    • Removedemailfolders_delete
    • Removedemailfolders_empty
    • Removedemailfolders_get
    • Removedemailfolders_get_tree
    • Removedemailfolders_list
    • Removedemailfolders_mark_all_as_read
    • Removedemailfolders_move
    • Removedemailfolders_rename
    • Removedemailrules_create
    • Removedemailrules_delete
    • Removedemailrules_get
    • Removedemailrules_list
    • Removedemailrules_move_bottom
    • Removedemailrules_move_down
    • Removedemailrules_move_top
    • Removedemailrules_move_up
    • Removedemailrules_update
    • Removedfile_copy
    • Removedfile_create
    • Removedfile_delete
    • Removedfile_download_url
    • Removedfile_get
    • Removedfile_list
    • Removedfile_move
    • Removedfile_rename
    • Removedfile_share
    • Removedfile_update
    • Removedfolder_create
    • Removedfolder_delete
    • Removedfolder_get
    • Removedfolder_get_tree
    • Removedfolder_list
    • Removedfolder_move
    • Removedfolder_rename
    • Addedm365_create
    • Addedm365_delete
    • Addedm365_get
    • Addedm365_get_content
    • Addedm365_list
    • Addedm365_move
    • Addedm365_search
    • Addedm365_update
    • Removedsearch_contacts
    • Removedsearch_emails
    • Removedsearch_events
    • Removedsearch_files
    • Removedsearch_unified
    • Removedserver_get_version
  2. 85 tool updatesv0.2.3
    • First observedaccount_authenticate
    • First observedaccount_complete_auth
    • First observedaccount_list
    • First observedcache_get_stats
    • First observedcache_invalidate
    • First observedcache_task_get_status
    • First observedcache_task_list
    • First observedcache_warming_status
    • First observedcalendar_check_availability
    • First observedcalendar_create_calendar
    • First observedcalendar_create_event
    • First observedcalendar_delete_calendar
    • First observedcalendar_delete_event
    • First observedcalendar_forward_event
    • First observedcalendar_get_event
    • First observedcalendar_get_free_busy
    • First observedcalendar_list_calendars
    • First observedcalendar_list_events
    • First observedcalendar_propose_new_time
    • First observedcalendar_respond_event
    • First observedcalendar_update_event
    • First observedcontact_add_to_list
    • First observedcontact_create
    • First observedcontact_create_list
    • First observedcontact_delete
    • First observedcontact_export
    • First observedcontact_get
    • First observedcontact_list
    • First observedcontact_update
    • First observedemail_add_category
    • First observedemail_archive
    • First observedemail_create_draft
    • First observedemail_delete
    • First observedemail_flag
    • First observedemail_forward
    • First observedemail_get
    • First observedemail_get_attachment
    • First observedemail_list
    • First observedemail_mark_read
    • First observedemail_move
    • First observedemail_reply
    • First observedemail_reply_all
    • First observedemail_send
    • First observedemail_update
    • First observedemailfolders_create
    • First observedemailfolders_delete
    • First observedemailfolders_empty
    • First observedemailfolders_get
    • First observedemailfolders_get_tree
    • First observedemailfolders_list
    • First observedemailfolders_mark_all_as_read
    • First observedemailfolders_move
    • First observedemailfolders_rename
    • First observedemailrules_create
    • First observedemailrules_delete
    • First observedemailrules_get
    • First observedemailrules_list
    • First observedemailrules_move_bottom
    • First observedemailrules_move_down
    • First observedemailrules_move_top
    • First observedemailrules_move_up
    • First observedemailrules_update
    • First observedfile_copy
    • First observedfile_create
    • First observedfile_delete
    • First observedfile_download_url
    • First observedfile_get
    • First observedfile_list
    • First observedfile_move
    • First observedfile_rename
    • First observedfile_share
    • First observedfile_update
    • First observedfolder_create
    • First observedfolder_delete
    • First observedfolder_get
    • First observedfolder_get_tree
    • First observedfolder_list
    • First observedfolder_move
    • First observedfolder_rename
    • First observedsearch_contacts
    • First observedsearch_emails
    • First observedsearch_events
    • First observedsearch_files
    • First observedsearch_unified
    • First observedserver_get_version

TDQS

A4/5.0

Scored across 23 tools

Disambiguation4/5

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.

Naming Consistency4/5

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.

Tool Count4/5

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.

Completeness4/5

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

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers