mcpField
P
pim-mcp

pim-mcp

Local
github.com/da-the-devProductivity0Updated 4d ago

About pim-mcp

pim-mcp is a local MCP server that combines calendars from Nextcloud, iCloud, Google, and CalDAV services for agents to read and manage. It keeps credentials outside its TOML configuration and uses guardrails and ETag checks to limit risky or conflicting edits.

Key features

  1. 01Merge calendars into a sorted event view
  2. 02Search events and inspect full details
  3. 03Find free time and create events
  4. 04Update events with instance or series scope
  5. 05Protect deletion, invitations, and concurrent edits

Use cases

  1. 01Check events across multiple calendar accounts
  2. 02Find an available slot before scheduling
  3. 03Create or update a recurring calendar event
  4. 04Prevent overwriting changes made elsewhere

MCP support

Runs locally over stdio and exposes calendar tools to MCP clients, which start the process when needed. It connects to Nextcloud, iCloud, Google, and other CalDAV servers.

Configuration

Local server config is the same for every client. Copy it into your client’s MCP config file.

mcp.json · Universal config
{
"mcpServers": {
"da-the-dev-pim": {
"command": "npx",
"args": [
"-y",
"pim-mcp"
]
}
}
}
Run commandnpx -y pim-mcp

Local servers need a runtime on your machine (e.g. Node.js 18+). Config file locations differ by client; see your client’s docs.

Packages
npmpim-mcp0.1.0

Tools

8

Saved tool list · updated 4d ago

This tool takes no parameters.

Details

From the project 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


 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

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 agent

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

sudo apt install libsecret-tools     # Debian / Ubuntu
sudo dnf install libsecret           # Fedora
sudo 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:

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
[[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
[[accounts]]
id = "icloud"
provider = "icloud"
username = "[email protected]"   # the email you sign into your Apple Account with
password = "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.
[[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
[[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)

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
{
  "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
{
  "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:

"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.
🕐find_free_timeFree windows of at least N minutes, optionally within working hours.
➕create_eventTimed or all-day, with recurrence, a reminder, and busy/free status.
✏️update_eventChanges only the fields you pass. Recurring events take scope: instance or series.
🗑️delete_eventOff unless allow_delete = true.

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

Comments

Markdown supported

New to MCP?

From what the protocol is to installing your first server, these answers cover most first questions.

An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.