safari-mcp 2.21.2 → 2.21.4
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.
- package/README.md +13 -12
- package/extension/background.js +10 -1
- package/extension/manifest.json +1 -1
- package/index.js +10 -1
- 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 —
|
|
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
|
-
**
|
|
22
|
+
**98 tools** · **No Chrome/Puppeteer/Playwright needed** · **~5ms per command** · **60% less CPU than Chrome**
|
|
23
23
|
|
|
24
|
-
[Quick Start](#quick-start) · [All
|
|
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
|

|
|
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.
|
|
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
|
|
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
|
-
- **
|
|
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 (
|
|
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 (
|
|
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 |
|
|
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** | **
|
|
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** | **
|
|
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
|
[](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.%
|
|
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
|
[](https://star-history.com/#achiya-automation/safari-mcp&Date)
|
|
929
930
|
|
package/extension/background.js
CHANGED
|
@@ -2761,7 +2761,16 @@ async function handleCommand(type, payload) {
|
|
|
2761
2761
|
if (mainResult && JSON.parse(mainResult).length > 0) return mainResult;
|
|
2762
2762
|
} catch { return mainResult; }
|
|
2763
2763
|
const frameResult = await execAcrossFrames(queryFn, [payload.selector, payload.limit || 20], tabId);
|
|
2764
|
-
|
|
2764
|
+
if (!frameResult) return mainResult;
|
|
2765
|
+
// Reaching here means the main frame matched nothing, so every element below came
|
|
2766
|
+
// from a child frame and its x/y are that frame's viewport coordinates. Say so in
|
|
2767
|
+
// the payload: the caller is an agent reading this JSON, and the click tools take
|
|
2768
|
+
// page coordinates — a comment in this file never reaches it.
|
|
2769
|
+
try {
|
|
2770
|
+
return JSON.stringify(JSON.parse(frameResult).map((el) => ({ ...el, frameRelative: true })));
|
|
2771
|
+
} catch {
|
|
2772
|
+
return frameResult;
|
|
2773
|
+
}
|
|
2765
2774
|
}
|
|
2766
2775
|
|
|
2767
2776
|
default:
|
package/extension/manifest.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"manifest_version": 3,
|
|
3
3
|
"name": "Safari MCP Bridge",
|
|
4
4
|
"description": "Connects AI agents to Safari — fast JS execution, screenshots, clicks with your real cookies/logins",
|
|
5
|
-
"version": "2.10.
|
|
5
|
+
"version": "2.10.12",
|
|
6
6
|
"icons": {
|
|
7
7
|
"48": "images/icon-48.png",
|
|
8
8
|
"96": "images/icon-96.png",
|
package/index.js
CHANGED
|
@@ -3014,7 +3014,7 @@ server.tool(
|
|
|
3014
3014
|
|
|
3015
3015
|
server.tool(
|
|
3016
3016
|
"safari_query_all",
|
|
3017
|
-
"Find all elements matching a CSS selector (returns tag, text, href, value)",
|
|
3017
|
+
"Find all elements matching a CSS selector (returns tag, text, href, value). x/y are relative to each element's own frame viewport — for matches inside an iframe, click by selector or snapshot ref, not by these coordinates",
|
|
3018
3018
|
{
|
|
3019
3019
|
selector: z.string().describe("CSS selector"),
|
|
3020
3020
|
limit: z.coerce.number().optional().describe("Max results (default: 20)"),
|
|
@@ -3025,6 +3025,15 @@ server.tool(
|
|
|
3025
3025
|
"query_all", { selector: args.selector, limit: args.limit, ..._explicitReceipt(args) },
|
|
3026
3026
|
() => safari.querySelectorAll(args)
|
|
3027
3027
|
);
|
|
3028
|
+
// The matches live inside a child frame, so their x/y are that frame's viewport
|
|
3029
|
+
// coordinates while safari_click and friends take page coordinates. Warn in the
|
|
3030
|
+
// result text, which is the only part of this an agent actually reads.
|
|
3031
|
+
if (typeof result === "string" && result.includes('"frameRelative":true')) {
|
|
3032
|
+
return textResult(
|
|
3033
|
+
result +
|
|
3034
|
+
"\n\nNote: these matches are inside a child frame. Their x/y are relative to that frame's viewport (see \"frame\"), not to the page — click them by selector or by a safari_snapshot ref; passing these coordinates to safari_click lands somewhere else."
|
|
3035
|
+
);
|
|
3036
|
+
}
|
|
3028
3037
|
return textResult(result);
|
|
3029
3038
|
}
|
|
3030
3039
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "safari-mcp",
|
|
3
|
-
"version": "2.21.
|
|
3
|
+
"version": "2.21.4",
|
|
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",
|