> **TL;DR:** Use your real Safari with all your logins, cookies, and sessions. No headless browsers, no Chrome, no Puppeteer. Just native AppleScript + JavaScript 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 | Just AppleScript — no extra browser |
| 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 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
---
## 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 (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
Add to your client's config file — all clients use the same JSON:
```json
{
"mcpServers": {
"safari": {
"command": "npx",
"args": ["safari-mcp"]
}
}
}
```
Where does each client store this?
| Client | Config file |
|--------|------------|
| **Claude Code** | `~/.mcp.json` |
| **Claude Desktop** | `~/Library/Application Support/Claude/claude_desktop_config.json` |
| **Cursor** | `.cursor/mcp.json` in your project |
| **Windsurf** | `.windsurf/mcp.json` in your project |
| **VS Code + Continue** | `.vscode/mcp.json` in your project |
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:
```
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_snapshot` to 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 | De
---