- Safari MCP
Safari MCP
🦁 Safari MCP
The only MCP server for Safari — native browser automation for AI agents.
80 tools · Zero dependencies · ~5ms per command · 60% less CPU than Chrome
Quick Start · All 80 Tools · Examples · Why Safari MCP? · Architecture · Changelog

TL;DR: Use your real Safari with all your logins, cookies, and sessions. No headless browsers, no Chrome, no Puppeteer. Just pure AppleScript + JavaScript running natively on macOS — 60% less CPU/heat on Apple Silicon.
🤔 Why not just use Playwright or Chrome DevTools MCP?
| Problem | Safari MCP Solution |
|---|---|
| Chrome DevTools MCP heats up your Mac | Native WebKit — ~60% less CPU |
| Playwright launches a new browser without your logins | Uses your real Safari with all sessions |
| Puppeteer requires Chrome + debug port | Zero dependencies — just AppleScript |
| Headless browsers can't access your authenticated sessions | Gmail, GitHub, Slack — already logged in |
| Browser automation steals window focus | Safari stays in background, never interrupts |
Highlights
- 80 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 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
Quick Start
Prerequisites
- macOS (any version with Safari)
- Node.js 18+
- Safari → Settings → Advanced → Show features for web developers ✓
- Safari → Develop → Allow JavaScript from Apple Events ✓
Install
Option A — npm (recommended):
npm install -g safari-mcp
Option B — Homebrew:
brew install achiya-automation/tap/safari-mcp
Option C — from source:
git clone https://github.com/achiya-automation/safari-mcp.git
cd safari-mcp
npm install
Configure
Add to your MCP client config:
Claude Code (~/.mcp.json)
{
"mcpServers": {
"safari": {
"command": "node",
"args": ["/path/to/safari-mcp/index.js"]
}
}
}
Claude Desktop (claude_desktop_config.json)
{
"mcpServers": {
"safari": {
"command": "node",
"args": ["/path/to/safari-mcp/index.js"]
}
}
}
Cursor (.cursor/mcp.json)
{
"mcpServers": {
"safari": {
"command": "node",
"args": ["/path/to/safari-mcp/index.js"]
}
}
}
Windsurf / VS Code + Continue
{
"mcpServers": {
"safari": {
"command": "node",
"args": ["/path/to/safari-mcp/index.js"]
}
}
}
Usage Workflow
The recommended pattern for AI agents using Safari MCP:
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:
| Strategy | Example | Best 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_snapshotto get element refs, then use refs for precise targeting. This is faster and more reliable than CSS selectors.
Tools (80)
Navigation (4)
| Tool | Description |
|---|---|
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)
| Tool | Description |
|---|---|
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 (5)
| Tool | Description |
|---|---|
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 |
Form Input (7)
| Tool | Description |
|---|---|
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 |
Screenshots & PDF (3)
| Tool | Description |
|---|---|
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)
| Tool | Description |
|---|---|
safari_scroll | Scroll up/down by pixels |
safari_scroll_to | Scroll to exact position |
safari_scroll_to_element | Smooth scroll to element |
Tab Management (4)
| Tool | Description |
|---|---|
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 |
Wait (2)
| Tool | Description |
|---|---|
safari_wait_for | Wait for element, text, or URL change |
safari_wait | Wait for specified milliseconds |
JavaScript (1)
| Tool | Description |
|---|---|
safari_evaluate | Execute arbitrary JavaScript, return result |
Element Inspection (4)
| Tool | Description |
|---|---|
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 (1)
| Tool | Description |
|---|---|
safari_accessibility_snapshot | Full a11y tree: roles, ARIA, focusable elements |
Drag & Drop (1)
| Tool | Description |
|---|---|
safari_drag | Drag between elements or coordinates |
File Operations (2)
| Tool | Description |
|---|---|
safari_upload_file | Upload file via JS DataTransfer (no file dialog!) |
safari_paste_image | Paste image into editor (no clipboard touch!) |
Dialog & Window (2)
| Tool | Description |
|---|---|
safari_handle_dialog | Handle alert/confirm/prompt |
safari_resize | Resize browser window |
Device Emulation (2)
| Tool | Description |
|---|---|
safari_emulate | Emulate device (iPhone, iPad, Pixel, Galaxy) |
safari_reset_emulation | Reset to desktop |
Cookies & Storage (10)
| Tool | Description |
|---|---|
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)
| Tool | Description |
|---|---|
safari_clipboard_read | Read clipboard text |
safari_clipboard_write | Write text to clipboard |
Network (6)
| Tool | Description |
|---|---|
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)
| Tool | Description |
|---|---|
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)
| Tool | Description |
|---|---|
safari_performance_metrics | Navigation timing, Web Vitals, memory |
safari_throttle_network | Simulate slow-3g/fast-3g/4g/offline |
Data Extraction (4)
| Tool | Description |
|---|---|
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 (5)
| Tool | Description |
|---|---|
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 |
Automation (1)
| Tool | Description |
|---|---|
safari_run_script | Run multiple actions in a single call (batch) |
Security
Safari MCP runs locally on your Mac with minimal attack surface:
| Aspect | Detail |
|---|---|
| Network | No remote connections — all communication is local (stdio + localhost) |
| Permissions | macOS system permissions required (Screen Recording for screenshots) |
| Data | No telemetry, no analytics, no data sent anywhere |
| Extension | Communicates only with localhost:9224, validated by Safari |
| Code | Fully open source (MIT) — audit every line |
Safari MCP vs Alternatives
| Feature | Safari MCP | Chrome DevTools MCP | Playwright MCP |
|---|---|---|---|
| CPU/Heat | 🟢 Minimal | 🔴 High | 🟡 Medium |
| Your logins | ✅ Yes | ✅ Yes | ❌ No |
| macOS native | ✅ WebKit | ❌ Chromium | ❌ Chromium/WebKit |
| Dependencies | None | Chrome + debug port | Playwright runtime |
| Tools | 80 | ~30 | ~25 |
| File upload | JS (no dialog) | CDP | Playwright API |
| Image paste | JS (no clipboard) | CDP | Playwright 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.
Safari MCP Servers Comparison
| Feature | safari-mcp | MCPSafari | safari-mcp-server |
|---|---|---|---|
| Tools | 80 | 23 | ~10 |
| License | MIT | None | MIT |
| Install | npm / Homebrew | Binary | npm |
| Storage (cookies, localStorage) | 10 tools | None | None |
| Data extraction (tables, links) | 5 tools | None | None |
| Network mocking | Yes | No | No |
| Device emulation | Yes | No | No |
| File upload (no dialog) | Yes | No | No |
| PDF export | Yes | No | No |
| Console capture | 4 tools | 1 | No |
| Performance metrics | Yes | No | No |
| Fallback engine | Dual (Extension + AppleScript) | Extension only | WebDriver |
Architecture
Safari MCP uses a dual-engine architecture — the Extension is preferred for speed and advanced capabilities, with AppleScript as an always-available fallback:
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
| Capability | With Extension | AppleScript 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):
Prerequisites: Xcode (install from App Store — free)
# 1. Build the extension app
cd safari-mcp
xcodebuild -project "xcode/Safari MCP/Safari MCP.xcodeproj" \
-scheme "Safari MCP (macOS)" -configuration Release build
# 2. Find and open the built app
open ~/Library/Developer/Xcode/DerivedData/Safari_MCP-*/Build/Products/Release/Safari\ MCP.app
Then in Safari:
- Safari → Settings → Advanced → enable Show features for web developers
- Safari → Develop → Allow Unsigned Extensions (required each Safari restart)
- Safari → Settings → Extensions → enable Safari MCP Bridge
The extension connects automatically to the MCP server on port 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:
| Permission | Where | Why |
|---|---|---|
| JavaScript from Apple Events | Safari → Develop menu | Required for do JavaScript |
| Screen Recording | System Settings → Privacy | Required for safari_screenshot |
| Accessibility | System Settings → Privacy | Required for safari_save_pdf only |
Troubleshooting
| Issue | Fix |
|---|---|
| "AppleScript error" | Enable "Allow JavaScript from Apple Events" in Safari → Develop |
| Screenshots empty | Grant Screen Recording permission to Terminal/VS Code |
| Tab not found | Call safari_list_tabs to refresh tab indices |
| Hebrew keyboard issues | All typing uses JS events — immune to keyboard layout |
| HTTPS blocked | safari_navigate auto-tries HTTPS first, falls back to HTTP |
| Safari steals focus | Ensure you're on latest version — newTab restores your active tab |
Works With
Safari MCP works with any MCP-compatible client:
| Client | Status |
|---|---|
| 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
Star History
If Safari MCP saved you from Chrome overhead, consider giving it a ⭐
License
MIT — use it however you want.
Server Config
{
"mcpServers": {
"safari-mcp": {
"command": "npx",
"args": [
"-y",
"safari-mcp"
]
}
}
}Recommend Servers
View Allsummarize chat message
A Serper MCP Server
Playwright MCP server