Skip to main content
Glama
README.md
# Oppen Apple Bridge

[![Release](https://img.shields.io/github/v/release/HaobinZhou/OppenAppleBridge-MCP)](https://github.com/HaobinZhou/OppenAppleBridge-MCP/releases/latest)
[![Tests](https://github.com/HaobinZhou/OppenAppleBridge-MCP/actions/workflows/tests.yml/badge.svg)](https://github.com/HaobinZhou/OppenAppleBridge-MCP/actions/workflows/tests.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)

English | [简体中文](README.zh-CN.md)

Turn a conversation into a reminder, a calendar event, or a note on your Mac.

After talking something through with an AI assistant, you usually still have to open another app and type it all in again. Oppen Apple Bridge connects that last step: a remote MCP client can ask your Mac to create the item through an Apple Shortcut.

Once connected, you can ask things like:

> Remind me tomorrow at 3 pm to submit the funding application. Add a note to bring the printed form.
>
> Put our team meeting on Friday from 2 to 3 pm, in meeting room A.
>
> Save the points we just discussed as a note called “Meeting prep.”

Your assistant interprets the request and calls a tool. The bridge handles the local app. There is no model bundled with this project. Tunnel mode needs an OpenAI runtime key for tunnel access, not for running a model.

**v0.3.1 · macOS · Python 3.13+ · MIT**

[Get started](#get-started) · [Tools](#tools) · [Deployment guide (中文)](docs/deployment.md)

![ChatGPT creates a Funding Application list and a reminder in Apple Reminders.](docs/assets/demo.gif)

Create a list and a reminder from one request. Waiting time is sped up.

## What it does

| Tool | What it creates |
| --- | --- |
| `apple_create_reminder` | An ordinary reminder with a due date, time, notes, and a choice of list |
| `apple_create_reminder_list` | An iCloud Reminders list; returns the existing list if its name already exists uniquely |
| `apple_create_calendar_event` | A timed event in a chosen calendar, with a location and notes |
| `apple_create_note` | A plain-text note in a chosen iCloud folder |
| `apple_bridge_health` | Nothing—it checks that the local Shortcut responds |

By default, items go into a list, calendar, or folder named **Oppen Apple Bridge**. You can choose another destination in each tool call. Your system default list is not changed.

This release only creates items. Searching, editing, completing, and deleting existing records are not implemented yet. Calendar events do not support all-day events, recurrence, or invitations; notes do not support attachments.

**Apple's Urgent reminder property is not supported.** High priority is not a substitute, and the tool does not expose an `urgent` parameter. A Reminders *list* holds reminders; creating a group of lists is also outside the current tools.

## How it works

```text
ChatGPT → OpenAI Secure MCP Tunnel → private stdio bridge
                 OR
Remote MCP client → HTTPS + OAuth → loopback Python service
    ↓ shortcuts CLI, with JSON over stdin
Oppen Apple Bridge Shortcut
    ↓ macOS application scripting interfaces
Reminders / Calendar / Notes
```

The service handles authentication, permissions, and input validation. The Shortcut handles Apple apps. It does not simulate mouse clicks or keystrokes, and user input is never assembled into a shell command.

This is a single-owner service for a Mac you control. The Mac must be awake, online, and logged in. Reminders and Notes use iCloud; Calendar uses the writable calendar you choose. It is not a Linux-hosted service or a multi-user account system.

## Get started

**New in v0.3.1: OpenAI Secure MCP Tunnel and a guided Mac installer.** You do not need FRP, your own domain, or a public server for this mode.

Before installing, check that you can access [OpenAI Platform → Tunnels](https://platform.openai.com/settings/organization/tunnels). You need a Tunnel ID and a **runtime API key with Tunnels Read + Use permissions**. Account/workspace availability is controlled by OpenAI; a ChatGPT subscription alone is not a guarantee of access. Do not use an admin key for the running service.

### Download and install

**[Download for Mac — complete installation package](https://github.com/HaobinZhou/OppenAppleBridge-MCP/releases/download/v0.3.1/OppenAppleBridge-v0.3.1-macos.zip)**

1. Unzip the download and move the whole folder to a permanent location.
2. Double-click **Install.command**.
3. Follow the prompts. The Shortcut is already included; nothing else needs downloading separately.

If macOS blocks double-clicking, open Terminal in the extracted folder and run `bash Install.command`. The installer is not a notarized Mac app.

The installer checks the packaged files, installs Homebrew if needed, installs Python and the official `tunnel-client`, prepares the Python environment, opens the signed Shortcut, and starts a dedicated login service. It asks you to:

1. Import **Oppen Apple Bridge** and approve macOS first-use permissions. There are no actions to assemble.
2. Enter your Tunnel ID and runtime key (hidden input, saved locally with `0600` permissions).
3. Choose whether to enable Calendar and Notes. Reminders and list creation are enabled by default.
4. Select the tunnel in [ChatGPT connector settings](https://chatgpt.com/#settings/Connectors), after the installer reports `ready: true`.

This is guided installation, not zero-interaction setup: OpenAI account setup and Apple's import/permission dialogs still need you. The Mac must remain awake, online, and logged in.

**Tunnel authentication:** the local bridge uses a private stdio pipe, not an HTTP port. OpenAI tunnel permissions control access; select **None** for additional MCP authentication in this mode. There is no bridge-password page. Anyone you grant access to this tunnel can use the capabilities enabled in its local configuration. Never share it more broadly than intended.

Try: “Create a Reminders list called Funding Application, then remind me in 10 minutes to submit the form in that list.” Calendar and Notes destinations must already exist if those capabilities are enabled.

### Existing HTTPS / FRP users

Your existing setup still uses the password-protected OAuth flow. Follow [HTTPS setup](docs/https-setup.md); you do not need to switch to Tunnel. The installer does not modify FRP configuration. Do not run a second copy of the same tunnel ID during an upgrade.

See [Tunnel setup and troubleshooting](docs/tunnel.md) for restart, logs, upgrades, and account requirements.

## Tools

| Tool | Required arguments | Optional arguments |
| --- | --- | --- |
| `apple_bridge_health` | None | None |
| `apple_create_reminder` | `title`, `due_at` | `notes`, `list` |
| `apple_create_reminder_list` | `name` | None |
| `apple_create_calendar_event` | `title`, `start_at`, `end_at` | `calendar`, `location`, `notes` |
| `apple_create_note` | `title`, `body` | `folder` |

Use ISO 8601 timestamps with seconds and an explicit time zone, such as `2027-01-15T15:00:00+08:00`. An event's end must be later than its start. Note bodies are plain text: line breaks are preserved, and HTML-like text is escaped.

Example arguments for `apple_create_reminder`:

```json
{
  "title": "Submit funding application",
  "due_at": "2027-01-15T15:00:00+08:00",
  "notes": "Bring the printed form",
  "list": "Oppen Apple Bridge"
}
```

## Keep it running

For **Tunnel mode**: `.venv/bin/python tunnel.py status`, `restart`, `stop`, or `logs`. Use `configure` followed by `install` to change the tunnel key or capabilities.

The commands below apply to **HTTPS / OAuth mode**.

After checking the foreground service, stop it with `Ctrl+C` and install the LaunchAgent:

```sh
.venv/bin/python service.py install
```

It starts at user login and restarts if the process exits.

```sh
.venv/bin/python service.py status
.venv/bin/python service.py restart
.venv/bin/python service.py logs
```

Change `APPLE_BRIDGE_PASSWORD` in `.env`, then restart to apply it. Passwords may contain **1–256 characters** and cannot be empty or contain newlines or NUL. Quote values containing spaces or `#`. Changing the password revokes existing grants; restarting with the same password preserves them.

Logs live in `.runtime/server.log`, `.runtime/launchd.log`, and `.runtime/launchd-error.log`. Stop the old service before moving the checkout. See the [deployment guide (中文)](docs/deployment.md) for service removal and troubleshooting.

## Data and permissions

The bridge uses the Apple apps already signed in on your Mac. It does not collect Apple ID credentials. OAuth grants separate permissions for reminders, lists, calendar events, and notes.

Request content passes through your chosen AI client as well as your Mac, so this is not an entirely local data flow. Routine server logs omit titles, bodies, and credentials. Live verification scripts save their test results under `.runtime/`.

**A timed-out creation may still have succeeded.** Check the app before retrying; another call can create a duplicate.

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for the development workflow and [the changelog](CHANGELOG.md) for release notes.

Bug reports with a macOS version, tool name, sanitized arguments, and the actual error are useful. Please leave passwords, the OAuth database, and private note content out of issues and attachments.

Run the tests with:

```sh
.venv/bin/python -m pytest -q
```

They cover input validation, OAuth, password changes, scope isolation, and Shortcut input handling. Live scripts can also create and read back real records; those are separate checks, described in the deployment guide.

A few places to start:

| File | Responsibility |
| --- | --- |
| [applebridge/server.py](applebridge/server.py) | MCP tools and permission checks |
| [applebridge/shortcut.py](applebridge/shortcut.py) | Input validation, CLI calls, and response checks |
| [applebridge/auth.py](applebridge/auth.py) | OAuth, passwords, and tokens |
| [repair/bridge.js](repair/bridge.js) | Application scripting inside the Shortcut |
| [repair/build_shortcut.py](repair/build_shortcut.py) | Shortcut plist generation |

If you change the Shortcut script, rebuild, validate, sign, and import the resulting file. Updating the Python service alone does not update an imported Shortcut.

## License and acknowledgments

[MIT](LICENSE). The OAuth implementation builds on OppenSteward-MCP's single-owner design and retains its license notice. Shortcut building, validation, and signing use [Shortcuts Playground](https://github.com/viticci/shortcuts-playground-plugin).

The documentation takes cues from [apple-mcp](https://github.com/griches/apple-mcp), [Apple Events MCP Server](https://github.com/FradSer/mcp-server-apple-events), and the [MCP Feature Reference Server](https://github.com/modelcontextprotocol/example-remote-server). They are also worth exploring for other approaches to Apple apps and remote MCP.