# Che Ical Mcp

> macOS Calendar & Reminders MCP server with 29 tools — Native Swift EventKit integration for Claude. Attendees/organizer, per-event timezone, undo/redo, --cli mode, --setup TCC, --self-update, signed + notarized binary for macOS 26. Supports iCloud, Google, Exchange.

- **Type:** MCP server
- **Install:** `agentstack add mcp-psychquant-che-ical-mcp`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [PsychQuant](https://agentstack.voostack.com/s/psychquant)
- **Installs:** 0
- **Category:** [Productivity](https://agentstack.voostack.com/c/productivity)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [PsychQuant](https://github.com/PsychQuant)
- **Source:** https://github.com/PsychQuant/che-ical-mcp
- **Website:** https://github.com/PsychQuant/che-ical-mcp/releases

## Install

```sh
agentstack add mcp-psychquant-che-ical-mcp
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# che-ical-mcp

[](https://opensource.org/licenses/MIT)
[](https://www.apple.com/macos/)
[](https://swift.org/)
[](https://modelcontextprotocol.io/)

**macOS Calendar & Reminders MCP server** - Native EventKit integration for complete calendar and task management.

[English](README.md) | [繁體中文](README_zh-TW.md)

---

> ## ⚠️ Claude Desktop `.mcpb` install is temporarily broken (2026-05-12)
>
> The `.mcpb` extension install for Claude Desktop **cannot write to Calendar / Reminders** on Claude Desktop **1.6608.2 and later** (released ~2026-05-09). Write tools return `Calendar access denied`; read tools still work.
>
> **Use one of these instead** until Anthropic ships a fix:
>
> | Path | Status |
> |------|--------|
> | **Claude Code plugin** (`claude plugin install che-ical-mcp@psychquant-claude-plugins`) | ✓ Works |
> | Legacy `claude_desktop_config.json` (point Claude Desktop at the binary directly) | ⚠ Untested, may bypass the broken wrapper |
> | Google Calendar API + manual move to target calendar | ✓ Works |
>
> **Tracking**: upstream [`anthropics/claude-code#58239`](https://github.com/anthropics/claude-code/issues/58239), local [`#132`](https://github.com/PsychQuant/che-ical-mcp/issues/132). Detailed evidence + structural diagnosis in those threads. This banner will be removed once Anthropic restores `.mcpb` Calendar access.

---

## Why che-ical-mcp?

| Feature | Other Calendar MCPs | che-ical-mcp |
|---------|---------------------|--------------|
| Calendar Events | Yes | Yes |
| **Reminders/Tasks** | No | **Yes** |
| **Reminder #Tags** | No | **Yes** (MCP-level) |
| **Multi-keyword Search** | No | **Yes** |
| **Duplicate Detection** | No | **Yes** |
| **Conflict Detection** | No | **Yes** |
| **Batch Operations** | No | **Yes** |
| **Local Timezone** | No | **Yes** |
| **Source Disambiguation** | No | **Yes** |
| Create Calendar | Some | Yes |
| Delete Calendar | Some | Yes |
| Event Reminders | Some | Yes |
| Location & URL | Some | Yes |
| Language | Python | **Swift (Native)** |

---

## Quick Start

### For Claude Desktop

#### Option A: MCPB One-Click Install (Recommended)

Download the latest `.mcpb` file from [Releases](https://github.com/PsychQuant/che-ical-mcp/releases) and double-click to install.

#### Option B: Manual Configuration

Edit `~/Library/Application Support/Claude/claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "che-ical-mcp": {
      "command": "/usr/local/bin/che-ical-mcp"
    }
  }
}
```

### For Claude Code (CLI)

#### Option A: Install as Plugin (Recommended)

The plugin includes slash commands (`/today`, `/week`, `/quick-event`, `/remind`), skills, and **a PreToolUse hook that automatically verifies day-of-week** when creating or updating events — preventing date/weekday mismatch errors.

Two steps — register the marketplace once, then install the plugin. This repo is its
own self-hosted marketplace (the plugin definition lives in `plugin/`):

```bash
# 1. Register the marketplace (one-time)
claude plugin marketplace add PsychQuant/che-ical-mcp

# 2. Install the plugin
claude plugin install che-ical-mcp@che-ical-mcp
```

> **Inside Claude Code?** The slash-command equivalents `/plugin marketplace add PsychQuant/che-ical-mcp` and `/plugin install che-ical-mcp@che-ical-mcp` work the same way.
>
> **Add via git, not a raw URL.** The marketplace's plugin `source` is a same-repo relative path (`./plugin`), which only resolves when the marketplace is added through its Git repo (GitHub `owner/repo`, as above) — not via a direct URL to `marketplace.json`.
>
> The plugin is also still bundled in the `psychquant-claude-plugins` aggregator (`claude plugin install che-ical-mcp@psychquant-claude-plugins`); both serve the same versioned binary.

> **Note:** The plugin wraps the MCP binary with auto-download. If the binary is not found at `~/bin/CheICalMCP`, it will be downloaded from GitHub Releases on first use.

#### Option B: Install as standalone MCP

If you only need the MCP server without plugin features:

```bash
# Create ~/bin if needed
mkdir -p ~/bin

# Download the latest release
# Note: if upgrading from an older version, `rm -f ~/bin/CheICalMCP` first.
# Without this, on macOS 26 the kernel may kill the new binary with a stale
# code-signature cache from the old inode (which running MCP processes might
# still be holding open).
rm -f ~/bin/CheICalMCP
curl -L https://github.com/PsychQuant/che-ical-mcp/releases/latest/download/CheICalMCP -o ~/bin/CheICalMCP
chmod +x ~/bin/CheICalMCP

# Add to Claude Code
# --scope user    : available across all projects (stored in ~/.claude.json)
# --transport stdio: local binary execution via stdin/stdout
# --              : separator between claude options and the command
claude mcp add --scope user --transport stdio che-ical-mcp -- ~/bin/CheICalMCP
```

> **💡 Tip:** Always install the binary to a local directory like `~/bin/`. Avoid placing it in cloud-synced folders (Dropbox, iCloud, OneDrive) as file sync operations can cause MCP connection timeouts.

### Build from Source (Optional)

```bash
git clone https://github.com/PsychQuant/che-ical-mcp.git
cd che-ical-mcp
make release && make install
```

> **⚠️ Swift 6 / Xcode 18 users:** Do not use `swift build` directly — upstream MCP SDK has a concurrency error ([swift-sdk#214](https://github.com/modelcontextprotocol/swift-sdk/issues/214)). The Makefile auto-detects this and falls back to Swift 5 language mode.

On first use, macOS will prompt for **Calendar** and **Reminders** access - click "Allow".

### CLI Mode (No MCP Server)

All 29 tools can be invoked directly from the command line without running the MCP server:

```bash
# Flag-based: --key value pairs
CheICalMCP --cli list_events --start_date 2026-03-29 --end_date 2026-03-30

# JSON via stdin
echo '{"tool":"list_calendars","arguments":{}}' | CheICalMCP --cli

# Use with Claude Code via shell
claude -p "Run: ~/bin/CheICalMCP --cli list_events_quick --range today"
```

Useful for launchd jobs, shell scripts, CI pipelines, and agents that prefer subprocess over MCP protocol. TCC permissions still required — run `CheICalMCP --setup` first if needed.

### Upgrading an existing install

The plugin wrapper auto-downloads on **fresh** installs, but does NOT replace an existing binary. To upgrade in place:

```bash
~/bin/CheICalMCP --self-update
```

This queries GitHub Releases for the latest tag, downloads the new binary, and atomically replaces the current one. If the binary is currently running as an MCP server, restart your MCP host (Claude Desktop / Claude Code) afterward to pick up the new version. Manual alternative if `--self-update` is unavailable: `rm -f ~/bin/CheICalMCP && curl -L https://github.com/PsychQuant/che-ical-mcp/releases/latest/download/CheICalMCP -o ~/bin/CheICalMCP && chmod +x ~/bin/CheICalMCP`.

---

## All 29 Tools

Calendars (4)

| Tool | Description |
|------|-------------|
| `list_calendars` | List all calendars and reminder lists (includes source_type) |
| `create_calendar` | Create a new calendar |
| `delete_calendar` | Delete a calendar |
| `update_calendar` | Rename a calendar or change its color (v0.9.0) |

Events (4)

| Tool | Description |
|------|-------------|
| `list_events` | List events with filter/sort/limit (v1.0.0) |
| `create_event` | Create an event (with reminders, location, URL, per-event timezone) |
| `update_event` | Update an event (including timezone, recurrence, span for recurring) |
| `delete_event` | Delete an event (with occurrence support for recurring) |

Reminders (8)

| Tool | Description |
|------|-------------|
| `list_reminders` | List reminders with filter/sort/limit, tags extraction (v1.0.0) |
| `create_reminder` | Create a reminder with due date, tags (v1.3.0) |
| `update_reminder` | Update a reminder (including tags, `clear_due_date`) (v1.3.0) |
| `complete_reminder` | Mark as completed/incomplete |
| `delete_reminder` | Delete a reminder |
| `search_reminders` | Search reminders by keyword(s) or tag (v1.3.0) |
| `list_reminder_tags` | List all unique tags with usage counts (v1.3.0) |
| `cleanup_completed_reminders` | Delete all completed reminders in one call, dry_run preview by default (v1.7.2) |

Advanced Features (10) ✨ New in v0.3.0+

| Tool | Description |
|------|-------------|
| `search_events` | Search events by keyword(s) with AND/OR matching |
| `list_events_quick` | Quick shortcuts: `today`, `tomorrow`, `this_week`, `next_7_days`, etc. |
| `create_events_batch` | Create multiple events at once (with per-event timezone) |
| `check_conflicts` | Check for overlapping events in a time range |
| `copy_event` | Copy an event to another calendar (with optional move) |
| `move_events_batch` | Move multiple events to another calendar |
| `delete_events_batch` | Delete events by IDs or date range, with dry-run preview (v1.0.0) |
| `find_duplicate_events` | Find duplicate events across calendars (v0.5.0) |
| `create_reminders_batch` | Create multiple reminders at once (v0.9.0) |
| `delete_reminders_batch` | Delete multiple reminders at once (v0.9.0) |

Undo/Redo (3) ✨ New in v1.4.0

| Tool | Description |
|------|-------------|
| `undo` | Undo the most recent calendar/reminder operation |
| `redo` | Redo the last undone operation |
| `undo_history` | List undoable operations with timestamps |

---

## Installation

### Requirements

- macOS 14.0+ (Sonoma or later — required since cluster v1.11.0+ for full TCC permission API support)
- Xcode Command Line Tools (only if building from source)

### For Claude Desktop

#### Method 1: MCPB One-Click Install (Recommended)

1. Download the latest `che-ical-mcp-.mcpb` from [Releases](https://github.com/PsychQuant/che-ical-mcp/releases)
2. Double-click the `.mcpb` file to install
3. Restart Claude Desktop

#### Method 2: Manual Configuration

1. Download the binary:
   ```bash
   curl -L https://github.com/PsychQuant/che-ical-mcp/releases/latest/download/CheICalMCP -o /usr/local/bin/che-ical-mcp
   chmod +x /usr/local/bin/che-ical-mcp
   ```

2. Edit `~/Library/Application Support/Claude/claude_desktop_config.json`:
   ```json
   {
     "mcpServers": {
       "che-ical-mcp": {
         "command": "/usr/local/bin/che-ical-mcp"
       }
     }
   }
   ```

3. Restart Claude Desktop

### For Claude Code (CLI)

```bash
# Create ~/bin if needed
mkdir -p ~/bin

# Download the binary
curl -L https://github.com/PsychQuant/che-ical-mcp/releases/latest/download/CheICalMCP -o ~/bin/CheICalMCP
chmod +x ~/bin/CheICalMCP

# Register with Claude Code (user scope = available in all projects)
claude mcp add --scope user --transport stdio che-ical-mcp -- ~/bin/CheICalMCP
```

### Build from Source (Optional)

```bash
git clone https://github.com/PsychQuant/che-ical-mcp.git
cd che-ical-mcp
make release && make install

# Register with Claude Code
claude mcp add --scope user --transport stdio che-ical-mcp -- ~/bin/CheICalMCP
```

> **⚠️ Swift 6 / Xcode 18 使用者：** 不要直接使用 `swift build` — 上游 MCP SDK 有 concurrency 錯誤（[swift-sdk#214](https://github.com/modelcontextprotocol/swift-sdk/issues/214)）。Makefile 會自動偵測並回退到 Swift 5 語言模式。

### Grant Permissions

On first use, macOS will prompt for **Calendar** and **Reminders** access. Click **Allow** for both.

> **⚠️ macOS Sequoia (15.x) Note:** The permission dialog is attributed to the **parent application** that launched the MCP server, not the binary itself. This means:
>
> | Environment | Permission Attributed To |
> |-------------|------------------------|
> | Claude Desktop | Claude Desktop.app ✅ (works automatically) |
> | Claude Code in **Terminal.app** | Terminal.app ✅ (works automatically) |
> | Claude Code in **VS Code** | VS Code ❌ (may not show dialog) |
> | Claude Code in **iTerm2** | iTerm2 ✅ (works automatically) |
>
> **If the permission dialog doesn't appear** (common with VS Code), you need to add `NSCalendarsFullAccessUsageDescription` to VS Code's Info.plist:
>
> ```bash
> # Add calendar usage description to VS Code
> /usr/libexec/PlistBuddy -c "Add :NSCalendarsFullAccessUsageDescription string 'VS Code needs calendar access for MCP extensions.'" \
>   "/Applications/Visual Studio Code.app/Contents/Info.plist"
> /usr/libexec/PlistBuddy -c "Add :NSRemindersFullAccessUsageDescription string 'VS Code needs reminders access for MCP extensions.'" \
>   "/Applications/Visual Studio Code.app/Contents/Info.plist"
>
> # Re-sign VS Code (required after Info.plist modification)
> codesign -s - -f --deep "/Applications/Visual Studio Code.app"
>
> # Restart VS Code, then the permission dialog will appear
> ```
>
> **Note:** This modification will be overwritten when VS Code updates. You'll need to re-apply it after each VS Code update.

---

## v1.0.0 Features

### Flexible Date Parsing

All date parameters now accept 4 formats:

| Format | Example | Interpretation |
|--------|---------|----------------|
| Full ISO8601 | `"2026-02-06T14:00:00+08:00"` | Exact date and time (offset preserved) |
| Without timezone | `"2026-02-06T14:00:00"` | Uses event `timezone` if provided, otherwise system timezone |
| Date only | `"2026-02-06"` | Midnight in event `timezone` or system timezone |
| Time only | `"14:00"` | Today at that time |

### Per-Event Timezone (v1.5.0)

Set the display timezone for individual events — essential for multi-timezone travel itineraries.

```
"Create a flight departure at 09:14 Berlin time"
→ create_event(title: "Flight LH123", start_time: "2026-04-08T09:14:00", timezone: "Europe/Berlin", ...)

"Update the hotel check-in to Dubai time"
→ update_event(event_id: "...", timezone: "Asia/Dubai")

"Remove the custom timezone from an event"
→ update_event(event_id: "...", clear_timezone: true)
```

- **`timezone`** parameter accepts IANA identifiers (e.g., `Europe/Berlin`, `America/New_York`, `Asia/Taipei`)
- When `timezone` is provided, naive datetimes (without offset) are interpreted in that timezone
- Event output includes the event's own timezone in `timezone` field and formats `start_date_local`/`end_date_local` accordingly
- Available on `create_event`, `update_event`, and `create_events_batch`
- Undo/redo preserves per-event timezone

### Attendees & Organizer (Read-Only)

Event responses include participant information when available. These fields are **read-only** due to EventKit limitations — they cannot be set or modified through the MCP.

Available in: `list_events`, `search_events`, `list_events_quick`, `check_conflicts`

**`attendees`** (array, optional) — Present when the event has participants. Each attendee object contains:

| Field | Type | Description |
|-------|------|-------------|
| `name` | string or null | Display name, null if not in Address Book |
| `email` | string | Email address extracted from participant URL |
| `role` | string | One of: `unknown`, `required`, `optional`, `chair`, `non_participant` |
| `status` | string | One of: `unknown`, `pending`, `accepted`, `declined`, `tentative`, `delegated`, `completed`, `in_process` |
| `type` | string | One of: `unknown`, `person`, `room`, `resource`, `group` |
| `is_current_user` | boolean | Whether this participant is the current user |

**`organizer`** (object, optional) — Present when the event has an organizer. Contains:

| Field | Type | Description |
|-------|------|-------------|
| `name` | string or null | Display name |
| `email` | string | Email address |
| `is_current_user` | boolean | Whether the organizer is the current user |

> **Note:** Both fields are omitted when the event has no participants or organizer (e.g., local calendar events created without invitees).

### Fuzzy Calendar Matching

Calendar names are now matched **case-insensitively**. If not found, the error message lists all available calendars.

### Enhanced list/delete Tools

- **`list_events`**: `filter` (all/past/future/all_day), `sort` (asc/desc), `limit`
- **`list_reminders`**: `filter` (all/incomplete/completed/overdue), `sort` (due_date/creation_date/priority/title), `limit`
- **`delete_events_batch`**: d

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [PsychQuant](https://github.com/PsychQuant)
- **Source:** [PsychQuant/che-ical-mcp](https://github.com/PsychQuant/che-ical-mcp)
- **License:** MIT
- **Homepage:** https://github.com/PsychQuant/che-ical-mcp/releases

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** yes
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-psychquant-che-ical-mcp
- Seller: https://agentstack.voostack.com/s/psychquant
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
