ms-graph-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ms-graph-mcpwhat meetings do I have on my calendar today?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ms-graph-mcp
A Model Context Protocol server that gives an AI assistant access to your own Microsoft 365 data — Outlook mail and calendar, OneDrive, SharePoint, To Do, Planner, Teams chat, Entra ID and Intune — through the Microsoft Graph API. It runs locally over stdio, signs in as you with delegated permissions, and stores its token cache encrypted on your machine.
Not affiliated with Microsoft. This is an independent community project. Microsoft, Microsoft 365, Microsoft Graph, Outlook, OneDrive, SharePoint, Teams, Entra and Intune are trademarks of the Microsoft group of companies, used here only to describe what this software connects to.
Why an MCP server
Microsoft Graph is an ordinary HTTP API. Everything this server does could, in principle, be a
curl command or a fifty-line script, and for a question you ask once it should be. This project
exists for the other case: an assistant that reaches the same API many times a day, on your
behalf, without being handed your credentials and without being told how Graph works on every
turn.
Five things move from the conversation into the server.
The assistant never handles your token
For a model to call Graph directly, an access token has to reach the model — pasted into the conversation, returned by a shell command, or read out of a file the model can open. Once it is there it is in the transcript, in the context window, and in whatever logs that client keeps. Access tokens are bearer credentials: anyone holding one is you, for an hour, to the full extent of the scopes it carries.
Here the token never leaves the server process. The model sees tool names, JSON Schemas and
results; the refresh token sits encrypted on disk and the access token exists only inside a
request the model cannot observe. That boundary is the reason getToken refuses to become
interactive mid-request, and the reason no tool returns a @microsoft.graph.downloadUrl — a
pre-authenticated link that would hand file contents to anyone who read the transcript.
Graph's sharp edges are encoded once, in the tool descriptions
Graph is not uniform, and its inconsistencies are the kind a model rediscovers by getting them wrong. A few that this server already knows about, each of which cost a real debugging session to establish:
GET /chats/{id}/messagesdoes not support$select. You cannot ask Graph for fewer fields; you get the wholechatMessageand trim it yourself.On that same endpoint
$filteris silently ignored unless$orderbynames the same property. Not rejected — ignored. A date-bounded query returns the wrong window and no error, which is whychat_fetch_historypins the ordering rather than exposing it.Channel messages are narrower still: no
$filter, no$orderby, and an order derived from the reply chain rather than creation time. A date window there cannot be a server-side query or an early stop, soteams_fetch_channel_historyfilters while paging and tells you the window may be incomplete.Page size caps at 50, and Teams allows roughly one request per second per chat or channel. A naive loop over a long history is throttled; the paginator paces itself.
Planner rejects every update and delete without an
If-Matchetag from a prior read.Outlook
$searchtakes a quoted term and supports no date range at all; a date-bounded mail query has to use$filter.Directory queries using
$countor$searchneed aConsistencyLevel: eventualheader that nothing in the URL suggests.
A model driving curl relearns these from error responses, or worse, from a 200 that quietly
returned the wrong rows. Written into a tool description once, they are in front of the model
before it makes the call.
Responses are projected down to something a model can read
A single chatMessage carries an HTML body, reactions, mentions, attachments and hosted-content
references. Fifty of them is far more than a useful answer needs and more than many clients will
accept — Claude Code truncates tool output near 25,000 tokens. Raw Graph responses spend that
budget on markup.
Every tool here returns a projection instead: for a message, the sender, the timestamp, the body
stripped of HTML and truncated to a caller-controlled budget, and a count of attachments. Long
results carry a nextLink cursor so the model can continue deliberately rather than by
re-requesting and hoping.
Guardrails a script does not have
Host pinning.
graph_requestlets the model choose a path, and every request carries your bearer token, so a path that escapes the Graph host leaks that token. Three checks sit between the two: the path is validated, the URL is built through the URL API rather than by concatenation, and the resulting host is compared against the pinned Graph hostname. The same check runs on every@odata.nextLinkbefore it is followed, because a paging link comes from a server response rather than from you. This is not hypothetical: a comparable Graph MCP server shipped a string-concatenated path that allowed an@attacker.comhost escape.Read-only mode.
--read-onlyremoves write tools from the catalogue entirely, so a client never sees them.Least-privilege consent. The scopes requested at sign-in are derived from the enabled groups and the tools inside them, so
--groups mail --read-onlyasks forMail.Readand nothing else.Retry and backoff. 429 and 503 are retried with
Retry-Afterhonoured; a mutating request is replayed only when Graph said it did not process it.
One server, many clients
The same process serves Claude Code, Claude Desktop, VS Code and any other MCP client, over both the 2026-07-28 revision and the 2025-11-25 one, from a single factory. A shell script is bound to the one place it runs.
When you do not need this
If you want one answer once, use curl. If you are writing a program that talks to Graph, use the
Microsoft Graph SDK — this is not a client library, and graph_request is a deliberate escape
hatch rather than a general interface. The server earns its keep when the caller is a model, the
access is ongoing, and the credential must not be in the conversation.
Worth being plain about the split: rather more than half of the code here is not MCP at all. It is the part that calls Graph correctly — retries, batching, pagination, path validation, scope derivation — and you would need it whatever the caller was. MCP is the thin, typed surface over the top that lets a model use it safely.
Related MCP server: Microsoft Graph MCP
Quick start
You need Node.js 20 or later. Sign in once, in a terminal:
npx ms-graph-mcp loginThere is no application to register first: the server signs in with a shared multi-tenant Entra application published by this project. See Which application am I signing in to for what that means for you and for your tenant.
The shared registration is not published yet. The constant it will occupy, SHIPPED_CLIENT_ID in src/config.ts, is still empty, so this build has no default application to fall back on. login says so and stops before it contacts Entra, and status prints the same registration walkthrough. Until the real ID ships, register an application of your own — or use one your organisation already has — and name it on each command:
npx ms-graph-mcp login --client-id <your-client-id>Register your own Entra application has the steps. When the shared ID lands, nothing else in this README changes: --client-id keeps working and keeps taking precedence over the shipped default.
Either way, your system browser opens on the Microsoft sign-in page. Pick the account you want the server to act as, approve the permissions it asks for, and the tab reports that sign-in is complete. Back in the terminal, the command has caught the redirect, exchanged it for tokens, and written the refresh token to an encrypted cache under your config directory.
On a machine with no browser to open — an SSH session, a container, a headless server — ask for the device code flow instead:
npx ms-graph-mcp login --auth-flow deviceThat prints a short code and a URL to open on any other device. Enter the code there and the terminal finishes on its own. The default, --auth-flow auto, already falls back to this when the browser cannot be opened; passing device explicitly skips the attempt that would fail. Both are OAuth 2.0 sign-ins and both end with the same delegated token — see How sign-in works.
Either way, check it worked:
npx ms-graph-mcp statusstatus prints the application ID in use and where it came from, the account it resolved, and the scopes this configuration will request. Then point an MCP client at the server.
As a Claude Code plugin
The plugin wires the server into Claude Code and asks you for its settings, so there is no MCP config to edit and nothing to export in a shell profile.
/plugin marketplace add devyhan/ms-graph-mcp
/plugin install ms-graph-mcp@devyhanClaude Code prompts for four settings when the plugin is enabled, and fills in sensible values for three of them:
Setting | Default | What it does |
Application (client) ID | none, and required | The Entra application to sign in with. The dialog will not accept an empty value, because there is nothing to fall back on. |
Directory (tenant) ID |
| Suits most work and school accounts. Use |
Tool groups | the personal set | Profile, mail, calendar, files, To Do, contacts and search. A shorter list means a smaller consent prompt. |
Read-only | on | Hides every tool that writes and drops the write scopes from the consent request. Turn it off when you want the server to act, not just read. |
Read-only defaults to on here, and to off on the command line. The plugin is the path someone takes without reading this file first, and an assistant that can send mail and delete files on a fresh install is the wrong first state; on the command line the choice is already explicit.
You can change any of them later from /config.
You still need your own Entra application — see Register your own Entra application — because this project publishes no shared one. Paste its Application (client) ID into the first prompt.
Sign-in remains a terminal step, once:
npx ms-graph-mcp loginThe server will not open a browser from inside a Claude Code session. The MCP
transport owns stdout, and a sign-in prompt in the middle of a tool call would
corrupt the JSON-RPC stream, so it returns an error telling you to run login
instead. See How sign-in works.
Everything works before you configure anything: the server starts, lists its tools,
and status explains what is missing. An installed-but-unconfigured plugin shows a
working server rather than a broken one.
If a setting does not take effect, run npx ms-graph-mcp status and read
the Client ID from: line — it names which source won. Should a value arrive as the
literal text ${user_config.client_id}, the placeholder was never substituted;
the server refuses it and says so rather than passing it to Entra, where it would
fail much later and blame something else.
Without the plugin
Every setting is also an MS365_MCP_* environment variable, which is what the plugin
sets under the hood, and every one has a command-line flag — see
Commands and flags. Use these when you run the server directly:
export MS365_MCP_CLIENT_ID="<your application (client) ID>"
export MS365_MCP_TENANT_ID="<your tenant ID>"
export MS365_MCP_GROUPS="mail,calendar,files"
export MS365_MCP_READ_ONLY=1A client launched from a desktop icon rather than a terminal does not read your shell profile, so a variable exported there will not reach it. That is the failure the plugin's prompts exist to avoid; if you are configuring by hand, prefer the flags.
Claude Code
claude mcp add microsoft-graph -- npx -y ms-graph-mcp --preset workOr add it to .mcp.json in the project root:
{
"mcpServers": {
"microsoft-graph": {
"command": "npx",
"args": ["-y", "ms-graph-mcp", "--preset", "work"]
}
}
}Claude Desktop
Edit claude_desktop_config.json (Settings > Developer > Edit Config):
{
"mcpServers": {
"microsoft-graph": {
"command": "npx",
"args": ["-y", "ms-graph-mcp", "--preset", "work"]
}
}
}VS Code
Add .vscode/mcp.json to the workspace:
{
"servers": {
"microsoft-graph": {
"type": "stdio",
"command": "npx",
"args": ["-y", "ms-graph-mcp", "--preset", "work"]
}
}
}While the shared registration is unpublished, give each of these your own application ID as well: add "env": { "MS365_MCP_CLIENT_ID": "<your-client-id>" } beside args, or append "--client-id", "<your-client-id>" to args.
The server starts whether or not an application is configured. With none it writes a warning to stderr, lists its tools as normal, and fails every Graph call until you sign in.
Which application am I signing in to
A shared application published by this project. Unless you override it, the client ID the server presents to Entra is a multi-tenant registration this project publishes — the same one every other user of this package signs in with. The server picks one in this order, and stops at the first that is set:
--client-id <id>MS365_MCP_CLIENT_IDthe application shipped with the package
nothing, in which case sign-in refuses to start and prints the registration steps
status reports which of the four it landed on, and login names the authority and the application on stderr before it opens the browser, so you can see whose application you are about to consent to while you can still stop. Shipping an application ID is the model Lokka and the Softeria MS-365 MCP server use, and it exists for one reason: registering an application is the step most people never get past.
First use in an organisation creates an enterprise application in that tenant. The first time anyone in a tenant consents to a multi-tenant app, Entra creates a service principal for it in that directory — an entry under Enterprise applications carrying this project's application name. Administrators can see it there, review the delegated permissions it has been granted, and disable or block it. From then on every request the server makes is attributed to that application, alongside your user, in the tenant's sign-in and Graph activity logs. This is a consequence of signing in with a shared application, not a footnote: if your organisation would object to an unfamiliar third-party application appearing in its directory, register your own before the first sign-in.
The application holds no secret and no data. It is a public client: there is no client secret anywhere in this package, and there could not be one, because a secret shipped to every user is not a secret. Every token Entra issues is issued to the signed-in user, is scoped to what that user can already reach, and is cached encrypted on that user's own machine (see Security). No server of ours sits between you and Microsoft, and neither the package nor the owner of the registration ever receives your tokens, mail, files or directory records. What the owner of a registration does control is the registration object itself, which is what the next two paragraphs are about.
Using your own registration instead. Pass --client-id (or set MS365_MCP_CLIENT_ID) and follow Register your own Entra application. Reasons to do it:
An enterprise policy that permits only applications registered in its own tenant, or that requires an internal owner and a review for every enterprise application.
A sovereign cloud. The shared registration exists in the global cloud only, so the server refuses to offer it to
--cloud usgov,usgovdodorchinaand says why, rather than letting you discover it after typing your password. Register an application in that cloud and name it with--client-id.A tenant that has blocked the shared application, or an administrator who will grant consent only to something they own.
If the shared registration is ever deleted or blocked, sign-in starts failing with AADSTS700016, AADSTS7000112 or AADSTS700054, and --client-id <your-id> is the entire fix. Nothing else changes: same flows, same scopes, same tool catalogue, same cache location. Run login once after switching, because the cached refresh token belongs to the application that obtained it.
Consent
Shipping an application ID removes the registration step. It does not remove the consent step. Entra still asks the signed-in user to approve every delegated scope the server requests, and the tenant's consent policy still decides which of those a user is allowed to approve without an administrator.
Work and school accounts in a default tenant. Under the Microsoft-managed default consent policy that new tenants get, an ordinary user cannot self-consent to Mail.Read, Calendars.Read, Calendars.ReadWrite, Calendars.Read.Shared, Chat.Read, Tasks.Read, Tasks.ReadWrite, Files.Read.All, Sites.Read.All or MailboxSettings.Read, among others — even though Microsoft's permissions reference marks every one of them as not requiring admin consent. That covers most of what the personal and work presets ask for. Sign-in fails at the consent screen, and the server prints which of your requested scopes fall under that policy, however small the request was. An administrator clears it once: Enterprise applications > (the application) > Permissions > Grant admin consent for the shared app, or App registrations > (your app) > API permissions > Grant admin consent for your own.
Personal Microsoft accounts consent for themselves — no administrator, no tenant policy. In exchange, a large part of the catalogue is unavailable to them at any consent level: the Teams chat and channel APIs are documented as not supported for delegated personal-account access, and Planner, SharePoint, the directory tools and Intune do not exist for a personal account at all. Use a narrow group set, and sign in against the personal-account authority with --tenant-id consumers; a refresh token issued through the common authority is rejected at its first refresh.
Ask for less, then widen. The scopes requested at sign-in are derived from the enabled groups, so start narrow and add:
npx ms-graph-mcp login --groups me,mail
npx ms-graph-mcp login --groups me,mail,calendar,filesEntra prompts again only for what you added; what was already granted stays granted. --read-only drops every write scope from the request. npx ms-graph-mcp permissions --preset work prints the exact scope list for a configuration, formatted for pasting into an admin consent request.
Register your own Entra application
Once the shared registration ships, most users can skip this section. It remains the supported fallback for the reasons listed in Which application am I signing in to, and until then it is the only way to sign in.
Open the Microsoft Entra admin center and go to Applications > App registrations > New registration.
Give it a name. Under Supported account types, pick the audience you need. A personal Microsoft account (outlook.com, hotmail.com) requires "Accounts in any organizational directory and personal Microsoft accounts"; a work or school account used only in its own tenant needs nothing more than the single-tenant option.
Leave the redirect URI empty for now and click Register. Copy the Application (client) ID from the Overview page — that is the value for
--client-id.Go to Authentication > Add a platform > Mobile and desktop applications and tick the redirect URI
http://localhost. The browser flow, which is the default, redirects the finished sign-in there — to a listener on 127.0.0.1 — and fails without it.On the same page, scroll to Advanced settings and set Allow public client flows to Yes. Neither sign-in flow works without it.
Optionally, under API permissions, add the delegated Microsoft Graph permissions for the tool groups you plan to enable (see the table below). This is not required for user-consentable scopes — you will be prompted to consent at first sign-in — but it is required for the admin-consent groups, and for anything the tenant's consent policy withholds from ordinary users, where an administrator must click Grant admin consent.
http://localhost is a wildcard: Entra accepts a redirect back to it on whatever port the machine happened to be listening on. Some tenants have policies that reject it and require an exact port. In that case register http://localhost:53682 (any free port will do) instead, and start the server with --auth-port 53682 so it binds the port the registration names.
No client secret is needed, and you should not create one. This is a public client running on your machine: it authenticates you interactively and stores a refresh token, and a secret shipped alongside it would not be a secret.
A personal Microsoft account also needs --tenant-id consumers at sign-in, whatever the registration looks like.
Registering a multi-tenant application
Step 2 above is enough for a registration you alone use. An organisation cloning this project's setup — one registration, many users, more than one tenant — needs the same shape the shared application has:
Manifest property | Value | Why |
|
|
|
|
| Required by any audience that includes personal Microsoft accounts. |
|
| Both sign-in flows are public-client flows. |
Redirect URI |
| Where the browser flow's authorization code lands. |
The ordering gotcha: if you change the audience to one that includes personal accounts while the token version is still 1, the portal rejects the save with "Property api.requestedAccessTokenVersion is invalid". Set api.requestedAccessTokenVersion to 2 in the manifest and save that on its own first, then change signInAudience.
A multi-tenant registration also means the enterprise application described in Which application am I signing in to appears in every tenant whose users sign in, including yours.
How sign-in works
Both sign-in flows are OAuth 2.0, and both end with the same delegated access token. They differ in how you prove who you are, not in what they are.
browser is the authorization code grant with PKCE (RFC 7636). The server binds a one-shot listener on the loopback address, 127.0.0.1, opens the system browser at the Entra authorize endpoint, and Entra sends the finished sign-in back to that listener as a redirect carrying an authorization code. The server exchanges the code, together with the proof key it generated before opening the browser, for tokens. The code is valid only on this machine and only for that one exchange.
device is the device authorization grant (RFC 8628). The server asks Entra for a user code, prints it with a URL, and polls the token endpoint while you enter the code in a browser somewhere else. It is no less an OAuth flow than the browser one; it exists for the case where the machine running the server has no browser it can open, and the sign-in has to happen on a different device.
auto is the default. It tries browser, and when that fails — no desktop session, no way to launch a browser, no loopback port — it writes the reason to stderr and runs device instead. Pass --auth-flow browser when you would rather see that error than a fallback, and --auth-flow device when you never want a browser opened.
Delegated permissions only. The server signs in as you and calls Graph as you. It never authenticates as an application, holds no client secret, and requests no application permissions, so it reaches exactly what your account reaches and nothing more. Every request it makes is attributable to your user in the tenant's sign-in logs.
The session is a refresh token in an encrypted cache. What sign-in leaves behind is the MSAL cache blob, encrypted with AES-256-GCM into token-cache.enc in your config directory (~/.config/microsoft-graph-mcp on macOS and Linux, %APPDATA%\microsoft-graph-mcp on Windows), with the 32-byte key beside it in cache.key at mode 0600. See Security for the details and for --cache-dir.
getToken never prompts. In serve mode the server refreshes access tokens silently and does nothing else. When the refresh token has expired, been revoked, or no longer covers a scope, the tool call returns an error telling you to run login again rather than starting a sign-in. That is deliberate: the MCP transport owns stdout, so a prompt or a browser launched in the middle of a request would corrupt the JSON-RPC stream. Sign-in happens out of band, in a terminal.
This is a local server. It does not implement the MCP authorization specification, and per that specification it should not: the spec covers HTTP transports and directs stdio servers to take credentials from the environment instead. So the server obtains user credentials itself, as an ordinary public OAuth client, and the MCP client is not involved in authentication at all. A remote HTTP mode — where the MCP client performs OAuth against Entra and the server exchanges that token for a Graph token on the user's behalf — is not implemented.
When the browser flow does not work
Nothing opens, or the command sits there. There is no desktop session to open a browser in, which is normal over SSH and inside containers. Use --auth-flow device and sign in from another machine. Under the default auto flow this resolves itself, with a line on stderr saying what failed.
The browser opens but the redirect is rejected (AADSTS50011, redirect URI mismatch). The app registration has no matching redirect URI. Add the Mobile and desktop applications platform with http://localhost, as in step 4 above.
The loopback listener cannot bind. With the default --auth-port 0 the operating system picks a free port, so this only comes up when a port has been pinned and something else already holds it, or when a local firewall blocks the listener. Choose another port with --auth-port <n>. Pin a port deliberately, and register http://localhost:<n> alongside it, when the tenant rejects the bare http://localhost wildcard.
Sign-in errors
Entra reports a failure as an AADSTS code inside the error text. These are the ones that come from the application identity or from consent, rather than from the browser leg.
Code | What it means | What fixes it |
| The application exists, but not in the tenant you signed in to. A single-tenant registration returns this to every tenant except its own; so does one the tenant has blocked, or whose enterprise application an administrator deleted. | Sign in to the tenant that owns the registration ( |
| Entra did not accept the value as an application identifier at all. A mistyped GUID, or one that was never registered. | Check what |
| The account comes from a different identity provider than the application accepts: a personal Microsoft account at a work-only application, or the reverse. |
|
| The application accepts Microsoft Entra work or school users only, and you signed in with a personal Microsoft account. | Sign in with a work or school account, or pass |
| The application is disabled in that tenant — its enterprise application was disabled, or the service principal was blocked from sign-in. | Ask an administrator to re-enable it under Enterprise applications > Properties > "Enabled for users to sign-in", or pass |
| The consent screen was declined. Nothing was granted and no session was created. | Ask for less: a narrower |
| The requested permissions need an administrator, and the signed-in user is not allowed to grant them. | Drop the admin-consent groups (do not pass |
The server sorts these into three kinds, and only one of them falls back.
Application rejections — the first five rows — are reported as Sign-in failed (<code>), followed by the likely cause, the flag that fixes it, and the first line of what Entra actually said. auto does not retry them on the device code path: an application that is absent, disabled, or wrong for your account type is exactly as absent on another device. The MSAL stack goes to stderr separately, prefixed [auth].
Consent decisions — the last two rows, plus AADSTS65001 and AADSTS900941 — print Sign-in was refused at the consent screen, the number of scopes requested, and the subset of them the default tenant consent policy withholds from ordinary users. auto does not fall back here either, because the device code flow shows the same consent screen and would be refused the same way.
Browser failures are everything else. Under auto the server writes Browser sign-in failed: ... to stderr and continues on the device code path. Under --auth-flow browser it stops and prints the three usual causes: no desktop session, a loopback redirect that could not be served, and a registration with no matching redirect URI.
Tools
101 tools across 14 groups. --read-only removes every write tool, leaving 64. The reference for each group is below; the descriptions here are the first line of what the model itself is shown.
Tool groups
Tools are grouped by product area. Enable only the groups you need — the scopes requested at sign-in are derived from the enabled groups, so a narrower selection means a narrower consent prompt.
Group | Product | Delegated scopes | Admin consent | Tools |
| Entra ID profile, Outlook mailbox settings |
| No | 2 |
| Outlook mail |
| No | 12 |
| Outlook calendar |
| No | 9 |
| OneDrive |
| No | 10 |
| Microsoft To Do |
| No | 8 |
| Microsoft Planner |
| No | 9 |
| Outlook contacts |
| No | 6 |
| Teams one-to-one and group chats |
| No | 6 |
| SharePoint sites, libraries, lists |
| No | 11 |
| Microsoft Search across mail, files, sites |
| No | 1 |
| Teams teams, channels, channel messages |
| Yes | 9 |
| Entra ID user and group lookups |
| Yes | 9 |
| Intune managed device inventory |
| Yes | 6 |
| Any Graph endpoint, plus introspection | reuses the union of the above | No | 3 |
offline_access and User.Read are always requested: the first keeps refresh tokens working, the second identifies the account.
The three groups marked Yes request scopes that no ordinary user can consent to, so they stay disabled unless you pass --org-mode. Enabling them in a tenant where an administrator has not granted consent means sign-in fails outright, not that those tools quietly return errors.
The Admin consent column is Microsoft's own classification of each permission. A tenant's consent policy is a second, separate gate, and it withholds more than this column shows — Mail.Read and Calendars.Read among them. See Consent.
The generic group is always on and cannot be selected or removed. It holds graph_request (the escape hatch for endpoints no other tool covers), graph_schema (fetches one item from a path and reports its property names and types), and graph_list_permissions (reports the enabled groups, their scopes, and the signed-in account).
Tool reference
Tool | What it does | Arguments | |
| Returns the signed-in user's own Entra ID profile from /me: by default id, displayName, mail, userPrincipalName, jobTitle, officeLocation and preferredLanguage. |
| |
| Returns the signed-in user's Outlook mailbox configuration: time zone, date and time format, locale, working hours, and the automatic-reply (out-of-office) setting. |
|
Bodies are the expensive part of a mailbox, so list calls return bodyPreview only and mail_get_message fetches one message in full, HTML stripped to text by default.
Tool | What it does | Arguments | |
| Lists Outlook messages newest-first, 10 per call by default (50 max), as a compact projection: id, subject, from, toRecipients, receivedDateTime, isRead, hasAttachments, bodyPreview and webLink. |
| |
| Finds messages by text, returning the same compact projection as mail_list_messages, 10 per call by default (50 max). |
| |
| Returns one message with its body plus sender, recipients, timestamps, importance, conversationId and webLink. |
| |
| Lists the top-level Outlook mail folders with their ids, unread counts and total counts, 50 per call by default. |
| |
| Lists attachment metadata for one message — id, name, contentType, size in bytes, whether it is inline, and its kind (file, item, or reference) — 20 per call by default. |
| |
| write | Sends a message immediately from the signed-in mailbox — there is no undo and no confirmation step, so confirm the recipients and text with the user first. |
|
| write | Creates an unsent draft in the Drafts folder and returns its id and webLink. |
|
| write | Sends a reply to an existing message immediately — it does not create a draft, and there is no undo, so confirm the text with the user first. |
|
| write | Forwards an existing message immediately, attachments included — it does not create a draft and there is no undo, so confirm the recipients with the user first. |
|
| write | Moves a message to another mail folder. |
|
| write | Sets the read flag on one message. |
|
| write | Deletes a message. |
|
calendar_list_events switches to /me/calendarView when you give it a date range, which is the only form that expands recurring series. calendar_get_schedule and calendar_find_meeting_times are POSTs that read rather than write.
Tool | What it does | Arguments | |
| Lists events with subject, start, end, location, organizer and attendee count, plus a nextLink when more pages exist. |
| |
| Returns one event in full: subject, start, end, location, organizer, the attendee list with each response, the description body (HTML converted to text and capped), recurrence summary, and the Outlook web link. |
| |
| Lists the signed-in user's calendars with id, name, colour, owner and whether they can be edited or shared. |
| |
| Returns free/busy availability for up to 20 people or rooms over a time window, as an availabilityView string where each character covers one interval (0 free, 1 tentative, 2 busy, 3 out of office, 4 working elsewhere), plus working hours and any visible busy blocks. |
| |
| Suggests meeting slots that work for the signed-in user and the given attendees, ranked by confidence, with the attendees who are unavailable in each slot. |
| |
| write | Creates an event on the primary calendar and returns the created event. |
|
| write | Patches the given fields on an event and returns the updated event; omitted fields are left alone. |
|
| write | Deletes an event, moving it to Deleted Items. |
|
| write | Accepts, declines, or tentatively accepts a meeting invitation, optionally with a comment to the organizer. |
|
Path-addressed calls encode each segment separately, so spaces and & in filenames work. files_read_text refuses binary types by extension before downloading, and no tool returns @microsoft.graph.downloadUrl, which is a pre-authenticated link to the file contents.
Tool | What it does | Arguments | |
| Lists the direct children of a folder in the signed-in user's OneDrive, returning id, name, kind (file or folder), size, mime type, child count, last-modified time and webUrl per entry, plus count and nextLink when more pages exist. |
| |
| Reads the metadata of one OneDrive file or folder: name, kind, size, mime type, created and last-modified times and authors, parent folder path and ids, and webUrl. |
| |
| Searches the whole of the signed-in user's OneDrive for free text, matching file names and indexed file contents, and returns the same compact fields as files_list_children plus count and nextLink. |
| |
| Lists files the signed-in user recently opened or edited, most recent first, with count and nextLink. |
| |
| Lists files and folders other people have shared with the signed-in user, with count and nextLink. |
| |
| Returns the contents of a text-like OneDrive file (plain text, Markdown, CSV, JSON, XML, source code, config) as a string, truncated to maxChars, which defaults to 20000. |
| |
| write | Creates a folder in the signed-in user's OneDrive and returns the created item. |
|
| write | Writes a text file to the given path in the signed-in user's OneDrive and returns the stored item. |
|
| write | Deletes a file or folder from the signed-in user's OneDrive. |
|
| write | Creates a sharing link for a OneDrive file or folder and returns its URL, permission type and scope. |
|
Tool | What it does | Arguments | |
| Lists the signed-in user's Microsoft To Do lists with their id, display name and well-known name (for example defaultList for the built-in Tasks list). | none | |
| Lists tasks in one To Do list, returning id, title, status, importance, due and reminder times and a short body preview per task, plus count and nextLink when more pages exist. |
| |
| Reads one To Do task in full: title, status, importance, reminder state, start/due/completed times, categories and the notes body (truncated). |
| |
| write | Creates a task in a To Do list and returns the created task. |
|
| write | Patches an existing To Do task and returns the updated task. |
|
| write | Marks a To Do task completed by patching its status to 'completed', and returns the updated task including the completedDateTime Graph stamps on it. |
|
| write | Deletes a To Do task permanently and returns a confirmation. |
|
| write | Creates a new To Do list and returns its id and display name. |
|
Planner requires an If-Match etag on every update and delete. The tools fetch the item first and supply the etag themselves.
Tool | What it does | Arguments | |
| Lists the Planner plans the signed-in user can see, with id, title, owning Microsoft 365 group id and container. |
| |
| Lists Planner tasks assigned to the signed-in user across every plan, with title, planId, bucketId, due date, percentComplete and assignee ids. |
| |
| Returns one Planner plan: id, title, owning Microsoft 365 group id, container and creation time. |
| |
| Lists the buckets (columns) of a plan with id, name and orderHint. |
| |
| Lists every task in a plan regardless of assignee, with title, bucketId, due date, percentComplete and assignee ids. |
| |
| Returns one Planner task. |
| |
| write | Creates a task in a plan and returns it. |
|
| write | Updates a Planner task and returns it. |
|
| write | Permanently deletes a Planner task; there is no recycle bin. |
|
Tool | What it does | Arguments | |
| Lists personal contacts from the signed-in user's default Outlook Contacts folder, 25 per page by default (max 100). |
| |
| Returns one personal contact by id, with names, company, job title, department, every email address, phone numbers, postal addresses, birthday, categories and timestamps. |
| |
| Full-text search over the default Contacts folder using Outlook |
| |
| write | Creates a personal contact in the signed-in user's default Contacts folder and returns the stored contact, including the new id. |
|
| write | Updates the given fields of one personal contact and returns the stored result. |
|
| write | Deletes one personal contact. |
|
Graph offers no $select and no date filter on chat messages, so projection happens here and date windows are applied while paging. chat_fetch_history is the one to reach for beyond a single page.
Tool | What it does | Arguments | |
| Lists the Teams chats the signed-in user belongs to (one-to-one, group, and meeting chats — never channel conversations, which the teams group covers). |
| |
| Returns one Teams chat by id: topic, chatType, created and last-updated timestamps, the Teams deep link, whether the signed-in user has hidden it, how far they have read, and the meeting join URL for a meeting chat. |
| |
| Reads recent messages from one Teams chat, newest first. |
| |
| Lists everyone in one Teams chat: the per-chat membership id, display name, email, directory user id, and roles (an owner of a group chat has ["owner"]; ordinary members have none). |
| |
| write | Posts a message to a Teams chat as the signed-in user. |
|
| Reads a long run of one Teams chat, newest first, paging automatically so you do not have to follow nextLink yourself. |
|
Tool | What it does | Arguments | |
| Searches SharePoint sites and returns id, display name, description and web URL for each match, plus a count and a nextLink when more pages exist. |
| |
| Returns one site: its composite id, display name, description, web URL, hostname and timestamps. |
| |
| Lists the document libraries (drives) on a site with id, name, description, drive type and web URL, plus a count and a nextLink when more pages exist. |
| |
| Lists the children of a document-library folder: name, whether it is a file or a folder, size, child count, MIME type, last modified time and author, and the web URL, plus a count and a nextLink when more pages exist. |
| |
| Lists the SharePoint lists on a site with id, display name, description, template and web URL, plus a count and a nextLink when more pages exist. |
| |
| Returns one list: id, display name, description, template, web URL and timestamps. |
| |
| Lists items in a SharePoint list with their column values, plus a count and a nextLink when more pages exist. |
| |
| Returns one list item with its column values, creator, last editor, timestamps and web URL. |
| |
| write | Creates an item in a SharePoint list and returns its new id, web URL and stored column values. |
|
| write | Updates column values on an existing list item and returns the stored values. |
|
| write | Deletes one item from a SharePoint list. |
|
Tool | What it does | Arguments | |
| Runs a relevance-ranked Microsoft Search query across Microsoft 365 and returns a flattened list of hits, each with its rank, a text summary and the resource's id, name or subject, web URL and last-modified time. |
|
Channel messages have an even narrower query surface than chats: no $filter, no $orderby, and an order based on the reply chain rather than creation time. teams_fetch_channel_history filters client-side for that reason and says so.
Tool | What it does | Arguments | |
| Lists the Microsoft Teams teams the signed-in user is a member of, returning id, displayName, description, visibility and archived state. | none | |
| Lists the channels of one team, returning id, displayName, description, membershipType and webUrl for each. |
| |
| Returns one channel: displayName, description, membershipType, creation time, the channel email address (empty unless the channel has one provisioned) and the deep link webUrl. |
| |
| Lists the top-level messages of a channel, newest first, with sender, timestamp, plain-text body (HTML stripped and truncated to |
| |
| Returns one channel message in full: sender, timestamps, plain-text body truncated to |
| |
| Lists the replies to one top-level channel message, newest first, with the same compact projection as teams_list_channel_messages. |
| |
| Walks a channel's message history and returns a bounded page of root messages with sender, creation and modification times, plain-text body (HTML stripped, truncated to |
| |
| Lists the members of a team with displayName, email, the directory userId and their roles ("owner" for owners, empty for ordinary members, "guest" for guests). |
| |
| write | Posts a new top-level message to a channel as the signed-in user and returns the created message id, timestamp and deep link. |
|
Advanced queries against the directory need the ConsistencyLevel: eventual header; the client sets it automatically when a request uses $count or a directory $search.
Tool | What it does | Arguments | |
| Lists users in the Microsoft Entra ID tenant, 25 per page by default (max 999). |
| |
| Finds users by name or email address, returning the same compact rows as directory_list_users, 25 per page by default. |
| |
| Returns one user by object id or userPrincipalName, with names, contact details, job title, department, office, employee id, account state, usage location and on-premises sync fields. |
| |
| Returns the user's manager as a compact row (id, displayName, userPrincipalName, mail, jobTitle, department). |
| |
| Lists the users who report directly to the given user, 25 per page by default (max 999), as compact rows. |
| |
| Lists groups in the Microsoft Entra ID tenant, 25 per page by default (max 999). |
| |
| Returns one group by object id, with its description, mail nickname, type flags, visibility, classification, lifecycle dates, dynamic membership rule and on-premises sync fields. |
| |
| Lists the direct members of a group, 25 per page by default (max 999). |
| |
| Returns the ids of every group the user belongs to, including memberships inherited through nested groups. |
|
Tool | What it does | Arguments | |
| Lists Intune-managed devices in the tenant with id, name, operating system and version, compliance state, last sync time, primary user, manufacturer and model, plus count and nextLink when more pages exist. |
| |
| Reads one Intune-managed device in detail: hardware identity, primary user, enrollment and management state, encryption and supervision flags, Exchange access state, storage and memory in GB, and the last sync time. |
| |
| Lists the applications Intune has detected on one managed device, returning display name, version, size in MB and the tenant-wide deviceCount for each, with count and nextLink. |
| |
| Lists the tenant's Intune device compliance policies with id, display name, platform-specific policyType (from the @odata.type discriminator, e.g. |
| |
| Returns the tenant-wide Intune device counts in one call: total enrolled devices, MDM-enrolled and dual-enrolled counts, a per-operating-system breakdown, and the Exchange access state breakdown. | none | |
| Lists managed devices whose compliance state is exactly 'noncompliant', with the usual device fields plus the compliance grace period expiry, count and nextLink. |
|
Always enabled and not selectable. graph_request is the escape hatch for endpoints no purpose-built tool covers.
Tool | What it does | Arguments | |
| write | Sends an arbitrary request to Microsoft Graph and returns the raw JSON response. |
|
| Fetches one item from a Graph path ($top=1) and reports the property names it carries with their JSON types, plus the @odata.context that names the resource type. |
| |
| Reports how this server is configured: which tool groups are enabled, the delegated Microsoft Graph scopes each one uses, which of them need a tenant administrator to consent, whether write tools are suppressed, and the signed-in account. | none |
Presets
Preset | Groups |
| me, mail, calendar, files, todo, contacts, search |
| personal plus chat, planner, sharepoint |
| directory, intune, teams |
| every group |
personal is the default when neither --groups nor --preset is given. --groups and --preset can be combined; their union is taken.
Commands and flags
ms-graph-mcp [command] [options]Command | Effect |
| Run the MCP server on stdio. The default when no command is given. |
| Sign in and write the token cache. Opens a browser by default; see |
| Clear the stored token cache. |
| Print the signed-in account and the resolved configuration. |
| Print the delegated scopes this configuration requests, grouped. |
Every option has an MS365_MCP_* environment variable fallback; the flag wins. Boolean environment variables accept 1/0, true/false, yes/no, on/off. An unrecognised flag is a hard error rather than a silent no-op.
Flag | Environment variable | Default | Effect |
|
| the shipped application | Entra application (client) ID. Overrides the shipped default, and is required in a build that has none, in a sovereign cloud, or wherever your tenant will not accept the shared app. |
|
|
| Tenant ID, or |
|
|
| Sovereign cloud: |
|
|
| Interactive sign-in flow: |
|
|
| Loopback port for the browser flow's redirect. |
|
| see presets | Comma-separated tool groups to enable. |
|
|
| Group bundle: |
|
| off | Hide every tool that writes. |
|
| off | Enable the groups whose scopes need tenant admin consent. |
|
| off | Expose |
|
| off | Allow requests against the Graph beta endpoint. |
|
| off | Let |
|
|
| Truncate serialised tool output beyond this many characters. |
|
| OS config directory | Directory holding the token cache. |
|
| off | Log Graph requests to stderr. |
| Print help and exit. | ||
| Print the package version and exit. |
MS365_MCP_AUTH_FLOW=interactive, the undocumented value that used to select the browser flow, is still accepted as an alias for browser.
--discovery is worth knowing about: with every group enabled the server exposes 101 tools, and 101 tool schemas is a large, permanent cost on the first turn of every conversation. In discovery mode the client sees three tools instead — discover_tools searches the catalogue and returns names and descriptions without schemas, call_tool invokes one by name, and graph_list_permissions reports the configuration. The model pays for a tool's schema only when it actually calls it.
Security
Version 1.0 by default. Requests go to the v1.0 Graph endpoint. The beta endpoint is refused unless the server is started with --beta, because beta resources change without notice and without deprecation.
Host pinning on the generic tool. graph_request lets the model choose the request path, and every request this server sends carries your bearer token, so a path that escapes the Graph host leaks that token. Three independent checks stand between the two: the path is validated before use (absolute URLs, URI schemes, .. segments, percent-encoded separators and protocol-relative references are all rejected), the URL is then built through the URL API rather than string concatenation, and the resulting host is compared against the pinned Graph hostname for the selected cloud before the request goes out. The same host check is applied to every @odata.nextLink before it is followed, because a paging link is chosen by the server response rather than by you.
Read-only mode. --read-only removes every write tool from the catalogue, so a client never sees them and cannot call them. graph_request stays available but refuses every method except GET, and call_tool re-checks the target in case a write tool reached it another way.
Generic writes are opt-in separately. Even without --read-only, graph_request refuses POST, PATCH, PUT and DELETE unless --allow-generic-write is passed. A purpose-built tool states in its description exactly what it changes; an arbitrary write to an arbitrary path does not.
Least-privilege groups. The scopes requested at sign-in are derived from the enabled groups and their tools, so enabling --groups mail asks for mail permissions and nothing else. --read-only also drops the write scopes from the consent request, rather than consenting to permissions the server will never exercise. The three admin-consent groups are excluded unless --org-mode is passed, so a personal-account user is never shown a consent prompt they cannot satisfy.
A shared client ID is an identifier, not a credential. The application ID the server ships with is public by construction — it appears in every authorize URL — and it grants nothing on its own. Access still requires an interactive sign-in by a user, consent recorded in that user's tenant, and a refresh token held on that user's machine. What it does mean for a tenant is a service principal visible to its administrators; see Which application am I signing in to.
Where the token cache lives. The MSAL cache blob is encrypted with AES-256-GCM and written to token-cache.enc in your config directory, with the 32-byte key beside it in cache.key. Both files are created with mode 0600 inside a directory with mode 0700.
Platform | Default location |
macOS, Linux |
|
Windows |
|
Override with --cache-dir. Run npx ms-graph-mcp status to see the resolved path, and logout to delete both files. Keeping the key next to the ciphertext protects against a stray backup or a file synced to the cloud, not against an attacker who already has read access to your home directory.
No secrets in configuration. The server is a public client and takes no client secret. The only credential it holds is the refresh token in the cache described above.
What this is not
This is a local, delegated-permission MCP server. It acts as you, with the permissions you have, over a stdio transport on your own machine. It is not a replacement for Microsoft's own Agent 365 MCP servers, which are remote, run inside Microsoft's tenant boundary, use application permissions and admin-managed agent identities, and require a Microsoft 365 Copilot licence. If you need agent identity, tenant-wide governance, or auditing that a tenant administrator controls, that is the product to look at.
It is also not a general Microsoft Graph client library. The tools cover the common read and write paths for each product area and project their results down to what a model can usefully read; graph_request exists for everything else, deliberately behind a flag.
Licence
MIT — see LICENSE.
Available Tools
51 toolscalendar_create_eventCreate a calendar eventA
Creates an event on the primary calendar and returns the created event. Listing attendees sends them a meeting invitation immediately, so confirm the details with the user first. A start or end without an explicit UTC offset is treated as local time in timeZone (UTC when that is omitted).
| Name | Required | Description | Default |
|---|---|---|---|
| end | Yes | ISO-8601 end, interpreted the same way as `start`. | |
| body | No | Event description shown in the invitation. | |
| start | Yes | ISO-8601 start. Without an offset it is read as local time in `timeZone`; with a Z or ±HH:MM offset it is an absolute instant. | |
| subject | Yes | Event subject line. | |
| bodyType | No | How to interpret `body`. Defaults to 'text'. | text |
| isAllDay | No | Make this an all-day event. Graph then requires start and end to be midnight and at least 24h apart. | |
| location | No | Free-text location, e.g. "Room 4B" or "Zurich office". | |
| timeZone | No | IANA or Windows time-zone name (e.g. "Europe/Berlin", "Pacific Standard Time") used to interpret naive start/end values and to render returned times. | |
| attendees | No | People and rooms to invite. Creating the event sends them an invitation immediately. | |
| isOnlineMeeting | No | Attach a Microsoft Teams meeting link. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description discloses critical behavioral details: the side effect of immediately sending invitations to attendees, the return of the created event, and the timezone interpretation for naive start/end values. This is exactly the kind of context an agent needs for a mutating tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each earning its place: purpose/return, side-effect warning, and timezone behavior. The most important operational warning is front-loaded after the purpose, and there is no redundant or filler text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 10-parameter mutation tool with no output schema and minimal annotations, the description covers the non-obvious essentials: target calendar, return value, immediate invitation side effect, and ambiguous timezone handling. The remaining parameter details are already fully documented in the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds one meaningful clarification beyond the schema: when timeZone is omitted, naive times default to UTC. It does not repeat parameter docs, which is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Creates an event on the primary calendar' and adds that it returns the created event. This clearly distinguishes it from update, delete, respond, and list tools in the sibling set.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when to use the tool: creating a new calendar event on the primary calendar. It also provides explicit pre-call guidance by warning that attendees will receive invitations immediately and telling the agent to confirm details first. It does not explicitly name alternatives, but the usage context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_delete_eventDelete a calendar eventADestructive
Deletes an event, moving it to Deleted Items. If the signed-in user organized a meeting, every attendee is sent a cancellation; if they were only invited, this removes it from their calendar without telling the organizer — use calendar_respond_event with decline for that. Deleting a series master deletes every occurrence.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Event id to delete. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, but the description goes well beyond that. It discloses that the event is moved to Deleted Items, that attendees receive cancellations when the user organized, and that the invitee-only case removes it without notifying the organizer. It also explains series master behavior. This is rich behavioral context that annotations alone do not convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, each carrying distinct and essential information: the primary action and its outcome, the attendee vs organizer behavior, and the series master handling. It is front-loaded with the core action and has zero filler, making it efficient for an agent to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of the delete operation (different behavior for organizer vs invitee, series handling), the description covers all critical decision points an agent needs to invoke the tool correctly. There is no output schema, but a delete typically returns a standard success/failure, so no return format is necessary. The description is complete for safe and correct usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has a single 'id' parameter with full 100% coverage, and the description references the series master case, which gives additional meaning to that id: it may represent a series master and then all occurrences are deleted. While the description does not explicitly say 'if the id is a series master,' it implies it, adding value beyond the schema's minimal 'Event id to delete.' This warrants a 4 rather than the baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action: 'Deletes an event, moving it to Deleted Items.' It specifies the resource (calendar event) and the immediate effect. It also distinguishes itself from the sibling calendar_respond_event by explaining the attendee vs organizer scenario, which prevents an agent from confusing the two tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use this tool versus the alternative: 'use calendar_respond_event with decline for that.' It also covers the series master case, clarifying that deleting a series master deletes all occurrences. This gives clear usage boundaries and eliminates guesswork about which tool fits the situation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_find_meeting_timesFind meeting timesARead-onlyIdempotent
Suggests meeting slots that work for the signed-in user and the given attendees, ranked by confidence, with the attendees who are unavailable in each slot. Returns 10 suggestions by default. Read-only despite being an HTTP POST. All attendees are treated as required, and an empty result comes back with emptySuggestionsReason explaining why (commonly "AttendeesUnavailable" or a window that is too narrow).
| Name | Required | Description | Default |
|---|---|---|---|
| end | No | ISO-8601 latest acceptable end. Must be given together with `start`. | |
| start | No | ISO-8601 earliest acceptable start. Must be given together with `end`; omit both to let Graph pick the window. | |
| timeZone | No | IANA or Windows time-zone name (e.g. "Europe/Berlin", "Pacific Standard Time") used to interpret naive start/end values and to render returned times. | |
| attendees | Yes | SMTP addresses of the required attendees. The signed-in user is the organizer and must not be listed. | |
| maxCandidates | No | Maximum suggestions to return. Defaults to 10. | |
| durationMinutes | Yes | Meeting length in minutes. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds meaningful behavioral context beyond the annotations: it notes the tool is 'Read-only despite being an HTTP POST' and explains that empty results include an 'emptySuggestionsReason' such as 'AttendeesUnavailable' or a too-narrow window. This discloses behavior that annotations alone do not convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three concise, front-loaded sentences. It opens with the core function, then adds key behavioral details without redundancy or fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the parameter schema and annotations, the description covers the main operational aspects: ranking, default count, required attendees, and empty-result behavior. With no output schema, it appropriately mentions the emptySuggestionsReason that callers would need to interpret results, though it could slightly expand on the shape of successful suggestions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the input schema already documents all parameters. The description adds minor clarifications (default of 10 suggestions, all attendees required) but does not substantially enrich parameter meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'Suggests meeting slots that work for the signed-in user and the given attendees, ranked by confidence.' It clearly distinguishes this from sibling tools like calendar_get_schedule by focusing on proposing available times rather than reading existing events.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage: use this when you need to find meeting slots for a set of attendees. However, it does not explicitly state when to use this tool versus alternatives such as calendar_get_schedule or calendar_list_events, nor does it provide exclusion criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_get_eventGet a calendar eventARead-onlyIdempotent
Returns one event in full: subject, start, end, location, organizer, the attendee list with each response, the description body (HTML converted to text and capped), recurrence summary, and the Outlook web link. Use calendar_list_events first to find the id.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Event id, from calendar_list_events. | |
| timeZone | No | IANA or Windows time-zone name (e.g. "Europe/Berlin", "Pacific Standard Time") used to interpret naive start/end values and to render returned times. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, covering safety. The description adds valuable behavioral details beyond annotations: the description body is HTML-converted to text and capped (a truncation limit), and it mentions recurrence summary and the Outlook web link. This gives the agent a good sense of the return shape and transformation applied, going beyond the basic read-only nature.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no redundancy. The first sentence enumerates the return fields in a compact list, and the second gives the essential usage instruction. All content earns its place; nothing extraneous.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read tool with one required parameter, the description is quite complete. It lists all major return fields, explains the prerequisite, and the schema covers timezone handling. It doesn't mention error behavior (e.g., event not found) but that is standard and not critical for an agent to invoke correctly. Overall, an agent has enough to call it properly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%: both id and timeZone are fully described in the schema. The description does not add new parameter semantics, though it reiterates the id source ('from calendar_list_events') which is already in the schema. Baseline of 3 is appropriate given the schema carries the parameter documentation burden.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: returns one event in full, listing the specific fields (subject, start, end, location, organizer, attendees, description, recurrence, link). This distinguishes it from sibling tools like calendar_list_events (which lists events) and calendar_get_schedule (which gets availability) by focusing on a single event's complete details.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit guidance to use calendar_list_events first to find the id, which is the key prerequisite. It clearly implies this tool is for retrieving a single event after identifying it. Does not explicitly contrast with alternatives like calendar_get_schedule, but the usage context is clear from the instruction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_get_scheduleGet free/busy scheduleARead-onlyIdempotent
Returns free/busy availability for up to 20 people or rooms over a time window, as an availabilityView string where each character covers one interval (0 free, 1 tentative, 2 busy, 3 out of office, 4 working elsewhere), plus working hours and any visible busy blocks. Read-only despite being an HTTP POST. Subject and location are only returned for people who share those details with you; everything else comes back as a bare busy block.
| Name | Required | Description | Default |
|---|---|---|---|
| end | Yes | ISO-8601 end of the window. Keep the window under a few days: the availability string grows with it. | |
| start | Yes | ISO-8601 start of the window to check, e.g. 2026-01-31T08:00:00Z. | |
| timeZone | No | IANA or Windows time-zone name (e.g. "Europe/Berlin", "Pacific Standard Time") used to interpret naive start/end values and to render returned times. | |
| schedules | Yes | SMTP addresses of the people or rooms to check, at most 20 per call. | |
| availabilityViewInterval | No | Minutes each character of availabilityView represents. Defaults to 30. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint/idempotentHint annotations, the description adds genuinely useful behavioral detail: it is read-only despite being an HTTP POST, the availabilityView character encoding (0-4), the inclusion of working hours and busy blocks, and the visibility caveat for subject/location. This is substantial context an agent would not get from annotations alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the core purposematic and then adding the encoding details and caveat. Every sentence carries essential information and there is no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description compensates by explaining the availabilityView encoding, working-hours return, busy blocks, and visibility behavior. It is slightly vague about the exact structure of 'visible busy blocks' but is otherwise sufficient for an agent to invoke and interpret the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the parameters are already well-documented. The description reinforces some constraints (20 people, time window, interval characters) but does not add significant new parameter-level meaning beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('returns') and clearly names the resource: free/busy availability for up to 20 people or rooms over a time window. It also details the output format, making it easy to distinguish from calendar_list_events or calendar_get_event.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly establishes its context: checking free/busy availability for multiple people/rooms over a time window. It does not explicitly name sibling alternatives or exclusion conditions, but the purpose is distinct enough that an agent can infer when to use it, particularly against calendar_find_meeting_times.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_list_calendarsList calendarsARead-onlyIdempotent
Lists the signed-in user's calendars with id, name, colour, owner and whether they can be edited or shared. Returns 50 by default. Use the returned id as calendarId in calendar_list_events.
| Name | Required | Description | Default |
|---|---|---|---|
| top | No | Maximum calendars to return. Defaults to 50. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds that it 'Returns 50 by default' (pagination limit) and further explains the return payload fields. These are behavioral traits not in the annotations, adding value beyond the structured metadata. No contradictions found.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is only two sentences, with the core purpose front-loaded and the default behavior and chaining guidance included in the second sentence. No fluff, no redundant repetition of schema or annotations. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list tool with one optional parameter and no output schema, the description is complete. It tells the agent what it returns (fields), the default page size, how to use the results (via calendarId), and implicitly that it operates on the signed-in user's calendars. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema description coverage is 100%, and the only parameter `top` is fully documented in the schema (maximum, default, meaning). The description repeats the default of 50 but does not add any new meaning beyond the schema. Per the rubric, a baseline of 3 is appropriate when the schema already covers parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Lists' and the resource 'the signed-in user's calendars', enumerating the fields returned (id, name, colour, owner, edit/share flags). This is specific and distinguishes it from sibling tools like calendar_get_event (which fetches a single calendar) and calendar_list_events (which lists events). The scope is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear usage context by saying 'Use the returned id as calendarId in calendar_list_events', which tells the agent a common workflow. It does not explicitly contrast with alternatives like calendar_get_event, nor state when not to use it, but the chaining instruction gives a definite purpose. This merits a 4 (clear context, but no exclusions).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_list_eventsList calendar eventsARead-onlyIdempotent
Lists events with subject, start, end, location, organizer and attendee count, plus a nextLink when more pages exist. Returns 25 events by default. Passing both start and end switches to calendarView, which expands recurring meetings into their individual occurrences; without them the raw event list is returned, where a recurring series appears once as its series master. Times without an explicit offset in start/end are read as UTC — pass a timeZone to control how returned times are rendered.
| Name | Required | Description | Default |
|---|---|---|---|
| end | No | ISO-8601 end of the window. Must be given together with `start`. | |
| top | No | Maximum events to return in this page. Defaults to 25. | |
| start | No | ISO-8601 start of the window, e.g. 2026-01-31T00:00:00Z. Must be given together with `end`; supplying both switches to calendarView, which expands recurring series into individual occurrences. | |
| select | No | Graph field names to return, e.g. ["id","subject","start"]. When given, the raw selected fields are returned instead of the compact projection. | |
| orderby | No | OData sort expression, e.g. "start/dateTime desc". Defaults to "start/dateTime" ascending. | |
| timeZone | No | IANA or Windows time-zone name (e.g. "Europe/Berlin", "Pacific Standard Time") used to interpret naive start/end values and to render returned times. | |
| calendarId | No | Calendar to read from, from calendar_list_calendars. Defaults to the primary calendar. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate a safe read-only operation, and the description adds valuable non-obvious behaviors: default page size of 25, nextLink pagination, calendarView expansion of recurring meetings, and UTC interpretation of naive times with timeZone rendering control. This goes well beyond the structured annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each earning its place: the first states output payload, the second states pagination default, the third explains the critical start/end and timeZone behavior. Information is front-loaded and dense without being verbose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (7 optional params, no output schema, read-only safe annotations), the description covers return fields, pagination, recurring behavior, defaults, and timezone handling. An agent has enough to invoke it correctly without further research.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the input schema covers all 7 parameters with descriptions, the tool description adds crucial cross-parameter semantics: start and end must be used together to trigger calendarView, and timeZone affects interpretation of naive values and rendering. This meaning is not present in the schema and materially improves correct invocation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Lists events') and details the exact output fields (subject, start, end, location, organizer, attendee count, nextLink), making the tool's purpose unmistakable. It is clearly distinct from siblings like calendar_get_event (single event) and calendar_list_calendars (calendar list).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear, explicit guidance on how to use the start/end parameters to switch between raw event list and calendarView, including the behavioral difference for recurring series. While it does not name alternative tools, the usage context is unambiguous and the parameter-level when/when-not guidance is strong enough for an agent to call it correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_respond_eventRespond to a meeting invitationADestructive
Accepts, declines, or tentatively accepts a meeting invitation, optionally with a comment to the organizer. Graph returns no content on success. Only works on events where the signed-in user is an attendee — responding to an event they organized fails. Proposing a new time is not supported.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Event id of the invitation to respond to. | |
| comment | No | Optional message included with the reply. | |
| response | Yes | The reply to send. | |
| sendResponse | No | Whether the organizer is notified. Defaults to true. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true nhận readOnlyHint=false, but the description adds meaningful behavior beyond that: 'Graph returns no content on success,' the attendee-only constraint, response failure for organizer-created events, and the inability to propose a new time. This gives an agent a realistic picture of side effects and limitations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no wasted words. The main action is front-loaded, followed by the success return behavior awaited then the critical constraints. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with no output schema, this description covers the essential facts: what the reply does, the success response (empty content), attendee precondition, and unsupported proposal flow. An agent has enough to decide when and how to call the tool without encountering surprises.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and each parameter (id, comment, response, sendResponse) already has a clear schema description. The tool description adds little parameter-specific meaning beyond restating the response options and the optional comment, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Accepts, declines, or tentatively accepts a meeting invitation...' This clearly distinguishes the tool from siblings like calendar_create_event or calendar_update_event. The additional note that proposing a new time is not supported further sharpens its scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context: responding only works when the signed-in user is an attendee, and it explicitly fails for events the user organized. It also names the unsupported 'propose new time' flow. However, it does not explicitly point to alternatives or say 'use calendar_update_event for edits,' so the when-not-to-use guidance is not fully explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_update_eventUpdate a calendar eventAIdempotent
Patches the given fields on an event and returns the updated event; omitted fields are left alone. Two traps: sending attendees replaces the whole list, so anyone left out is uninvited, and changing the time or attendees of a meeting sends an update to everyone invited. Updating a recurring series master changes every occurrence.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Event id to update. | |
| end | No | New ISO-8601 end. | |
| body | No | Replacement event description. | |
| start | No | New ISO-8601 start. Send `end` too whenever the new start would land after the existing end. | |
| showAs | No | How the event shows on the free/busy view. | |
| subject | No | New subject line. | |
| bodyType | No | How to interpret `body`. Defaults to 'text'. | text |
| isAllDay | No | Switch the event to or from all-day. | |
| location | No | Replacement location. | |
| timeZone | No | IANA or Windows time-zone name (e.g. "Europe/Berlin", "Pacific Standard Time") used to interpret naive start/end values and to render returned times. | |
| attendees | No | Replaces the entire attendee list — anyone omitted is uninvited, so send the full list, not just additions. | |
| categories | No | Replaces the category list. | |
| isOnlineMeeting | No | Add a Teams meeting link. Removing one after the fact is not supported. | |
| reminderMinutesBeforeStart | No | Reminder lead time in minutes. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate idempotentHint=true (safe to retry), readOnlyHint=false and destructiveHint=false (mutation but not destructive). The description adds behavioral context beyond annotations: it explicitly warns about side effects (emails to attendees, impact on series), and states that omitted fields are left alone, which clarifies idempotency and partial update behavior. It doesn't mention auth requirements, but that's likely covered elsewhere. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact: three sentences, front-loaded with the core patch semantics, followed by the most critical traps. Every sentence carries operational weight. It avoids boilerplate and directly addresses the highest-risk aspects of the tool. No fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (14 params, many with nuanced behavior), the description covers the most critical operational details: partial update semantics, the attendees replacement issue, and notification side effects. It does not cover every parameter (e.g., timeZone interpretation, isOnlineMeeting removal limitation), but the schema descriptions provide that. With annotations covering idempotency, and high schema coverage, the description is sufficiently complete for correct invocation. It could mention recurring series implications more explicitly, but the warning about updating the series master covers it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents each parameter. The description adds value by highlighting the 'attendees' replacement trap, which is not fully captured in the schema description (schema says 'replaces the entire attendee list' but description reinforces it with the 'uninvited' consequence). It also adds the context that changing start/end triggers notifications. For a complex tool with 14 params, this extra guidance is valuable beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that it patches given fields on an event and returns the updated event, with a clear verb ('patches') and resource ('event'). It distinguishes itself from sibling tools like calendar_create_event (creates new) and calendar_delete_event (removes), and from read-only tools like calendar_get_event. The description also emphasizes partial update semantics, which is key for an update tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly warns about common pitfalls: sending 'attendees' replaces the whole list (so users must send the full list), changing time/attendees sends updates to invitees, and updating a recurring series master affects all occurrences. It doesn't explicitly name alternatives, but given the unrelated sibling set (files, mail, todo), the context is clear. The warnings provide critical when-to-be-careful guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
contacts_createCreate a contactA
Creates a personal contact in the signed-in user's default Contacts folder and returns the stored contact, including the new id. Outlook builds displayName from givenName and surname. Outlook holds at most 3 email addresses per contact. Graph does not de-duplicate: calling this twice creates two contacts, so search first when the contact may already exist.
| Name | Required | Description | Default |
|---|---|---|---|
| surname | No | The contact's last name. | |
| jobTitle | No | Job title at that organisation. | |
| givenName | Yes | The contact's first name. | |
| companyName | No | Employer or organisation. | |
| mobilePhone | No | Mobile phone number, as free text, e.g. "+1 425 555 0109". | |
| emailAddresses | No | Up to 3 email addresses, in Outlook slot order (Email 1, 2, 3). Outlook has no fourth slot. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, idempotentHint=false, destructiveHint=false. The description adds crucial behavior: displayName is derived from givenName/surname, max 3 emails, and no de-duplication. These are non-obvious and critical for correct invocation, going well beyond the annotation hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with zero fluff. The primary action and return value are front-loaded, followed by two essential constraints (displayName construction, email limit, de-duplication warning). Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a creation tool with 6 parameters, no output schema, and critical platform-specific behaviors, the description covers all essential context: what it does, what it returns, and pitfalls (de-duplication, displayName, email limits). An agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description enriches parameter meaning: explains that givenName and surname together form displayName, and that emailAddresses is capped at 3 due to Outlook's slot limitation. This adds semantic relationships not present in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (creates), resource (personal contact in signed-in user's default Contacts folder), and the return value (stored contact with new id). It clearly distinguishes from sibling tools like contacts_update or contacts_delete by focusing on creation and explicitly naming the de-duplication caveat.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly describes when to use the tool (create a contact) and when not to (search first if contact may exist, due to lack of de-duplication). This provides clear guidance for an agent to choose correctly among contact-related tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
contacts_deleteDelete a contactADestructive
Deletes one personal contact. The contact moves to the Deleted Items folder, so it is recoverable from Outlook but not through these tools, and Graph returns no body — only a confirmation of the id. Deleting an id that is already gone fails with 404 ErrorItemNotFound.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The contact id, as returned by contacts_list or contacts_search. This is the long opaque Outlook item id, not an email address or display name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (destructiveHint=true, idempotentHint=false), the description adds critical behavior: the contact moves to Deleted Items, recovery is only via Outlook, Graph returns no body, and deleting an already-gone id yields 404. This enriches the agent's understanding of side effects and error handling without contradicting any annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences that front-load the primary action, then cover side effects, response, and error behavior. No redundant phrasing; every sentence contributes value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter delete tool, the description covers the outcome, recoverability, response shape, and failure mode. No output schema exists, but the response is described. It is fully sufficient for an agent to call correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and already specifies the id must come from contacts_list or contacts_search and be the opaque Outlook item id. The description adds nothing beyond that, so it does not improve parameter understanding beyond the schema's baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Deletes one personal contact,' a specific verb and resource that clearly differentiates it from the other contact tools (list, get, search, create, update). It leaves no ambiguity about what action the tool performs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage context by stating the id must come from contacts_list or contacts_search and clarifying that deletion is permanent within these tools (recoverable only via Outlook). It does not explicitly name alternatives, but it's the sole contact-deletion tool among siblings, so the guidance is adequate though not exhaustive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
contacts_getGet a contactARead-onlyIdempotent
Returns one personal contact by id, with names, company, job title, department, every email address, phone numbers, postal addresses, birthday, categories and timestamps. Personal notes are truncated to 1000 characters. Properties Graph reports as empty are omitted, so a missing key means the field is not set. An id from a different mailbox or a deleted contact fails with 404 ErrorItemNotFound.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The contact id, as returned by contacts_list or contacts_search. This is the long opaque Outlook item id, not an email address or display name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, but the description adds valuable behavioral context: personal notes are truncated to 1000 characters, empty properties are omitted, a missing key means the field is not set, and wrong-mailbox/deleted ids fail with 404 ErrorItemNotFound. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, each earning its place: return-field list, truncation behavior, omission semantics, and failure mode. The core purpose is front-loaded, and there is no filler or repetition of annotations.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter, read-only getter with no output schema, the description covers the returned fields, important data-shaping behavior, and error semantics. An agent has enough information to invoke the tool and interpret its response correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% description coverage for the single id parameter, including its source and what it is not. The description only restates that the operation is by id and adds no additional parameter-level meaning beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Returns') and resource ('one personal contact by id'), and enumerates the exact fields returned. This clearly distinguishes it from collection-returning siblings like contacts_list and contacts_search and from mutating siblings like contacts_create or contacts_delete.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description and parameter schema imply that the agent must already have an opaque contact id from contacts_list or contacts_search, but it does not explicitly state when to prefer this tool over alternatives or when not to use it. The usage context is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
contacts_listList contactsARead-onlyIdempotent
Lists personal contacts from the signed-in user's default Outlook Contacts folder, 25 per page by default (max 100). Each row carries id, displayName, given/surname, company, job title, email addresses and phone numbers; pass select for different properties. A nextLink in the result means more pages exist — call again with skip set to the number already seen. Contacts stored in a custom contact folder are not included.
| Name | Required | Description | Default |
|---|---|---|---|
| top | No | How many contacts to return in this page. Graph itself defaults to 10. | |
| skip | No | How many contacts to skip before this page, for paging: pass the running total already seen. Only meaningful while `nextLink` is present in the previous result. | |
| filter | No | Raw OData $filter over `contact` properties, e.g. "companyName eq 'Contoso'" or "startswith(surname,'Mc')". Single quotes inside a literal must be doubled. Filtering on emailAddresses is not supported by Outlook — use contacts_search for that. | |
| select | No | Graph `contact` property names to return instead of the default compact projection, e.g. ["displayName","department","birthday"]. Bare property names only; OData expressions and navigation paths are rejected. `id` is always included. | |
| orderby | No | Sort order, e.g. "displayName" or "lastModifiedDateTime desc". Bare property names only. Omit to get Outlook's own ordering. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, and non-destructive, so the tool's safety profile is covered. The description adds valuable behavior beyond annotations: default page size, the default row projection, nextLink-based paging with skip, and the exclusion of custom contact folders.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and then efficiently covers output shape, pagination, and scope limitations. Every sentence earns its place without unnecessary padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description still tells the agent what fields each row carries and how to request different properties. Pagination is fully explained, and the custom-folder exclusion prevents misuse, making the tool callable without hidden assumptions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the schema already documents top, skip, filter, select, and orderby in detail. The description restates the default page size, select behavior, and nextLink skip pattern, but adds little parameter-level meaning beyond the custom-folder scope caveat.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence names a specific verb and resource: it lists personal contacts from the signed-in user's default Outlook Contacts folder. The final sentence also clarifies what is not included, which helps distinguish it from tools that search across custom folders.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells the agent to use contacts_search when filtering on emailAddresses is needed, and it flags that custom contact folders are out of scope. This gives clear when-to-use and when-not-to-use guidance relative to alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
contacts_searchSearch contactsARead-onlyIdempotent
Full-text search over the default Contacts folder using Outlook $search, returning the same compact rows as contacts_list, 25 per page by default. Results come back ranked by relevance, which is why $filter and $orderby cannot be combined with a search and are not offered here — use contacts_list for filtered or sorted results. Search matches whole words and prefixes only: it will not do date ranges, wildcards in the middle of a term, or "not equal" style conditions.
| Name | Required | Description | Default |
|---|---|---|---|
| top | No | How many contacts to return in this page. Graph itself defaults to 10. | |
| skip | No | How many contacts to skip before this page, for paging: pass the running total already seen. Only meaningful while `nextLink` is present in the previous result. | |
| query | Yes | What to look for. A plain term such as "Irene" or "contoso.com" matches across display name, given/surname, company and every email address. A field-scoped term such as "displayName:Irene" or "emailAddresses:contoso.com" narrows it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnlyHint, idempotentHint, and non-destructiveness, but the description goes well beyond them. It discloses default pagination (25 per page), relevance ranking, the inability to combine search with $filter/$orderby, and exact matching semantics. This is substantial behavioral context that annotations alone would not convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every clause earns its place: purpose, output shape, defaults, ranking rationale, alternative tool, and limitations. The key differentiators are front-loaded before the more detailed caveats. No filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a search tool with three parameters, no output schema, and rich annotations, the description covers the essential behavior needed to invoke it correctly: scope, ranking, pagination defaults, return shape, and matching limitations. The schema fills in the remaining parameter details. Nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is a 3. The top-level description adds meaningful query semantics beyond the schema by explaining whole-word/prefix matching, ranking behavior, and unsupported conditions. It does not add extra detail about top/skip, but the schema already documents those fully.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific action ('full-text search') and resource ('default Contacts folder'), and also specifies the output format ('same compact rows as contacts_list'). It differentiates itself from contacts_list by explicitly saying that $filter and $orderby are not available here. An agent can immediately tell this apart from sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives concrete when-to-use guidance: relevance-ranked full-text search, and it explicitly names the alternative for filtered/sorted results ('use contacts_list'). It also states hard limitations up front—no date ranges, mid-term wildcards, or 'not equal' conditions—helping an agent avoid calling this tool for queries it cannot satisfy.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
contacts_updateUpdate a contactAIdempotent
Updates the given fields of one personal contact and returns the stored result. Omitted fields are left alone, but emailAddresses is a collection: supplying it REPLACES every address on the contact, so read the contact first and resend the ones to keep. There is no optimistic-concurrency check here — a concurrent edit from Outlook is silently overwritten. At least one field besides id is required.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The contact id, as returned by contacts_list or contacts_search. This is the long opaque Outlook item id, not an email address or display name. | |
| surname | No | The contact's last name. | |
| jobTitle | No | Job title at that organisation. | |
| givenName | No | The contact's first name. | |
| companyName | No | Employer or organisation. | |
| displayName | No | The name Outlook files the contact under. Outlook derives it from the given and surname when it has never been set explicitly; setting it here stops that. | |
| mobilePhone | No | Mobile phone number, as free text. | |
| emailAddresses | No | Replacement list of up to 3 email addresses. This REPLACES every existing address rather than adding to them, so include the ones to keep. Read the contact first if unsure. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes far beyond the annotations by disclosing patch semantics (omitted fields left alone), the replacement behavior of emailAddresses, and the lack of optimistic concurrency checking with silent overwrites. These are critical behavioral traits that the annotations alone do not convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, each earning its place: the main purpose, the critical emailAddresses replacement warning, and the concurrency caveat. It is front-loaded and free of redundant phrasing.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no output schema, the description adequately notes that it returns the stored result and covers the most important behavioral pitfalls. It does not mention error cases (e.g., contact not found) or provide details about the return structure, but given the schema richness and clear warnings, it is substantially complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and each parameter has a rich description. The overall description adds collective semantic value: 'Omitted fields are left alone' and 'At least one field besides id is required' are not stated in the schema and provide crucial update semantics beyond the individual property descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Updates') and resource ('one personal contact'), making the tool's purpose unmistakable. It naturally distinguishes itself from sibling tools like contacts_create, contacts_delete, contacts_get, and contacts_list by focusing on partial modification of existing contacts.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear usage context, including the requirement that at least one field besides id be provided, and warns about emailAddresses replacement behavior. It does not explicitly mention when NOT to use this tool versus alternatives, but the update semantics are evident from the description and name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
files_create_folderCreate a OneDrive folderA
Creates a folder in the signed-in user's OneDrive and returns the created item. Give the parent as parentItemId or parentPath, or omit both for the drive root. A name collision does not fail: Graph renames the new folder with a numeric suffix, so read the returned name rather than assuming it.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Name of the new folder. An existing folder of the same name does not cause a failure; the new one gets a numeric suffix. | |
| parentPath | No | Path of the parent folder from the drive root, e.g. "Documents/Reports". Mutually exclusive with parentItemId. Omit both to create in the drive root. | |
| parentItemId | No | Id of the parent folder. Mutually exclusive with parentPath. Omit both to create in the drive root. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate a mutating, non-idempotent operation. The description adds valuable context by disclosing collision behavior (numeric suffix rename) and that the created item is returned, which goes beyond what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no fluff. Purpose is front-loaded, followed by parameter guidance and a key behavioral warning. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers essential behaviors: what it creates, parent specification, collision handling, and return of the created item. Given full schema coverage and no output schema, it is sufficiently complete, though return fields could be specified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all three parameters are already described. The description repeats mutual exclusivity and root omission but does not add new meaning beyond the schema. Baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Creates' and the resource 'folder in the signed-in user's OneDrive', making the purpose unambiguous. It doesn't explicitly contrast with sibling file tools, but the folder-specific action is distinct enough to differentiate.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains how to specify the parent (parentItemId or parentPath, omit both for root), which is parameter usage, but it does not provide guidance on when to choose this tool over alternatives like files_upload_text or files_create_link. Usage context is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
files_create_linkCreate a OneDrive sharing linkA
Creates a sharing link for a OneDrive file or folder and returns its URL, permission type and scope. Defaults to a view link scoped to the organization. Anonymous links are blocked by policy in many tenants, which surfaces as a 403: retry with scope organization. Calling this twice with the same type and scope returns the existing link rather than creating a second one.
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | Link permission: view for read-only, edit for read-write. Defaults to view. | view |
| scope | No | Who can use the link. organization requires the recipient to sign in to the same tenant; anonymous works for anyone holding the URL and is disabled by policy in many tenants. | organization |
| itemId | Yes | Id of the file or folder to create a sharing link for. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description reveals meaningful behavior: call outcomes, defaults, a 403 failure mode for anonymous links, and the fact that duplicate calls return the existing link rather than creating a second one. This adds substantial practical context that annotations alone do not convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each earning its place: purpose and return value, defaults, then the two important behavioral caveats. The most actionable information is front-loaded, and there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a three-parameter tool with no output schema, the description is complete: it explains what is returned, the safe default behavior, and the error/retry path. The annotations cover mutation and non-destructiveness, so nothing essential is missing for an agent to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds value by tying scope to a concrete error/retry pattern and by explaining repeated-call behavior for type and scope, which is not present in the schema. It does not add new semantics for itemId, but the schema already defines it clearly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: it creates a sharing link for a OneDrive file or folder and explicitly lists the returned data (URL, permission type, scope). This distinguishes it clearly from sibling file tools like files_get_item or files_create_folder, and from the broader graph_request fallback.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear operational context: defaults, a policy-related failure mode with a recommended retry scope, and idempotent behavior for repeated calls with the same type and scope. It does not explicitly enumerate when-not-to-use alternatives, but the tool's unique purpose makes that less necessary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
files_deleteDelete a OneDrive itemADestructive
Deletes a file or folder from the signed-in user's OneDrive. Deleting a folder deletes everything inside it. The item goes to the OneDrive recycle bin rather than being destroyed, but this server has no tool to restore it, so confirm the id with files_get_item first.
| Name | Required | Description | Default |
|---|---|---|---|
| itemId | Yes | Id of the file or folder to delete. Deleting a folder deletes everything inside it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this as destructive and non-idempotent, and the description adds valuable behavior beyond that: folder deletion removes contents, items go to the recycle bin, and no restore tool exists. There is no contradiction with the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense, purposeful sentences: the core action first, then the folder caveat, then the safety and recovery warning. Every sentence earns its place with no redundant wording.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter destructive tool, the description covers what is deleted, the scope of deletion, the recycle-bin behavior, the lack of restore capability, and the recommended pre-check. No critical information is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents itemId at 100% coverage, so the baseline is 3. The description adds extra meaning by advising the agent to confirm the id with files_get_item first, which helps the agent supply a valid parameter value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Deletes' and the resource 'file or folder from the signed-in user's OneDrive'. It also calls out the folder-recursion consequence, which helps distinguish this tool from other delete tools among the siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit pre-use guidance: confirm the id with files_get_item first and be aware there is no restore tool. This is strong practical context, though it doesn't explicitly list alternatives or conditions when not to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
files_get_itemGet a OneDrive itemARead-onlyIdempotent
Reads the metadata of one OneDrive file or folder: name, kind, size, mime type, created and last-modified times and authors, parent folder path and ids, and webUrl. Address it by itemId or by path, not both. The pre-authenticated download URL is deliberately not returned; use files_read_text for text contents or files_create_link to share the item.
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | Path from the OneDrive root, e.g. "Documents/Reports/q3.docx". Leading slashes are ignored. Mutually exclusive with itemId. | |
| itemId | No | Drive item id, as returned by any files_* listing tool. Mutually exclusive with path. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish the safety profile (readOnly=true, idempotent=true, destructive=false). The description adds meaningful behavioral context beyond that by disclosing that the pre-authenticated download URL is deliberately not returned and listing the metadata fields that are. It could still say more about error cases or permission expectations, but the read-only annotations lower the bar.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tightly written sentences: the first establishes what and which fields, the second covers addressing mode, and the third handles an important caveat plus alternatives. There is no filler or redundant restating of the title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only metadata tool with only two optional parameters and no output schema, the description is sufficient: it lists the return fields, explains how to address the item, and clarifies the notable missing field (download URL) with fallback tools. An agent can call this tool correctly without needing the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the parameters are already well documented. The description reinforces the mutual exclusivity of itemId and path, but that constraint is already present in the schema. No new parameter-level meaning is added, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Reads the metadata of one OneDrive file or folder' and enumerates exactly which fields are returned. It also distinguishes itself from content/download tools by noting the download URL is intentionally absent and pointing to files_read_text and files_create_link.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states the tool is for reading metadata of a single item, explains the addressing constraint ('by itemId or by path, not both'), and explicitly names alternatives when the pre-authenticated download URL is expected: files_read_text for contents and files_create_link for sharing. This gives an agent clear when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
files_list_childrenList OneDrive folder contentsARead-onlyIdempotent
Lists the direct children of a folder in the signed-in user's OneDrive, returning id, name, kind (file or folder), size, mime type, child count, last-modified time and webUrl per entry, plus count and nextLink when more pages exist. Address the folder by itemId or by path; omit both for the drive root. Page size defaults to 50. This is not recursive: use files_search to look through the whole drive.
| Name | Required | Description | Default |
|---|---|---|---|
| top | No | Maximum number of children to return in this page. Defaults to 50. | |
| path | No | Path of the folder to list, e.g. "Documents/Reports". Path from the OneDrive root, e.g. "Documents/Reports/q3.docx". Leading slashes are ignored. Mutually exclusive with itemId. Omit both to list the drive root. | |
| itemId | No | Id of the folder to list. Drive item id, as returned by any files_* listing tool. Mutually exclusive with path. Omit both to list the drive root. | |
| orderby | No | Sort order for the children. Graph defaults to name ascending. OneDrive for Business (SharePoint-backed) drives silently ignore some sorts, notably by size. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering safety and idempotency. The description adds valuable behavioral context: non-recursive nature, pagination via nextLink, default page size, and the fact that it returns multiple entries. It also notes that SharePoint-backed drives may ignore some sorts, which is a useful caveat. The only minor gap is lack of detail on error handling or rate limits, but with strong annotations, this is above baseline.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences: the first is information-dense, covering return fields, addressing, and pagination; the second clarifies non-recursion and points to the alternative. It is concise, front-loaded with the primary purpose, and every sentence earns its place without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity (4 params, no required params, decisive annotations), the description is complete: it explains return fields, pagination, default page size, non-recursion, and alternate addressing. No output schema exists, but the description lists all return fields, making it self-sufficient. There is no missing guidance for an agent to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all parameters are fully described in the schema. The description adds context by explicitly mentioning the mutual exclusivity of itemId and path, and the omission for root, which reinforces but does not extend the schema. Since coverage is high, baseline 3 is appropriate; no significant added meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it lists direct children of a folder in OneDrive, enumerates the exact fields returned, and distinguishes it from recursive search by naming files_search as the non-recursive alternative. This is a specific verb+resource with sufficient detail to differentiate from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use this tool (list direct children) and when not to (use files_search for whole-drive search). It also clarifies how to address the folder (by itemId, by path, or omit for root), which serves as usage guidance. No exclusions are needed beyond that.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
files_list_recentList recent OneDrive filesARead-onlyIdempotent
Lists files the signed-in user recently opened or edited, most recent first, with count and nextLink. Defaults to 25 items. Entries can come from other people's drives or from SharePoint; those carry remoteDriveId and remoteItemId, and their plain id will not resolve against your own drive.
| Name | Required | Description | Default |
|---|---|---|---|
| top | No | Maximum number of recent items to return. Defaults to 25. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the tool read-only, idempotent, and non-destructive. The description adds valuable behavior beyond this: results include count and nextLink, default to 25 items, and may include remote items from other drives or SharePoint with an important caveat about remote IDs not resolving against the user's own drive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no filler, front-loading the core action and output, then providing the default limit and the remote-item caveat. Every sentence contributes necessary information for correct invocation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read-only listing tool with no output schema, the description is complete: it states what is returned (items, count, nextLink), the sort order, the default count, and a non-obvious remote-item edge case. An agent has enough to call it correctly without further inference.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for the single 'top' parameter, so the schema already documents its meaning, default, and bounds. The description adds context like 'most recent first' and 'defaults to 25 items,' but the latter is already in the schema, so the added parameter-specific value is minimal.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'Lists files the signed-in user recently opened or edited.' It clearly distinguishes this from sibling tools like files_search (search-based), files_list_shared (shared items), and files_list_children (folder contents) by focusing on recency and the user's own activity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The usage context is implied rather than explicit: the tool is for retrieving recently opened or edited files. However, it does not explicitly state when to prefer this tool over files_list_shared or files_search, nor does it mention any exclusions or alternative conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
files_read_textRead a text file from OneDriveARead-onlyIdempotent
Returns the contents of a text-like OneDrive file (plain text, Markdown, CSV, JSON, XML, source code, config) as a string, truncated to maxChars, which defaults to 20000. Reads the file metadata first and refuses binary formats — PDFs, images, Office documents, archives, media — with an explanation, because their bytes are not readable as text. Word, Excel and PowerPoint files are zip containers and cannot be read here.
| Name | Required | Description | Default |
|---|---|---|---|
| itemId | Yes | Id of the file to read, as returned by files_list_children or files_search. | |
| maxChars | No | Maximum characters of file content to return. Defaults to 20000; longer files are truncated with a marker. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent/non-destructive annotations, the description discloses meaningful behavior: it reads metadata first, refuses binary formats with an explanation, truncates to maxChars with a default, and explains that Office files are zip containers. This gives the agent an accurate model of what the tool will and will not do.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the core return behavior, then the binary-format refusal and the Office-file explanation. Every sentence contributes actionable guidance with no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a relatively simple read tool with well-documented parameters and strong annotations, the description covers what it returns, how it truncates, what it refuses, and why. The absence of an output schema is compensated by the explicit 'returns a string' statement, making the description complete for invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents itemId and maxChars, including default, range, and truncation marker. The description reinforces the truncation behavior but adds little beyond what the schema provides; the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a precise action — 'returns the contents of a text-like OneDrive file' — and clearly scopes the resource to text-like formats while excluding binaries. This distinguishes it from sibling tools like files_get_item (metadata) and files_upload_text (writing) without ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear when-to-use context (plain text, Markdown, CSV, JSON, XML, source code, config) and explicit when-not-to-use context (PDFs, images, Office documents, archives, media). It does not name alternative sibling tools, but the exclusion criteria are concrete enough for an agent to select this tool correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
files_searchSearch OneDriveARead-onlyIdempotent
Searches the whole of the signed-in user's OneDrive for free text, matching file names and indexed file contents, and returns the same compact fields as files_list_children plus count and nextLink. Page size defaults to 25. This endpoint accepts only a search term: it supports no date range, no file-type filter and no sort order, so narrow the results yourself or list a folder with files_list_children instead. Recently uploaded files are missing until the service has indexed them.
| Name | Required | Description | Default |
|---|---|---|---|
| top | No | Maximum number of matches to return in this page. Defaults to 25. | |
| query | Yes | Free text matched against file names and indexed file contents across the whole drive. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, and the description adds behavioral detail beyond that: the default page size, the compact return fields plus count and nextLink, the index-lag behavior for recently uploaded files, and the lack of filtering. This gives the agent a realistic model of what the call returns and what it may miss.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, each earning its place: purpose and return shape, page size, explicit limitations and routing to an alternative, and a material freshness caveat. The most important scoping information is front-loaded before the caveats, and there is no filler or redundancy beyond the intentional schema reinforcement.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even without an output schema or rich sibling descriptions, the description tells the agent what to expect by referencing the compact fields of files_list_children plus count and nextLink. It covers pagination default, filtering limitations, when to use an alternative, and the indexing lag that affects result completeness. Nothing needed to call and interpret this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and both parameters are already documented with meaningful descriptions in the schema. The description reinforces the 'accepts only a search term' constraint and the page-size default, but it does not add substantial new meaning beyond the schema. Baseline 3 is appropriate given the schema already carries the full parameter documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific action ('Searches the whole of the signed-in user's OneDrive') and a specific matching behavior ('file names and indexed file contents'). It also differentiates from siblings by naming the return shape relative to files_list_children and by noting the endpoint accepts only a search term. This lets an agent distinguish it from files_list_children and search_query without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states what the endpoint does not support ('no date range, no file-type filter and no sort order') and routes the agent to an alternative ('list a folder with files_list_children instead'). The indexing-lag caveat also tells the agent when results may be incomplete, which is directly useful for choosing this tool over a direct list or recent-files tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
files_upload_textUpload a text file to OneDriveA
Writes a text file to the given path in the signed-in user's OneDrive and returns the stored item. Missing parent folders are created automatically. An existing file at that path is REPLACED, not merged or appended, so read it with files_read_text first if you mean to edit it. Text only, up to 4 MB; larger or binary uploads need a resumable upload session, which this server does not expose.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Destination path from the OneDrive root including the file name, e.g. "Notes/meeting-2026-09-03.md". Missing parent folders are created automatically. | |
| content | Yes | The full text to write. This replaces the file contents; there is no append mode. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite annotations not marking destructiveHint, the description clearly discloses that an existing file is REPLACED, not merged or appended, and warns about size limits and binary content. This goes well beyond the minimal annotation info and fully informs the agent of side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no fluff. The primary action is stated first, followed by critical behavioral warnings and limits. Information is front-loaded and every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a write operation with two parameters, no output schema, and minimal annotations, the description covers the core behavior, side effects, limits, and alternatives. An agent has all necessary information to call it correctly without ambiguity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both parameters are already documented. The description adds a note about automatic folder creation and replacement semantics, but these are also echoed in the schema descriptions. The description doesn't significantly enhance parameter meaning beyond the schema, so a baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Writes') and resource ('a text file to the given path in the signed-in user's OneDrive'), and distinguishes it from siblings like files_read_text and files_create_folder. It is immediately clear what the tool does and how it differs from related file operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly explains when to use it (text files up to 4 MB) and when not to (larger or binary uploads need a resumable session not exposed). It also advises reading the file first with files_read_text before editing, giving clear usage and exclusion criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
graph_list_permissionsList granted permissionsARead-onlyIdempotent
Reports how this server is configured: which tool groups are enabled, the delegated Microsoft Graph scopes each one uses, which of them need a tenant administrator to consent, whether write tools are suppressed, and the signed-in account. Call it when a request fails with 403 or "insufficient privileges" to see whether the needed area is switched on at all. Reads only the signed-in account from Graph.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false. The description reinforces this by adding 'Reads only the signed-in account from Graph,' which tells the agent the call has a narrow read footprint rather than enumerating all permissions or making changes. This adds behavioral context beyond the annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences with no filler. It front-loads the core purpose ('Reports how this server is configured'), then lists the concrete output categories, gives a practical usage trigger, and closes with the read scope. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-argument, read-only diagnostic tool, the description is complete. It tells the agent what the tool reveals, when to call it, and what side effects it has. Although there is no output schema, the description sufficiently characterizes the return content for an agent to decide whether this tool fits the situation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, and the schema confirms an empty properties object with 100% coverage. With no parameters to describe, the baseline of 4 applies; the description appropriately avoids inventing parameter-related noise.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Reports how this server is configured' and enumerates exactly what it covers: enabled tool groups, delegated Graph scopes, admin consent requirements, write-tool suppression, and the signed-in account. This clearly distinguishes it from the sibling tools, which perform actions on mail, files, calendar, and contacts rather than inspecting server permission configuration.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an explicit trigger: 'Call it when a request fails with 403 or "insufficient privileges" to see whether the needed area is switched on at all.' This is a clear context for use. It does not explicitly name alternative tools or say when not to use it, but the diagnostic purpose is distinct from the action-oriented sibling tools, so no exclusion is necessary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
graph_requestCall Microsoft Graph directlyARead-onlyIdempotent
Sends an arbitrary request to Microsoft Graph and returns the raw JSON response. Use this only when no purpose-built tool covers the endpoint: the dedicated tools project and trim their results, while this one returns everything Graph sends, which is often far more text. The host is fixed to this tenant's Graph endpoint and path must be relative, so an absolute URL is rejected. GET is always available; the write methods require --allow-generic-write. Pass maxPages to follow @odata.nextLink, and prefer $select and $top in query to keep the response small.
| Name | Required | Description | Default |
|---|---|---|---|
| body | No | Request body for a write method, as JSON. Ignored for GET. A string is sent as raw bytes (which is what Graph content endpoints expect); anything else is JSON-encoded. | |
| path | Yes | Graph-relative path beginning with "/", e.g. "/me/messages" or "/users/alice@contoso.com/drive/root/children". Never a full URL: the host is fixed and an absolute URL is rejected. A "?query" suffix is accepted and merged with the `query` argument, but passing options in `query` is clearer. | |
| query | No | Query string parameters, e.g. {"$select":"id,subject","$top":"10"}. Values are sent verbatim, so OData operators belong here rather than spliced into `path`. | |
| method | No | HTTP method. Defaults to GET. The write methods are refused unless the server was started with --allow-generic-write, and always under --read-only. | |
| version | No | Graph endpoint. Defaults to the server default (v1.0). "beta" is refused unless the server was started with --beta; beta resources can change without notice. | |
| maxPages | No | How many pages of a collection to follow via @odata.nextLink, 1-5. Defaults to 1 (no paging). Pages are merged into a single value array. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, so the safety profile is covered. The description adds valuable behavioral context beyond annotations: it returns raw unprojected JSON ('often far more text'), follows @odata.nextLink when maxPages is set, merges pages into a single value array, and rejects absolute URLs. It also discloses that write methods are refused under --read-only. The only minor gap is not detailing error response shapes, but the description adds substantial context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: the core purpose and the key caveat ('returns everything Graph sends, which is often far more text') appear in the first two sentences. Every sentence earns its place, covering when to use, host/path constraints, write-method gating, and response-size control. No filler or repetition of schema details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a generic passthrough tool with 6 parameters, full schema coverage, and no output schema, the description covers everything an agent needs to call it correctly: when to use it, path constraints, method gating, paging behavior, and response-size guidance. The output is raw JSON, which the description states, so no output schema is needed. The only thing not detailed is error handling, but that is minor for a passthrough tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all 6 parameters thoroughly. The description adds meaningful semantics beyond the schema: it explains the host is fixed and path must be relative, that a '?query' suffix in path is merged with the query argument, that query values are sent verbatim, and that body strings are sent as raw bytes for content endpoints. This goes beyond the baseline 3 for full schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Sends an arbitrary request to Microsoft Graph') and resource ('Microsoft Graph'), and explicitly distinguishes itself from purpose-built tools by noting they 'project and trim their results' while this returns raw JSON. This clearly differentiates it from the many sibling tools like mail_list_messages or files_get_item.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'Use this only when no purpose-built tool covers the endpoint' and names the alternative class ('the dedicated tools'). It also gives concrete guidance on when write methods are allowed (--allow-generic-write), when beta is refused (--beta), and how to keep responses small ($select, $top, maxPages). This is exemplary usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
graph_schemaInspect a Graph resource shapeARead-onlyIdempotent
Fetches one item from a Graph path ($top=1) and reports the property names it carries with their JSON types, plus the @odata.context that names the resource type. Use it before graph_request to learn what $select and $filter can reference. It reports the shape of one real item, so properties that happen to be null on that item are absent from the list, and an empty collection yields no properties at all. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| version | No | Graph endpoint to probe. Defaults to the server default (v1.0). | |
| entityPath | Yes | Graph-relative path to a collection or a single entity, e.g. "/me/messages", "/me/drive/root/children" or "/me". Must begin with "/". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish read-only/idempotent/non-destructive behavior. The description adds meaningful behavioral detail beyond that: it fetches only one item via $top=1, reports the shape of a real item, omits null properties, and returns no properties for an empty collection. This helps set expectations about incomplete results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is four sentences and front-loads the core function in the first sentence. The caveats about null properties and empty collections are necessary and earn their place. The final 'Read-only' is redundant with annotations but not harmful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter probe tool with no output schema, the description covers what the tool returns, how it behaves with real data, and when to use it relative to graph_request. Nothing an agent needs to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents both parameters. The description mentions the Graph path concept and $top=1 but does not add significant parameter-level meaning beyond what the input schema provides. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource: it fetches one item from a Graph path and reports property names, JSON types, and @odata.context. It also explicitly positions itself against graph_request by saying it is meant to be used before that tool to learn what $select and $filter can reference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context: 'Use it before graph_request to learn what $select and $filter can reference.' This names the alternative tool and the condition for using graph_schema. It does not explicitly state when not to use it, but the intended workflow is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_create_draftCreate a mail draftA
Creates an unsent draft in the Drafts folder and returns its id and webLink. Nothing is transmitted — this tool cannot send, and there is no companion tool that sends an existing draft, so the user must send it from Outlook (or you can use mail_send instead). Recipients are optional on a draft.
| Name | Required | Description | Default |
|---|---|---|---|
| cc | No | Carbon-copy recipients. | |
| to | No | Primary recipients. Optional — a draft may be saved without any. | |
| bcc | No | Blind carbon-copy recipients. | |
| body | Yes | Message body, in the format given by contentType. | |
| subject | Yes | Subject line. | |
| contentType | No | How to interpret body. "Text" (default) is safest; "HTML" renders markup. | Text |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate this is a mutating, non-idempotent, non-destructive operation. The description adds valuable context beyond annotations: nothing is transmitted, the draft is unsent, and the tool returns id and webLink. This meaningfully clarifies the tool's side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no filler. The core behavior is front-loaded, and each sentence adds distinct value: what it creates, what it cannot do, and how recipients behave.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a create-draft tool with a fully documented schema, the description covers the essential behavioral context: return values, non-sending behavior, and the fallback path. It does not explain error conditions or permissions, but those are not necessary for correct invocation here.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all six parameters. The description adds the useful note that recipients are optional, but does not need to explain each parameter further. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: creates an unsent draft in the Drafts folder. It explicitly differentiates itself from mail_send by noting it cannot send, so an agent can distinguish it from the sibling tools without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit guidance on when to use this tool versus mail_send, and notes that there is no companion tool to send an existing draft. It also clarifies that recipients are optional, which is directly useful for invocation decisions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_delete_messageDelete a messageADestructive
Deletes a message. This is a soft delete: the message moves to Deleted Items and the user can restore it from Outlook, but this server has no tool to undo it, so confirm with the user first. Deleting a message already in Deleted Items removes it permanently.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Id of the message to delete. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the destructiveHint annotation, the description discloses critical behavioral details: the operation is a soft delete, the message is recoverable in Outlook, no server-side undo exists, and deleting from Deleted Items is permanent. This gives the agent the full side-effect picture needed to decide safely.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, each carrying essential information: the action, the soft-delete behavior and recoverability, the lack of server-side undo with a confirmation instruction, and the permanent-deletion edge case. No filler or repetition; the most important warning is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive single-id operation with one documented parameter and no output schema, the description covers the key contextual needs: what happens, what the user can do to recover, what the server cannot do, and when deletion becomes permanent. The agent has enough information to invoke the tool responsibly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents the single required id parameter with full coverage and a clear description ('Id of the message to delete'). The tool description adds no additional parameter-level semantics, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Deletes a message,' a specific verb and resource that clearly identifies the operation. It further clarifies the exact behavior (soft delete moving the message to Deleted Items), which distinguishes this from sibling tools like mail_move_message or mail_mark_read. The purpose is unambiguous and immediately actionable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear practical guidance: confirm with the user first, since the server has no undo tool, and warns that deleting a message already in Deleted Items is permanent. This establishes when caution is required, though it does not explicitly compare to alternatives like mail_move_message or state when not to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_forwardForward a messageADestructive
Forwards an existing message immediately, attachments included — it does not create a draft and there is no undo, so confirm the recipients with the user first. Your comment, if any, is placed above the forwarded content. Sending needs the Mail.Send permission, which is separate from read/write access.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Id of the message being forwarded. | |
| to | Yes | Who to forward it to. At least one is required. | |
| comment | No | Optional note above the forwarded message. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark destructive and non-idempotent, and the description adds meaningful behavioral detail: immediate sending, no undo, attachments included, comment placement, and the separate Mail.Send permission requirement. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences front-load the core behavior and warning, then add only necessary context about comment placement and permissions. Every clause contributes actionable information with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-parameter tool with no output schema, the description covers what the action does, side effects, safety guidance, and required permission. An agent has enough to decide whether to call it and what to tell the user before invoking.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents id, to, and comment. The description adds only that attachments are included and that no undo exists, which is behavioral context rather than new parameter semantics; the comment placement detail essentially repeats the schema description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb, resource, and mode ('Forwards an existing message immediately, attachments included') and explicitly distinguishes itself from draft creation. An agent can reliably tell this apart from mail_send, mail_create_draft, and mail_reply.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context: the tool acts immediately, includes attachments, and is not a draft; it also tells the agent to confirm recipients with the user first because there is no undo. It does not explicitly name alternative tools or state 'use X instead', but the actionable guidance is strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_get_messageGet one mail messageARead-onlyIdempotent
Returns one message with its body plus sender, recipients, timestamps, importance, conversationId and webLink. The body defaults to plain text and is capped at 8000 characters; raise maxBodyChars for a long thread, or pass format:"preview" to skip the body when you only need to identify the message. Attachment contents are never included — use mail_list_attachments. Reading a message here does not mark it read; use mail_mark_read for that.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The message id, as returned by mail_list_messages. | |
| format | No | How to return the body. "text" (default) asks Graph for plain text and strips any HTML that comes back anyway. "html" returns the raw markup, which costs several times more tokens. "preview" skips the body entirely and returns only the 255-character bodyPreview — use it when you just need to confirm you have the right message. | text |
| maxBodyChars | No | Character budget for the body. Defaults to 8000, which covers most messages. The server's own output cap still applies on top of this. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is known. The description adds valuable behavioral context beyond annotations: the body caps at 8000 characters (with maxBodyChars override), preview skips the body, attachment contents are never included, and reading does not change read state. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with zero filler: the first fronts the core return value, the second covers body format and size, and the third handles attachments and read-state side effects. Every sentence earns its place, and the most important information (what the tool returns) comes first.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 1-required-parameter tool with no output schema, the description covers all essential aspects: return fields, body format and truncation, the preview mode, exclusion of attachments, and the lack of a read-mark side effect. It also names the relevant sibling tools for follow-up actions. Nothing an agent needs to call this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already documents all three parameters well. The description adds practical guidance beyond the schema by explaining when to raise maxBodyChars ('for a long thread') and when to use format:'preview' ('when you only need to identify the message'), which helps the agent choose correct values in context. This exceeds the baseline of 3 for full schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Returns') and resource ('one message') and enumerates the returned fields (body, sender, recipients, timestamps, importance, conversationId, webLink). It clearly differentiates from siblings by noting attachments are excluded and reading does not mark as read, so an agent can distinguish it from mail_list_messages, mail_list_attachments, and mail_mark_read without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use and when-not-to-use guidance: it tells the agent to use mail_list_attachments when attachment contents are needed, mail_mark_read to mark as read, and format:'preview' when only identifying the message. These are direct routing instructions to sibling tools, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_list_attachmentsList message attachmentsARead-onlyIdempotent
Lists attachment metadata for one message — id, name, contentType, size in bytes, whether it is inline, and its kind (file, item, or reference) — 20 per call by default. File contents are deliberately never returned: a single attachment would exceed the output budget many times over. Check hasAttachments on the message first; inline images count as attachments, so a message with no visible attachment can still list several.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The message id, as returned by mail_list_messages. | |
| top | No | How many attachments to return. Defaults to 20. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnly, idempotent, non-destructive), the description discloses that file contents are never returned and explains why (output budget), plus notes the default limit of 20 per call. This adds valuable behavioral context that the annotations do not cover, with no contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured, front-loading the main purpose and fields, then adding the important caveats about file contents and inline images. It is slightly verbose with the output budget explanation, but every sentence earns its place by conveying essential behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a list tool with no output schema, the description fully explains the return metadata, pagination default, and a necessary prerequisite. It is complete enough for an agent to call the tool correctly without additional context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already describes both parameters (id and top) with full coverage (100%). The description reinforces the default of 20 per call but does not add new semantic meaning beyond the schema. Baseline of 3 is appropriate when the schema carries the parameter documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's action ('Lists attachment metadata for one message') and enumerates the specific fields returned (id, name, contentType, size, inline flag, kind). It is unambiguous and distinguishes itself from other mail tools by scoping to a single message's attachments.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides a clear usage guideline: 'Check hasAttachments on the message first' and warns that inline images count as attachments, which is a practical caveat. It doesn't explicitly mention alternatives or when not to use it, but the prerequisite and the clarification about inline images offer sufficient guidance for typical use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_list_foldersList mail foldersARead-onlyIdempotent
Lists the top-level Outlook mail folders with their ids, unread counts and total counts, 50 per call by default. Pass includeChildren to also get one level of subfolders. Only top-level folders are returned otherwise, so a nested folder needs a second call. Use an id from here as folderId in mail_list_messages, though the well-known names (inbox, archive, sentitems) work there without looking anything up.
| Name | Required | Description | Default |
|---|---|---|---|
| top | No | How many top-level folders to return. Defaults to 50. | |
| includeChildren | No | Also return one level of subfolders under each top-level folder. Nesting deeper than one level needs a second call with that folder as the parent. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent annotations, the description discloses pagination behavior (50 per call by default), the nesting limitation (only one level with includeChildren), and the requirement for a second call otherwise. It also reveals the output fields (ids, counts) and cross-tool contract (folderId reuse), giving an agent a clear picture of runtime behavior without needing to inspect schemas.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each carrying distinct information: what is returned and default page size, how to expand nesting, and how to use the result with a sibling tool. The most critical facts are front-loaded, and there is no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the lack of an output schema, the description names the fields returned (ids, unread counts, total counts), states the default pagination, explains the nesting behavior, and points to the dependent sibling – everything an agent needs to decide whether to call it and to interpret the result. The only minor omission is explicit error/edge-case handling, but that is not essential for a simple list tool with strong input schema coverage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides high-quality descriptions for both parameters (top default/range, includeChildren behavior), and the description's parameter mentions largely mirror that. The description adds minor value by reinforcing the 50-default and the second-call nesting nuance, but it does not meaningfully extend parameter meaning beyond the schema. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action (lists), the resource (top-level Outlook mail folders), and the specific fields returned (ids, unread counts, total counts). It also distinguishes this tool from mail_list_messages by explaining how folder IDs feed into that sibling, avoiding ambiguity about which tool handles folders vs messages.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit usage context: it clarifies that only top-level folders are returned by default, that includeChildren adds one subfolder level, and that a nested folder requires a second call. It also directly names the sibling tool (mail_list_messages) and explains when to use it with well-known folder names, providing a clear when-to-use and when-not-to-use alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_list_messagesList mail messagesARead-onlyIdempotent
Lists Outlook messages newest-first, 10 per call by default (50 max), as a compact projection: id, subject, from, toRecipients, receivedDateTime, isRead, hasAttachments, bodyPreview and webLink. Bodies are never included — bodyPreview is Graph's first 255 characters, and mail_get_message returns the rest. Page with skip. Note that Exchange rejects some filter/orderby combinations with "The restriction or sort order is too complex"; when that happens, drop orderby or sort on the same property you filtered.
| Name | Required | Description | Default |
|---|---|---|---|
| top | No | How many messages to return. Defaults to 10; 50 is the ceiling. | |
| skip | No | Messages to skip before returning results. Use it to page: 0, then 10, then 20. | |
| filter | No | Raw OData $filter, e.g. "importance eq 'high'" or "receivedDateTime ge 2026-01-01T00:00:00Z". Combined with unreadOnly using and. | |
| select | No | Graph message property names to return instead of the default projection, e.g. ["subject","importance","conversationId"]. id is always included. Do not ask for "body" here — use mail_get_message. | |
| orderby | No | Sort order. Defaults to "receivedDateTime desc" (newest first). | receivedDateTime desc |
| folderId | No | Restrict to one mail folder. Accepts a folder id from mail_list_folders or a well-known name: inbox, drafts, sentitems, deleteditems, archive, junkemail, outbox, clutter, conversationhistory, scheduled. Omit to list the whole mailbox. | |
| unreadOnly | No | Return only unread messages (adds "isRead eq false" to the filter). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, so the description doesn't need to repeat safety. It adds valuable behavioral context: bodies are never included, bodyPreview is only the first 255 characters, pagination uses skip, and it warns about Exchange filter/orderby restrictions with a concrete workaround. This goes beyond the annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, front-loaded with the core behavior, then covers body handling, pagination, and a caveat in a logical order. Every sentence adds value; there is no filler or repetition of schema details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only listing tool with seven optional parameters and no output schema, the description is remarkably complete. It covers the default projection, how to retrieve full bodies (delegating to mail_get_message), pagination mechanics, folder scoping (including well-known names), and a known error scenario with a workaround. An agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds meaning beyond the schema by explaining the compact projection, that bodyPreview is a preview, and that bodies are intentionally excluded. It also contextualizes the 'skip' parameter for paging and hints at the filter/orderby interplay, which enriches parameter understanding.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb (Lists), the resource (Outlook messages), and specific behavioral details (newest-first, 10 per call, compact projection). It explicitly distinguishes itself from mail_get_message by noting bodies are never included and that mail_get_message returns the rest, effectively differentiating from a key sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context: it lists messages in a folder or mailbox with optional filtering and paging. It explicitly points to mail_get_message for full body content, which serves as an alternative. However, it does not explicitly contrast with mail_search_messages or other listing tools, so the when-not-to-use guidance is implicit rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_mark_readMark a message read or unreadAIdempotent
Sets the read flag on one message. Defaults to marking it read; pass isRead:false to mark it unread again. Reading a message with mail_get_message does not change this flag, so unread counts stay accurate until you call this.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Id of the message to flag. | |
| isRead | No | True marks it read, false marks it unread. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=false, idempotentHint=true, and destructiveHint=false. The description adds meaningful behavioral context: the default is read, isRead:false flips it back, and reading via mail_get_message has no effect on the flag, which helps the agent understand side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The core action is front-loaded, the optional parameter is explained clearly, and the relationship to mail_get_message is stated in one efficient clause.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter mutation with annotations covering safety and idempotency, the description provides everything needed to invoke it correctly. No output schema is present, so explaining return values is not required.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents both parameters and the default for isRead. The description restates the default behavior but adds little beyond the schema, making a baseline 3 appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'Sets the read flag on one message.' It clearly distinguishes the tool from mail_get_message, mail_list_messages, and mail_delete_message by focusing on the read-flag mutation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains the default behavior and how to invert it with isRead:false. It also gives useful context by noting that mail_get_message does not alter the flag, implying this tool is the way to change read state, though it does not explicitly list exclusions or alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_move_messageMove a message to a folderAIdempotent
Moves a message to another mail folder. The move assigns the message a NEW id — the old one stops resolving, so use the id returned here for any follow-up call. destinationId accepts a folder id from mail_list_folders or a well-known name such as archive or deleteditems; moving to deleteditems is how you soft-delete without mail_delete_message.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Id of the message to move. | |
| destinationId | Yes | Target folder id from mail_list_folders, or a well-known name: inbox, archive, deleteditems, junkemail, drafts, sentitems. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only indicate readOnlyHint=false, idempotentHint=true, and destructiveHint=false. The description adds critical behavioral disclosure not covered by annotations: the move reassigns a new id, invalidating the old one and requiring the returned id for follow-ups. It also clarifies the soft-delete semantics of the deleteditems destination. This is valuable, non-obvious behavior that an agent must know.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences of high information density. It front-loads the core action, then the most critical behavioral caveat (new id), then the parameter-specific guidance. Every sentence adds value, and there is no redundant fluff or restating of the tool's name or title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (2 simple params, no output schema, no nested objects), the description covers all essential contexts: the action, the id reassignment side effect, the referral to mail_list_folders, and the soft-delete use case. An agent has everything needed to invoke it correctly and interpret the result. No critical information is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both id and destinationId are documented. The description adds meaning for destinationId by referencing mail_list_folders and the soft-delete nuance, which helps an agent choose the right value. For id, it explains the consequence (new id) but that's more about output than the parameter itself. It supplements the schema meaningfully without repeating it, justifying above-baseline scoring.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource: 'Moves a message to another mail folder.' It clearly distinguishes this from sibling tools like mail_delete_message (a delete, not a move) and mail_mark_read (a state change). The unique consequence of the move—the message receiving a NEW id—is stated up front, further differentiating it.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context on when to use this tool: it references mail_list_folders for obtaining destinationId and explicitly explains that 'moving to deleteditems is how you soft-delete without mail_delete_message.' This provides a usage nuance relative to the delete tool, though it doesn't explicitly enumerate all alternative tools or exclusions. Overall, it offers solid guidance beyond the schema.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_replyReply to a messageADestructive
Sends a reply to an existing message immediately — it does not create a draft, and there is no undo, so confirm the text with the user first. Your comment is placed above the quoted original as plain text; Graph builds the subject and recipients itself. replyAll includes every original recipient. Sending needs the Mail.Send permission, which is separate from read/write access.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Id of the message being replied to. | |
| comment | Yes | Your reply text. It is placed above the quoted original as plain text. | |
| replyAll | No | Reply to every recipient rather than only the sender. Defaults to false. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true, and the description adds significant context: immediate send, no undo, and the Mail.Send permission requirement. It also explains how the comment is placed above the quoted original and that Graph builds subject and recipients. This goes beyond the annotations and covers key behavioral traits, though it doesn't mention potential failures or idempotency nuances (already covered by idempotentHint=false).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences with no filler. The most critical caveat (immediate send, no undo, confirm first) is front-loaded, followed by formatting details and permission requirements. Every sentence earns its place and the structure is logical and efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple 3-parameter tool with no output schema, the description covers the essential aspects: behavior, permission, formatting, and recipient semantics. It lacks explicit mention of return values or error handling, but these are not critical for a basic reply action. The description is sufficiently complete for an agent to call the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds value by explaining that the comment is placed above the quoted original as plain text, and that replyAll includes every original recipient. This clarifies the semantics of comment and replyAll beyond their schema descriptions. The id parameter is self-explanatory and needs no extra context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool sends a reply to an existing message immediately, and explicitly contrasts with creating a draft. It names the specific resource (message) and the action (reply), making it distinct from siblings like mail_create_draft and mail_send. The verb 'sends' is specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear usage guidance by stating it sends immediately, has no undo, and requires confirmation with the user first. It implies when to use this tool (when an immediate send is desired) and contrasts with draft creation. However, it does not explicitly name alternative sibling tools (e.g., mail_create_draft) as the recommended path for draft scenarios, leaving some 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.
mail_search_messagesSearch mail messagesARead-onlyIdempotent
Finds messages by text, returning the same compact projection as mail_list_messages, 10 per call by default (50 max). Two modes, because Graph will not combine them: with no date range it uses $search, a relevance-ranked KQL search over subject, body and participants (results are NOT in date order, and $search supports no date syntax). Passing after or before switches to $filter on receivedDateTime, which sorts newest-first but can only match query as a substring of the subject — body text is not searched in that mode. The response reports which mode ran. To search body text within a period, search first and filter the dates yourself.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | Only messages addressed to this exact address. | |
| top | No | How many messages to return. Defaults to 10; 50 is the ceiling. | |
| from | No | Only messages sent by this exact address. | |
| after | No | Only messages received at or after this ISO-8601 date or datetime, e.g. "2026-01-01" or "2026-01-01T09:00:00Z". A bare date starts at 00:00:00Z. Supplying this switches the tool to $filter mode. | |
| query | Yes | Words to look for. Without a date range this is a KQL search across subject, body, and participants, so "subject:budget" or "quarterly review" both work. With after/before it degrades to a subject substring match — see the tool description. | |
| before | No | Only messages received at or before this ISO-8601 date or datetime. A bare date ends at 23:59:59Z that day. Supplying this switches the tool to $filter mode. | |
| hasAttachments | No | Only messages with (or without) attachments. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly, idempotent, and non-destructive behavior, so the burden is on behavior beyond that. The description adds high-value traits: results are not in date order in $search mode, $search supports no date syntax, $filter only matches subject substrings, and the response reports which mode ran. This is substantial behavioral disclosure that structured fields cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every clause earns its place: projection, pagination, mode selection, ordering, and a workaround for the body-text-with-date limitation. The most important scoping fact (text search) is front-loaded, and there is no filler or restatement of obvious annotation data.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a search tool with no output schema, the description tells the agent what projection to expect (via mail_list_messages), the default page size and cap, the mode behavior, and how to compensate for mode limitations. Nothing an agent needs to invoke it correctly or interpret its response is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description adds meaning the schema alone cannot: after and before are not just date filters but mode switches, and query changes semantics depending on whether a date range is present. This directly affects correct invocation and interpretation of results, going well beyond the schema's property-level descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: "Finds messages by text," and immediately distinguishes it from mail_list_messages via the "same compact projection" reference. The two-mode explanation further separates it from both a plain list operation and a generic search, so an agent can select it confidently.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use each mode: no date range triggers $search, while passing after/before triggers $filter, and it explains the trade-offs of each. It even gives a concrete fallback strategy for searching body text within a period, which is exactly the kind of actionable usage guidance an agent needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_sendSend mailADestructive
Sends a message immediately from the signed-in mailbox — there is no undo and no confirmation step, so confirm the recipients and text with the user first. Graph returns no message id for a send: if you need one, use mail_create_draft instead. A copy lands in Sent Items unless saveToSentItems is false. Sending needs the Mail.Send permission, which is separate from read/write access.
| Name | Required | Description | Default |
|---|---|---|---|
| cc | No | Carbon-copy recipients. | |
| to | Yes | Primary recipients. At least one is required. | |
| bcc | No | Blind carbon-copy recipients. | |
| body | Yes | Message body, in the format given by contentType. | |
| subject | Yes | Subject line. | |
| contentType | No | How to interpret body. "Text" (default) is safest; "HTML" renders markup. | Text |
| saveToSentItems | No | Keep a copy in Sent Items. Defaults to true. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (non-read-only, non-idempotent, destructive), the description discloses critical behavior: no undo or confirmation step, no returned message id, a copy in Sent Items unless saveToSentItems is false, and a specific permission requirement. This goes well beyond what the annotations alone convey and gives the agent a realistic model of the operation's consequences.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is four sentences, front-loads the core behavior first, and then adds the most decision-relevant caveats (no undo, no id, Sent Items behavior, permission). Every sentence earns its place; there is no filler or repetition of schema content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a send-message tool with no output schema, the description covers the operational essentials: side effects, failure-relevant behavior, permission requirements, and an explicit sibling alternative. The input schema handles parameter details, and the annotations handle the low-level safety profile, so nothing an agent needs to call this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the input schema fully documents every parameter. The description adds only modest semantic color, such as the saveToSentItems behavior and the overall emphasis on confirming recipients, but it does not materially extend the schema's parameter explanations. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action and resource: 'Sends a message immediately from the signed-in mailbox.' It also distinguishes itself from the sibling mail_create_draft by noting that a send returns no message id and that creating a draft is the alternative. This makes the tool's purpose unambiguous and clearly differentiated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells the agent when to use this tool and when not to: confirm recipients and text because there is no undo, and use mail_create_draft when a message id is needed. It also warns about the separate Mail.Send permission requirement, giving practical usage context beyond a simple 'send a message' statement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
me_get_mailbox_settingsGet my mailbox settingsARead-onlyIdempotent
Returns the signed-in user's Outlook mailbox configuration: time zone, date and time format, locale, working hours, and the automatic-reply (out-of-office) setting. Automatic-reply bodies are HTML in Graph and come back stripped to plain text and truncated to replyBodyChars. The scheduled start and end times are only meaningful when status is "scheduled" — when status is "alwaysEnabled" or "disabled" they are stale leftovers from the last schedule. Accounts with no Exchange Online mailbox fail with 404 MailboxNotEnabledForRESTAPI.
| Name | Required | Description | Default |
|---|---|---|---|
| replyBodyChars | No | Maximum characters of each automatic-reply message to return after HTML is stripped. Use 0 to omit the reply bodies entirely and keep only the status and schedule. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool read-only and idempotent, and the description adds substantial behavior beyond that: reply bodies are stripped to plain text and truncated to replyBodyChars, scheduled start/end times are only meaningful when status is 'scheduled,' and missing mailboxes surface as a specific 404. This is exactly the contextual detail an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, each with a distinct job: scope, reply-body behavior, schedule semantics, and error condition. The most decision-relevant information is front-loaded in the first sentence, with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even without an output schema, the description covers what is returned, the only parameter's effect, edge-case semantics for scheduled replies, and the failure mode. Nothing an agent needs to call and interpret this tool correctly is omitted.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so replyBodyChars is already fully documented in the schema, including the 0-omits-bodies behavior. The description adds that bodies are 'HTML in Graph' and are truncated, but this largely restates the schema's semantics rather than providing new meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb-plus-resource phrase, 'Returns the signed-in user's Outlook mailbox configuration,' and enumerates the exact fields returned. This makes the tool distinguishable from sibling tools like me_get_profile or mail_get_message without inspecting the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly establishes when the tool applies: signed-in user's mailbox settings. It also flags a boundary case with 'Accounts with no Exchange Online mailbox fail with 404 MailboxNotEnabledForRESTAPI,' but it does not explicitly name sibling alternatives or say when not to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
me_get_profileGet my profileARead-onlyIdempotent
Returns the signed-in user's own Entra ID profile from /me: by default id, displayName, mail, userPrincipalName, jobTitle, officeLocation and preferredLanguage. Pass select to ask for different properties instead. Properties Graph returns as null or empty are omitted, so a missing key means "not set" rather than "not requested". mail is null for accounts without an Exchange mailbox and personal Microsoft accounts leave the work fields empty — userPrincipalName is the identifier that is always present.
| Name | Required | Description | Default |
|---|---|---|---|
| select | No | Graph `user` property names to return instead of the default set, e.g. ["displayName","department","mobilePhone"]. Bare property names only: navigation paths such as "manager/displayName" and any other OData expression are rejected. Omit for the compact default projection. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent annotations, the description discloses important behavioral nuances: null/empty properties are omitted, 'mail' is null for accounts without Exchange mailboxes, personal accounts return empty work fields, and userPrincipalName is always present. This adds meaningful runtime expectations the schema cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and every sentence earns its place: default set, how to override, omission semantics, and field-specific edge cases. It is front-loaded with the core purpose and avoids repetition or fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With only one optional parameter, no output schema, and strong annotations, the description fully covers what an agent needs to call it correctly: default projection, selection behavior, and interpretation of absent keys. No critical operational detail is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already thoroughly describes the select parameter, its format, examples, validation, and default behavior. The description's 'Pass select to ask for different properties instead' is helpful but does not substantially exceed what the schema already documents.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Returns the signed-in user's own Entra ID profile from /me'. It clearly scopes the operation to the caller's own profile intest and enumerates the default fields, making it easy to distinguish from sibling tools like me_get_mailbox_settings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context: this is the tool for the signed-in user's own profile. It does not explicitly name alternatives, but the '/me' scoping and default property list are enough to signal when it is appropriate. No exclusion guidance is provided, so slightly short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_querySearch Microsoft 365ARead-onlyIdempotent
Runs a relevance-ranked Microsoft Search query across Microsoft 365 and returns a flattened list of hits, each with its rank, a text summary and the resource's id, name or subject, web URL and last-modified time. Defaults to 10 hits per entity-type group over ['message','driveItem']; page with from. Traps: chatMessage cannot be combined with other entity types, so a mixed request is split into two calls and merged, and its hits ignore fields; searching driveItem, listItem or site needs Sites.Read.All, event needs Calendars.Read and chatMessage needs Chat.Read, so enable the matching tool group or the split for that type fails on its own while the rest still return; results are ranked, not sorted by date, and freshly changed items may not be indexed yet. This is read-only despite using POST.
| Name | Required | Description | Default |
|---|---|---|---|
| from | No | Zero-based offset of the first hit to return; use it to page. Defaults to 0. | |
| size | No | Maximum hits to return per entity-type group. Defaults to 10, capped at 25. | |
| query | Yes | The search terms, in Microsoft Search KQL. Free text works ("quarterly budget"), as do property restrictions such as "subject:budget", "from:sara@contoso.com", "filetype:pptx" and "lastModifiedTime>=2026-01-01", combined with AND/OR/NOT. | |
| fields | No | Extra resource properties to retrieve and include on each hit, for example ["from","importance"] or a SharePoint managed property. Ignored for chatMessage, which does not support field selection. | |
| entityTypes | No | Which kinds of content to search. Defaults to ['message','driveItem'] (Outlook mail plus OneDrive/SharePoint files). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as read-only, idempotent, and non-destructive, but the description adds substantial behavior beyond that: results are ranked not date-sorted, fresh items may not be indexed, chatMessage cannot combine with other types, and mixed requests are split into two calls. It also explains the read-only nature despite POST, which directly complements the annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but well front-loaded with the main purpose and return shape, then defaults, then traps. Every sentence adds necessary information, though the long trap section is a single block and could benefit from clearer bullet structure.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex tool with multiple entity types, permissions, paging, and splitting behavior, the description covers all necessary operational details: defaults, paging, per-type permission needs, result ordering caveats, and the read-only POST behavior. Even without an output schema, it enumerates the returned fields.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description meaningfully extends parameter understanding with KQL syntax examples, the per-entity-type-group meaning of size, paging via from, and the chatMessage exception for fields. This goes well beyond the schema's property descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: it runs a relevance-ranked Microsoft Search query across Microsoft 365 and returns a flattened list of hits with concrete fields. It distinguishes itself from more scoped sibling tools by emphasizing cross-Microsoft-365 coverage over multiple entity types.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context on defaults, paging, entity-type groups, and permission requirements, making it evident this is the cross-entity search tool. It does not explicitly name alternatives like mail_search_messages or files_search for single-entity searches, so it falls just short of fully explicit when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
todo_complete_taskComplete a To Do taskAIdempotent
Marks a To Do task completed by patching its status to 'completed', and returns the updated task including the completedDateTime Graph stamps on it. Recurring tasks are rolled forward by the service rather than closed outright.
| Name | Required | Description | Default |
|---|---|---|---|
| listId | Yes | Id of the To Do list that holds the task. | |
| taskId | Yes | Id of the task to mark completed. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes beyond the annotations by clarifying that the operation patches status, that the updated task with completedDateTime stamps is returned, and that recurring tasks are rolled forward rather than closed. This adds meaningful behavioral context beyond readOnlyHint/idempotentHint/destructiveHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The primary action and return value are front-loaded, and the second sentence adds a valuable edge case about recurring tasks without bloat.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a low-complexity mutation with two simple parametersley and no output schema, the description covers the action, the return value, and the notable recurring-task behavior. Nothing critical is missing for an agent to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and both parameters are simple string IDs with clear descriptions. The description does not add parameter-specific details, but the schema already documents the parameters adequately, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Marks'), a clear resource ('a To Do task'), and an explicit outcome ('completed by patching its status to completed'). It also distinguishes this completion action from sibling tools like todo_update_task and todo_delete_task by narrowing the operation to marking complete, not generic updating.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The intended use is implied: use this tool when you want to complete a To Do task. However, the description does not explicitly state when not to use it or mention alternatives such as todo_update_task for broader status changes, leaving some routing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
todo_create_listCreate a To Do listA
Creates a new To Do list and returns its id and display name. Display names are not required to be unique, so check todo_list_lists first if the user expects one list per name.
| Name | Required | Description | Default |
|---|---|---|---|
| displayName | Yes | Name of the new To Do list, as it appears in the To Do apps. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnly=false and idempotent=false, and the description adds the important behavioral detail that display names are not unique. It also clarifies the return values, which are not in the schema or annotations. No contradiction exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences with no filler. The core action is front-loaded, and the important uniqueness caveat is included without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter creation tool with no output schema, the description is complete: it states what is created, what is returned, and the key behavioral caveat about duplicate names. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has 100% coverage for the single displayName parameter, including a helpful description. The tool description adds little beyond the schema, so the baseline score of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool creates a new To Do list and returns its id and display name, using a specific verb and resource. It is easily distinguished from sibling tools like todo_list_lists and todo_create_task.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit guidance to check todo_list_lists first when uniqueness is expected, which is a useful pre-condition. It does not fully enumerate when to use this tool versus alternatives, but the context is clear for a create operation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
todo_create_taskCreate a To Do taskA
Creates a task in a To Do list and returns the created task. Only title is required. Due and reminder values are sent as Graph dateTimeTimeZone objects using the timeZone argument (default UTC), and a date-only dueDateTime becomes midnight, matching how the To Do apps store all-day due dates. Supplying reminderDateTime also switches the reminder on, since Graph leaves isReminderOn false otherwise.
| Name | Required | Description | Default |
|---|---|---|---|
| body | No | Plain-text notes stored on the task body. | |
| title | Yes | Task title. This is the only required task field. | |
| listId | Yes | Id of the To Do list to create the task in. | |
| timeZone | No | Time zone the due and reminder wall-clock times are expressed in, e.g. 'UTC' or 'Pacific Standard Time'. Ignored for values that already carry a UTC offset. | UTC |
| importance | No | Task importance. Graph defaults to normal. | |
| dueDateTime | No | Due date, '2026-09-10' or a full ISO 8601 date-time. Use 'YYYY-MM-DD' or a full ISO 8601 date-time such as '2026-09-10T14:30:00'. | |
| reminderDateTime | No | Reminder date-time. Supplying this also turns the reminder on. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare this as a write operation (readOnlyHint=false) and non-idempotent. The description adds value by disclosing specifics: it returns the created task, normalizes date-only due dates to midnight, and turns on reminder when reminderDateTime is supplied because Graph defaults isReminderOn to false. These behaviors are not apparent from the schema or annotations alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concisely structured, leading with the primary action and return value, then adding essential details about required fields and date handling. Each sentence contributes value without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (7 params, date-time nuances, no output schema), the description covers the critical edge cases (timezone handling, all-day dates, reminder enabling) and clearly states the return of the created task. It is sufficient for an agent to invoke correctly, though it omits potential error conditions and auth details, which are not always required.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers all parameters with descriptions, so baseline is 3. The description adds nuance: explains that due/reminder values are converted to Graph dateTimeTimeZone using the timeZone argument, and clarifies the midnight behavior for all-day dates. This goes beyond the schema's notes, enhancing the agent's understanding.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Creates'), a resource ('task in a To Do list'), and a return value ('returns the created task'). It clearly distinguishes from sibling tools like todo_update_task and todo_delete_task by naming the create action. No ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear guidance on required fields ('Only title is required') and explains the handling of due and reminder dates, which is essential for correct usage. However, it does not explicitly contrast with alternative tools (e.g., todo_update_task) or state when not to use it. Still, the context is strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
todo_delete_taskDelete a To Do taskADestructive
Deletes a To Do task permanently and returns a confirmation. There is no recycle bin for To Do tasks, so prefer todo_complete_task when the user only wants it out of the way.
| Name | Required | Description | Default |
|---|---|---|---|
| listId | Yes | Id of the To Do list that holds the task. | |
| taskId | Yes | Id of the task to delete permanently. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate destructiveHint: true, but the description adds critical context: 'permanently' and 'There is no recycle bin for To Do tasks.' This reinforces the irreversibility and gives the agent a stronger reason to prefer the completion tool when appropriate. It also notes the tool returns a confirmation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The core action and permanence are front-loaded, followed by the alternative usage guidance. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple delete operation with two straightforward parameters, the description fully covers what it does, the irreversibility, the return of a confirmation, and when to choose an alternative. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and both parameters have clear descriptions (listId and taskId). The tool description adds no additional parameter semantics beyond the schema, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action (deletes a To Do task), the resource (To Do task), and the key characteristic (permanently). It also differentiates from the sibling todo_complete_task by explicitly noting the alternative for non-permanent removal, making the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly instructs when to use this tool versus the alternative: 'prefer todo_complete_task when the user only wants it out of the way.' This direct guidance leaves no ambiguity about selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
todo_get_taskGet a To Do taskARead-onlyIdempotent
Reads one To Do task in full: title, status, importance, reminder state, start/due/completed times, categories and the notes body (truncated). Needs both the list id and the task id, which come from todo_list_lists and todo_list_tasks.
| Name | Required | Description | Default |
|---|---|---|---|
| listId | Yes | Id of the To Do list that holds the task. | |
| taskId | Yes | Id of the task, as returned by todo_list_tasks. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering safety. The description adds a key behavioral detail beyond annotations: the notes body is truncated, informing the agent that the returned content is not fully complete. This is valuable context for a read operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no fluff. The core purpose is front-loaded, followed by a precise list of returned fields and the ID prerequisite. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read tool with two parameters, full schema coverage, and annotations covering safety, the description is complete. It conveys the returned fields, warns about truncation, and explains the dependency on sibling tool outputs. No gap that an agent needs to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both parameters are already documented with descriptions. The description adds source information—that the IDs come from specific sibling tools—which the schema does not provide, enhancing the agent's ability to fill parameters correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Reads') and resource ('one To Do task') and enumerates the exact fields returned (title, status, importance, etc.), making it clear this is a single-task fetch distinct from todo_list_tasks and the mutation tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says the tool needs both listId and taskId, and tells the agent where those come from (todo_list_lists and todo_list_tasks). While it doesn't explicitly name when not to use it, the prerequisite and purpose make the usage context evident.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
todo_list_listsList To Do listsARead-onlyIdempotent
Lists the signed-in user's Microsoft To Do lists with their id, display name and well-known name (for example defaultList for the built-in Tasks list). Follows up to three pages, which covers any realistic number of lists. Use the returned id as listId for every other todo tool; To Do is delegated-only, so these are always the caller's own lists.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent annotations, the description discloses pagination behavior ('Follows up to three pages'), the delegated-only ownership model, and the output fields. This adds meaningful behavioral context an agent needs before calling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each earning its place: purpose and output, pagination behavior, and cross-tool usage. Information is front-loaded and there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a parameterless list tool with no output schema, the description is complete: it states what is returned, how many pages are followed, and how the result should be used with other tools. No critical information is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so there is no parameter semantics to explain. The description appropriately focuses on output fields and usage instead, matching the baseline for a no-parameter tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Lists') and resource ('signed-in user's Microsoft To Do lists'), and names the exact returned fields (id, display name, well-known name). It clearly distinguishes from sibling tools like todo_list_tasks by focusing on lists rather than tasks.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit usage guidance: 'Use the returned id as listId for every other todo tool.' It also clarifies scope with 'these are always the caller's own lists.' It does not explicitly name alternatives, but the list-vs-task distinction is clear from context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
todo_list_tasksList To Do tasksARead-onlyIdempotent
Lists tasks in one To Do list, returning id, title, status, importance, due and reminder times and a short body preview per task, plus count and nextLink when more pages exist. Page size defaults to 50. Completed tasks are excluded unless includeCompleted is true. To Do tasks do not support $search: narrow with filter instead, and note that dueDateTime is a complex type, so a date filter reads dueDateTime/dateTime ge '2026-01-01T00:00:00'.
| Name | Required | Description | Default |
|---|---|---|---|
| top | No | Maximum number of tasks to return in this page. Defaults to 50. | |
| filter | No | Raw OData $filter, ANDed with the completed-task filter. Example: "importance eq 'high'" or "dueDateTime/dateTime ge '2026-01-01T00:00:00'". | |
| listId | Yes | Id of the To Do list, as returned by todo_list_lists. | |
| includeCompleted | No | Include completed tasks. Defaults to false, which adds status ne 'completed' to the filter. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly, idempotent, and non-destructive hints. The description adds value by disclosing pagination (count and nextLink), page size default (50), and the default exclusion of completed tasks. It does not contradict annotations, and the added context enriches the behavioral picture without requiring the agent to infer from schema alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is information-dense but every sentence earns its place: return fields, pagination, defaults, exclusions, and filter guidance. It is front-loaded with the core purpose and each subsequent sentence adds a distinct useful detail. No fluff or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a list operation with no output schema, the description covers all essential aspects: the exact data returned, pagination details, default page size, completion filtering, and a critical filter caveat about complex types. An agent has everything needed to call this tool correctly without consulting additional documentation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. The description goes beyond by clarifying the filter syntax for dueDateTime as a complex type, giving a concrete example, and reasserting the top default. It also explains the interaction between includeCompleted and the filter, which is not fully explicit in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Lists'), a specific resource ('tasks in one To Do list'), and enumerates the exact fields returned (id, title, status, importance, due and reminder times, body preview). It clearly distinguishes from sibling tools like todo_list_lists (lists lists) and todo_get_task (single task) by focusing on the list-task scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells when to use the filter and what not to use ($search), including a concrete example for the complex dueDateTime type. It also explains the includeCompleted default behavior, giving clear conditions for when to set it. This goes beyond mere context and provides actionable alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
todo_update_taskUpdate a To Do taskAIdempotent
Patches an existing To Do task and returns the updated task. Only the supplied fields change; omitting dueDateTime or reminderDateTime leaves the existing value alone, so use clearDueDateTime or clearReminderDateTime to remove one. Due and reminder values are sent as Graph dateTimeTimeZone objects using the timeZone argument (default UTC).
| Name | Required | Description | Default |
|---|---|---|---|
| body | No | Replacement plain-text notes. Pass an empty string to clear them. | |
| title | No | New task title. | |
| listId | Yes | Id of the To Do list that holds the task. | |
| status | No | New task status. Use todo_complete_task for the common completed case. | |
| taskId | Yes | Id of the task to update. | |
| timeZone | No | Time zone for the due and reminder wall-clock times. Ignored for values that already carry a UTC offset. | UTC |
| importance | No | New task importance. | |
| dueDateTime | No | New due date. Use 'YYYY-MM-DD' or a full ISO 8601 date-time such as '2026-09-10T14:30:00'. | |
| clearDueDateTime | No | Remove the due date. Omitting dueDateTime alone never clears it. | |
| reminderDateTime | No | New reminder date-time. Supplying this also turns the reminder on. | |
| clearReminderDateTime | No | Remove the reminder and turn it off. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint=false, idempotentHint=true, destructiveHint=false), the description discloses important behavior: omitted due/reminder fields are preserved, clearing requires dedicated flags, and date-time values are sent as Graph dateTimeTimeZone objects with a default UTC timeZone. This meaningfully explains how the patch behaves without contradicting the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each earning its place: the first states the core operation and return value, the second explains partial-update and clearing behavior, and the third clarifies the date-time serialization and timezone default. No filler or repetition of schema details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 11 parameters, no output schema, and annotations covering safety/idempotence, the description plus schema is complete enough for correct invocation. It explains patch semantics, clearing behavior, timezone handling, and the return value ('returns the updated task'), leaving no critical gap for an agent deciding how to call it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3, but the description adds crucial semantics that the schema alone does not make obvious: omitting dueDateTime/reminderDateTime leaves existing values untouched, clearing requires separate boolean flags, and timeZone governs how wall-clock values are interpreted. This is genuinely additive value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Patches an existing To Do task and returns the updated task,' which names a specific verb, resource, and operation style. It clearly distinguishes this from todo_create_task, todo_delete_task, and todo_complete_task, and the status enum even points to todo_complete_task for the common completed case.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear patch semantics ('Only the supplied fields change') and explicit guidance for clearing fields via clearDueDateTime/clearReminderDateTime. The schema adds a direct alternative recommendation for todo_complete_task when setting status to completed, though the tool description itself does not fully enumerate when to prefer this tool over all sibling update/create paths.
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.
51 tool updates
v0.1.0- First observed
calendar_create_event - First observed
calendar_delete_event - First observed
calendar_find_meeting_times - First observed
calendar_get_event - First observed
calendar_get_schedule - First observed
calendar_list_calendars - First observed
calendar_list_events - First observed
calendar_respond_event - First observed
calendar_update_event - First observed
contacts_create - First observed
contacts_delete - First observed
contacts_get - First observed
contacts_list - First observed
contacts_search - First observed
contacts_update - First observed
files_create_folder - First observed
files_create_link - First observed
files_delete - First observed
files_get_item - First observed
files_list_children - First observed
files_list_recent - First observed
files_list_shared - First observed
files_read_text - First observed
files_search - First observed
files_upload_text - First observed
graph_list_permissions - First observed
graph_request - First observed
graph_schema - First observed
mail_create_draft - First observed
mail_delete_message - First observed
mail_forward - First observed
mail_get_message - First observed
mail_list_attachments - First observed
mail_list_folders - First observed
mail_list_messages - First observed
mail_mark_read - First observed
mail_move_message - First observed
mail_reply - First observed
mail_search_messages - First observed
mail_send - First observed
me_get_mailbox_settings - First observed
me_get_profile - First observed
search_query - First observed
todo_complete_task - First observed
todo_create_list - First observed
todo_create_task - First observed
todo_delete_task - First observed
todo_get_task - First observed
todo_list_lists - First observed
todo_list_tasks - First observed
todo_update_task
TDQS
Scored across 51 tools
The 51 tools are organized into clear domains (todo, mail, files, calendar, contacts, me, graph) with each tool addressing a distinct resource-action pair. Even within rich domains like mail, tools like mail_list_messages, mail_search_messages, and mail_get_message have clearly separated purposes (listing, searching, and fetching full content). The only generic tool, graph_request, is explicitly positioned as a fallback for uncovered endpoints, and its description clarifies its distinct role.
Every tool follows a strict domain_verb_noun (or domain_noun_verb) snake_case pattern, consistently using the domain prefix (todo_, mail_, files_, calendar_, contacts_, me_, graph_, search_). Verbs are uniform across similar operations (list_, get_, create_, update_, delete_, send_, etc.). This creates a highly predictable naming convention that lets an agent infer tool purposes without reading descriptions.
51 tools is a large surface, but the scope is a broad Microsoft Graph integration covering mail, calendar, files, contacts, To Do, user profile, and search. Each domain has a focused, manageable set (3–10 tools per area) that justifies the total count. It is slightly on the heavy side, but the breadth of the domain makes it reasonable rather than excessive.
The tool surface provides full CRUD coverage for contacts, To Do tasks, calendar events, and basic file operations, plus send/reply/forward/move for mail. Notable gaps exist: no way to send an existing draft, no file rename/move/copy, no todo list deletion or update, and no binary file download. These are acknowledged in descriptions as deliberate limitations, so agents can work around them, but they prevent a perfect score.
Related MCP Connectors
Permissioned access to Outlook, OneDrive and Teams via the user's own Microsoft account
Gives your AI assistant persistent memory and intelligence about your work patterns.
GDPR-compliant calendar access for AI assistants: read, create, edit, RSVP. Google, MS 365, Apple.
Gmail, Outlook, Drive, OneDrive and calendars for AI agents. Many accounts, one endpoint, audit log.
Related MCP Servers
- AlicenseNot gradedqualityFmaintenanceEnables AI assistants to interact with Microsoft 365 services (users, mail, calendar, files) via Microsoft Graph API.28 npm1MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to interact with Microsoft 365 through the Microsoft Graph API, including searching Teams messages, managing chats, and sending messages.77 npmMIT
- FlicenseNot gradedqualityCmaintenanceEnables AI assistants to seamlessly interact with Microsoft 365 services through the Graph API, featuring super tools, unified search, and intelligent learning.-
- AlicenseNot gradedqualityCmaintenanceEnables multiple users to securely connect their own Microsoft 365 account and use natural language to manage Outlook mail, Teams, and SharePoint/OneDrive files through Microsoft Graph, with support for shared mailboxes and admin governance.MIT