Claude Hotmail Connector
This server lets Claude read a personal Microsoft mailbox and view, create, and update calendar events.
Confirm the connected Microsoft account with
whoami.Search/list and read email messages read-only, including subject, sender, received time, web link, body preview/body, and attachment metadata.
List calendar events over a date range in a requested IANA time zone.
Create calendar events using local wall-clock times plus an IANA time zone, with optional body, location, reminders, and idempotency via
transactionId.Update existing calendar events (time, subject, location, body, reminder settings); the schema marks updates as destructive, so confirm changes first.
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., "@Claude Hotmail Connectorlist my unread emails from 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.
Claude Hotmail Connector
A local Model Context Protocol (MCP) server that lets Claude
read email and read/write calendar events in a personal Microsoft account
(@hotmail.com / @outlook.com / @live.com) via the Microsoft Graph API. If you turn it on, Claude
can also send email, but only after you confirm each one in your browser.
Claude's official Microsoft 365 connector only supports work/school (Microsoft Entra) accounts and rejects personal Microsoft accounts. This project fills that gap as a personal, single-user tool that runs entirely on your own machine.
Status: v1.0, stable. The connector ships as a Claude Desktop extension (
.mcpb) for Windows, macOS and Linux (only Windows is tested and supported by the maintainer; see Platforms). What changed is in the changelog, the requirements are in spec v2, and further work is tracked in the open issues.
How it works — local stdio
The connector is a local stdio MCP server (spec v2 §4). Claude Desktop (as an extension) or Claude Code / VS Code launches it as a subprocess and talks to it over stdin/stdout. There is no public URL, no tunnel and no hosting cost, and no Claude ↔ server OAuth. The only sign-in is to Microsoft: a native public-client OAuth 2.0 authorization-code + PKCE flow with a loopback redirect, opened in your browser the first time a tool needs it. No client secret is involved.
Claude Desktop / Claude Code ──stdio──▶ this server ──HTTPS──▶ Microsoft Graph (personal account)
(MCP client) (local subprocess) graph.microsoft.com/v1.0Because it runs locally, it works in Claude Desktop and Claude Code / VS Code on the same PC. It does not work in claude.ai on the web or mobile; that would need a remote mode, which isn't planned (#58, deferred).
Related MCP server: Outlook MCP Server
Tools
Tool | Purpose | Graph permission |
| Confirm the connected account |
|
| Search/list mail (find booking confirmations) |
|
| Read one email as text |
|
| Read a text, HTML, PDF or calendar (.ics) attachment |
|
| List mail folders |
|
| List your calendars (own and shared) |
|
| Read the calendar over a date range |
|
| Read one event in full (notes, attendees, pattern) |
|
| Find free slots in a date range |
|
| Add a calendar event (timezone-correct, idempotent) |
|
| Edit a calendar event (destructive: overwrites) |
|
| Delete an event, guarded (see below) |
|
| Remove the saved sign-in from this computer | (none) |
| Send an email, after you confirm it (opt-in) |
|
| Reply to a sender, after you confirm it (opt-in) |
|
Mail is read-only unless you turn sending on (Sending email), and
then every email is shown to you in your browser and sent only when you click Send there.
Calendar writes never add attendees or send invitations.
There is no hard-delete. cancel_event moves an event to Outlook's Deleted Items, and only after
three checks:
you've confirmed it and the event's exact title matches;
the event has no attendees, since deleting a meeting could email cancellations;
it isn't recurring.
update_event likewise refuses events with attendees, because changing a meeting emails its attendees.
A few behaviours worth knowing:
Junk and Deleted are left out. Across all folders,
list_messagesleaves out Junk Email and Deleted Items, and the folders beneath them, unless you ask for them. Mail in Junk is flagged as such, so phishing can't pass for a real booking.Attachments:
get_attachmentreads text, HTML, calendar (.ics) and PDF attachments. For a PDF it reads the text of the first 30 pages, in an isolated worker with time and memory limits. Password-protected and scanned PDFs (no text layer) can't be read, nor can images or other binary files. Size limits: 5 MB for PDFs, 1 MB for other files. Open anything refused from the message in Outlook.Times use your time zone.
find_free_timeand the other calendar tools work in your computer's time zone unless you name another, with daylight saving applied. All-day events count as whole days in that zone.
Full tool contracts are in spec v2 §7.
Sending email (optional)
Off by default. When it's on, Claude can send new emails, and replies to the person who sent you a message, but only after you confirm each one:
Claude prepares the email, and the connector opens a page in your browser showing exactly what will be sent: To, Cc, Subject and the whole text. Anyone who has never emailed you is flagged.
Nothing is sent until you click Send on that page. Don't send cancels it, and the page stops working after 5 minutes. Claude never sees the page's link, so it can't confirm for you.
Claude is told whether you sent or cancelled it.
To turn it on, tick Allow sending email under Settings → Extensions → Hotmail Connector, or set
ALLOW_SEND_MAIL=true when running from source. Then:
Fully restart Claude Desktop (Quit from the tray icon, then reopen it). Claude Desktop keeps using its earlier list of tools in chats until it restarts, so Claude won't see the send tools yet.
The first time you send, Claude will say your sign-in doesn't include permission to send. Ask it to sign out (
sign_out) and try again: Microsoft will ask you to allow sending.
Plain text only, to at most 10 people. Forwarding, reply-all, attachments and BCC aren't supported, since they're the easiest ways to leak mail. Replies go to the message's Reply-To address if it has one, else its sender, and don't quote the original.
Step 1: register your own Microsoft Entra application
Every user needs their own registration; the connector doesn't ship a shared one, so each user owns their own Microsoft access. Registering is free, but it needs a Microsoft Entra tenant, and a personal account doesn't come with one. If you don't have a tenant, create a free one first (typically by signing up for a free Azure account).
Shortcut: from a source checkout,
pwsh ./scripts/register-app.ps1does all of the steps below and prints the client ID. It needs the Azure CLI. On Windows, install it withwinget install -e --id Microsoft.AzureCLI, open a new terminal, and sign in withaz login --allow-no-subscriptions. The flag is needed because a free tenant usually has no Azure subscription; add--tenant <your-tenant>if you belong to several. Use the script from v0.2.1 or later: the earlier one created the registration without its API permissions listed.
The connector signs in as a public/native client. No client secret is ever used or stored.
Go to the Entra admin center → App registrations → New registration.
Name: e.g.
Claude Hotmail Connector.Supported account types: choose "Personal Microsoft accounts only". That's what the connector is for (
hotmail.com/outlook.com/live.com), and it matches the defaultMICROSOFT_TENANT=consumers. Work/school accounts are served by Claude's official Microsoft 365 connector. To allow them anyway, pick the multitenant + personal option instead and setMICROSOFT_TENANT=common.Redirect URI: select platform "Public client/native (mobile & desktop)" and enter
http://localhost. Microsoft allows any loopback port for native clients, so you don't need a specific port.Click Register, then copy the Application (client) ID.
Under Authentication, confirm the platform is Mobile and desktop applications with
http://localhost, and that "Allow public client flows" is Yes. Do not create a client secret.Under API permissions → Add a permission → Microsoft Graph → Delegated permissions, add:
openid,profile,email,offline_access,User.Read,Mail.Read,Calendars.ReadWrite. If you'll turn sending on, addMail.Sendtoo. A personal account doesn't need admin consent; you consent at sign-in.
Step 2a: install in Claude Desktop (extension)
Download
hotmail-connector.mcpbfrom the latest release. You can verify it againstSHA256SUMS.txt, or check where it was built, with the GitHub CLI:gh attestation verify hotmail-connector.mcpb --repo TGoodhew/Claude-Hotmail-Connector.In Claude Desktop, open Settings → Extensions → Advanced settings → Install Extension…, choose the downloaded file, then Install. (Double-clicking it, or dragging it onto the Extensions page, may also work in some versions; dropping it on a chat only attaches it to the chat.)
Enter your Application (client) ID from step 1. You can change it later under Settings → Extensions → Hotmail Connector. Make sure the extension is switched on there. If you also run the connector from source (step 2b), use the same client ID. On Windows each keeps its own saved sign-in, because Claude Desktop is an MSIX app (see Security).
Ask Claude something that needs your mailbox or calendar. The first time, a Microsoft sign-in opens in your browser. Finish it within about 45 seconds and that request carries on; otherwise ask again once you've signed in.
Updating to a newer release: install the new
.mcpbthe same way, over the old one. If Claude Desktop asks for your client ID again, enter the same one. What changed is in the changelog. Claude Desktop only replaces an installed extension with a newer version number: a different build with the same version (e.g. one you built yourself) is treated as already installed, so uninstall first, or give the build a new version.Upgrading from the v0.1.0 Windows installer:
Uninstall Claude Hotmail Connector from Windows Settings → Apps. That removes its Claude Desktop entry; keeping both would show every tool twice.
Install the extension with your own client ID, then sign in again. v0.1.0's shared registration has been deleted, so v0.1.0 can no longer sign in (#68).
More detail, including how the bundle is built, is in docs/packaging.md.
Step 2b: run from source (Claude Code / VS Code)
Prerequisites: Node.js 22.12 or later; Node.js 24 LTS is recommended, and CI builds and releases on it. CI also tests on 22.12, the minimum. Node 20 is no longer supported: it reached end-of-life in April 2026 (#148).
git clone https://github.com/TGoodhew/Claude-Hotmail-Connector.git
cd Claude-Hotmail-Connector
npm install
npm run build # produces dist/index.jsThen point your client at dist/index.js and pass your client ID in the server's environment.
Claude Code:
claude mcp add --scope user --env MICROSOFT_CLIENT_ID=<your-client-id> --transport stdio \
hotmail-connector -- node /path/to/Claude-Hotmail-Connector/dist/index.jsKeep --transport stdio where it is, between the --env value and the server name. --env accepts
several KEY=value pairs, so without something in between, the name is read as another pair.
VS Code: use Command Palette → "MCP: Add Server…" → Command (stdio), or copy
.vscode/mcp.json.example to .vscode/mcp.json and edit the path and
client ID:
{
"servers": {
"hotmail-connector": {
"type": "stdio",
"command": "node",
"args": ["C:\\path\\to\\Claude-Hotmail-Connector\\dist\\index.js"],
"env": { "MICROSOFT_CLIENT_ID": "<your-entra-app-client-id>" },
},
},
}(Claude Desktop can also run a source checkout through claude_desktop_config.json, see
examples/claude_desktop_config.example.json. The
extension is simpler.)
You don't need to sign in first: the first tool call opens the Microsoft sign-in in your browser. From
a source checkout you can also sign in, check or reset explicitly (with MICROSOFT_CLIENT_ID set, e.g.
in a .env in the checkout root, see .env.example. It's only ever read from there,
never from the folder you launch from):
node dist/index.js login # browser sign-in, caches the token
node dist/index.js whoami # prints your name and account, e.g. Jane Doe <jane@outlook.com>
node dist/index.js logout # removes the saved sign-in (token cache and key)On Windows, Claude Desktop (a Microsoft Store/MSIX app) keeps the extension's sign-in separate from
the checkout's (see Security), so logout doesn't sign it out there.
Configuration
Variable | Default | Notes |
| — (required) | Your Entra app's Application (client) ID. The extension sets it from its settings. |
|
| Personal accounts only. |
| This computer's time zone (UTC if unknown) | IANA zone used when a call doesn't specify one. An invalid name stops the server at startup. |
|
|
|
| least-privilege set (spec §6) | Narrowing only: drop scopes or use |
|
|
|
|
|
|
| per-OS profile dir | Where the encrypted token cache (and the log file, if on) lives. |
Usage example
"Find my Monsoon Aquatics and Macadamias Australia booking confirmation emails, then add each to my calendar with 15-minute travel-time blocks before and after."
Claude uses list_messages / get_message to read the confirmations and confirms the details with
you. It then calls create_event for each booking (and the travel blocks) at the correct local times,
with no duplicates if it retries.
More things to ask:
"Read the calendar invite attached to my hotel booking email." The connector uses
get_attachmentto read the.icsfile's events."What's the booking reference in the PDF attached to my flight confirmation?"
get_attachmentreads the PDF's text."Find me a free hour on Thursday between 9 and 5 Berlin time." This uses
find_free_timeinEurope/Berlin, with your events converted across time zones and daylight saving."What's in my Junk folder from this week?" This is
list_messageswithfolder: junkemail; Claude is told those messages were judged spam.
Security
Least privilege:
Mail.Read(read-only) +Calendars.ReadWrite.Mail.Sendonly if you turn sending on; neverMail.ReadWrite, no hard delete, no attendees/invitations.No client secret: a public/native client using PKCE.
Token storage: the refresh token is encrypted with AES-256-GCM in your user profile (
%LOCALAPPDATA%\claude-hotmail-connectoron Windows; elsewhere$XDG_STATE_HOME/claude-hotmail-connectorif that's set, else~/.claude-hotmail-connector). Claude for Windows is a Microsoft Store (MSIX) app, so Windows keeps the extension's copy in a private folder for Claude:%LOCALAPPDATA%\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Local\claude-hotmail-connector. The extension and a source checkout therefore sign in separately, andlogoutdoesn't sign Claude Desktop out; ask Claude to sign out (sign_out) for that (#176). On Windows the encryption key is protected with DPAPI, so only your Windows account on this PC can unlock it; copying the folder elsewhere isn't enough. On macOS/Linux the key is an owner-only file in the same folder: Keychain/libsecret support isn't planned, but a PR adding it is welcome (#83). Tokens are never committed, logged or returned to the client.Logging: structured logs go to stderr (stdout is reserved for MCP JSON-RPC) and are scrubbed of tokens,
Authorizationheaders, OAuth codes, secrets, your account name and any email address. They never include what's in your emails or events. With Write a log file on (LOG_FILE), they also go toconnector.log(see Troubleshooting).Email (and others' invites) are untrusted input: they're written by strangers and may try to steer the model. Unless you turn sending on, the connector can't send mail; when it's on, every email waits for your click on the connector's own page, which the model can't reach. There are no attendees, and no changing or deleting meetings with attendees. Writes and deletes are marked destructive so Claude asks before running them, but only if your client's tool permissions ask. Don't auto-approve the calendar write tools. Claude Desktop 3.1623.4 doesn't show these approval prompts for extension tools at all (#138, reported to Anthropic), so read what Claude says it will change before it does it. The full threat model is in spec v2 §9.2. Review what Claude proposes before approving calendar changes.
Timezone-correct writes: events are sent as local wall-clock time + an IANA time zone (never a UTC
Zwith a named zone), so they land at the intended local time.
Known security issues are tracked under the area:security label. To report a vulnerability, use
private reporting as described in SECURITY.md; please don't open a public issue.
Troubleshooting
Seeing what the connector did: Claude Desktop doesn't keep the extension's logs, so turn on Write a log file under Settings → Extensions → Hotmail Connector, then restart Claude Desktop fully (Quit from the tray icon). The log is
connector.login%LOCALAPPDATA%\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Local\claude-hotmail-connector(the folder Windows gives Claude Desktop, #176), or in%LOCALAPPDATA%\claude-hotmail-connectorfrom a source checkout withLOG_FILE=true. Each line starts with the time (UTC) and the process id. It never grows past 2 MB: when it would, the older half is dropped. Signing out leaves it in place; delete it by hand if you like. SetLOG_LEVEL=debugin a source checkout for more detail.AADSTS50020/ "account does not exist in tenant" / personal account rejected: the app registration doesn't accept personal accounts. Set its account type to Personal Microsoft accounts only (or multitenant + personal) per step 1.3.AADSTS9002331/ "configured for use by Microsoft Account users only": a personal-only registration is being used withMICROSOFT_TENANT=common. Use the default,consumers.A work/school account can't sign in: expected with the default
consumerstenant. See step 1.3 for the multitenant option.AADSTS7000218/ "client_assertion or client_secret required": the app is registered as a confidential/web client. Register it as a public client with "Allow public client flows" = Yes (step 1.6).redirect_urimismatch: addhttp://localhostunder the Mobile & desktop platform.Event lands an hour off: always pass a local wall-clock
dateTime(e.g.2026-07-20T10:00:00) with an IANAtimeZone, never aZ-suffixed value. The connector rejectsZ/offset values for event times."No Microsoft app registration is configured": no client ID is set. Enter it in Claude Desktop → Settings → Extensions → Hotmail Connector, or set
MICROSOFT_CLIENT_IDin your client's server config (step 2b).A tool says to finish signing in, or "sign-in is required": finish the Microsoft sign-in in the browser window that opened, then ask Claude to retry. If no window appeared, check that a default web browser is set; from a source checkout you can also run
node dist/index.js login. After a cancelled sign-in, the connector waits 30 seconds before opening another window."Microsoft refused the saved sign-in": the saved sign-in expired or was revoked, or it was made with a different client ID. Outside Windows, a common cause is giving Claude Desktop and a source checkout different client IDs while they share one saved sign-in, so use the same ID in both. Then sign in again: ask Claude, or run
node dist/index.js login."Sending email is turned on, but your Microsoft sign-in doesn't include permission to send": ask Claude to sign out (
sign_out), then try again. Microsoft will ask you to allow sending.No confirmation page appears when sending: check that a default web browser is set. Nothing is sent without the page.
v0.1.0 can't sign in any more: its shared registration was deleted. Upgrade as described in step 2a, with your own client ID.
Claude changes or deletes calendar events without asking: Claude Desktop 3.1623.4 doesn't show approval prompts for extension tools (#138). The connector's own guards still apply (see Tools).
find_free_timeshows part of an all-day busy day as free: fixed in v0.2.1 (#158); update the extension.Every tool appears twice: you have both the extension and an older installer/manual config entry. Uninstall the v0.1.0 installer, or remove the
hotmail-connectorentry fromclaude_desktop_config.json.npm installtimes out or hangs (dead IPv6 route): force IPv4:NODE_OPTIONS="--dns-result-order=ipv4first --no-network-family-autoselection" npm install.
Development
npm run dev # rebuild on change (tsup --watch)
npm run typecheck # tsc --noEmit
npm run lint # eslint
npm run format # prettier --write (format:check in CI)
npm run check:text # reject raw control characters in tracked files (CI)
npm test # vitest (unit + in-memory + built-subprocess smoke)
npm run test:coverage # the same, failing below the coverage thresholds (CI)
npm run test:live # opt-in: real Graph, your account (after `node dist/index.js login`)
npm run build:mcpb # Claude Desktop extension -> build/hotmail-connector.mcpbLayout (tests are colocated as src/**/*.test.ts):
src/index.ts: CLI and stdio entry (login,logout,whoami; default = server), withsrc/cli.ts(argument parsing).src/mcp.ts: server assembly.src/pdf-worker.ts: the isolated PDF text extractor.src/auth: Microsoft OAuth (PKCE + loopback, on-demand sign-in) and the encrypted token cache (DPAPI-protected key on Windows).src/graph: Graph client (auth, retries, paging) plus the mail, attachments, calendar, free/busy and user modules.src/tools: zod schemas and thin tool handlers.src/send: the browser confirmation page that every email waits on when sending is on.src/util: time zones, HTML-to-text, iCalendar parsing, file retries, logging and the log file, errors.scripts/:build-mcpb.mjs(extension),check-text.mjs,test-live.mjs,register-app.ps1.assets/: the extension icon (SVG source and the PNG the bundle uses).
Requirements, design & roadmap
docs/personal-outlook-mcp-connector-requirements.md: the build spec, v2 (tools, Graph, auth, security, timezone, packaging, decision log). Requirements not yet implemented link to their tracking issues.docs/packaging.md: the Claude Desktop extension (.mcpb): install, upgrade, build.docs/local-hosting-investigation-and-requirements.md: the original local-hosting investigation (superseded by spec v2; kept for the record).CHANGELOG.md: what changed in each release.Roadmap: everything planned is done as of v1.0. The Spec v2 epic (#66) and the follow-up list (#150) are closed, and a remote mode for claude.ai is deferred (#58). Anything new is in the open issues.
Platforms
The maintainer uses and tests the connector on Windows only. The extension also builds for macOS and Linux, and CI runs the tests on Linux, but nothing on those platforms has been tested by hand, and no macOS/Linux-specific work is planned. Known gaps there: the saved sign-in's key isn't protected by the OS keychain (#83), a rare lock-recovery race on macOS (#131), and setup notes for those platforms (#56). If you use macOS or Linux, PRs are very welcome.
Support & contributing
This is a personal, open-source tool, community-supported on a best-effort basis with no SLA and no hosted service. You run your own copy with your own Microsoft app registration. See SUPPORT.md for how to get help, CONTRIBUTING.md before opening a PR, and SECURITY.md for private vulnerability reporting.
License
MIT © 2026 Tony Goodhew
Available Tools
6 toolscreate_eventCreate a calendar eventAIdempotent
Create a calendar event (e.g. a booking, plus separate travel-time blocks). Times are LOCAL wall-clock paired with an IANA time zone (never a UTC 'Z'), so the event lands at the intended local time. A transactionId makes repeated calls idempotent (no duplicates). IMPORTANT: confirm the details (title, date, start/end, timezone, location) with the user BEFORE calling, then echo back the created event.
| Name | Required | Description | Default |
|---|---|---|---|
| end | Yes | Event end (local wall-clock + IANA time zone). | |
| body | No | Plain-text notes/body. | |
| start | Yes | Event start (local wall-clock + IANA time zone). | |
| subject | Yes | Event title. | |
| location | No | Location display name. | |
| isReminderOn | No | Whether a reminder is set. | |
| transactionId | No | Idempotency key; if omitted one is generated so retries don't duplicate. | |
| reminderMinutesBeforeStart | No | Reminder lead time in minutes. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations (readOnlyHint=false, idempotentHint=true, etc.), the description adds key behavioral traits: time zone handling (local wall-clock, never UTC), idempotency via transactionId, and system-side default time zone. 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 concise, front-loaded with purpose, and contains only essential information. Every sentence adds value, and important notes are flagged with 'IMPORTANT'.
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 (8 params, nested objects, no output schema), the description covers idempotency, time zone details, confirmation step, and return behavior indirectly (echo back the created event). It is complete enough for correct invocation, though explicit return structure would push it to 5.
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 highlighting the time zone nuance (local wall-clock, never UTC Z) and idempotency key, which go beyond the schema descriptions. This justifies a 4.
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 ('Create a calendar event') and includes an example ('e.g. a booking, plus separate travel-time blocks'), clearly distinguishing it from siblings like list_events and update_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 advises confirming details with the user before calling and echoing back the created event, providing clear usage context. It does not explicitly mention when not to use or list alternatives, but the guidance is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_messageRead an emailARead-only
Read a single email message by id, returning subject, sender, receivedDateTime, webLink, the body (HTML converted to plain text by default), and attachment metadata (names/sizes only — no file contents). Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The message id (from list_messages). | |
| format | No | Body format. 'text' converts HTML to plain text (default, token-efficient). | text |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses that the body is HTML converted to plain text by default, that attachment metadata excludes file contents, and that it is read-only. Annotations already mark readOnlyHint=true, so the description adds valuable detail beyond what annotations provide. 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 a single, well-structured sentence that clearly states the tool's purpose and key behaviors without extraneous words. Information about attachments is appended concisely. 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 read tool with two parameters and no output schema, the description covers the input requirement, the parameter options, the return fields, and important limitations (no file contents). It is complete given the tool's simplicity and the presence of annotations.
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?
Both parameters are fully described in the input schema (100% coverage). The description mentions 'by id' and the format parameter's default, but does not add significant meaning beyond the schema's descriptions. 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 ('Read a single email message by id'), specifies the return fields (subject, sender, etc.), and distinguishes from sibling tools like list_messages which does not return the full body. The verb 'Read' and resource 'email message' are 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 implies when to use this tool (when you need full details of one message) and provides context through the 'format' parameter hint. However, it does not explicitly state when not to use it or mention alternatives like list_messages for overviews, though the sibling context makes this clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_eventsList calendar eventsARead-only
List calendar events in a date range (e.g. to check for conflicts before adding a booking). Times are returned in the requested IANA time zone. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max events to return (1-100). | |
| timeZone | No | IANA time zone for the returned times (defaults to the server's DEFAULT_TIMEZONE). | |
| endDateTime | Yes | Range end, ISO 8601. | |
| startDateTime | Yes | Range start, ISO 8601. Include a timezone offset/Z to pin it precisely. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint and openWorldHint. The description adds the behavioral detail that times are returned in the requested IANA time zone, which is not in annotations. 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?
Two sentences, no wasted words. Front-loads the main purpose and use case, then adds time zone and read-only behavior. Highly concise.
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 no output schema and rich annotations, the description covers the core operation, example use, and time zone handling. It does not repeat pagination details (already in schema), which is acceptable. The tool is adequately described.
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 description adds minimal new meaning. It reinforces the timeZone parameter and links start/end to conflict checking, but does not extend beyond schema documentation. 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 verb 'list' and resource 'calendar events', and provides an example use case ('check for conflicts before adding a booking'). It is distinct from sibling tools like create_event, update_event, and get_message due to the list and read-only nature.
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 a specific context for use (checking conflicts before a booking) and declares the tool as read-only. While it does not explicitly state when not to use or mention alternatives, the purpose is clear enough for an agent to decide.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_messagesList / search emailARead-only
Search or list email messages (e.g. to find booking or confirmation emails). Read-only. Returns id, subject, sender, receivedDateTime, webLink, a body preview, and hasAttachments, plus a nextPageToken when more results exist. Use get_message to read a full message body.
| Name | Required | Description | Default |
|---|---|---|---|
| from | No | Sender email address to match. | |
| limit | No | Max results (1-25, default 10). | |
| query | No | Free-text keyword search (maps to Graph $search, KQL-style). | |
| pageToken | No | Opaque token from a previous call's nextPageToken. | |
| receivedAfter | No | Only messages received on/after this ISO 8601 date/time. | |
| receivedBefore | No | Only messages received on/before this ISO 8601 date/time. | |
| subjectContains | No | Text the subject should contain. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint. The description adds value by listing returned fields (subject, sender, etc.) and pagination behavior, going beyond 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?
Two concise sentences with no wasted words. Front-loaded with purpose and key info, followed by actionable advice.
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 no output schema, the description adequately covers return fields and pagination. It addresses the key aspects for a list tool with 7 parameters.
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 fully documents parameters. The description does not add parameter-level detail beyond the schema, earning 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 it searches or lists email messages, provides concrete examples (booking/confirmation emails), and distinguishes from the sibling get_message 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?
It explains when to use the tool (find emails) and advises using get_message for full body reads. While not exhaustive, it provides clear guidance relative to siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_eventUpdate a calendar eventADestructiveIdempotent
Update an existing calendar event's time, location, subject, or body. Only the fields you provide are changed. Times use LOCAL wall-clock + IANA time zone. Confirm changes with the user before calling.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The event id to update (from list_events). | |
| end | No | New end (local wall-clock + IANA time zone). | |
| body | No | New plain-text body. | |
| start | No | New start (local wall-clock + IANA time zone). | |
| subject | No | New title. | |
| location | No | New location display name. | |
| isReminderOn | No | ||
| reminderMinutesBeforeStart | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations provide idempotentHint and destructiveHint. The description adds partial-update behavior ('Only the fields you provide are changed.') and clarifies time format (local wall-clock + IANA time zone), which goes beyond annotations. 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?
Three concise sentences each serving a distinct purpose: purpose, partial update, time format, and usage instruction. No redundancy, front-loaded with the most critical information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 8 parameters, nested objects, destructive action, and no output schema, the description covers core functionality, partial update, time handling, and user confirmation. Missing return value description, which would be helpful since no output schema exists.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 75%, with detailed descriptions for most parameters. The description adds value by summarizing the partial-update nature and time zone handling, complementing the schema without repeating it. Not all params are mentioned, but the schema covers them.
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 'Update' and specifies the resource 'an existing calendar event' and some fields (time, location, subject, body). It distinguishes from list/read tools but does not explicitly differentiate from create_event (e.g., by stating not for creation).
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 for modifying existing events and provides a direct instruction to 'Confirm changes with the user before calling.' However, it does not mention when not to use this tool or name alternatives like create_event for new events.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
whoamiShow the connected accountARead-only
Return the signed-in Microsoft account's display name and email address. Useful to confirm the correct personal account is connected. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint. Description adds 'Read-only' which is consistent but does not add new behavioral context 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 concise sentences, front-loaded with purpose, no unnecessary words.
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?
Tool has no parameters and no output schema, but description explains return values (display name, email) and usage context. Annotations provide safety info, so description is 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?
No parameters (0 params), baseline 4. Description does not need to add parameter info since schema is empty.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb 'return' and resource 'signed-in account's display name and email' clearly state the tool's function. Distinguishes from sibling tools which are about events and 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?
States it is useful to confirm correct account connected, providing context for when to use. No explicit exclusions or alternatives given, but siblings are distinct.
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.
6 tool updates
v0.1.0- First observed
create_event - First observed
get_message - First observed
list_events - First observed
list_messages - First observed
update_event - First observed
whoami
TDQS
Scored across 6 tools
Each tool targets a distinct resource (events, messages, or user) with clearly separate actions, leaving no ambiguity for an agent selecting between them.
All tools follow a consistent verb_noun pattern in snake_case (e.g., list_events, create_event), making the purpose predictable from the name.
With 6 tools covering calendar and email operations, the set is well-scoped for a personal assistant connector—neither too few nor too many.
The tool set covers core read and create operations for events and messages, but lacks delete capabilities for events or send/reply for emails, leaving minor gaps.
Maintenance
Related MCP Connectors
Connect any mailbox to Claude, ChatGPT & AI: read, send, reply, schedule & search emails.
Connect Apple iCloud and Microsoft 365 mail, calendars, contacts and tasks to AI.
Multiple Google accounts (Gmail, Calendar, Drive, Contacts, Tasks) in one Claude connector.
Multiple Google accounts (Gmail, Calendar, Drive, Contacts, Tasks) in one Claude connector.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceConnects Claude with Microsoft Outlook through the Graph API, providing comprehensive email, calendar, folder management, and rules creation capabilities.19MIT
- AlicenseNot gradedqualityCmaintenanceConnects Claude to Microsoft Outlook through the Microsoft Graph API, enabling email management (list, search, read, send) and calendar operations (list, create, accept, decline, delete events) via OAuth 2.0 authentication.1MIT
- FlicenseNot gradedqualityDmaintenanceProvides Claude Desktop and Claude Code with access to Microsoft 365 email and calendar services via the Microsoft Graph API. It enables users to manage emails, search folders, schedule calendar events, and check availability through natural language commands.-
- AlicenseNot gradedqualityBmaintenanceConnects Claude with Microsoft 365 services such as Email, Calendar, Teams, OneDrive, and more through the Microsoft Graph API.45 npm17MIT