A community-driven registry for Claude, Cursor, Windsurf, Cline & more. Not affiliated with Anthropic.
Are you the author? Sign in to claim
Mac-resident MCP server: securely proxies Mail / Calendar / Drive / Contacts to AI agents over stdio or Tailnet HTTP, wi
A Mac-resident MCP server that proxies Apple-native services — Mail, Calendar, iCloud Drive, Voice Memos, Reminders — to AI agents over stdio or HTTP. One trust boundary, one audit log, one place to enforce safety.
The bridge is built around a simple premise: an LLM agent talking to your iCloud should look more like a service account with scoped permissions than a fully-trusted user. Every call passes through the same policy pipeline (auth → ACL → redaction → injection-tagging → approval-gate → audit), and every layer is configurable per token.
Status: v1.0.0-beta.3 (public beta). 43 tools across 6 services, codesigned + notarized Developer ID build, 111 unit tests (incl. a schema validator that walks every registered tool), daemon + menubar UI with first-launch onboarding, auto-update via Sparkle (UI) and deckard self-update (CLI), CI on every push. Designed for personal homelab use; security model documented in docs/security-model.md. Known beta issues + roadmap in CHANGELOG.md.
Most "AppleScript MCP" projects expose Mail or Calendar as a thin RPC: tools fire, results come back as flat strings, the agent reads whatever the user reads. That's fine for trusted prompts and demo screenshots; it's wrong for any system where the agent might be compromised, the email content might be hostile, or the action chain might run unattended.
Deckard sits between the agent and macOS and adds:
mail.list_messages + mail.mark_read + nothing else. A "trusted" agent gets the full surface but mail.send still routes through an approval dialog. A "readonly" experiment can't write anything anywhere.[REDACTED:<rule>]. Cloud creds (AWS / GCP / Azure / DO), API keys (OpenAI / Anthropic / Stripe / Google / Twilio / npm), GitHub PATs, Slack/JWT tokens, RSA private blocks, SSN-like patterns — and one-time tokens: 2FA / OTP / verification / sign-in codes, magic-link URL params, inline password: / passwd= values, PIN: 1234. The OTP rule requires the matched value to contain at least one digit, so common words like "expired" or "invalid" don't trip it. New rules drop in via config.<untrusted>…</untrusted> so the agent treats it as data, not instructions. When known injection patterns ("ignore previous instructions", role-impersonation prefixes, etc.) are detected, the wrapper escalates to a strong warning banner.mail.send, drive.write, calendar.delete_event, reminders.delete_reminder — set their ACL to approve and every call pops a macOS dialog showing what's about to happen (recipients, body preview, file path, event title) before it executes. Per-token interactive_approval = "never" lets trusted remote tokens skip the dialog (audit logs as approved_by_policy for forensics).caller: "bearer:triage" instead of bearer:default.[tailscale] enabled = true the daemon also binds the tailnet IPv4. Peer ACLs are delegated to tailscaled — set them in the Tailscale admin console, not here. tailscale whois runs per request so audit rows for tailnet calls record transport=tailnet caller=ts:laptop:user@github. Bearer auth still applies on top.mail.move_message, mail.mark_read, mail.mark_unread accept a single id OR an ids: [string] array (up to 500). The batch path is one osascript invocation regardless of N — one Mail.app activation, one audit row, one approval dialog.tools/list, so context isn't burned on capabilities they can't use.swift build.deckard self-update subcommand that verifies SHA-256 + codesign + Developer ID team + Gatekeeper assess before swapping the binary and kickstart-ing the LaunchAgent.What it doesn't do:
~/Library/Application Support/Deckard/tokens.toml has every bearer.Tested on macOS 14+ (Sonoma) and macOS 26 (Tahoe). Apple Silicon.
Grab the latest DMG from the Releases page. Drag Deckard.app into /Applications, double-click, and the menubar icon appears. First launch opens a 6-step onboarding window (Welcome → Daemon → Token → Permissions → Connect → Done) that walks through token creation, surfaces required TCC grants with deep-links to System Settings, and gives you a copy-paste claude mcp add snippet.
After onboarding:
http://127.0.0.1:8787/mcp~/Library/Logs/Deckard/audit.jsonl~/Library/Application Support/Deckard/tokens.tomlThe release artifacts are codesigned and notarized — Gatekeeper accepts them on first open. Verify the SHA-256 sidecar against the DMG before running if you'd like.
The book icon turns green when the daemon's running, outline-only when stopped. Click for status; "Open Settings…" for the multi-tab window. Reopen onboarding anytime via Settings → Status → "Show Onboarding…".
For a Mac Mini sitting on a shelf or any server-style deployment. The Homebrew tap pulls the same notarized release tarball the DMG uses; brew handles the version pinning and updates.
brew tap lapidakis/deckard
brew install deckard
deckard config init
deckard auth add default --profile trusted
deckard install # writes the LaunchAgent and bootstraps the daemon
Updates: brew upgrade deckard. deckard self-update refuses on Homebrew-managed binaries — brew owns the metadata, and a self-update would leave it stale.
If brew isn't an option (offline install, locked-down server), grab the tarball asset directly:
TAG="v1.0.0-beta.3" # latest tag from the Releases page
curl -L -o deckard.tar.gz \
"https://github.com/lapidakis/Deckard/releases/download/${TAG}/deckard-${TAG}-arm64.tar.gz"
curl -L -o deckard.tar.gz.sha256 \
"https://github.com/lapidakis/Deckard/releases/download/${TAG}/deckard-${TAG}-arm64.tar.gz.sha256"
# Verify the checksum before extracting (sidecar is `<sha> <filename>`).
shasum -a 256 -c deckard.tar.gz.sha256
tar -xzf deckard.tar.gz
sudo mv deckard /usr/local/bin/
deckard config init # writes config.toml with defaults
deckard auth add default --profile trusted # mints a bearer token
deckard install # registers + bootstraps LaunchAgent
deckard install writes ~/Library/LaunchAgents/com.lapidakis.deckard.plist and bootstraps it under gui/<uid> so the daemon starts on login and respawns on crash. The first call to each surface (Mail / Calendar / Reminders / Apple Events) triggers a TCC prompt — click Allow once per surface; the grants persist across rebuilds because the binary is signed with a stable Developer ID.
To grab the bearer for your MCP client:
deckard auth show default
To uninstall:
deckard uninstall # bootouts + removes the LaunchAgent
sudo rm /usr/local/bin/deckard # or `brew uninstall deckard` if you used the tap
rm -rf ~/Library/Application\ Support/Deckard ~/Library/Logs/Deckard
For development, contributors, or anyone with a Developer ID and a preference for self-signed builds:
git clone https://github.com/lapidakis/Deckard.git
cd Deckard
make build # auto-detects your Developer ID; falls back to adhoc
.build/debug/deckard config init
.build/debug/deckard install # registers LaunchAgent, starts the daemon
make ui # builds the menubar app bundle
The codesign script (scripts/codesign.sh) resolves the signing identity in this order: $DECKARD_SIGN_IDENTITY → first detected Developer ID Application: in your keychain → adhoc with a warning. Adhoc builds run, but TCC grants don't persist across rebuilds — each make build re-prompts for Mail/Calendar/Reminders permissions.
CI runs swift test on every push (see .github/workflows/ci.yml). PRs that break the schema validator or any other test are blocked.
TOKEN=$(.build/debug/deckard auth show default)
claude mcp add --transport http deckard http://127.0.0.1:8787/mcp \
--header "Authorization: Bearer $TOKEN"
Verify in any Claude Code session with /mcp — should show deckard ✓ connected and however many tools the default token's ACL allows.
config.toml and tokens.toml referencedeckard self-update and Sparkle one-time setup), audit, troubleshootBuilt-in
health.ping — liveness probe; tiny payload, useful diagnosticMail (Phase 1) — Mail.app via NSAppleScript subprocess
mail.list_mailboxes, mail.list_messages, mail.searchmail.get_messagemail.create_draft (safe — opens in Mail.app for user), mail.send (approval-gated)mail.mark_read, mail.mark_unread, mail.move_message — each accepts single id OR ids: [string] (up to 500), returns BatchResult { matched, missing, failed, elapsed_ms }Calendar (Phase 2) — native EventKit
calendar.list_calendars, calendar.list_events, calendar.search_eventscalendar.get_event, calendar.nowcalendar.create_event, calendar.update_event, calendar.delete_event (all approval-gated)Drive (Phase 3) — filesystem with traversal guard
drive.list, drive.stat, drive.read, drive.search, drive.usagedrive.materialize (force .icloud placeholder download)drive.write (approval-gated; optional sandbox prefix in config)Voice Memos (Phase 4) — read-only
voice_memo.list_recordings, voice_memo.get_recordingvoice_memo.read_audio (base64 .m4a, 25 MiB hard cap)Reminders (Phase 4.5) — EventKit .reminder entities
reminders.list_lists, reminders.list_reminders, reminders.get_reminderreminders.create_reminder, reminders.update_reminder, reminders.complete_reminder, reminders.delete_reminderContacts (Phase 4.6) — Contacts framework (CNContactStore)
contacts.search, contacts.get, contacts.list_groups, contacts.list_in_groupcontacts.create, contacts.update, contacts.delete, contacts.set_groups (all approval-gated)Per-tool detail in docs/configuration.md.
Default-deny. Every tool starts at deny. ACL turns things on individually. There's no "everything's allowed" mode that you might forget to switch off.
Trust boundary at the bridge, not the agent. The agent could be malicious, compromised, or fed prompt-injected content. The bridge's job is to make every layer of that hostile input safe before it reaches code that touches iCloud, and to make every output safe before it reaches the model.
One audit log, append-only. Every call, every decision, with retention. If something happened, it's in the log, regardless of which agent made the call.
Native frameworks where they exist. EventKit for Calendar/Reminders, Contacts framework for the address book, FileManager + brctl for Drive, sqlite3 for Voice Memos and Mail's own indexes. AppleScript only when nothing else works (Mail.app, no public framework).
No fancy abstractions. Six service modules, one shape: *Adapter (talks to macOS) → *Tools (MCP handlers) → registered into the same dispatch pipeline. New phases plug in without touching BridgeCore.
Operate on files, not network APIs (for the UI). The menubar app reads tokens.toml, config.toml, and audit.jsonl directly. Same machine, same user. No control protocol to maintain.
chat.db, send via AppleScript, sender allowlist.approve outcomes prompt remote tokens reliably without falling back to interactive_approval = "never"SessionHolder.recreate() should drain in-flight requests before swapping the transport — closes the rare "Transport already started" race in the stale-session self-heal pathRun Claude Code as an MCP server so any agent can delegate coding tasks to it
Browser automation using accessibility snapshots instead of screenshots
MCP server integration for DaVinci Resolve Studio
A Jetbrains IDE IntelliJ plugin aimed to provide coding agents the ability to leverage intelliJ's indexing of the codeba