Pim Mcp

io.github.da-the-devPublished by GitHub account da-the-devv0.2.0Updated Nov 6, 2026

Local MCP server for your calendars across Nextcloud, iCloud, Google and any CalDAV server.

Overview

AI-generated overview

Local MCP server that merges Nextcloud, iCloud, Google and other CalDAV calendars so an assistant can read, search, create, edit and delete events.

What you can do
  • List calendars and events across all configured accounts, merged and sorted, with recurring events expanded
  • Search events by title, location or description and read full details of a single event
  • Find free time windows of a given length across all or selected calendars
  • Create and update timed or all-day events, including recurrence, reminders and busy/free status
  • Delete events, with a title check and per-account or per-calendar guardrails
When to use it
Useful when you keep calendars on several CalDAV accounts and want an assistant to answer scheduling questions, find open slots and book or move appointments from one merged view. It fits users who prefer a thin local process with no cloud in between over a hosted calendar service.
Requirements
Node.js 22 or later, run locally over stdio via npx or a global install. A TOML config file at ~/.config/pim-mcp/config.toml (override with PIM_MCP_CONFIG) listing accounts. Credentials are app passwords or OAuth tokens referenced from the OS secret store, an environment variable or a command; Google needs a one-time OAuth client setup. Network access to each CalDAV server.
Before you install
It holds credentials for your calendar accounts: passwords and tokens are stored as references to the OS keychain, env vars or a password manager, so protect those stores and the config file. Writes change real calendars; deletion and anything that emails attendees are off by default and must be enabled in the guardrails settings. Google support is beta and several listed providers are untested. Outlook, Microsoft 365 and Exchange are not supported.

Installation

In SourceWeft

  1. Open Pim Mcp in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Other MCP clients

Follow the launch instructions in the repository.

README

[pim-mcp: your calendars, in every agent]

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.


[npm] [CI] [MCP Registry] [Node] [Platforms] [License: MIT]

Quick start · Accounts · Connect · Tools · Guardrails · Providers · Contributing


text
 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.

🧭 How it works

mermaid
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+.

sh
npm install -g pim-mcp                         # 1 · install (or prefix commands with `npx -y`)pim-mcp init                                   # 2 · write ~/.config/pim-mcp/config.tomlpim-mcp secret set pim-mcp/icloud              # 3 · store an app password (prompted, not echoed)pim-mcp check                                  # 4 · verify every accountclaude mcp add pim -s user -- npx -y pim-mcp   # 5 · connect your agent

pim-mcp check lists what it found:

text
✓ nextcloud (nextcloud) — 3 calendar(s)    nextcloud/personal               Personal    nextcloud/work                   Work✓ icloud (icloud) — 2 calendar(s)    icloud/family                    Family    icloud/travel                    Travel

The 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:

ReferenceResolves to
keychain:service/accountyour OS secret store. Easiest: pim-mcp secret set service/account
env:NAMEan environment variable
cmd:<command>a command's output, e.g. cmd:op read op://Private/iCloud/password, cmd:pass show icloud, cmd:bw get password icloud
🍎 macOS: login Keychain

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.

🐧 Linux: Secret Service (GNOME Keyring / KWallet)

Needs secret-tool:

sh
sudo apt install libsecret-tools     # Debian / Ubuntusudo dnf install libsecret           # Fedorasudo pacman -S libsecret             # Arch

On a headless machine there's usually no keyring running. Use env: refs (set them in your MCP client's env block) or pass:

toml
password = "cmd:pass show pim-mcp/icloud"
🪟 Windows: DPAPI

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 (any Nextcloud / ownCloud server)
  1. Nextcloud → Settings → Security → Devices & sessions → Create new app password
  2. pim-mcp secret set pim-mcp/nextcloud
toml
[[accounts]]id = "nextcloud"provider = "nextcloud"url = "https://your.next.cloud/remote.php/dav"username = "your-login"password = "keychain:pim-mcp/nextcloud"
🍎 iCloud
  1. account.apple.com → Sign-In and Security → App-Specific Passwords
  2. pim-mcp secret set pim-mcp/icloud
toml
[[accounts]]id = "icloud"provider = "icloud"username = "[email protected]"   # the email you sign into your Apple Account withpassword = "keychain:pim-mcp/icloud"
📅 Google (one-time OAuth setup)

Google only allows OAuth for CalDAV:

  1. Google Cloud Console: create a project and enable the CalDAV API.
  2. 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.
  3. 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-secret
  4. pim-mcp auth google --account google opens your browser and stores the refresh token in your OS secret store.
toml
[[accounts]]id = "google"provider = "google"username = "[email protected]"client_id = "xxxx.apps.googleusercontent.com"client_secret = "keychain:pim-mcp/google-client-secret"refresh_token = "keychain:pim-mcp/google"
🌐 Any other CalDAV server
toml
[[accounts]]id = "fastmail"provider = "caldav"url = "https://caldav.fastmail.com/"username = "[email protected]"password = "keychain:pim-mcp/fastmail"

Known URLs are in Providers.

🔌 Connect your agent

Claude Code (any OS)

sh
claude mcp add pim -s user -- npx -y pim-mcp

Claude Desktop, Cursor and other GUI clients. Add this to the client's MCP config:

🍎 macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
json
{  "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.

🪟 Windows: %APPDATA%\Claude\claude_desktop_config.json
json
{  "mcpServers": {    "pim": { "command": "cmd", "args": ["/c", "npx", "-y", "pim-mcp"] }  }}

npx is a batch script on Windows, so it runs through cmd /c.

🐧 Linux

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:

json
"pim": {  "command": "npx",  "args": ["-y", "pim-mcp"],  "env": { "ICLOUD_PASSWORD": "…" }}

🧰 Tools

ToolWhat it does
📚list_calendarsAll calendars and their ids (icloud/work). Anywhere a tool takes a calendar, a plain name works too.
🗓️list_eventsEvents from all calendars in a range, merged and sorted. Defaults to today through the next 7 days.
🔎search_eventsText search over title, location and description.
📄get_eventFull details: description, attendees, organizer, recurrence rule, reminders.
🕐find_free_timeFree windows of at least N minutes, optionally within working hours.
➕create_eventTimed or all-day, with recurrence, up to 3 reminders, and busy/free status.
✏️update_eventChanges only the fields you pass. Recurring events take scope: instance or series.
🗑️delete_eventOff unless allow_delete = true. Takes the event's title, so approval prompts show its name, and refuses a title that doesn't match the event.

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

toml
timezone = "Europe/Amsterdam"            # default: the system timezone
[guardrails]allow_delete  = false                    # delete_event is refusedallow_invites = false                    # no adding attendees, no editing/deleting events that have them
[[accounts]]# …read_only           = true               # no writes to this account at allread_only_calendars = ["Family"]         # protect specific calendarshide_calendars      = ["Birthdays"]      # don't show these at all
  • Refusals 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

ProviderStatusSetup
Nextcloud / ownCloud✅ testednextcloud · https://<host>/remote.php/dav
iCloud✅ testedicloud · app-specific password
Google Calendar🧪 betagoogle · OAuth. Not yet tried with a real account; reports welcome
Fastmail🟡 untestedcaldav · https://caldav.fastmail.com/
Yahoo🟡 untestedcaldav · https://caldav.calendar.yahoo.com
mailbox.org🟡 untestedcaldav · https://dav.mailbox.org/
Posteo🟡 untestedcaldav · https://posteo.de:8443/
Radicale · Baïkal · SOGo · Synology🟡 untestedcaldav · your server's DAV URL
Outlook · Microsoft 365 · Exchange🚧 wantedno CalDAV; needs a Microsoft Graph backend
Proton Calendar❌ n/ano 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.


MIT © Aleksey Tkachenko · built for agents, readable by humans

Source: README.md at commit 006f369

Tools

8

list_calendars

List every calendar across all configured accounts (Nextcloud, iCloud, Google, …), with ids usable in other tools.

Takes no parameters.

list_events

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.

Parametersendstartaccountscalendars

search_events

Find events whose title, location or description contains the query (case-insensitive). Defaults to 90 days back through 365 days ahead.

Parametersendqueryrequiredstartcalendars

get_event

Full details of one event (description, attendees, organizer, recurrence rule, reminders).

Parametersidrequired

find_free_time

Free time windows of at least `duration_minutes` across all (or selected) calendars. Events marked free/transparent and cancelled events do not block time.

Parametersendrequiredstartrequiredaccountscalendarsworking_hoursduration_minutesrequired

create_event

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.

Parametersendbusyrrulestartrequiredtitlerequiredcalendarrequiredlocationattendeesdescriptionalarm_minutes

update_event

Change an event. Only the fields you pass change; moving `start` alone keeps the duration. For recurring events pass `scope`.

Parametersidrequiredendbusyrrulescopestarttitlelocationattendeesdescriptionalarm_minutes

delete_event

Delete an event. The user reviews this call by its `title`, and a title that does not match the event is refused. For recurring events pass `scope` ("instance" removes one occurrence, "series" removes all).

Parametersidrequiredscopetitlerequired

Version history

2
  1. v0.2.0LatestNov 5, 2026
  2. v0.1.0Oct 25, 2026

Score

90% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts
  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listedRequired15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts