trackmcp
Back to directory
achiya-automation

safari-mcp

View on GitHub

Native Safari browser automation for AI agents. 97 tools via AppleScript — zero overhead, keeps logins, runs silently in background. Drop-in alternative to Chrome DevTools MCP with 40-60% less CPU/heat on Apple Silicon.

181 stars JavaScriptOthers Updated Sep 4, 2026
applescriptbrowser-automationclaudecursormacosmcp-servermodel-context-protocolsafariwebkitapple-siliconai-agentsweb-automationwindsurfai-toolsautomationdevtoolsllm-toolsclaude-codemcpsafari-mcp

Documentation

❌ Without Safari MCP

Your AI agent needs to browse. So it either:

  • Spins up Chromium via Playwright — with no logins, no cookies, no sessions
  • Uses Chrome DevTools MCP — and melts your fan running a second browser
  • Relies on headless scrapers — blocked by Cloudflare, reCAPTCHA, and bot detection

✅ With Safari MCP

Your AI drives the Safari you're already logged into — Gmail, GitHub, Ahrefs, Slack, banking.

Native WebKit. ~60% less CPU. Background operation. 97 tools. One `npx` command. macOS only.

> 📰 Featured on freeCodeCamp: How to Connect Your AI Coding Agent to a Browser on macOS · HackerNoon: Reverse-Engineering React, Shadow DOM, and CSP

> 🍎 Apple shipped an official Safari MCP (July 2026 — Safari Technology Preview 247+ and the Safari 27 beta). It's built on `safaridriver` for isolated debugging sessions. safari-mcp drives the real Safari you're already logged into — on the stable Safari that ships with macOS today, with 97 tools. See the full comparison below.


Highlights

  • 97 tools — navigation, clicks, forms, screenshots, network, storage, accessibility, and more
  • Zero heat — native WebKit on Apple Silicon, ~60% less CPU than Chrome
  • Your real browser — keeps all logins, cookies, sessions (Gmail, GitHub, Ahrefs, etc.)
  • Background operation — Safari stays in the background, no window stealing
  • No browser dependencies — no Puppeteer, no Playwright, no WebDriver, no Chrome
  • Persistent process — reuses a single osascript process (~5ms per command vs ~80ms)
  • Framework-compatible — React, Vue, Angular, Svelte form filling via native setters

In users' own words

Not solicited testimonials — quotes lifted from the public issue tracker, each linked to the thread it came from.

> "I run multiple Pi sessions/subagents against my normal Safari profile in parallel. Sharing its cookies and logins is intentional."

> — @maxim, on running concurrent agents against a real browser

> "The server has a deliberate tab-ownership model … the code is careful about this, and for the default case that's the right safety posture."

> — @turner-moore, on why the guards refuse to touch your tabs

> "Direct local validation from the package: Safari MCP doctor 6/6."

> — @jrepp, who found and fixed a queue-alignment bug in the focus helper


Quick Start

Prerequisites

  • macOS (any version with Safari)
  • Node.js 20+
  • Safari → Settings → Advanced → Show features for web developers
  • Safari → Develop → Allow JavaScript from Apple Events

Install (one command)

bash
npx safari-mcp

That's it — no global install needed. Or install permanently:

bash
npm install -g safari-mcp

Configure your MCP client

All clients run Safari MCP the same way — `npx safari-mcp`. Pick your editor:

Claude Code

bash
claude mcp add safari -- npx safari-mcp

Or edit `~/.mcp.json`:

json
{
  "mcpServers": {
    "safari": {
      "command": "npx",
      "args": ["safari-mcp"]
    }
  }
}

Claude Desktop

Edit `~/Library/Application Support/Claude/claude_desktop_config.json`:

json
{
  "mcpServers": {
    "safari": {
      "command": "npx",
      "args": ["safari-mcp"]
    }
  }
}

Restart Claude Desktop after saving.

Cursor

One-click: **Install in Cursor**

Or edit `.cursor/mcp.json` in your project:

json
{
  "mcpServers": {
    "safari": {
      "command": "npx",
      "args": ["safari-mcp"]
    }
  }
}

VS Code / VS Code Insiders

One-click: **Install in VS Code**

Or edit `.vscode/mcp.json`:

json
{
  "servers": {
    "safari": {
      "type": "stdio",
      "command": "npx",
      "args": ["safari-mcp"]
    }
  }
}

Windsurf

Edit `.windsurf/mcp.json` in your project (or `~/.codeium/windsurf/mcp_config.json` globally):

json
{
  "mcpServers": {
    "safari": {
      "command": "npx",
      "args": ["safari-mcp"]
    }
  }
}

Cline

Open Cline in VS Code → click the MCP icon → Edit MCP Settings → add:

json
{
  "mcpServers": {
    "safari": {
      "command": "npx",
      "args": ["safari-mcp"]
    }
  }
}

Continue

Edit `~/.continue/config.yaml` (or `.continue/config.yaml` in workspace):

yaml
mcpServers:
  - name: safari
    command: npx
    args:
      - safari-mcp

Goose

Edit `~/.config/goose/config.yaml`:

yaml
extensions:
  safari:
    name: safari
    type: stdio
    cmd: npx
    args:
      - safari-mcp
    enabled: true

LM Studio

Open LM Studio → SettingsMCP ServersAdd Server:

  • Name: `safari`
  • Command: `npx`
  • Args: `safari-mcp`

Zed

Open Zed → Settings → search for "Context Servers" and add:

json
{
  "context_servers": {
    "safari": {
      "command": {
        "path": "npx",
        "args": ["safari-mcp"]
      }
    }
  }
}

Alternative: Homebrew

bash
brew install achiya-automation/tap/safari-mcp

Alternative: from source

bash
git clone https://github.com/achiya-automation/safari-mcp.git
cd safari-mcp && npm install

Usage Workflow

The recommended pattern for AI agents using Safari MCP:

code
1. safari_snapshot        → Get page state (accessibility tree)
2. safari_click/fill/...  → Interact with elements by ref
3. safari_snapshot        → Verify the result

Element targeting — tools accept multiple targeting strategies:

StrategyExampleBest for
CSS selector`#login-btn`, `.submit`Unique elements
Visible text`"Sign In"`, `"Submit"`Buttons, links
Coordinates`x: 100, y: 200`Canvas, custom widgets
Ref from snapshot`ref: "e42"`Any element from accessibility tree

> Tip: Start with `safari_snapshot` to get element refs, then use refs for precise targeting. This is faster and more reliable than CSS selectors.


Running several agents at once

Multiple agents or subagents driving one Safari at the same time will fight over the active tab — unless you run them against a shared HTTP daemon instead of one process per client:

bash
SAFARI_MCP_HTTP=1 SAFARI_MCP_HTTP_PORT=9225 npx safari-mcp

Then point every client at it:

json
{ "mcpServers": { "safari-mcp": { "type": "http", "url": "http://127.0.0.1:9225/mcp" } } }

One daemon, many sessions — and each session gets its own tab state. The server keys `activeTabIndex`, the ownership flag and a unique tab marker off the MCP session id, so session A physically cannot read or steer session B's tab.

Two properties make this safe rather than merely tidy:

  • Tab identity is a marker, not an index. Each session stamps a unique id into the page it opens, so ownership survives navigation *and* survives the user reordering or closing other tabs. An index alone would silently drift onto the wrong tab.
  • It fails closed. If a session's marked tab can't be re-found, every tool refuses instead of falling back to whatever tab is in front — because that tab is usually yours:
code
Tab tracking lost — refusing to fall back to "current tab of window"
  (would target the user's active tab). Call safari_new_tab to reopen.

This also drops process count sharply: ~17 node processes for 17 concurrent sessions becomes 1.

`SAFARI_PROFILE` stays optional — leave it unset and sessions bind to your ordinary Safari windows, cookies and logins intact. Details in docs/http-transport-design.md.

Prefer stdio (one process per agent) over a persistent daemon? That works too — isolation then comes from the process boundary itself. One caveat: if your client multiplexes agents through mcporter, mcporter caches a single MCP client for all of them — whichever transport you pick — so the server never sees distinct sessions and per-session isolation can't engage. mcporter-lanes (a pi extension by @maxim, born out of #76) fixes this upstream: each agent session gets its own daemon dir — and therefore its own safari-mcp — with an idle timeout so processes don't pile up.


Environment variables

VariableDefaultWhat it does
`SAFARI_MCP_HTTP`offRun one shared HTTP daemon instead of a process per client (see above).
`SAFARI_MCP_HTTP_PORT``9225`Port for that daemon.
`SAFARI_PROFILE`unsetBind sessions to a named Safari profile. Unset = your ordinary windows.
`SAFARI_MCP_RAISE_ON_NAVIGATE`offLet navigation bring Safari to the front, and stop the focus guard from putting your previous app back.
`SAFARI_MCP_SCREENSHOT_MAX_WIDTH`unsetDownscale every `safari_screenshot` to this pixel width (Retina captures are 2× the viewport). Per-call `maxWidth` overrides it.
`SAFARI_MCP_KEEPALIVE_TAB`offKeep one daemon-served page open in the profile window so Safari never parks the extension worker between commands.
`SAFARI_MCP_OPEN_WINDOW_CMD`unsetCommand run with the profile name when the profile window is absent (e.g. after a reboot). Must open the window without focusing Safari.

`SAFARI_MCP_RAISE_ON_NAVIGATE=1` is for agents whose whole point is *showing* you a page — a voice assistant answering "open YouTube", a demo driver. Everything else should leave it off: by default Safari MCP works in the background and hands focus back to whatever app you were using, so an agent can drive a page while you keep typing somewhere else.


Tools (97)

Click to expand the full tool list — organized by category

ToolDescription
`safari_navigate`Navigate to URL (auto HTTPS, wait for load)
`safari_go_back`Go back in history
`safari_go_forward`Go forward in history
`safari_reload`Reload page (optional hard reload)

Page Reading (3)

ToolDescription
`safari_read_page`Get title, URL, and text content
`safari_get_source`Get full HTML source
`safari_navigate_and_read`Navigate + read in one call

Click & Interaction (6)

ToolDescription
`safari_click`Click by CSS selector, visible text, or coordinates
`safari_double_click`Double-click (select word, etc.)
`safari_right_click`Right-click (context menu)
`safari_hover`Hover over element
`safari_click_and_wait`Click + wait for navigation
`safari_click_and_read`Click then return the updated page — saves a round-trip (React Router + full loads)

Form Input (11)

ToolDescription
`safari_fill`Fill input (React/Vue/Angular compatible)
`safari_clear_field`Clear input field
`safari_select_option`Select dropdown option
`safari_fill_form`Batch fill multiple fields
`safari_fill_and_submit`Fill form + submit in one call
`safari_type_text`Type real keystrokes (JS-based, no System Events)
`safari_press_key`Press key with modifiers
`safari_react_select_set`Set a react-select v5 value via React fiber — bypasses the menu UI
`safari_react_select_list_options`List a react-select v5 dropdown's options without opening it
`safari_replace_editor`Replace all content in a code editor (Monaco, CodeMirror, Ace, ProseMirror)
`safari_verify_state`Verify an editor's framework-level state matches expected — catch stale DOM before Submit

Screenshots & PDF (3)

ToolDescription
`safari_screenshot`Screenshot as PNG (viewport or full page)
`safari_screenshot_element`Screenshot a specific element
`safari_save_pdf`Export page as PDF

Scroll (3)

ToolDescription
`safari_scroll`Scroll up/down by pixels
`safari_scroll_to`Scroll to exact position
`safari_scroll_to_element`Smooth scroll to element

Tab Management (5)

ToolDescription
`safari_list_tabs`List all tabs (index, title, URL)
`safari_new_tab`Open new tab (background, no focus steal)
`safari_close_tab`Close tab
`safari_switch_tab`Switch to tab by index
`safari_wait_for_new_tab`Wait for a new tab (e.g. OAuth popup) and auto-switch to it

Wait (2)

ToolDescription
`safari_wait_for`Wait for element, text, or URL change
`safari_wait`Wait for specified milliseconds

JavaScript (1)

ToolDescription
`safari_evaluate`Execute arbitrary JavaScript, return result
`safari_eval_file`Execute JavaScript read from a file path (avoids huge inline scripts)

Element Inspection (4)

ToolDescription
`safari_get_element`Element details (tag, rect, attrs, visibility)
`safari_query_all`Find all matching elements
`safari_get_computed_style`Computed CSS styles
`safari_detect_forms`Auto-detect all forms with field selectors

Accessibility (2)

ToolDescription
`safari_accessibility_snapshot`Full a11y tree: roles, ARIA, focusable elements
`safari_snapshot`Accessibility tree with ref IDs for every interactive element — preferred way to see page state

Drag & Drop (1)

ToolDescription
`safari_drag`Drag between elements or coordinates

File Operations (2)

ToolDescription
`safari_upload_file`Upload file via JS DataTransfer (no file dialog!)
`safari_paste_image`Paste image into editor (no clipboard touch!)

Dialog & Window (2)

ToolDescription
`safari_handle_dialog`Handle alert/confirm/prompt
`safari_resize`Resize browser window

Device Emulation (2)

ToolDescription
`safari_emulate`Emulate device (iPhone, iPad, Pixel, Galaxy)
`safari_reset_emulation`Reset to desktop

Cookies & Storage (11)

ToolDescription
`safari_get_cookies`Get all cookies
`safari_set_cookie`Set cookie with all options
`safari_delete_cookies`Delete one or all cookies
`safari_local_storage`Read localStorage
`safari_set_local_storage`Write localStorage
`safari_delete_local_storage`Delete/clear localStorage
`safari_session_storage`Read sessionStorage
`safari_set_session_storage`Write sessionStorage
`safari_delete_session_storage`Delete/clear sessionStorage
`safari_export_storage`Export all storage as JSON (backup/restore sessions)
`safari_import_storage`Import storage state from JSON

Clipboard (2)

ToolDescription
`safari_clipboard_read`Read clipboard text
`safari_clipboard_write`Write text to clipboard

Network (6)

ToolDescription
`safari_network`Quick network requests via Performance API
`safari_start_network_capture`Start detailed capture (fetch + XHR)
`safari_network_details`Get captured requests with headers/timing
`safari_clear_network`Clear captured requests
`safari_mock_route`Mock network responses (intercept fetch/XHR)
`safari_clear_mocks`Remove all network mocks

Console (4)

ToolDescription
`safari_start_console`Start capturing console messages
`safari_get_console`Get all captured messages
`safari_clear_console`Clear captured messages
`safari_console_filter`Filter by level (log/warn/error)

Performance (2)

ToolDescription
`safari_performance_metrics`Navigation timing, Web Vitals, memory
`safari_throttle_network`Simulate slow-3g/fast-3g/4g/offline

Data Extraction (4)

ToolDescription
`safari_extract_tables`Tables as structured JSON
`safari_extract_meta`All meta: OG, Twitter, JSON-LD, canonical
`safari_extract_images`Images with dimensions and loading info
`safari_extract_links`Links with rel, external/nofollow detection

Advanced (7)

ToolDescription
`safari_override_geolocation`Override browser geolocation
`safari_list_indexed_dbs`List IndexedDB databases
`safari_get_indexed_db`Read IndexedDB records
`safari_css_coverage`Find unused CSS rules
`safari_analyze_page`Full page analysis in one call
`safari_doctor`Diagnose the macOS permission + daemon chain (Apple Events, Accessibility, Screen Recording, codesign) with per-failure fixes
`safari_reload_extension`Hot-reload the Safari MCP Bridge extension without a manual toggle

Automation (1)

ToolDescription
`safari_run_script`Run multiple actions in a single call (batch)

Native Input — CGEvent (4)

ToolDescription
`safari_native_click`OS-level mouse click (CGEvent, `isTrusted: true`) — bypasses WAF/bot detection when `safari_click` is blocked (405/403)
`safari_native_hover`OS-level cursor hover — triggers real `:hover`/`mouseenter` for tooltips and obfuscated UIs
`safari_native_type`Insert text via the real paste pipeline — ProseMirror/Slate/Draft.js process it natively so Submit sends real data
`safari_native_keyboard`OS-level keypress + modifiers to Safari, no focus steal — reaches React trust-gated handlers (Discord/Slack send)

iOS & WebKit Validation (4)

ToolDescription
`safari_inspect_viewport`Validate the `` tag for iOS Safari (device-width, zoom/WCAG, viewport-fit)
`safari_safe_area_insets`Read live safe-area-inset values + viewport-fit / `env()` usage (notch / Dynamic Island)
`safari_check_pwa`Audit iOS "Add to Home Screen" / PWA readiness (apple-touch-icon, manifest, theme-color, splash)
`safari_webkit_compat`Check page CSS against this Safari via `CSS.supports()` — unsupported props, missing `-webkit-` prefixes, known quirks

Security

Safari MCP runs locally on your Mac with minimal attack surface:

AspectDetail
NetworkNo remote connections — all communication is local (stdio + localhost)
PermissionsmacOS system permissions required (Screen Recording for screenshots)
DataNo telemetry, no analytics, no data sent anywhere
ExtensionCommunicates only with the local profile bridges (`localhost:9224/9228/9232/9236`), validated by Safari
CodeFully open source (MIT) — audit every line

Safari MCP vs Alternatives

FeatureSafari MCPChrome DevTools MCPPlaywright MCP
CPU/Heat🟢 Minimal🔴 High🟡 Medium
Your logins✅ Yes✅ Yes❌ No
macOS native✅ WebKit❌ Chromium❌ Chromium/WebKit
Browser dependenciesNoneChrome + debug portPlaywright runtime
Tools97~30~25
File uploadJS (no dialog)CDPPlaywright API
Image pasteJS (no clipboard)CDPPlaywright API
Focus steal❌ Background❌ Background❌ Headless
Network mocking
Lighthouse
Performance trace

> Tip: Use Safari MCP for daily browsing tasks (95% of work) and Chrome DevTools MCP only for Lighthouse/Performance audits.

vs Apple's Official Safari MCP (safaridriver)

In July 2026 Apple shipped an official Safari MCP server built on `safaridriver` — first in Safari Technology Preview 247, and now also in the Safari 27 beta. That's great validation for the category — and it's built for a different job. Apple's server drives an isolated WebDriver automation session for debugging; safari-mcp drives the real Safari you're already logged into.

It has not reached a stable Safari release yet: on macOS 26.5.2 with Safari 26.5.2, `safaridriver --help` lists `--port`, `--bidi`, `--enable` and `--diagnose`, and no `--mcp` (verified 2026-07-23). Check your own machine with `safaridriver --help | grep mcp` before assuming either way.

🦁 safari-mcp *(this repo)*Apple `safaridriver --mcp`
Your real logins / cookies✅ Your actual Safari⚠️ Isolated automation session — no access to AutoFill or browsing activity
Runs on✅ Stable Safari, every Mac⚠️ Safari Technology Preview 247+ or the Safari 27 beta — not in stable Safari 26.5
Background (no focus steal)✅ Yes❌ Dedicated window with a "controlled by automation" banner
Tools97~17
Storage (cookies, localStorage, IndexedDB)✅ 10 tools
Network mocking + throttling✅ Yes❌ Read-only network inspection
Device emulation (iPhone, iPad)✅ Yes⚠️ Viewport + media type only
Setup`npx safari-mcp`Enable "remote automation and external agents", then point your client at that build's `safaridriver --mcp`
Official Apple support❌ Community (MIT)✅ Apple, WebDriver-standard

> When Apple's server is the right pick: you specifically want a clean-room, WebDriver-standard session for compatibility debugging and you already run a preview or beta build. For everything else — daily automation on the browser you're already signed into, on the Safari that shipped with your Mac — safari-mcp is built for exactly that.

Why Safari MCP and Not the Other Safari MCP Projects?

There are several "safari-mcp" projects floating around. Here's how they compare:

Feature🦁 safari-mcp *(this repo)*lxman/safari-mcp-serverEpistates/MCPSafariHayoDev/safari-devtools-mcp
Tools97~1023~15
Install`npx safari-mcp`ManualBinary`npx`
EngineDual (Extension + AppleScript)WebDriverExtension onlyDevTools Protocol
Keeps your real Safari logins✅ Yes⚠️ Limited✅ Yes❌ Debug session
Background (no focus steal)✅ Yes❌ No⚠️ Sometimes✅ Yes
Storage tools (cookies, localStorage, IndexedDB)10002
Data extraction (tables, meta, images, links)4000
Network mocking✅ Yes❌ No❌ No❌ No
Device emulation (iPhone, iPad, Pixel)✅ Yes❌ No❌ No❌ No
File upload (no dialog)✅ JS DataTransfer❌ No❌ No❌ No
Image paste (no clipboard touch)✅ Yes❌ No❌ No❌ No
PDF export✅ Yes❌ No❌ No❌ No
Console capture4 tools011
Performance metrics + Web Vitals✅ Yes❌ No❌ No⚠️ Partial
Active maintenance✅ Multiple releases/week🟡 Sporadic🟡 Slow🟡 Slow
LicenseMITMITNone specifiedMIT
In MCP Registry
In Awesome MCP

> TL;DR — if you want the most complete Safari MCP with the smoothest install, the most tools, and active maintenance, this is the one.


Architecture

Safari MCP uses a dual-engine architecture — the Extension is preferred for speed and advanced capabilities, with AppleScript as an always-available fallback:

code
Claude/Cursor/AI Agent
        ↓ MCP Protocol (stdio)
   Safari MCP Server (Node.js)
        ↓                    ↓
   Extension (HTTP)     AppleScript + Swift daemon
   (~5-20ms/cmd)        (~5ms/cmd, always available)
        ↓                    ↓
   Content Script       do JavaScript in tab N
        ↓                    ↓
   Page DOM ←←←←←←←←←← Page DOM

Key design decisions:

  • Dual engine with automatic fallback — Extension is preferred; if not connected, AppleScript handles everything seamlessly
  • Persistent Swift helper — one long-running process instead of spawning per command (16x faster)
  • Tab-indexed operations — all JS runs on a specific tab by index, never steals visual focus
  • JS-first approach — typing, clicking, file upload all use JavaScript events (no System Events keyboard conflicts)
  • No `activate` — Safari is never brought to foreground

Safari Extension (Optional)

The Safari MCP Extension is optional but recommended. Without it, ~80% of functionality works via AppleScript alone. The extension adds capabilities that AppleScript cannot provide:

What the Extension Adds

CapabilityWith ExtensionAppleScript Only
Closed Shadow DOM (Reddit, Web Components)✅ Full access❌ Invisible
Strict CSP sites✅ Bypasses via MAIN world❌ Often blocked
React/Vue/Angular state manipulation✅ Deep (Fiber, ProseMirror)⚠️ Basic
Loading state detection (spinners, skeletons)✅ Smart detection❌ No
Dialog handling (alert/confirm)✅ Only AppleScript
Native OS-level click (CGEvent)✅ Only AppleScript
PDF export✅ Only AppleScript

> When do you need the extension? If you're automating modern SPAs with closed shadow DOM (e.g., Reddit), sites with strict Content Security Policy, or framework-heavy editors (Draft.js, ProseMirror, Slate).

Installing the Extension

The extension requires a one-time build with Xcode (free, included with macOS).

> Note for npm users: The `xcode/` directory is not included in the npm package.

> Clone the GitHub repository to build from source.

Prerequisites: Xcode (install from App Store — free)

bash
# 1. Clone the repo (the npm package does not include the Xcode project)
git clone https://github.com/achiya-automation/safari-mcp.git
cd safari-mcp

# 2. Build a clean, Apple Development-signed app
# If needed, first choose your Team in Xcode → Signing & Capabilities.
xcodebuild -project "xcode/Safari MCP/Safari MCP.xcodeproj" \
  -scheme "Safari MCP (macOS)" -configuration Release \
  -allowProvisioningUpdates clean build

# 3. Locate the signed app
APP_PATH=$(find ~/Library/Developer/Xcode/DerivedData/Safari_MCP-*/Build/Products/Release -name "Safari MCP.app" -maxdepth 2 | head -1)

# 4. Re-sign safari-helper with the Apple Events entitlement
# (helps macOS surface the TCC Automation prompt reliably)
codesign --sign - --force --entitlements safari-helper.entitlements safari-helper

# 5. Open the app (needed once so Safari registers the extension)
open "$APP_PATH"

> Do not ad-hoc re-sign `Safari MCP.app` with `codesign --deep --sign -`. That replaces the Apple Development identity on the wrapper and embedded extension; current Safari can then silently disable or mark the extension as removed. If a previous build was ad-hoc signed, run the `clean build` command above again.

Alternatively, open `xcode/Safari MCP/Safari MCP.xcodeproj` directly in Xcode, select your Apple ID under Signing & Capabilities, and click Run. A free personal Apple Developer account is sufficient for local use.

Then in Safari:

1. Safari → Settings → Advanced → enable Show features for web developers

2. Safari → Develop → Allow Unsigned Extensions (required each Safari restart)

3. Safari → Settings → Extensions → enable Safari MCP Bridge

The extension connects automatically to the first local bridge whose declared Safari profile matches its own. The default bridge ports are `9224`, `9228`, `9232`, and `9236`; a single-profile setup normally uses `9224`.

> Note: "Allow Unsigned Extensions" resets every time Safari restarts. You'll need to re-enable it in the Develop menu after each restart. The extension itself stays installed.

Toolbar icon status:

  • ON — connected to MCP server
  • OFF — manually disabled via popup
  • *(no badge)* — server not running, will auto-reconnect

macOS Permissions

Safari MCP needs these one-time permissions:

PermissionWhereWhy
JavaScript from Apple EventsSafari → Develop menuRequired for `do JavaScript`
Automation → SafariSystem Settings → Privacy & Security → AutomationRequired for all AppleScript-backed tools
Screen RecordingSystem Settings → Privacy & Security → Screen RecordingRequired for `safari_screenshot`
Accessibility (safari-helper)System Settings → Privacy & Security → AccessibilityRequired for `safari_native_click`, `safari_native_keyboard`, `safari_native_hover` and `safari_save_pdf`

Granting Accessibility to safari-helper (required for `safari_native_*`)

The `safari_native_click`, `safari_native_keyboard` and `safari_native_hover` tools inject OS-level `CGEvent` events into Safari without stealing focus. macOS requires the underlying helper binary to be approved in Accessibility before those events can reach a non-frontmost window.

1. Open System Settings → Privacy & Security → Accessibility.

2. Click `+` (unlock with your password if needed).

3. Navigate to the helper binary and add it:

    4. Make sure the toggle next to it is ON.

    The postinstall script re-signs the helper with a stable identifier (`com.achiya-automation.safari-mcp`) so this permission survives future upgrades — without that step, every `npm update` would silently revoke approval because the binary's adhoc-signed identifier changes per build.

    If `safari_native_click` reports success but the page doesn't react (no `isTrusted: true` click events fire), the helper is most likely missing this approval. The `safari_*` (non-`native_`) tools don't need it.

    Granting Automation → Safari (important for IDE users)

    macOS TCC grants Automation permission to the parent process that spawns the MCP server, not to `safari-mcp` itself. So you need to grant Automation → Safari to the app that runs Claude Code / Cursor / Windsurf — typically Visual Studio Code or Terminal.

    If the permission dialog never appears automatically, run this command once from a Terminal that already has Automation permission:

    bash
    osascript -e 'tell application "Safari" to get URL of current tab of window 1'

    That call registers the Terminal app in the Automation database and then triggers the prompt for Safari. After you approve it, subsequent MCP calls from any child process chain will work.


    Troubleshooting

    IssueFix
    "AppleScript error"Enable "Allow JavaScript from Apple Events" in Safari → Develop
    "Not authorized to send Apple events to Safari"Grant Automation → Safari to your IDE (see above)
    "Not authorized" after `npm update`Updating changes the binary's cdhash — macOS silently revokes Automation permission. Re-run the `osascript` one-liner above to re-grant it
    `safari_native_click` reports success but page doesn't reactAdd `safari-helper` to System Settings → Privacy & Security → Accessibility (see Granting Accessibility above). Confirm by attaching a `click` listener with `{capture:true}` in the page console — without the grant, no `isTrusted: true` event fires
    Screenshots emptyGrant Screen Recording permission to Terminal/VS Code
    Tab not foundCall `safari_list_tabs` to refresh tab indices
    Hebrew keyboard issuesAll typing uses JS events — immune to keyboard layout
    HTTPS blocked`safari_navigate` auto-tries HTTPS first, falls back to HTTP
    Safari steals focusEnsure you're on latest version — `newTab` restores your active tab

    Works With

    Safari MCP works with any MCP-compatible client:

    ClientStatus
    Claude Code✅ Tested daily
    Claude Desktop✅ Tested
    Cursor✅ Tested
    Windsurf✅ Compatible
    VS Code + Continue✅ Compatible

    Contributing

    PRs welcome! See CONTRIBUTING.md for setup instructions.

    The codebase is two files:

    • `safari.js` — Safari automation layer (AppleScript + JavaScript)
    • `index.js` — MCP server with tool definitions

    Sponsors

    Safari MCP is free and open source. If it saves you time or CPU cycles, consider supporting its development:

    Your support funds:

    • 🧪 Testing across macOS versions and Safari releases
    • 🛠️ New tools and features
    • 📖 Documentation and examples

    Become the first sponsor!


    Commercial Support

    Need Safari MCP integrated into your product or agent stack? Achiya Automation offers:

    • Priority bug fixes and custom tool development for your use case
    • Integration consulting — wiring Safari MCP into production agent systems (Claude, Cursor, n8n, custom)
    • Private deployment support — multi-user Safari MCP, non-standard macOS environments, CI/CD
    • Training workshops for engineering teams adopting MCP-based automation

    Built by the author of Safari MCP. Start a conversation →


    What agents unlock with Safari MCP

    When an AI agent drives Safari MCP, it gets things a headless browser can't:

    • Real authenticated sessions — Gmail, GitHub, Ahrefs, Slack, banking dashboards are all already logged in
    • Framework-aware form filling — `safari_fill_and_submit` calls React/Vue/Angular setters natively, no guessing whether `input` events fired
    • Background operation — the agent works in parallel while you keep using your Mac
    • One MCP call per workflow — `safari_run_script` batches navigation + clicks + extraction into a single roundtrip

    The pattern holds across models: drive the browser the human already trusts — you inherit logins, cookies, extensions, and the user's exact environment in one step.


    Community

    6,000+ monthly npm downloads — developers are building AI agents on macOS with Safari MCP.

    • GitHub Discussions — ask questions, share use cases
    • Issues — bug reports and feature requests
    • ![Good First Issues](https://github.com/achiya-automation/safari-mcp/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) — start contributing

    Ecosystem

    Other macOS MCP servers that complement Safari MCP:

    ProjectWhat it doesWhen to use
    mcp-server-macos-useOS-level macOS automation (accessibility, screen control)System-wide interactions beyond Safari
    chrome-devtools-mcpChrome DevTools ProtocolLighthouse audits, Chrome-specific performance traces

    > Using Safari MCP alongside Chrome DevTools MCP? Safari handles 95% of daily browsing (zero overhead), Chrome handles the 5% that needs Lighthouse or Chrome-specific traces.


    Like it? Give it a ⭐

    If Safari MCP saves you from Chrome overhead, a star helps others discover it:

    Star this repo

    Share on Twitter/X · Share on LinkedIn · Write about it

    Star History Chart

    Listed On

    Glama
    MCP Registry
    MCP Scoreboard
    CI

    License

    MIT — use it however you want.


    Built by **Achiya Automation** — automation & AI agents for business.

    Frequently asked questions

    What is safari-mcp?

    safari-mcp is Native Safari browser automation for AI agents. 97 tools via AppleScript — zero overhead, keeps logins, runs silently in background. Drop-in alternative to Chrome DevTools MCP with 40-60% less CPU/heat on Apple Silicon.

    How do I install safari-mcp?

    Open the GitHub repository and follow its README. Most MCP servers are added to your client's MCP config, then called by your agent.

    Is safari-mcp open source?

    Yes — it is hosted on GitHub at https://github.com/achiya-automation/safari-mcp and has 181 stars.

    Related MCP tools

    riponcmprojectmem

    Open-source coding agent memory. Records issues, attempts, fixes and decisions, then warns your agent before it repeats an approach that already failed. Native MCP server for Claude Code, Cursor, Antigravity and Codex. 100% local, no cloud, no telemetry. MIT.

    796 Python
    ai-agentsai-memoryai-tools+17
    atlassianatlassian-mcp-server

    Official remote MCP server for Atlassian. Securely connect Jira, Confluence, Jira Service Management, Bitbucket, and Compass to Claude, ChatGPT, Cursor, VS Code, and other AI tools using OAuth 2.1 or API tokens.

    1,015 JavaScript
    aiai-agentsatlassian+17
    IvanMurzakUnity-MCP

    AI Skills, MCP Tools, and CLI for Unity Engine. Full AI develop and test loop. Use cli for quick setup. Efficient token usage, advanced tools. Any C# method may be turned into a tool by a single line. Works with Claude Code, Gemini, Copilot, Cursor and any other absolutely for free.

    4,137 C#
    aiai-integrationgame-development+16
    jgravellejcodemunch-mcp

    Cut AI token costs 95%+ on code exploration. The leading MCP server for precise, symbol-level GitHub code retrieval via tree-sitter AST. Works with Claude Code, Cursor & any MCP client. 313B+ tokens saved.

    2,651 Python
    claudeclaude-codeai-coding+17
    firecrawlfirecrawl-mcp-server

    🔥 Official Firecrawl MCP Server - Adds powerful web scraping and search to Cursor, Claude and any other LLM clients.

    7,393 JavaScript
    batch-processingclaudecontent-extraction+11
    AVIDS2memorix

    Open-source cross-agent memory layer for coding agents via MCP. Compatible with Claude Code, Codex, Cursor, Windsurf, Gemini CLI, Antigravity, OpenClaw, Hermes Agent, Oh-my-Pi, Pi, Copilot, Kiro, OpenCode, and Trae.

    721 TypeScript
    ai-codingclaude-codecopilot+17

    Run your own MCP server? See who uses it and what to fix.

    Measure it with TrackMCP