Skip to main content
Glama

mcp-ical-swift

Bun Swift MCP License: MIT macOS

A local MCP server for Apple Calendar that uses a compiled Swift binary to bypass macOS Sequoia's TCC restrictions.

Why this exists

On macOS Sequoia (26.x), headless processes cannot obtain Calendar access through the standard TCC (Transparency, Consent, and Control) mechanism:

  • EventKit from Python (e.g. PyObjC) requires kTCCServiceCalendar, which can only be granted through a system dialog that headless processes cannot trigger. There is no + button in System Settings > Privacy & Security > Calendars on Sequoia.

  • AppleScript via osascript requires kTCCServiceAppleEvents (Automation permission), which is attributed to the calling binary (typically node or bun). Direct TCC database edits are silently ignored by the TCC daemon's integrity checks.

  • icalBuddy and other Homebrew tools use EventKit internally and hit the same wall.

The compiled Swift binary (swiftc) works because it produces an Apple-signed Mach-O executable that inherits Calendar TCC from the system Swift toolchain. When Node/Bun spawns this binary via execFileSync, EventKit reports authorizationStatus = .fullAccess and returns calendar data.

Features

  • List all calendars

  • List events within a date range

  • Search events by keyword

  • Create new events (with calendar, location, notes, all-day support)

  • Update existing events

  • Get full event details by UID

  • Delete events

  • Runs entirely locally over stdio -- no network, no API keys, no cloud

Prerequisites

  • macOS Sequoia (26.x) or later

  • Bun 1.1+

  • Xcode Command Line Tools (xcode-select --install) for swiftc

  • Calendar data in Apple Calendar (iCloud, Exchange, or local calendars)

Installation

git clone https://github.com/Sealjay/mcp-ical-swift.git
cd mcp-ical-swift
bun install
bun run build

The build script compiles src/calendar-reader.swift into bin/calendar-reader.

MCP client configuration

Claude Code

claude mcp add --transport stdio ical --scope user -- bun run /absolute/path/to/mcp-ical-swift/src/index.ts

OpenClaw

{
  "mcp": {
    "servers": {
      "ical": {
        "command": "bun",
        "args": ["run", "/absolute/path/to/mcp-ical-swift/src/index.ts"]
      }
    }
  }
}

Claude Desktop

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "ical": {
      "command": "bun",
      "args": ["run", "/absolute/path/to/mcp-ical-swift/src/index.ts"]
    }
  }
}

Tools

Tool

Description

ical__list_calendars

List all Apple Calendar calendars

ical__list_events

List events within a date range (YYYY-MM-DD)

ical__search_events

Search events by keyword (default: 30 days ahead)

ical__create_event

Create a new event (title, start, end, calendar, location, notes, all-day)

ical__update_event

Update an existing event by UID

ical__get_event

Get full details of an event by UID

ical__delete_event

Delete an event by UID

How it works

MCP Client (Claude, OpenClaw, etc.)
  --> stdio --> Bun MCP server (src/index.ts)
    --> execFileSync --> compiled Swift binary (bin/calendar-reader)
      --> EventKit framework --> Apple Calendar data

The Swift binary is compiled once (bun run build) and called synchronously for each tool invocation. It outputs JSON to stdout, which the Bun MCP server wraps in MCP tool results. The server uses execFileSync (not shell execution) to avoid injection risks.

The key insight: swiftc-compiled binaries are Apple-signed and inherit Calendar TCC from the system toolchain. This bypasses the TCC restrictions that block Node, Bun, Python, and AppleScript from accessing calendars in headless contexts.

Privacy and security

  • This server accesses all calendars on the system by default (iCloud, Exchange, local, shared, subscribed). You can filter by calendar name per-request using the optional calendar parameter on list_events and search_events.

  • Event notes are returned in responses and may contain sensitive data (meeting PINs, passwords, personal details). Consider this when granting MCP client access.

  • Write operations (create_event, update_event, delete_event) are available with no confirmation step. An MCP client (or a prompt injection within one) could modify your calendar data.

  • All communication is local over stdio -- no data is sent to external services.

  • To report a vulnerability, see SECURITY.md.

Limitations

  • macOS only (requires EventKit and the Swift toolchain)

  • Requires Bun runtime

  • The Swift binary is compiled once and called synchronously per tool invocation -- not suitable for very high-throughput use

  • Recurring event modifications apply to the single instance only (.thisEvent span)

  • Calendar access depends on macOS TCC granting permission to the compiled binary

Troubleshooting

"Calendar access is not granted"

The compiled binary needs to be run at least once from a context that has Calendar TCC. Run the build and test:

bun run build
bin/calendar-reader list-events $(date +%Y-%m-%d)

If this returns events, the binary has Calendar access. If not, try running from Terminal.app (which typically has Calendar TCC granted).

Events are empty

Check that you have calendars configured in Apple Calendar. Run:

bin/calendar-reader list-calendars

Compilation fails

Ensure Xcode Command Line Tools are installed:

xcode-select --install

Licence

MIT

A
license - permissive license
-
quality - not tested
C
maintenance

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Sealjay/mcp-ical-swift'

If you have feedback or need assistance with the MCP directory API, please join our Discord server