safari-mcp 2.21.3 → 2.21.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +13 -12
  2. package/index.js +19 -1
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <div align="center">
2
2
 
3
- <img src="social-preview.png" alt="Safari MCP Server — 97 native browser automation tools for AI agents on macOS" width="100%">
3
+ <img src="social-preview.png" alt="Safari MCP Server — 98 native browser automation tools for AI agents on macOS" width="100%">
4
4
 
5
5
  <br/>
6
6
 
@@ -19,9 +19,9 @@
19
19
  [VS Code Insiders](https://insiders.vscode.dev/redirect?url=vscode-insiders:mcp/install?%7B%22safari-mcp%22%3A%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22safari-mcp%22%5D%7D%7D) ·
20
20
  [Install in Cursor](cursor://anysphere.cursor-deeplink/mcp/install?name=safari-mcp&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22safari-mcp%22%5D%7D)
21
21
 
22
- **97 tools** · **No Chrome/Puppeteer/Playwright needed** · **~5ms per command** · **60% less CPU than Chrome**
22
+ **98 tools** · **No Chrome/Puppeteer/Playwright needed** · **~5ms per command** · **60% less CPU than Chrome**
23
23
 
24
- [Quick Start](#quick-start) · [All 97 Tools](#tools-97) · [Examples](examples/) · [Why Safari MCP?](#safari-mcp-vs-alternatives) · [Architecture](#architecture) · [Changelog](CHANGELOG.md)
24
+ [Quick Start](#quick-start) · [All 98 Tools](#tools-98) · [Examples](examples/) · [Why Safari MCP?](#safari-mcp-vs-alternatives) · [Architecture](#architecture) · [Changelog](CHANGELOG.md)
25
25
 
26
26
  ![Safari MCP Demo](https://github.com/achiya-automation/safari-mcp/raw/main/assets/safari-mcp-promo.gif)
27
27
 
@@ -39,17 +39,17 @@ Your AI agent needs to browse. So it either:
39
39
 
40
40
  Your AI drives the **Safari you're already logged into** — Gmail, GitHub, Ahrefs, Slack, banking.
41
41
 
42
- Native WebKit. ~60% less CPU. Background operation. 97 tools. One `npx` command. macOS only.
42
+ Native WebKit. ~60% less CPU. Background operation. 98 tools. One `npx` command. macOS only.
43
43
 
44
44
  > 📰 **Featured on freeCodeCamp:** [How to Connect Your AI Coding Agent to a Browser on macOS](https://www.freecodecamp.org/news/how-to-connect-your-ai-coding-agent-to-a-browser-on-macos/) · [HackerNoon: Reverse-Engineering React, Shadow DOM, and CSP](https://hackernoon.com/i-had-to-reverse-engineer-react-shadow-dom-and-csp-to-automate-safari-without-chrome)
45
45
 
46
- > 🍎 **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.
46
+ > 🍎 **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 98 tools. See the full comparison below.
47
47
 
48
48
  ---
49
49
 
50
50
  ## Highlights
51
51
 
52
- - **97 tools** — navigation, clicks, forms, screenshots, network, storage, accessibility, and more
52
+ - **98 tools** — navigation, clicks, forms, screenshots, network, storage, accessibility, and more
53
53
  - **Zero heat** — native WebKit on Apple Silicon, ~60% less CPU than Chrome
54
54
  - **Your real browser** — keeps all logins, cookies, sessions (Gmail, GitHub, Ahrefs, etc.)
55
55
  - **Background operation** — Safari stays in the background, no window stealing
@@ -390,7 +390,7 @@ What the flag deliberately does *not* do:
390
390
 
391
391
  ---
392
392
 
393
- ## Tools (97)
393
+ ## Tools (98)
394
394
 
395
395
  <details>
396
396
  <summary><b>Click to expand the full tool list — organized by category</b></summary>
@@ -464,11 +464,12 @@ What the flag deliberately does *not* do:
464
464
  | `safari_wait_for` | Wait for element, text, or URL change |
465
465
  | `safari_wait` | Wait for specified milliseconds |
466
466
 
467
- ### JavaScript (1)
467
+ ### JavaScript (3)
468
468
  | Tool | Description |
469
469
  |------|-------------|
470
470
  | `safari_evaluate` | Execute arbitrary JavaScript, return result |
471
471
  | `safari_eval_file` | Execute JavaScript read from a file path (avoids huge inline scripts) |
472
+ | `safari_list_frames` | List every document in the tab (main page + each iframe) with frameId, URL and text length — pass a frameId to `safari_evaluate`'s `frame` to run inside a cross-origin iframe |
472
473
 
473
474
  ### Element Inspection (4)
474
475
  | Tool | Description |
@@ -618,7 +619,7 @@ Safari MCP runs locally on your Mac with minimal attack surface:
618
619
  | Your logins | ✅ Yes | ✅ Yes | ❌ No |
619
620
  | macOS native | ✅ WebKit | ❌ Chromium | ❌ Chromium/WebKit |
620
621
  | Browser dependencies | None | Chrome + debug port | Playwright runtime |
621
- | Tools | 97 | ~30 | ~25 |
622
+ | Tools | 98 | ~30 | ~25 |
622
623
  | File upload | JS (no dialog) | CDP | Playwright API |
623
624
  | Image paste | JS (no clipboard) | CDP | Playwright API |
624
625
  | Focus steal | ❌ Background | ❌ Background | ❌ Headless |
@@ -639,7 +640,7 @@ It has not reached a stable Safari release yet: on macOS 26.5.2 with Safari 26.5
639
640
  | **Your real logins / cookies** | ✅ Your actual Safari | ⚠️ Isolated automation session — no access to AutoFill or browsing activity |
640
641
  | **Runs on** | ✅ Stable Safari, every Mac | ⚠️ Safari Technology Preview 247+ or the Safari 27 beta — not in stable Safari 26.5 |
641
642
  | **Background (no focus steal)** | ✅ Yes | ❌ Dedicated window with a "controlled by automation" banner |
642
- | **Tools** | **97** | ~17 |
643
+ | **Tools** | **98** | ~17 |
643
644
  | **Storage** (cookies, localStorage, IndexedDB) | ✅ 10 tools | ❌ |
644
645
  | **Network mocking + throttling** | ✅ Yes | ❌ Read-only network inspection |
645
646
  | **Device emulation** (iPhone, iPad) | ✅ Yes | ⚠️ Viewport + media type only |
@@ -654,7 +655,7 @@ There are several "safari-mcp" projects floating around. Here's how they compare
654
655
 
655
656
  | Feature | **🦁 safari-mcp** *(this repo)* | [lxman/safari-mcp-server](https://github.com/lxman/safari-mcp-server) | [Epistates/MCPSafari](https://github.com/Epistates/MCPSafari) | [HayoDev/safari-devtools-mcp](https://github.com/HayoDev/safari-devtools-mcp) |
656
657
  |---------|:------------------------------:|:----------------------:|:------------:|:----------------------:|
657
- | **Tools** | **97** | ~10 | 23 | ~15 |
658
+ | **Tools** | **98** | ~10 | 23 | ~15 |
658
659
  | **Install** | `npx safari-mcp` | Manual | Binary | `npx` |
659
660
  | **Engine** | **Dual** (Extension + AppleScript) | WebDriver | Extension only | DevTools Protocol |
660
661
  | **Keeps your real Safari logins** | ✅ Yes | ⚠️ Limited | ✅ Yes | ❌ Debug session |
@@ -923,7 +924,7 @@ If Safari MCP saves you from Chrome overhead, **a star helps others discover it:
923
924
 
924
925
  [![Star this repo](https://img.shields.io/github/stars/achiya-automation/safari-mcp?style=social)](https://github.com/achiya-automation/safari-mcp)
925
926
 
926
- [Share on Twitter/X](https://twitter.com/intent/tweet?text=Safari%20MCP%20%E2%80%94%20Stop%20running%20Chrome%20just%20so%20your%20AI%20agent%20can%20browse.%2097%20tools%2C%20native%20Safari%2C%2060%25%20less%20CPU.&url=https%3A%2F%2Fgithub.com%2Fachiya-automation%2Fsafari-mcp) · [Share on LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fgithub.com%2Fachiya-automation%2Fsafari-mcp) · [Write about it](https://dev.to/)
927
+ [Share on Twitter/X](https://twitter.com/intent/tweet?text=Safari%20MCP%20%E2%80%94%20Stop%20running%20Chrome%20just%20so%20your%20AI%20agent%20can%20browse.%2098%20tools%2C%20native%20Safari%2C%2060%25%20less%20CPU.&url=https%3A%2F%2Fgithub.com%2Fachiya-automation%2Fsafari-mcp) · [Share on LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fgithub.com%2Fachiya-automation%2Fsafari-mcp) · [Write about it](https://dev.to/)
927
928
 
928
929
  [![Star History Chart](https://api.star-history.com/svg?repos=achiya-automation/safari-mcp&type=Date)](https://star-history.com/#achiya-automation/safari-mcp&Date)
929
930
 
package/index.js CHANGED
@@ -1924,6 +1924,10 @@ async function extensionOrFallback(extensionType, extensionPayload, fallbackFn)
1924
1924
 
1925
1925
  let result;
1926
1926
  let usedExtension = false;
1927
+ // The extension's evaluate ladder has a terminal state: every injection strategy was
1928
+ // refused. It announces itself as "Falling back to AppleScript", so the caller must
1929
+ // never be handed an empty value as if the script had simply returned nothing (#106).
1930
+ let hardCspBlock = false;
1927
1931
  try {
1928
1932
  if (_extensionConnected && (!_preferAppleScript || _profileExtensionVerified)) {
1929
1933
  try {
@@ -1952,7 +1956,11 @@ async function extensionOrFallback(extensionType, extensionPayload, fallbackFn)
1952
1956
  if (reloadHandoff) _cancelReloadHttpWorkerHandoff(reloadHandoff);
1953
1957
  throw error;
1954
1958
  }
1955
- const isCspError = typeof result === 'string' && (result.includes('unsafe-eval') || result.includes('trusted-types') || result.includes('Trusted Type') || result.includes('Content Security Policy'));
1959
+ // The ladder's own terminal marker. It was not in this list, so the fallback the
1960
+ // marker's text promises never actually ran and its text reached the caller as
1961
+ // the tool's value instead of as a failure (#106).
1962
+ hardCspBlock = typeof result === 'string' && result.includes('CSP blocked all strategies');
1963
+ const isCspError = hardCspBlock || (typeof result === 'string' && (result.includes('unsafe-eval') || result.includes('trusted-types') || result.includes('Trusted Type') || result.includes('Content Security Policy')));
1956
1964
  const isPermissionDenied = typeof result === 'string' && result.includes('__SCREENSHOT_PERMISSION_DENIED__');
1957
1965
  const isElementMiss = typeof result === 'string' && result.startsWith('Element not found');
1958
1966
  const isFailed = result === null || isElementMiss;
@@ -1998,6 +2006,16 @@ async function extensionOrFallback(extensionType, extensionPayload, fallbackFn)
1998
2006
  const t0 = Date.now();
1999
2007
  result = await fallbackFn();
2000
2008
  console.error(`[Safari MCP] ${extensionType} via AppleScript (${Date.now() - t0}ms)`);
2009
+ // Both paths are now exhausted. An empty value here means the script never ran,
2010
+ // which is byte-identical to a script that legitimately returned nothing — and an
2011
+ // agent reads that as "no such element" and keeps building on it. Fail instead.
2012
+ if (hardCspBlock && (result === undefined || result === null)) {
2013
+ throw new Error(
2014
+ `safari_${extensionType}: this page refused every JavaScript injection strategy (CSP), ` +
2015
+ "and the AppleScript fallback returned nothing — the script did not run. " +
2016
+ "Reading the page still works here: safari_read_page, safari_snapshot, safari_get_element, safari_extract_links."
2017
+ );
2018
+ }
2001
2019
  }
2002
2020
  } finally {
2003
2021
  safari.setFocusGuard(false);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "safari-mcp",
3
- "version": "2.21.3",
3
+ "version": "2.21.5",
4
4
  "mcpName": "io.github.achiya-automation/safari-mcp",
5
5
  "description": "Safari browser automation for AI agents — native macOS, zero Chrome overhead. 97 tools via AppleScript + JavaScript.",
6
6
  "type": "module",