pim-mcp
Connects to Google Calendar through the CalDAV API with OAuth (desktop client + stored refresh token), merging its calendars into the shared view for listing, searching, free-time finding, and event creation, update and deletion.
Connects to iCloud calendars over CalDAV using an Apple app-specific password, exposing them for merged event listing and search, free-time finding, and creating, updating or deleting events (with recurring-event scope handling).
Connects to a Nextcloud server over CalDAV (app-password auth), exposing its calendars for merged event listing and search, event details, free/busy time finding, and creating, updating or deleting events.
Connects to an ownCloud server over CalDAV alongside Nextcloud, making its calendars available for merged listing, search, free-time lookup and event creation, update and deletion.
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., "@pim-mcpFind me an hour Thursday afternoon and book the dentist"
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.
One thin, local MCP server for all your calendars. Nextcloud · iCloud · Google · any CalDAV, merged into a single view your agent can read and manage.
Quick start · Accounts · Connect · Tools · Guardrails · Providers · Contributing
you › Find me an hour on Thursday afternoon and put the dentist there.
agent › find_free_time start=Thu 12:00 end=Thu 18:00 duration_minutes=60
↳ 13:00–15:30 · 16:15–18:00
› create_event calendar="icloud/personal" title="Dentist" start=Thu 13:00
↳ ✓ created Thu 13:00–14:00 · icloud/personal
Done. Thursday 13:00 is booked; you're free again from 14:00.✨ Why
🗂️ One merged view Every calendar on every account in one sorted list, with recurring events expanded. No more "which account was that in?"
🧳 Portable One TOML file with no secrets in it. Secrets are references to your OS secret store, env vars or a password manager, so the same config works on every machine.
🪶 Thin and local Your agent client starts it over stdio when needed. Nothing runs in the background, there's no port open, and no cloud sits in between.
🛡️ Safe by default Deleting events and anything that emails other people stay off until you allow them. Edits never overwrite changes made elsewhere.
Related MCP server: Radicale CalDAV MCP Server
🧭 How it works
flowchart LR
A["🤖 Agent<br><sub>Claude Code · Claude Desktop · Cursor</sub>"] -- "MCP · stdio" --> P["<b>pim-mcp</b><br><sub>on your machine</sub>"]
S[("🔐 OS secret store<br><sub>Keychain · Secret Service · DPAPI</sub>")] -. "app passwords / tokens" .-> P
P -- CalDAV --> N["☁️ Nextcloud"]
P -- CalDAV --> I["🍎 iCloud"]
P -- "CalDAV + OAuth" --> G["📅 Google"]
P -- CalDAV --> O["🌐 any CalDAV"]🚀 Quick start
Requires Node.js 22+.
npm install -g pim-mcp # 1 · install (or prefix commands with `npx -y`)
pim-mcp init # 2 · write ~/.config/pim-mcp/config.toml
pim-mcp secret set pim-mcp/icloud # 3 · store an app password (prompted, not echoed)
pim-mcp check # 4 · verify every account
claude mcp add pim -s user -- npx -y pim-mcp # 5 · connect your agentpim-mcp check lists what it found:
✓ nextcloud (nextcloud) — 3 calendar(s)
nextcloud/personal Personal
nextcloud/work Work
✓ icloud (icloud) — 2 calendar(s)
icloud/family Family
icloud/travel TravelThe config lives at ~/.config/pim-mcp/config.toml on every OS (C:\Users\<you>\.config\pim-mcp\config.toml on Windows). Set PIM_MCP_CONFIG to use another path.
🔐 Secrets
Passwords and tokens never go in the config. It holds a reference instead:
Reference | Resolves to |
| your OS secret store. Easiest: |
| an environment variable |
| a command's output, e.g. |
Stored as generic passwords in your login Keychain. You can also manage them in Keychain Access, or with security add-generic-password -s pim-mcp -a icloud -w.
Needs secret-tool:
sudo apt install libsecret-tools # Debian / Ubuntu
sudo dnf install libsecret # Fedora
sudo pacman -S libsecret # ArchOn a headless machine there's usually no keyring running. Use env: refs (set them in your MCP client's env block) or pass:
password = "cmd:pass show pim-mcp/icloud"Secrets are encrypted with DPAPI, the per-user encryption Credential Manager also uses. They're stored under %APPDATA%\pim-mcp\secrets\, and only your Windows user on this machine can decrypt them. Nothing to install. cmd: refs run in cmd.exe.
👤 Accounts
Nextcloud → Settings → Security → Devices & sessions → Create new app password
pim-mcp secret set pim-mcp/nextcloud
[[accounts]]
id = "nextcloud"
provider = "nextcloud"
url = "https://your.next.cloud/remote.php/dav"
username = "your-login"
password = "keychain:pim-mcp/nextcloud"account.apple.com → Sign-In and Security → App-Specific Passwords
pim-mcp secret set pim-mcp/icloud
[[accounts]]
id = "icloud"
provider = "icloud"
username = "you@icloud.com" # the email you sign into your Apple Account with
password = "keychain:pim-mcp/icloud"Google only allows OAuth for CalDAV:
Google Cloud Console: create a project and enable the CalDAV API.
OAuth consent screen: choose External and add yourself as a test user. Then set the publishing status to In production, because tokens issued in "Testing" mode expire after 7 days. An "unverified app" warning at sign-in is expected for a personal app.
Credentials → Create OAuth client ID → Desktop app. Put the client ID in the config and store the secret:
pim-mcp secret set pim-mcp/google-client-secretpim-mcp auth google --account googleopens your browser and stores the refresh token in your OS secret store.
[[accounts]]
id = "google"
provider = "google"
username = "you@gmail.com"
client_id = "xxxx.apps.googleusercontent.com"
client_secret = "keychain:pim-mcp/google-client-secret"
refresh_token = "keychain:pim-mcp/google"[[accounts]]
id = "fastmail"
provider = "caldav"
url = "https://caldav.fastmail.com/"
username = "you@fastmail.com"
password = "keychain:pim-mcp/fastmail"Known URLs are in Providers.
🔌 Connect your agent
Claude Code (any OS)
claude mcp add pim -s user -- npx -y pim-mcpClaude Desktop, Cursor and other GUI clients. Add this to the client's MCP config:
{
"mcpServers": {
"pim": { "command": "npx", "args": ["-y", "pim-mcp"] }
}
}GUI apps don't always see your shell's PATH. If the server fails to start, replace npx with the full path from which npx, e.g. /opt/homebrew/bin/npx.
{
"mcpServers": {
"pim": { "command": "cmd", "args": ["/c", "npx", "-y", "pim-mcp"] }
}
}npx is a batch script on Windows, so it runs through cmd /c.
Claude Desktop isn't available for Linux; use Claude Code or another MCP client with the same command / args as macOS. env: refs go in the client's env block:
"pim": {
"command": "npx",
"args": ["-y", "pim-mcp"],
"env": { "ICLOUD_PASSWORD": "…" }
}🧰 Tools
Tool | What it does | |
📚 |
| All calendars and their ids ( |
🗓️ |
| Events from all calendars in a range, merged and sorted. Defaults to today through the next 7 days. |
🔎 |
| Text search over title, location and description. |
📄 |
| Full details: description, attendees, organizer, recurrence rule. |
🕐 |
| Free windows of at least N minutes, optionally within working hours. |
➕ |
| Timed or all-day, with recurrence, a reminder, and busy/free status. |
✏️ |
| Changes only the fields you pass. Recurring events take |
🗑️ |
| Off unless |
What agents see:
Times without an offset are in your configured
timezone.Output is ISO 8601 with offsets.
All-day events use
YYYY-MM-DD, and their end date is inclusive.
🛡️ Guardrails
timezone = "Europe/Amsterdam" # default: the system timezone
[guardrails]
allow_delete = false # delete_event is refused
allow_invites = false # no adding attendees, no editing/deleting events that have them
[[accounts]]
# …
read_only = true # no writes to this account at all
read_only_calendars = ["Family"] # protect specific calendars
hide_calendars = ["Birthdays"] # don't show these at allRefusals explain themselves. When a guardrail blocks something, the agent is told which setting would allow it, so it asks you instead of retrying.
No lost edits. Every write checks the event's ETag. If the event changed elsewhere since it was read, the write fails instead of overwriting.
🌍 Providers
Provider | Status | Setup |
Nextcloud / ownCloud | ✅ tested |
|
iCloud | ✅ tested |
|
Google Calendar | 🧪 beta |
|
Fastmail | 🟡 untested |
|
Yahoo | 🟡 untested |
|
mailbox.org | 🟡 untested |
|
Posteo | 🟡 untested |
|
Radicale · Baïkal · SOGo · Synology | 🟡 untested |
|
Outlook · Microsoft 365 · Exchange | 🚧 wanted | no CalDAV; needs a Microsoft Graph backend |
Proton Calendar | ❌ n/a | no CalDAV or public API |
🟡 untested means standard CalDAV that should just work but hasn't been confirmed with pim-mcp yet. Tried one? A PR updating this table is very welcome.
🗺️ Roadmap
Calendars over CalDAV: Nextcloud, iCloud, Google, generic
macOS · Linux · Windows secret stores
Outlook / Microsoft 365 via Microsoft Graph
Mail: IMAP / SMTP, same accounts and config
Files: WebDAV (Nextcloud, …)
🤝 Contributing
New providers, bug fixes and "it works with X" confirmations are all welcome. See CONTRIBUTING.md for dev setup, a throwaway local CalDAV server for testing, and how to add a provider.
Available Tools
8 toolscreate_eventA
Create an event. start as a date makes an all-day event. Without end, timed events last 1 hour and all-day events 1 day.
| Name | Required | Description | Default |
|---|---|---|---|
| end | No | YYYY-MM-DD for all-day, or YYYY-MM-DDTHH:MM (local to the configured timezone unless it has Z/±HH:MM). For all-day events the end date is inclusive. | |
| busy | No | Whether the event blocks time (default: true for timed, false for all-day). | |
| rrule | No | iCalendar RRULE, e.g. "FREQ=WEEKLY;BYDAY=MO,WE;COUNT=10". null removes recurrence. | |
| start | Yes | YYYY-MM-DD for all-day, or YYYY-MM-DDTHH:MM (local to the configured timezone unless it has Z/±HH:MM) | |
| title | Yes | ||
| calendar | Yes | Calendar id (from list_calendars) or exact name. | |
| location | No | ||
| attendees | No | Email addresses. The server may email invitations. | |
| description | No | ||
| alarm_minutes | No | Reminder N minutes before start; null removes reminders. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does disclose important behavioral rules: a bare date on `start` creates an all-day event, and omitted `end` yields a 1-hour timed event or 1-day all-day event. It omits other side effects such as whether invitations are sent or whether recurrence changes propagate, so it falls short of full disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the action, then the two highest-value edge-case rules. 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 10-parameter mutation tool with no annotations and no output schema, the description covers the two behaviors most likely to cause a wrong call (all-day inference and implicit duration). The remaining parameters are well documented in the schema, so the gap is small but present — side effects like invitation emails and recurrence interaction are not addressed.
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 70%, and the description adds meaning the schema does not: the type of `start` changes the event kind, and the default duration depends on that kind. It says nothing about `busy`, `rrule`, `attendees`, or `alarm_minutes` beyond 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 opening 'Create an event' states a specific verb and resource, and the following sentences clarify the scope of the operation via date-type semantics. It is clearly distinguishable from siblings like update_event and delete_event by verb alone, though it never names them.
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?
There is no explicit when-to-use / when-not-to-use statement and no reference to alternatives such as update_event for modifying an existing event. Usage is implied by the verb 'create' and the defaults it describes.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_eventADestructive
Delete an event. For recurring events pass scope ("instance" removes one occurrence, "series" removes all).
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| scope | No | Required for recurring events: "instance" = only this occurrence, "series" = every occurrence. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With destructiveHint=true already declaring the mutation, the description adds the most important missing detail: the blast radius, i.e. that "series" removes every occurrence while "instance" removes only one. What it does not disclose is irreversibility/undo, or what happens when `scope` is omitted on a recurring event — a real ambiguity since scope is not in the required list.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with zero filler; the destructive action is stated first and the conditional scope rule follows immediately. Every clause carries information the agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive two-parameter tool with no output schema, the definition covers the recurring-event case but leaves gaps: what `id` refers to, whether deletion is permanent, and the default behavior when `scope` is omitted for a recurring event (the schema does not mark it required, creating a contradiction with "for recurring events pass scope").
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 50%: `scope` is fully documented in the schema and the description largely restates it (instance = one occurrence, series = all), which is mildly helpful but not additive. The `id` parameter has no schema description and is never mentioned in the description, so the agent must infer what identifier is expected (event ID vs. calendar+event pair).
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 ("Delete an event"), which cleanly separates it from the create_event/update_event siblings. It stops short of explicitly contrasting itself with those siblings, but the destructive verb makes the intent 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?
It gives one conditional usage rule — pass `scope` for recurring events — but that is parameter guidance rather than when-to-use-this-tool guidance. There is no statement about when deletion is appropriate versus updating, nor any preconditions such as required permissions or ownership.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_free_timeARead-only
Free time windows of at least duration_minutes across all (or selected) calendars. Events marked free/transparent and cancelled events do not block time.
| Name | Required | Description | Default |
|---|---|---|---|
| end | Yes | YYYY-MM-DD for all-day, or YYYY-MM-DDTHH:MM (local to the configured timezone unless it has Z/±HH:MM). A date-only end includes that whole day. | |
| start | Yes | YYYY-MM-DD for all-day, or YYYY-MM-DDTHH:MM (local to the configured timezone unless it has Z/±HH:MM) | |
| accounts | No | ||
| calendars | No | ||
| working_hours | No | Only return time inside these hours. | |
| duration_minutes | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
readOnlyHint already tells the agent this is a safe read, and the description adds real behavioral content beyond that: free/transparent events and cancelled events do not block time. Still silent on whether free windows are split per day, whether working_hours defaults apply, and timezone resolution beyond what the schema says.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero filler, with the core capability front-loaded and the blocking rule immediately after. Nothing could be cut without losing 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?
For a read-only availability query with well-documented date inputs, the definition covers purpose, the key constraint, and the blocking semantics. No output schema exists, but the natural return (windows of >= duration_minutes) is self-evident from the description. Minor gaps around per-day splitting don't make it incomplete for a 6-param query 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?
At 50% schema coverage, the description must compensate. It explains duration_minutes (minimum window length) and hints at calendars ('all (or selected)'), but the 'accounts' parameter and 'working_hours' object are untouched by the description, leaving two parameters documented only thinly or not at all.
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 ('Free time windows ... across all (or selected) calendars') with a quantified constraint. Among siblings, which are all event CRUD/listing tools, this is unmistakably the availability-computation tool, so no confusion is possible without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The parenthetical '(or selected) calendars' and the mention of duration_minutes imply the intended scenario (find a slot of a given length), but there is no explicit when-to-use, no prerequisite statement (e.g. calendars must be connected), and no comparison to list_events/search_events.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_eventBRead-only
Full details of one event (description, attendees, organizer, recurrence rule).
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
readOnlyHint=true already tells the agent this is a safe read, so the description's job is reduced. It usefully discloses the shape of the payload (description, attendees, organizer, recurrence rule) in the absence of an output schema, but says nothing about behavior when the id is unknown or about permissions/visibility limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence that leads with the retrieval scope and then enumerates the payload; every clause earns its place and nothing is padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read tool with annotation coverage and no output schema, the description adequately conveys both purpose and return fields. The only real omission is the meaning/format of 'id' and any error or visibility caveat.
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 0% and the sole 'id' parameter is undocumented in both schema and description; it is not stated whether this is an event id, a recurring-instance id, or a calendar-scoped id. Since only one self-evidently named parameter exists, this is a modest gap rather than a severe one.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb and resource ('Full details of one event') and enumerates what detail is returned (description, attendees, organizer, recurrence rule), which distinguishes it from list_events and search_events. It stops short of naming those siblings explicitly, so 4 rather than 5.
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?
There is no statement of when to use this tool over search_events or list_events, and no prerequisites (e.g., that the id must come from a prior list/search call). An agent must infer the usage pattern from the single required 'id' parameter.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_calendarsARead-only
List every calendar across all configured accounts (Nextcloud, iCloud, Google, …), with ids usable in other tools.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the safety profile is covered. The description adds real value by disclosing the multi-account aggregation scope (Nextcloud, iCloud, Google, …) — something the annotations do not say. It does not address what happens if a backend account is unreachable or credentials are missing, which matters for an aggregating 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?
One sentence, front-loaded with the verb and resource, with the cross-account scope and the downstream-use hint packed in without waste.
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?
There is no output schema, and the description compensates by stating the key return property — calendar ids usable in other tools. It stops short of saying what other fields (name, color, provider) come back, which would fully close the gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4. The description correctly signals that no arguments are needed to scope the listing.
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 (List) and resource (every calendar) and adds the scope 'across all configured accounts', with provider examples. The resource noun 'calendar' vs. the sibling tools' 'events' makes the distinction immediately obvious.
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 phrase 'with ids usable in other tools' implies the intended workflow: call this first to obtain calendar ids for the event tools. It gives clear context but names no explicit alternatives or when-not conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_eventsARead-only
Events in a time range, merged across all calendars and sorted by start. Recurring events are expanded into occurrences. Defaults to today through the next 7 days.
| Name | Required | Description | Default |
|---|---|---|---|
| end | No | YYYY-MM-DD for all-day, or YYYY-MM-DDTHH:MM (local to the configured timezone unless it has Z/±HH:MM). A date-only end includes that whole day. | |
| start | No | YYYY-MM-DD for all-day, or YYYY-MM-DDTHH:MM (local to the configured timezone unless it has Z/±HH:MM) | |
| accounts | No | Account ids to limit to (default: all). | |
| calendars | No | Calendar ids or names to limit to (default: all). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the safety profile is covered; the description adds genuinely non-obvious behavior: results are merged across all calendars, sorted by start, and recurring events are expanded into occurrences. It stops short of describing pagination, result limits, or return shape.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the core scope and behavior, and each sentence contributes distinct information (scope, recurrence expansion, defaults). 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?
A read-only list tool with full schema coverage and a clear behavioral summary; there is no output schema, and the description doesn't explain result shape or limits, but nothing critical to forming a correct call 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 all four parameters (start, end, accounts, calendars) are already documented with formats and defaults. The description only reinforces the default time window and adds nothing about the accounts/calendars filters, 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 resource (events) and scope (time range, merged across all calendars, sorted by start) plus the recurrence-expansion behavior, so an agent knows exactly what it gets back. It does not explicitly contrast itself with the sibling search_events, so it falls short of a 5.
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 stated default window (today through the next 7 days) implies when this is the convenient call, but there is no explicit when-to-use/when-not guidance and no pointer to search_events or find_free_time as alternatives. Usage must be inferred from the sibling names.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_eventsARead-only
Find events whose title, location or description contains the query (case-insensitive). Defaults to 90 days back through 365 days ahead.
| Name | Required | Description | Default |
|---|---|---|---|
| end | No | YYYY-MM-DD for all-day, or YYYY-MM-DDTHH:MM (local to the configured timezone unless it has Z/±HH:MM) | |
| query | Yes | ||
| start | No | YYYY-MM-DD for all-day, or YYYY-MM-DDTHH:MM (local to the configured timezone unless it has Z/±HH:MM) | |
| calendars | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the safety profile is covered. The description adds valuable behavior beyond annotations: case-insensitive matching across specific fields and a default date window. It omits result limits/pagination and how the calendars filter interacts with the search.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with no filler; the search scope is front-loaded and the default range follows immediately.
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 search tool with no output schema, the description gives the essentials: matching semantics and default time bounds. It could be more complete by explaining the calendars filter and any result-size limits, but nothing critical to invocation 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 50%: start/end are documented, while query and calendars are not. The description compensates well for the central query parameter by explaining which fields are searched and case-insensitivity, and it clarifies the default time range tied to start/end. The calendars array remains unexplained.
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 ('Find events') and specifies the matching fields (title, location, description) and case-insensitivity. This clearly distinguishes text search from list_events and 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?
Provides clear context for use via the query-based search and the default time window (90 days back to 365 days ahead). It does not explicitly name alternatives such as list_events or state when not to use it, but the purpose implies the right usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_eventA
Change an event. Only the fields you pass change; moving start alone keeps the duration. For recurring events pass scope.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| end | No | YYYY-MM-DD for all-day, or YYYY-MM-DDTHH:MM (local to the configured timezone unless it has Z/±HH:MM). For all-day events the end date is inclusive. | |
| busy | No | Whether the event blocks time (default: true for timed, false for all-day). | |
| rrule | No | iCalendar RRULE, e.g. "FREQ=WEEKLY;BYDAY=MO,WE;COUNT=10". null removes recurrence. | |
| scope | No | Required for recurring events: "instance" = only this occurrence, "series" = every occurrence. | |
| start | No | YYYY-MM-DD for all-day, or YYYY-MM-DDTHH:MM (local to the configured timezone unless it has Z/±HH:MM) | |
| title | No | ||
| location | No | ||
| attendees | No | Email addresses. The server may email invitations. | |
| description | No | ||
| alarm_minutes | No | Reminder N minutes before start; null removes reminders. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does deliver genuinely non-obvious behavior: partial updates, and that moving `start` alone preserves duration rather than shifting the whole event. It omits permissions/error behavior and, more importantly, does not warn that `scope: series` mutates every occurrence of a recurring event — a destructive consequence the agent should know about.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the core action, then the two constraints that matter most. No filler and nothing repeated from the schema.
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 an 11-parameter mutation tool with no annotations and no output schema, the description covers the two areas most likely to cause wrong calls: duration drift and recurrence scoping. Gaps remain around `id` validity, failure modes, and the blast radius of series updates, preventing a 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 64%, and the description reinforces the two trickiest parameters: `start` (duration preserved when moved alone) and `scope` (required for recurring events). However, the only required parameter `id` is undocumented in both schema and description, and it doesn't clarify edge cases like whether changing `rrule` on a recurring event requires a particular scope.
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?
"Change an event" is a specific verb plus resource, and the partial-update framing distinguishes it in practice from create_event and delete_event. It never names a sibling explicitly, so differentiation is implied rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Clear operating context: patch semantics ("only the fields you pass change") tells the agent to use this rather than delete-and-recreate, and "For recurring events pass `scope`" is a concrete conditional instruction. It stops short of stating exclusions or naming alternatives such as create_event/delete_event for the cases this tool shouldn't handle.
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.
8 tool updates
v0.1.0- First observed
create_event - First observed
delete_event - First observed
find_free_time - First observed
get_event - First observed
list_calendars - First observed
list_events - First observed
search_events - First observed
update_event
TDQS
Scored across 8 tools
Each tool maps to a distinct retrieval or mutation strategy: list_events filters by time range, search_events filters by text query, and get_event fetches a single event by id. find_free_time and the create/update/delete trio are unmistakable. No two tools overlap in a way that would cause misselection.
All eight tools follow the same snake_case verb_noun pattern (list_, search_, get_, find_, create_, update_, delete_). The verb choice matches the operation type consistently, and the resource noun is always the trailing token.
Eight tools is well within the healthy 3-15 range and every tool earns its place: discovery, three read modes, availability lookup, and full mutation coverage. Nothing feels padded or redundant.
Event lifecycle is fully covered (list/search/get/create/update/delete) with sensible recurrence scope and availability handling. Minor gaps remain around attendee interactions — no RSVP/accept-decline tool and calendars themselves can only be listed, not created or modified.
Maintenance
Related MCP Connectors
Calendar API for AI agents: events, availability, Google/Microsoft setup, scheduling, and iCal.
Sync Google, Outlook, and iCloud calendars and manage events, availability, and booking links.
Manage Google, Outlook & Apple calendars and create private sync rules from chat.
Scheduling infrastructure for AI agents across Google and Microsoft calendars.
Related MCP Servers
- FlicenseNot gradedqualityFmaintenanceEnables interaction with any CalDAV-compatible calendar server (Yandex, Google, Nextcloud, iCloud, etc.) to list calendars, create/manage events with reminders and attendees, search events, and handle recurring events through natural language.15-
- FlicenseNot gradedqualityCmaintenanceEnables LLM agents to read, schedule, update, and delete calendar events and tasks on a self-hosted CalDAV server, and to query availability for free/busy slots.-
- AlicenseNot gradedqualityAmaintenanceEnables AI assistants to connect to calendar servers and manage events and tasks, including listing calendars, querying timeframes, creating, updating, completing, and deleting items through tools.3,018 npmMIT
- AlicenseNot gradedqualityAmaintenanceEnables AI assistants to connect to CalDAV servers and manage calendars, events, and tasks through tools for listing, creating, updating, completing, and deleting items.3,018 npmMIT