streamable-httpMITupdated 1mo ago
Your Apple Calendar, in ChatGPT β on your own Mac.
What can you do with calendar bridge?
π CalendarBridge
Your Apple Calendar, in ChatGPT β on your own Mac.
CalendarBridge is a Model Context Protocol (MCP) connector that lets ChatGPT work with your Apple Calendar. It never uploads your events to a third party β every action runs on your own Mac through a tiny local agent. The cloud piece is only a stateless relay that shuttles requests between ChatGPT and your Mac.
ChatGPT ββOAuthβββΊ CalendarBridge relay ββjob queueβββΊ calendar-agent βββΊ Calendar.app
(connector) (Vercel, stateless) (your Mac, polls & executes) (on your Mac)
Your Mac is the only place your events are ever read or written. The relay stores only short-lived job payloads and your account record; it never sees an event unless a job is in flight, and jobs expire in seconds.
For users β 3 steps
1. Create your account at calendarbridge.vercel.app and generate a pairing code.
2. Install the Mac agent (needs Node 18+):
npx calendar-agent pair <YOUR-CODE> # link this Mac to your account
npx calendar-agent install # keep it running on every restart
The first time it touches Calendar, macOS asks "Terminal wants to control Calendar" β click OK (one time).
3. Connect ChatGPT: Settings β Plugins β turn on Developer mode (Security & login) β Create a custom plugin β paste the MCP Server URL https://calendarbridge.vercel.app/mcp β Authentication OAuth β sign in & Allow.
That's it. In a new chat: "Search my Apple Calendar for the dentist appointment" or "Add a Team Standup to my Work calendar tomorrow at 9am."
Your Mac must be awake with the agent running.
npx calendar-agent installmakes it start automatically at login and restart if it ever crashes.
Managing the agent
npx calendar-agent status # is it paired & reachable?
npx calendar-agent logs # recent activity
npx calendar-agent uninstall # stop auto-start
What ChatGPT can do
| Tool | Action |
|---|---|
list_calendars |
List all your calendars (Work, Personal, Family, β¦) |
list_events |
List upcoming events in a date window (default next 7 days), optionally one calendar |
search_events |
Find events whose title contains a keyword |
get_event |
Read one event by id |
create_event |
Create an event (title, start, end, optional location, notes, calendar, all-day) |
update_event |
Edit an event's fields (overwrites the fields you pass β read it first) |
Self-hosting
You can run your own relay so nothing depends on the hosted instance.
Prereqs: a Vercel account and a Supabase project (free tiers are fine).
- Storage β in your Supabase project's SQL editor, run
supabase/schema.sql. It creates a tiny Redis-shaped KV + queue surface (nb_*functions) with RLS on. - Deploy the
server/directory to Vercel. - Set env vars (see
server/.env.example):SUPABASE_URL,SUPABASE_SERVICE_ROLE_KEYβ your project + service-role keyJWT_SECRETβopenssl rand -hex 32
- Verify:
curl https://YOUR-APP.vercel.app/api/healthβredisConfigured,redisOk,jwtSecretSetalltrue. - Point the agent at it:
npx calendar-agent pair <CODE> --server https://YOUR-APP.vercel.app.
How it works
- Auth β OAuth 2.1 with PKCE and Dynamic Client Registration (RFC 7591). ChatGPT registers itself, the user signs in on the CalendarBridge consent page, and ChatGPT gets a scoped MCP access token. JWTs are HMAC-signed; three kinds (
session,agent,mcp) with distinct privileges. Optional email verification via Resend (RESEND_API_KEY); off unless configured, and enforcement is opt-in (REQUIRE_EMAIL_VERIFICATION). - Relay β MCP tool call β job pushed to
jobs:<user>(TTL β€ the caller's wait window, so an abandoned job can't run late) β the Mac agent (holding a hanging long-poll) is handed the job within ~200ms, executes it, pushes the result β the MCP handler returns it. The long-poll means jobs are delivered on arrival rather than on a fixed interval, so relay overhead is ~300ms instead of ~1s. The agent is considered "online" only while it's actively connected. - Agent β a dependency-free Node CLI. Tools run via JXA (
osascript -l JavaScript) against Calendar.app; arguments are passed as JSON over argv (never shell-interpolated). A macOS LaunchAgent keeps it alive across logins and crashes.
Repository layout
server/ Vercel functions: OAuth + MCP endpoint + relay (deploy this)
agent/ calendar-agent β the npm-published Mac CLI (users npx this)
kit/ Browser automations: register the dev-mode connector AND
fill the OpenAI directory submission (see kit/README.md)
supabase/ schema.sql for self-hosting the storage
test/ end-to-end OAuth + MCP integration test
Development
# server
cd server && cp .env.example .env.local # fill in, then: vercel dev
# end-to-end test against a live deployment (reads ../.env.local)
node test/e2e-oauth.mjs
# agent unit tests
node --test agent/test-agent-unit.mjs
Security & privacy
- Events are read/written only on your Mac. The relay never persists event content β job payloads live in Redis-shaped storage with a short TTL and are deleted on delivery.
- The agent token is stored at
~/.calendarbridge-agent.json(mode600). - No secrets are committed; see
.gitignoreand the.env.examplefiles. - Write tools are marked destructive so ChatGPT asks before changing an event.
License
MIT Β© Isaiah Dupree
Install
Add calendar bridge to your client. Pick the one you use.
claude mcp add --transport http calendar-bridge https://calendarbridge.vercel.app/mcpcodex mcp add calendar-bridge --url https://calendarbridge.vercel.app/mcp{
"mcpServers": {
"calendar-bridge": {
"url": "https://calendarbridge.vercel.app/mcp"
}
}
}Add to `~/.cursor/mcp.json`, or `.cursor/mcp.json` for a single project.
{
"servers": {
"calendar-bridge": {
"type": "http",
"url": "https://calendarbridge.vercel.app/mcp"
}
}
}Add to `.vscode/mcp.json` in your workspace.
{
"mcpServers": {
"calendar-bridge": {
"url": "https://calendarbridge.vercel.app/mcp"
}
}
}Add to `claude_desktop_config.json`, then restart Claude Desktop.
{
"mcpServers": {
"calendar-bridge": {
"serverUrl": "https://calendarbridge.vercel.app/mcp"
}
}
}Add to `~/.codeium/windsurf/mcp_config.json`.
Score
39 / 100
Incomplete
- Documentation25/25
- Maintenance16/25
- Trust13/20
- Capability0/15
- Install experience12/15
- Documents what it does and how to connect
- Has a resolvable package or endpoint
- Exposes at least one tool, prompt or resource
- README has substantive content
- Includes a code example
- Documents its configuration
- Mentions credentials or security posture
- Last commit 31 days ago
- Has a release history
- Repository is not archived
- Licensed MIT
- Namespace verified in the official MCP registry
- Claimed by its owner
- Published under an organisation
- 0 tool(s) documented
- Provides prompt templates
- Provides resources
- 6 documented install method(s)
- Published to a package registry
- Offers a hosted endpoint β no local install
Version history
| Versions | Published |
|---|---|
| 1.3.0Latest | Aug 1, 2026 |