{"id":50271495,"url":"https://github.com/kup-ip/the-bridge","last_synced_at":"2026-06-12T00:01:22.723Z","repository":{"id":348132803,"uuid":"1183830890","full_name":"KUP-IP/the-bridge","owner":"KUP-IP","description":"Native macOS menu-bar app that turns your Mac into an MCP server for Notion AI agents and local coding clients.","archived":false,"fork":false,"pushed_at":"2026-06-04T22:14:52.000Z","size":17899,"stargazers_count":6,"open_issues_count":4,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-04T23:05:48.281Z","etag":null,"topics":["apple-script","automation","chrome-automation","macos","mcp","menu-bar-app","model-context-protocol","notion","swift","swiftui"],"latest_commit_sha":null,"homepage":"https://kup.solutions/notion-bridge","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/KUP-IP.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-03-17T01:48:15.000Z","updated_at":"2026-06-04T18:12:29.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/KUP-IP/the-bridge","commit_stats":null,"previous_names":["kup-ip/notion-bridge","kup-ip/the-bridge"],"tags_count":20,"template":false,"template_full_name":null,"purl":"pkg:github/KUP-IP/the-bridge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KUP-IP%2Fthe-bridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KUP-IP%2Fthe-bridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KUP-IP%2Fthe-bridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KUP-IP%2Fthe-bridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/KUP-IP","download_url":"https://codeload.github.com/KUP-IP/the-bridge/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KUP-IP%2Fthe-bridge/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34222709,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-11T02:00:06.485Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apple-script","automation","chrome-automation","macos","mcp","menu-bar-app","model-context-protocol","notion","swift","swiftui"],"created_at":"2026-05-27T18:00:31.818Z","updated_at":"2026-06-12T00:01:22.707Z","avatar_url":"https://github.com/KUP-IP.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# The Bridge\n\n**A native macOS menu-bar app that turns your Mac into an MCP server for Notion AI agents and local coding clients.**\n\nThe Bridge exposes local Mac capabilities and connected services as MCP tools over **Streamable HTTP**, **legacy SSE**, and **stdio**. It is built in Swift 6.2 for macOS 26+ on Apple Silicon and is designed to be always-on, auto-launched, and safe enough for daily operator use.\n\n**~173 tools** across 25 module groups · **3 transports** · **3-tier security model** · **Customer-owned Cloudflare Tunnel support** · **Liquid Glass UI** (v3.6+)\n\n**Latest release:** [v3.6.0](https://github.com/KUP-IP/the-bridge/releases/tag/v3.6.0) — Liquid Glass complete (May 2026). Existing v3.4.x installs auto-update via Sparkle.\n\n**Product page:** https://kup.solutions/notion-bridge\n\n\u003e **Naming history:** \"NotionBridge\" was the product's original name. As of v3.6.0 the user-facing brand is **The Bridge**. The Swift target, bundle identifier (`kup.solutions.notion-bridge`), and Keychain service name (`com.notionbridge`) are intentionally preserved — that keeps existing user data continuous across the rename.\n\n---\n\n## What this repo is\n\nThis is the product repository for **The Bridge** (Swift target name `NotionBridge`).\n\nIt is not a generic Swift experiment and it is not an open-source demo server. It is the source-available codebase for a commercial macOS product that bridges Notion agents, local coding tools, and the user's Mac.\n\nCurrent commercial posture:\n- Direct purchase is the primary distribution path.\n- No free tier is planned.\n- Setapp distribution may follow later.\n\n---\n\n## Current product surface\n\nThe Bridge currently ships ~173 tools organized into 25 module groups, surfaced collapsibly in **Settings → Tools** (PKT-877 ModuleGroup UI). Highlights below; the full registry is in-app.\n\n| Module | Tools | Notes |\n|---|---:|---|\n| ShellModule | 2 | shell execution and approved scripts |\n| FileModule | 12 | files, directories, metadata, clipboard |\n| MessagesModule | 6 | iMessage and SMS read/send tooling |\n| SystemModule | 3 | system info, processes, notifications |\n| ContactsModule | 4 | CNContactStore search, get, resolve — no Contacts.app required |\n| NotionModule | 21 | Notion pages, blocks, databases, data sources, comments, files, queries |\n| SessionModule | 3 | session status and tool registry introspection |\n| AppleScriptModule | 1 | in-process AppleScript execution |\n| AccessibilityModule | 5 | AX tree, inspection, and actions |\n| ScreenModule | 5 | capture, OCR, recording, screen analysis |\n| ChromeModule | 5 | tabs, navigation, page reads, JS, screenshots |\n| CredentialModule | 4 | Keychain-backed credential storage |\n| PaymentModule | 1 | Stripe payment execution |\n| SkillsModule | 3 | `fetch_skill`, `list_routing_skills`, `manage_skill` |\n| ConnectionsModule | 5 | connection inventory, health, validation |\n| BuiltinModule | 1 | `echo` (registered in `ServerManager`, not a Swift `*Module` type) |\n| **Total** | **~173** | Across 25 ModuleGroups. Includes dynamic Stripe MCP tools (currently 26 when configured) and the v3.5+ additions: CommandStore (10-slot favorites), StandingOrders (per-client overlays), JobsManager (launchd-backed schedules), Git/Gh, BgProcess, LSP, Snippets, Dev, DevServer, Lighthouse, Playwright, Vitest, Wrangler |\n\nCore product traits:\n- Native macOS menu-bar app with onboarding, settings, and a status popover\n- **Liquid Glass UI** (v3.6+) — BridgeGlassCard, BridgeGlassBubble, dep-link chips, ModuleGroup cards, Standing Orders composer with per-client overlays\n- **Command Bridge popup** — global hotkey (⌃⌥⌘C default) opens a bottom-anchored SwiftUI tray with 10 favorite-slot bubbles + substring search + recents\n- Auto-launch via `SMAppService`\n- Streamable HTTP and legacy SSE on the same local server surface\n- stdio support for local clients such as Claude Code and Cursor\n- Local-first security gate with audit logging + **dispatch fail-closed** (disabled tool groups return typed `BridgeToolError.moduleGroupDisabled`, never silent failure)\n- Optional remote access through a customer-owned Cloudflare Tunnel\n\n---\n\n## Installation\n\n### Option 1: Download a release\n\n1. Download the latest DMG from [GitHub Releases](https://github.com/KUP-IP/the-bridge/releases).\n2. Open the DMG.\n3. Drag **The Bridge** (`NotionBridge.app` in the DMG; renamed on install) into `/Applications`.\n4. Launch the app and complete onboarding.\n\n### Option 2: Build from source\n\n```bash\ngit clone https://github.com/KUP-IP/the-bridge.git\ncd Notion-bridge\nmake app\n```\n\nThe app bundle is written to `.build/NotionBridge.app`.\n\n\u003e **Install naming:** The Swift target is `NotionBridge` (no space), so build output and DMG contents use `NotionBridge.app`. The Finder display name is **Notion Bridge** (with space), set by `CFBundleName` / `CFBundleDisplayName` in `Info.plist`. `make install` places the app at `/Applications/The Bridge.app` to match the display name. Both names refer to the same product.\n\n---\n\n## Requirements\n\n| Requirement | Version | Notes |\n|---|---|---|\n| macOS | 26.0+ | Tahoe or later |\n| Hardware | Apple Silicon | ARM64 only |\n| Xcode | 26.0+ | Needed for building from source |\n| Swift | 6.2+ | Defined by `Package.swift` |\n| Git | 2.39+ | For cloning and release workflows |\n\n---\n\n## Configuration\n\nPrimary configuration path:\n\n```text\n~/.config/notion-bridge/config.json\n```\n\nThe Bridge supports:\n- Notion workspace connections\n- connection health checks\n- customer-owned remote-access configuration\n- local security preferences\n\nIf you are using Notion tools, add a valid Notion integration token through the app's connection flow or config file.\n\n### Factory reset (Settings → Maintenance)\n\n**Factory Reset** clears local config, Keychain entries for The Bridge, resets macOS permissions for the app, and reloads in-memory workspace connection state. **Skills** are cleared to an **empty** list.\n\n**Credentials** (Settings → Credentials) are **opt-in**: enable “Keychain credentials \u0026 MCP tools” to use `credential_*` and `payment_execute` with stored payment methods. When disabled, those MCP tools are omitted from listings and fail closed if called.\n\nIf you launch the app with **`NOTION_API_TOKEN`** or **`NOTION_API_KEY`** set in the environment, Notion can still resolve a token after reset (that path is intentional for developers). Unset those variables when testing a truly empty workspace. Restart the app after reset so permission and connection UIs stay consistent.\n\n---\n\n## Transport surface\n\n### Streamable HTTP\n\n```text\nPOST http://127.0.0.1:9700/mcp\n```\n\nThis is the primary HTTP MCP endpoint. The listener is bound to **loopback** only. For remote agents (e.g. cloud IDEs) that reach your Mac through an **HTTPS tunnel** to that port, set **Settings → Connections → Remote access → Tunnel URL** to your tunnel’s base URL (for example `https://xyz.trycloudflare.com`). That extends Streamable HTTP **Origin** / **Host** validation to include the tunnel hostname while keeping the default localhost-only behavior when the field is empty.\n\n### Remote MCP security\n\nWhen a tunnel URL is set, **`POST /mcp` requires** a configured **MCP remote token** in the same settings section (generate/copy there) and matching **`Authorization: Bearer …`** in your MCP client. Without a token, new MCP sessions are rejected (fail closed). With an **empty** tunnel URL, local use is unchanged and a bearer is optional (you can still set a token to harden localhost-only clients). Tokens are stored in the **Keychain** in the app; **`com.notionbridge.mcpBearerToken`** remains a legacy read path. For defense in depth at the edge, operators can put **Cloudflare Access** in front of the tunnel hostname — see [docs/operator/cloudflare-access-notion-bridge.md](docs/operator/cloudflare-access-notion-bridge.md). Browser-based clients such as Claude chat generally cannot supply Cloudflare service-token headers, and Cloudflare browser challenges or Browser Integrity Check on `/mcp` can block valid MCP traffic before it reaches the app. In that case, use a narrow path-scoped bypass for `POST /mcp` and rely on the NotionBridge bearer token at the app layer.\n\n### Legacy SSE\n\n```text\nGET  http://127.0.0.1:9700/sse\nPOST http://127.0.0.1:9700/messages\n```\n\nThis is retained for clients that still use split SSE transport behavior.\n\n### stdio\n\nUse stdio when connecting local clients such as Claude Code or Cursor directly to the app process.\n\n#### Using Bridge with Antigravity\n\nGoogle Antigravity enforces a strict 100-tool limit per MCP server, whereas The Bridge exposes ~173 tools. To use Bridge with Antigravity, we have curated a subset of ~84 tools to stay under the limit.\n\nYou can launch the Bridge process with a `--multi-instance` flag (bypasses single-instance GUI guard) and `--allow-tools` flag pointing to the Antigravity allowlist:\n\n```json\n{\n  \"mcpServers\": {\n    \"Bridge MCP\": {\n      \"command\": \"/path/to/NotionBridge\",\n      \"args\": [\n        \"--multi-instance\",\n        \"--allow-tools\",\n        \"/path/to/the-bridge/configs/antigravity-allowlist.json\"\n      ]\n    }\n  }\n}\n```\n\n---\n\n## Security model\n\nThe Bridge currently uses a **3-tier execution model**:\n\n- **Open**\n\t- Executes immediately\n\t- Intended for read-only or low-risk operations\n- **Notify**\n\t- Executes immediately\n\t- Sends a post-execution macOS notification\n- **Request**\n\t- Requires explicit approval before execution\n\t- Used for sensitive or high-impact actions\n\nThe security gate also enforces command-aware escalation rules, sensitive-path handling, and handoff behavior for commands that should not run automatically.\n\n---\n\n## Permissions\n\nDepending on the tools you use, The Bridge may require:\n- Auto-prompted on first launch: Contacts, Notifications, and Automation target registration\n- Manual in System Settings: Accessibility, Screen Recording, and Full Disk Access\n- Separate grants for Contacts privacy access and Automation access to Contacts.app\n\nThe onboarding flow and Settings window surface current grant state, trigger native prompts when macOS allows it, and deep-link to recovery panes when manual re-authorization is required.\n\n---\n\n## Build and test\n\n```bash\nmake build\nmake test\nmake app\nmake dmg\n```\n\nOther useful targets:\n\n```bash\nmake clean\nmake install\nmake install-copy    # or: make install-agent-safe — copy .app to /Applications without full notarize (agent-safe)\nmake release\n```\n\nSparkle cache-busting is handled at the app level via httpHeaders (PKT-431). Pre-release manual QA: [docs/pre-ship-qa-checklist.md](docs/pre-ship-qa-checklist.md). Local MCP smoke (app running): `python3 scripts/qa_local_mcp_smoke.py`.\n\n---\n\n## Repo structure\n\n```text\nthe-bridge/\n├── NotionBridge/\n│   ├── App/\n│   ├── Config/\n│   ├── Modules/\n│   ├── Notion/\n│   ├── Security/\n│   ├── Server/\n│   └── UI/\n├── NotionBridgeTests/\n├── .github/\n├── Package.swift\n├── Makefile\n├── README.md\n├── SECURITY.md\n└── AGENTS.md\n```\n\n---\n\n## Security disclosures\n\nReport security issues per [SECURITY.md](SECURITY.md) (scope, out-of-scope, and contact).\n\n## Public updates (Sparkle)\n\nThe app’s `SUFeedURL` (see `Info.plist`) points at the **Sparkle appcast** (`appcast.xml`). For automatic updates to work for end users, that URL must return valid XML **without** logging into GitHub:\n\n- **Option A — Public GitHub repo:** Keep the default `https://raw.githubusercontent.com/KUP-IP/the-bridge/main/appcast.xml` and set the repository to **public** (anonymous `curl` / incognito browser must show XML).\n- **Option B — Private repo:** Host `appcast.xml` at any **public HTTPS** URL you control (e.g. CDN or static site), then set `SUFeedURL` to that URL and ship a new build. The file must match the repo’s generated appcast (`make dmg` / `make appcast`); **`length`** and **`sparkle:edSignature`** must match the exact DMG you publish.\n\nVerify locally: `make check-appcast` (committed `appcast.xml` vs `Info.plist`), then `make verify-sparkle-feed` (reads `SUFeedURL` from `Info.plist` and curls the live feed).\n\n### Purchase download (kup.solutions)\n\nStripe fulfillment uses the Cloudflare Worker in the **`kup.solutions`** repo (`workers/nb-fulfillment`). After each release:\n\n1. Run **`make dmg`** in this repo — artifact is **`.build/the-bridge-v$(VERSION).dmg`**, where **`VERSION`** is **`CFBundleShortVersionString`** in **`Info.plist`** (same as **`DMG_NAME`** in the Makefile).\n2. Upload that file to R2 bucket **`nb-downloads`** with object key **`DMG_OBJECT_KEY`** from **`kup.solutions/workers/nb-fulfillment/wrangler.toml`** (must match the filename exactly).\n3. Deploy the worker if **`DMG_OBJECT_KEY`** changed: **`cd workers/nb-fulfillment \u0026\u0026 npx wrangler deploy --env production`**.\n\nUntil the new object exists in R2, paid downloads return **500** (“Download artifact not found”).\n\n## License and distribution\n\nThe Bridge is **source-available commercial software**.\n\nThis repository is licensed under the **KUP Solutions Source-Available License** (Version 1.0, April 2026). You may view and reference the source code. Copying, modification, redistribution, derivative works, and commercial use are prohibited without written permission from KUP Solutions.\n\nSee [`LICENSE`](LICENSE) for the full license text. See also [`PRIVACY.md`](PRIVACY.md) and [`TERMS.md`](TERMS.md).\n\n### Commercial use\n\nFor commercial use of The Bridge, a separate **Commercial Use License** is required. See [`COMMERCIAL_LICENSE.md`](COMMERCIAL_LICENSE.md) for the full terms and purchase at [thebridge.kup.solutions/pricing](https://thebridge.kup.solutions/pricing).\n\n---\n\n## LSP server prerequisites (optional, for `lsp_*` tools)\n\nThe `lsp_*` tools (PKT-745, v2.2 · 2.3) wrap external Language Server Protocol implementations. The tools register and report `capability_missing` if the underlying servers are absent, so they are safe to leave uninstalled — they only become functional once the matching server is on disk. (The Bridge's `Tools` group `lsp` cleanly fails-closed via `BridgeToolError.moduleGroupDisabled` when the operator toggles the entire group off in Settings.)\n\n| Language    | LSP server                  | Install                                                                                                                       |\n|-------------|-----------------------------|-------------------------------------------------------------------------------------------------------------------------------|\n| TypeScript / JavaScript | `typescript-language-server` | `npm install -g typescript-language-server typescript`                                                                        |\n| Swift       | `sourcekit-lsp`             | Ships with the Xcode toolchain (`/Applications/Xcode.app/...`). Falls back to Command Line Tools (`xcode-select --install`).  |\n\nProbe-supported install locations (checked in order):\n\n- **typescript-language-server:** `/opt/homebrew/bin`, `/usr/local/bin`, `~/.npm-global/bin`, `~/.local/bin`\n- **sourcekit-lsp:** Xcode default toolchain, then CommandLineTools\n\nIf you install via a non-standard npm prefix, symlink the binary into one of the supported directories.\n\n### LSP session supervision (`lsp_session_list`)\n\nLSP servers are long-running processes; The Bridge supervises them out-of-band from the short-lived shell processes managed by `bg_process_*`. Each `(language, workspaceRoot)` pair gets a single `LspSession` lazy-spawned on first request, idle-disposed after 15 minutes of inactivity, and observable via `lsp_session_list` (PID, server name/version, spawn / last-used timestamps, idle seconds, request count, open-file count).\n\n- **`lsp_session_list`** — LSP server processes only (typescript-language-server, sourcekit-lsp). Use this for LSP-specific lifecycle questions: “is the TS server up?”, “how many open files does the Swift session have?”, “when will it idle out?”.\n- **`bg_process_list`** — Foreground-detached shell processes spawned via `bg_process_*` (long-running builds, watchers, dev servers). Use this for user-launched commands; LSP servers are **not** listed here.\n\nThe two surfaces are deliberately separated so observability for LSP supervision (which has its own RPC lifecycle, didOpen tracking, and capability probe) does not collide with generic shell lifecycle (which has none of those). When debugging cross-cutting state, query both.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkup-ip%2Fthe-bridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkup-ip%2Fthe-bridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkup-ip%2Fthe-bridge/lists"}