Safari MCP

Drives the Safari you already use on a Mac, with your logins, through AppleScript and an optional extension

By אחיה אוטומציה (individual) TypeScript Local · stdio Browser automation

59 popularity score ★ 239 ↓ 710/wk

Connect your client

Local (npm)

Add in one click

Opens the app, which asks before it adds the server.

Or add it by command or config

Claude CodeTerminal
claude mcp add safari -- npx safari-mcp
Claude Desktopclaude_desktop_config.json
{
  "mcpServers": {
    "safari": {
      "command": "npx",
      "args": [
        "safari-mcp"
      ]
    }
  }
}
Cursor~/.cursor/mcp.json
{
  "mcpServers": {
    "safari": {
      "command": "npx",
      "args": [
        "safari-mcp"
      ]
    }
  }
}
VS Code.vscode/mcp.json
{
  "servers": {
    "safari": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "safari-mcp"
      ]
    }
  }
}
Codex~/.codex/config.toml
[mcp_servers.safari]
command = "npx"
args = ["safari-mcp"]
Gemini CLITerminal
gemini mcp add --scope user safari npx -- safari-mcp

Settings 9

SAFARI_MCP_ALLOW_USER_TABS Optional: Set to 1 to let safari_switch_tab adopt a tab you opened; off by default.
MCP_MAX_TABS Optional: Tabs one session may keep open before its oldest is closed; default 6.
SAFARI_PROFILE Optional: Bind sessions to a named Safari profile; unset uses your ordinary windows.
SAFARI_MCP_HTTP Optional: Set to 1 to run one shared HTTP daemon for several clients instead of stdio.
SAFARI_MCP_HTTP_PORT Optional: Port of that daemon; default 9225.
SAFARI_MCP_RAISE_ON_NAVIGATE Optional: Set to 1 to bring Safari to the front on navigation; off by default.
SAFARI_MCP_SCREENSHOT_MAX_WIDTH Optional: Downscale screenshots to this pixel width.
MCP_WEBKIT_LIMIT_MB Optional: WebKit memory in MB above which the oldest server tabs are closed; default 3000 (in the code, not the README).
SAFARI_MCP_NO_AUTO_UPGRADE Optional: Set to 1 to stop the server reloading an outdated extension worker (in the code, not the README).

What it does

Safari MCP is a local Node.js server that controls the desktop Safari browser on macOS. Instead of starting a separate Chromium or a headless engine, it works in your ordinary Safari windows, so pages open with the cookies and signed-in sessions you already have. It talks to Safari through AppleScript plus a long-running Swift helper, and, when you build and enable it, a Safari extension that reaches closed Shadow DOM, pages with strict Content Security Policy and deeper React or Vue state. Without the extension its makers estimate about 80% of the tools still work.

The 98 tools cover navigation, page reading, clicking and form filling (including react-select widgets and code editors such as Monaco), screenshots and PDF export, tab handling, running JavaScript, an accessibility snapshot with element refs, cookies and local, session and IndexedDB storage, network capture and mocking, console capture, device emulation, data extraction and a few iOS Safari checks. Four native_ tools send OS-level mouse and keyboard events for sites that ignore script-made clicks.

By default a session only acts on tabs it opened itself and refuses to touch yours; SAFARI_MCP_ALLOW_USER_TABS=1 lets safari_switch_tab adopt a tab you name, and safari_close_tab still refuses those. Each session keeps at most 6 tabs (MCP_MAX_TABS) and closes its oldest one when it opens another. The code at v2.22.17 also watches total WebKit memory: past 3000 MB (MCP_WEBKIT_LIMIT_MB, a setting the README does not list) it closes up to two of the oldest tabs the server opened, and logs a warning at 70% of that figure. Several agents can share one Safari through an HTTP daemon (SAFARI_MCP_HTTP=1) that gives each session its own tab state.

What it needs

RuntimeNode.js 20+

macOS with stable Safari (not Safari Technology Preview) and Node.js 20 or later for npx. In Safari, turn on Show features for web developers and Allow JavaScript from Apple Events. Grant Automation → Safari to the app that launches the server (Terminal, VS Code and so on); Screen Recording for screenshots without the extension and for safari_save_pdf; Accessibility for the bundled safari-helper to use the safari_native_* tools and safari_save_pdf. The optional extension must be built from the git repository with Xcode and an Apple ID; it is not in the npm package.

Limits

macOS and Safari only; Safari Technology Preview is never addressed, and private windows are not a supported mode. Without the extension, closed Shadow DOM is invisible and strict-CSP sites often block it; with only the extension, dialogs, native clicks and PDF export still need AppleScript. The extension needs Safari's Allow unsigned extensions setting, which resets every time Safari restarts. After an npm update macOS may revoke the Automation grant, which then has to be given again. Tools refuse tabs the session did not open unless SAFARI_MCP_ALLOW_USER_TABS is set. Clients that multiplex agents through one MCP client (mcporter) defeat per-session tab isolation.

Who it suits

Suits Mac users who want an assistant to work in websites they are already signed into, in the background, without running a second browser. It writes as well as reads (forms, cookies, storage, clicks), so it fits work you would otherwise do by hand in Safari. Pick something else on Linux or Windows, for a clean throwaway browser session, or for Chromium-specific audits: its own README points to Chrome DevTools MCP for Lighthouse and performance audits, and to Apple's safaridriver --mcp (Safari 27+) for an isolated WebDriver session.

Tools 60 of 98

safari_navigate
Open a URL in the session's tab and wait for it to load
safari_go_back
Step back in the tab's history
safari_reload
Reload the page, optionally bypassing the cache
safari_read_page
Return the page title, URL and visible text
safari_get_source
Return the page's full HTML
safari_navigate_and_read
Open a URL and return its text in one call
safari_snapshot
Accessibility tree with a ref for each interactive element
safari_click
Click an element by selector, visible text, coordinates or ref
safari_click_and_read
Click, then return the page as it is afterwards
safari_hover
Move the pointer over an element
safari_fill
Set an input's value in a way React, Vue and Angular notice
safari_fill_form
Fill several fields at once
safari_fill_and_submit
Fill a form and submit it
safari_select_option
Choose an option in a dropdown
safari_type_text
Type text as key events from script
safari_press_key
Send a key with optional modifiers
safari_react_select_set
Set a react-select v5 value without opening its menu
safari_replace_editor
Replace the content of a Monaco, CodeMirror, Ace or ProseMirror editor
safari_screenshot
Capture the viewport or full page as PNG
safari_screenshot_element
Capture one element as an image
safari_save_pdf
Save the page as a PDF
safari_scroll
Scroll by a number of pixels
safari_list_tabs
List open tabs with index, title and URL
safari_new_tab
Open a tab in the background and return its receipt
safari_close_tab
Close a tab this session opened
safari_switch_tab
Move the session to another tab by index
safari_wait_for_new_tab
Wait for a popup tab, such as a sign-in window, and switch to it
safari_wait_for
Wait until an element, text or URL change appears
safari_evaluate
Run JavaScript in the page and return the result
safari_eval_file
Run JavaScript loaded from a local file
safari_list_frames
List the page and its iframes with frame ids
safari_get_element
Report an element's tag, position, attributes and visibility
safari_query_all
Find every element matching a selector
safari_detect_forms
Find the forms on a page and their field selectors
safari_drag
Drag from one element or point to another
safari_upload_file
Put a local file into a file input without a dialog
safari_paste_image
Paste an image into an editor without using the clipboard
safari_handle_dialog
Accept or dismiss an alert, confirm or prompt
safari_emulate
Emulate a phone or tablet such as iPhone or Pixel
safari_get_cookies
Read the page's cookies
safari_set_cookie
Create or change a cookie
safari_delete_cookies
Remove one cookie or all of them
safari_local_storage
Read localStorage
safari_set_local_storage
Write a localStorage entry
safari_export_storage
Dump cookies and storage to JSON for later restore
safari_import_storage
Restore storage from exported JSON
safari_get_indexed_db
Read records from an IndexedDB database
safari_clipboard_read
Read text from the macOS clipboard
safari_clipboard_write
Put text on the macOS clipboard
safari_start_network_capture
Begin recording fetch and XHR requests
safari_network_details
Return recorded requests with headers and timing
safari_mock_route
Answer matching fetch/XHR requests with a fake response
safari_get_console
Return captured console messages
safari_performance_metrics
Report navigation timing, Web Vitals and memory
safari_throttle_network
Simulate slow-3g, fast-3g, 4g or offline
safari_extract_tables
Turn HTML tables into JSON
safari_extract_links
List links with rel and external flags
safari_run_script
Run a batch of actions in one call
safari_native_click
Click with an OS-level mouse event when script clicks are blocked
safari_doctor
Check macOS permissions and the helper chain and suggest fixes

Similar servers