EK Bridge

io.github.bereciartuav0.8.0更新於 Oct 7, 2026

Scoped Apple Calendar and Reminders access for AI agents, with per-client grants and approvals

概覽

AI 產生的概覽

一款 macOS 選單列應用程式,透過本機 MCP 伺服器讓 AI 代理以受限、可撤銷、需核准的方式存取 Apple 行事曆與提醒事項。

功能
在 127.0.0.1 上執行本機 MCP 伺服器,提供十二個行事曆與提醒事項工具:列出集合、讀取與取得事件、建立、更新、刪除事件,以及讀取、取得、建立、更新、完成與刪除提醒事項,時間使用 ISO 8601 格式(R71)。每個代理只會看到其授權允許的工具,新用戶端一開始沒有任何權限(R67、R68、R72)。寫入可依用戶端要求你核准,並顯示將變更的每個欄位(R73)。讀取傳回有界的資料列,其他集合會被拒絕;寫入使用幂等鍵,編輯或刪除需要最新項目版本(R74、R75、R76)。
適用情境
當你希望 Mac 上的 AI 代理讀取或管理 Apple 行事曆與提醒事項,又不想交出完整的 EventKit 存取權時使用。它適合依代理限定範圍、變更前核准,並記錄每個請求的活動日誌。此專案是公開預覽階段的個人專案,僅提供盡力支援,應視為實驗性(R9)。
執行需求
需要 macOS 14 或以上版本,Apple 晶片或 Intel 皆可;此應用程式是 macOS 選單列應用程式,透過 DMG 或 Homebrew cask 安裝(R11、R15、R16)。必須在 macOS 中授予行事曆和/或提醒事項存取權(R25)。MCP 伺服器預設關閉,僅監聽 127.0.0.1:47615;每個用戶端有自己的權杖檔案(R42、R43、R111)。雲端代理還需要遠端存取、你自行執行的通道,以及依用戶端開啟雲端存取(R50、R51、R52)。
安裝前請注意
讀取的內容會交給該代理及其 AI 供應商,依其隱私條款處理,因此只授予必要權限(R105)。寫入可建立、編輯、刪除或完成項目;請保持「每次變更前詢問」,因為該選項可依用戶端關閉(R46、R47)。遠端存取為實驗性功能,預設關閉,其 URL 路徑即為密鑰;Tailscale Funnel 以外的通道可在邊緣讀取流量(R56、R57、R106)。這些控制無法隔離以同一個 macOS 使用者身分執行的其他行程(R119)。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 EK Bridge,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

EK Bridge

EK Bridge is a macOS menu bar app that gives scripts and AI agents scoped, revocable access to your Calendar and Reminders. Tools on the same Mac reach it two ways: a command-line client sends signed JSON requests through a private file exchange, and AI agents (Claude Code, Codex, Claude Desktop, Cursor and others) connect to an optional MCP server on 127.0.0.1. With optional Remote Access, cloud agents such as claude.ai, ChatGPT and Cursor's cloud agents reach that server through a tunnel you run. Either way, the app checks macOS Full Access, the client's saved grant for a specific calendar or reminder list, request shape, and write safeguards before using Apple's EventKit framework, and can ask you before each change.

[EK Bridge Overview: the bridge is on, Calendars and Reminders have Full Access, and three clients are listed with their access and last request.]

Everything is off until you turn it on. The only network listeners are the MCP server and Remote Access, both off by default and bound to the loopback address. A cloud agent can reach the bridge only through Remote Access and a tunnel you set up, only for clients you allowed; it can't reach a Mac that's asleep, offline or logged out.

This is a personal project in public preview, with best-effort support. It is not affiliated with Apple.

Install

  1. Download the latest .dmg from Releases.
  2. Open it and drag the app to Applications.
  3. Open the app. Its window opens on a setup checklist; later, use the calendar icon in the menu bar.

Or install it with Homebrew, which also links bridge-client into Homebrew's bin:

sh
brew install --cask bereciartua/tap/ek-bridge

It needs macOS 14 or later, on Apple silicon or Intel. Either way the app updates itself. Upgrading from EventKit Bridge, its earlier name? See Setup.

For scripts, install the command-line client from Settings ▸ Developer ▸ Install Command-Line Tool (Homebrew already linked it). It links bridge-client into ~/.local/bin; if your shell can't find it, add that folder to your PATH.

Quick start

These are the same steps as the setup checklist the app shows on first launch:

  1. Open the app (see Install).
  2. Allow Calendar and/or Reminders access. You need only the one your tools use.
  3. Create a client for each tool or script, with Connects from ▸ Command line. It gets its own key file and starts with no access. (For an AI agent, see below.)
  4. Choose what the client can use: which calendars and lists, and which actions (Read, Create, Edit, Delete, Complete). Then Save.
  5. Turn on the bridge and send a test request. The client page has a ready-to-run command:
sh
bridge-client scope_status --client "Claude Code"

From a source checkout, python3 client.py works the same way.

[A client page: Connect shows the client ID, key file path and a command to copy; Access shows calendars grouped by account with Read, Create, Edit and Delete checkboxes.]

bridge-client --help lists every command and the access it needs. Errors say what's wrong and how to fix it, with a distinct exit code for each kind of problem (API and CLI). The app's Activity pane shows every request with a plain explanation of its result.

Connect an AI agent

After steps 1 and 2 above, the checklist follows the same path for an agent:

  1. New Client…: name it after the agent and choose Connects from ▸ AI agent (MCP). The app creates a token file for it; the client has no access, and Ask me before each change is on.
  2. Choose access in the client's Access table, then Save. Grant Read only on what the agent needs: what it reads goes to its AI provider.
  3. Turn on the bridge and the MCP server (Settings ▸ MCP Server, or the checklist). The server listens on http://127.0.0.1:47615/mcp.
  4. Copy the setup from the client's Connect ▸ AI agent tab: pick your agent and paste the command or config. The status line says Connected when the first request arrives.
[Connect ▸ AI agent on a client page: Claude Code is selected with the recommended direct HTTP method, a claude mcp add-json command to copy, a Connected status, a hidden token with Reset, and the server URL.]

When the agent wants to change something, a small panel asks you first. You can turn that off per client.

[The Ask before changes panel: Claude Code wants to add a weekly event to Work in Europe/Madrid, with rows for when, repeats, where with a map pin, notes, the link with its host in bold, alerts and show as, Deny and Allow buttons, a 45-second countdown and a checkbox to allow changes for 15 minutes.]

Setups for every supported agent, the tool reference and troubleshooting are in the MCP guide.

Connect a cloud agent (experimental)

Cloud agents run on their vendor's servers and can't reach 127.0.0.1. Remote Access (Settings ▸ Remote Access, off by default) opens a second loopback port, 47616, for a tunnel you run, such as Tailscale Funnel; the app shows the commands and tests the result. Each client needs Allow cloud access on its page. Agents that send a header (the Anthropic and OpenAI APIs, Claude Code on the web, Cursor and Copilot cloud agents, Devin) use the client's separate remote token. claude.ai, ChatGPT and Gemini Enterprise sign in with OAuth, which you approve on the Mac by matching a six-digit code. See Use from cloud agents.

Remote Access is experimental: it has offline tests, but hasn't yet been tested live with every cloud agent and tunnel. Turn it on only while you need it, and keep the Remote Access URL private; its path is the secret.

Guides

GoalGuide
Install, build from source, signing and macOS accessSetup
Enroll a client and use the appUser guide
Connect an AI agent over MCP, or a cloud agent through Remote Access; tool referenceMCP guide
Call the CLI and understand command parametersAPI and CLI reference
Understand processes, file storage, and security limitsArchitecture and threat model
See what was tested and diagnose failuresTesting and troubleshooting
Contribute, or maintain and releaseContributing, Maintaining

What works today

  • The user chooses collections and Read, Create, Edit, Delete, or reminder Complete grants per client. New clients have zero grants. Saved grants persist until edited or revoked; the bridge itself is off until enabled locally. A client can be paused, which refuses its requests but keeps its credentials and access, and resumed later.
  • AI agents on the Mac use twelve MCP tools (list_collections, read_events, get_event, create_event, update_event, delete_event, read_reminders, get_reminder, create_reminder, update_reminder, complete_reminder, delete_reminder) with ISO 8601 times. Each agent sees only the tools its grants allow. Ask before changes can require your approval for every write, per client, and shows every field that would change.
  • Reads return bounded event or reminder rows, not unrestricted access to the user's EventKit store. Reads of other collections are denied. Writes use an idempotency key; edits and deletes require the latest item version.
  • Events support every field EventKit exposes: times saved in the time zone you choose (or the Mac's, never UTC by default), all-day events up to a year, notes, location with a map pin, URL, alarms (including arriving or leaving a place), availability, and repeat rules. Recurring events can be changed or deleted one occurrence at a time, from one occurrence on, or as a whole series. Attendees, the organizer and your response are readable; invitations stay read-only, because changing them can notify every attendee.
  • Reminders support title, due and start dates, notes, URL, priority, several alarms (including location alarms), repeat rules, completing and reopening, moving between lists, and deleting a repeating reminder as a series. One occurrence of a repeating reminder can be completed for the shapes and account types a supervised probe has verified (today an iCloud daily reminder with a due time).
  • Updates change only the fields they send, and every written field is read back: a mismatch removes a new item or puts an edited one back. Inviting people, answering invitations, attachments, travel time and the Reminders app's tags and subtasks aren't possible through EventKit.
  • Cloud agents can use the same tools through Remote Access, a tunnel you run and a per-client Allow cloud access switch, with a separate remote token per client or OAuth connections you approve on the Mac. Remote Access is off by default, can turn itself off on a timer, and is one click to turn off from the menu bar.
  • One window with Overview, Activity (which says whether each request came via MCP, Remote Access or the command line), each client and Settings; a menu bar icon that shows whether the bridge is on, off or needs attention, with a globe while Remote Access is on; and a first-run checklist.
  • The app can launch at login when you turn that on.

The support matrix and testing record distinguish implemented behavior from provider-specific observations and untested cases.

Privacy

The app has no analytics, telemetry or crash reporting, and no account. Your calendars, reminders, clients and Activity stay on your Mac. These are every network connection it makes:

ConnectionWhen
MCP server, listening on 127.0.0.1:47615Only while Settings ▸ MCP Server is on (off by default). Loopback only: other computers can't connect.
Remote Access, listening on 127.0.0.1:47616Only while Settings ▸ Remote Access is on (off by default). Loopback only; a tunnel you run forwards cloud agents to it.
One HTTPS request to your Remote Access addressOnly when you click Test in Settings ▸ Remote Access.
One HTTPS request for a cloud agent's client metadataOnly while you pair an OAuth cloud agent (claude.ai, ChatGPT), to the address that agent gives. Private and local addresses are refused.
bridge-mcp connecting to 127.0.0.1When an agent on your Mac starts it, to reach the MCP server.
One HTTPS request to GitHub for appcast.xml, the list of the latest versionOnce a day while Settings ▸ General ▸ Check for updates automatically is on (on in downloaded copies; a copy built from source never checks), and when you choose Check for Updates…. GitHub sees your IP address and the app's version; nothing else is sent.
Downloading an update from GitHubOnly after you click Install Update in the update window. The app checks the download's EdDSA signature and that it's signed by the same developer before installing it.

What an agent reads through the bridge goes to that agent and its AI provider, under their privacy terms, so grant only what each agent needs. Tunnels other than Tailscale Funnel can read Remote Access traffic at their edge.

Security boundary

The bridge stores each client's Ed25519 signing credential in a mode-0600 file under the user's Application Support directory; the registry stores a public verifier and grants.

The MCP server is off by default. When on, it listens only on 127.0.0.1:47615, never on a network interface. Every request needs the client's own 256-bit token, kept in a mode-0600 file; the registry stores only its SHA-256 hash, and the recommended agent setups read the file instead of putting the token in the agent's config. Requests with a foreign Host, any Origin (web pages), or tunnel forwarding headers are refused, and repeated failed sign-ins are locked out. See the threat review.

Remote Access is also off by default. While on, it listens on 127.0.0.1:47616 for a tunnel the user runs; every path except a 128-bit secret path gets 404, and only clients with Allow cloud access can use it, with a separate remote token or an OAuth connection the user approved on the Mac. Local tokens don't work through it, and its credentials don't work on the local port. See the Remote Access threat review. Request and response files are owned by the user and have restricted permissions. These controls do not isolate another process running as the same macOS user. Such a process can access the credential, token or policy files. A grant is therefore a boundary between enrolled clients in this app's protocol, not a defense against a compromised user account.

Report vulnerabilities privately, as described in SECURITY.md.

Build from source

You need macOS 14 or later, Xcode or the Xcode Command Line Tools, and Python 3. Building and the offline tests don't install the app or ask for access:

sh
sh test.shsh build.sh

The build creates build/EKBridge.app, with the MCP launcher bridge-mcp and the command-line client bridge-client inside it (build/bridge-client links to it). It signs the app ad hoc by default, which macOS treats as a new app each time; for lasting Calendar and Reminders access, sign with a stable identity as described in Setup. EVENTKIT_ARCHS="arm64 x86_64" sh build.sh builds a universal app. sh ui_test.sh runs the window and behavior tests and sh ui_snapshots.sh writes screenshots of every screen; both use fake data. See Contributing. Releases are built by release.sh (Developer ID signing, notarization, a DMG and a zip), by hand or by the release workflow; see Maintaining.

Uninstall

  1. Quit the app from its menu bar menu.

  2. Remove its Calendar and Reminders access. The first command reads the app's bundle ID, so run these before you delete the app:

    sh
    bundle_id=$(defaults read /Applications/EKBridge.app/Contents/Info CFBundleIdentifier)tccutil reset Calendar "$bundle_id"tccutil reset Reminders "$bundle_id"
  3. Delete the app from Applications, and its data: ~/Library/Application Support/EKBridge (clients, keys, tokens, Activity and the write journal). If you upgraded from EventKit Bridge, also delete the EventKitBridge link next to it. Settings and the updater's downloads are in ~/Library/Preferences/io.github.bereciartua.ekbridge.plist and ~/Library/Caches/io.github.bereciartua.ekbridge.

  4. If you installed the command-line tool, delete ~/.local/bin/bridge-client.

  5. Remove the server from your agents' configs (for example claude mcp remove ek-bridge), and stop any tunnel you ran for Remote Access.

Installed with Homebrew? Do steps 1, 2 and 5, and brew uninstall --cask ek-bridge removes the app and its bridge-client link; with --zap it also moves the data and settings in step 3 to the Trash.

Project status

Offline tests and bounded live tests have exercised the local bridge, UI, and synthetic EventKit items. The MCP server, launcher, agent setups, Remote Access and its OAuth server have offline tests over real loopback sockets and a local HTTPS fixture; neither the live agent matrix nor the live cloud matrix has been run yet. A full Mac reboot followed by login was observed with the bridge running and authorized scoped reads working. Notification and provider synchronization behavior is not established for every recurrence shape. Tested on macOS 27.0.1 on Apple silicon with iCloud. See testing and open checks and the changelog.

License

EK Bridge is licensed under the Apache License 2.0; see NOTICE. The license doesn't grant rights to the project's name or icon. Apple, Mac and macOS are trademarks of Apple Inc. This project is not affiliated with or endorsed by Apple.

來源:README.md,提交 27a57c5

工具

0
工具後設資料尚未被收錄。

版本歷史

1
  1. v0.8.0最新Oct 7, 2026