safari-mcp 2.10.8 → 2.10.9

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 CHANGED
@@ -645,7 +645,23 @@ Safari MCP needs these one-time permissions:
645
645
  | JavaScript from Apple Events | Safari → Develop menu | Required for `do JavaScript` |
646
646
  | Automation → Safari | System Settings → Privacy & Security → Automation | Required for all AppleScript-backed tools |
647
647
  | Screen Recording | System Settings → Privacy & Security → Screen Recording | Required for `safari_screenshot` |
648
- | Accessibility | System Settings → Privacy & Security → Accessibility | Required for `safari_save_pdf` only |
648
+ | Accessibility (safari-helper) | System Settings → Privacy & Security → Accessibility | Required for `safari_native_click`, `safari_native_keyboard`, `safari_native_hover` and `safari_save_pdf` |
649
+
650
+ ### Granting Accessibility to safari-helper (required for `safari_native_*`)
651
+
652
+ The `safari_native_click`, `safari_native_keyboard` and `safari_native_hover` tools inject OS-level `CGEvent` events into Safari without stealing focus. macOS requires the underlying helper binary to be approved in **Accessibility** before those events can reach a non-frontmost window.
653
+
654
+ 1. Open **System Settings → Privacy & Security → Accessibility**.
655
+ 2. Click `+` (unlock with your password if needed).
656
+ 3. Navigate to the helper binary and add it:
657
+ - npm global install: `$(npm root -g)/safari-mcp/safari-helper`
658
+ - npx / project install: `./node_modules/safari-mcp/safari-helper`
659
+ - From source clone: `/path/to/safari-mcp/safari-helper`
660
+ 4. Make sure the toggle next to it is **ON**.
661
+
662
+ The postinstall script re-signs the helper with a stable identifier (`com.achiya-automation.safari-mcp`) so this permission survives future upgrades — without that step, every `npm update` would silently revoke approval because the binary's adhoc-signed identifier changes per build.
663
+
664
+ If `safari_native_click` reports success but the page doesn't react (no `isTrusted: true` click events fire), the helper is most likely missing this approval. The `safari_*` (non-`native_`) tools don't need it.
649
665
 
650
666
  ### Granting Automation → Safari (important for IDE users)
651
667
 
@@ -668,6 +684,7 @@ That call registers the Terminal app in the Automation database and then trigger
668
684
  | "AppleScript error" | Enable "Allow JavaScript from Apple Events" in Safari → Develop |
669
685
  | "Not authorized to send Apple events to Safari" | Grant Automation → Safari to your IDE (see above) |
670
686
  | "Not authorized" after `npm update` | Updating changes the binary's cdhash — macOS silently revokes Automation permission. Re-run the `osascript` one-liner above to re-grant it |
687
+ | `safari_native_click` reports success but page doesn't react | Add `safari-helper` to **System Settings → Privacy & Security → Accessibility** (see [Granting Accessibility](#granting-accessibility-to-safari-helper-required-for-safari_native_) above). Confirm by attaching a `click` listener with `{capture:true}` in the page console — without the grant, no `isTrusted: true` event fires |
671
688
  | Screenshots empty | Grant Screen Recording permission to Terminal/VS Code |
672
689
  | Tab not found | Call `safari_list_tabs` to refresh tab indices |
673
690
  | Hebrew keyboard issues | All typing uses JS events — immune to keyboard layout |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "safari-mcp",
3
- "version": "2.10.8",
3
+ "version": "2.10.9",
4
4
  "mcpName": "io.github.achiya-automation/safari-mcp",
5
5
  "description": "Safari browser automation for AI agents — native macOS, zero Chrome overhead. 80 tools via AppleScript + JavaScript.",
6
6
  "type": "module",
package/safari-helper CHANGED
Binary file
@@ -1,8 +1,10 @@
1
1
  #!/usr/bin/env node
2
- // Safari MCP — postinstall welcome message
2
+ // Safari MCP — postinstall: codesign helper + welcome message
3
3
  // Skipped silently in CI and when stdout is not a TTY (npm install in scripts).
4
4
 
5
- if (process.env.CI || process.env.SAFARI_MCP_SILENT_INSTALL === "1") process.exit(0);
5
+ const path = require("path");
6
+ const { execSync } = require("child_process");
7
+ const fs = require("fs");
6
8
 
7
9
  const c = {
8
10
  reset: "\x1b[0m",
@@ -12,8 +14,36 @@ const c = {
12
14
  yellow: "\x1b[33m",
13
15
  magenta: "\x1b[35m",
14
16
  green: "\x1b[32m",
17
+ red: "\x1b[31m",
15
18
  };
16
19
 
20
+ // Re-sign safari-helper with a stable identifier so macOS Accessibility approval persists.
21
+ // The package ships with an adhoc-signed binary whose codesign Identifier is a one-off hash
22
+ // (e.g. `safari-helper-555549441c166aa237e130ddbe3d95629266ecaf`). macOS TCC keys grants by
23
+ // that identifier, so a fresh npm install or rebuild silently invalidates any previously-granted
24
+ // Accessibility approval — the helper keeps running but CGEvent injections to non-frontmost Safari
25
+ // windows stop reaching WebKit content (no isTrusted click events fire on the page).
26
+ // Re-signing here with the fixed identifier `com.achiya-automation.safari-mcp` keeps the grant
27
+ // stable across installs.
28
+ function ensureCodesign() {
29
+ if (process.platform !== "darwin") return;
30
+ const helper = path.join(__dirname, "..", "safari-helper");
31
+ if (!fs.existsSync(helper)) return;
32
+ try {
33
+ // Check current identifier; only re-sign if it doesn't already match.
34
+ const current = execSync(`codesign -d -- "${helper}" 2>&1 | grep ^Identifier=`, { encoding: "utf8" }).trim();
35
+ if (current.includes("com.achiya-automation.safari-mcp")) return;
36
+ const entitlements = path.join(__dirname, "..", "safari-helper.entitlements");
37
+ const entFlag = fs.existsSync(entitlements) ? `--entitlements "${entitlements}"` : "";
38
+ execSync(`codesign -s - -f --identifier com.achiya-automation.safari-mcp ${entFlag} "${helper}" 2>/dev/null`);
39
+ } catch (_e) {
40
+ // codesign may fail in environments without the toolchain; binary still works adhoc-signed.
41
+ }
42
+ }
43
+ ensureCodesign();
44
+
45
+ if (process.env.CI || process.env.SAFARI_MCP_SILENT_INSTALL === "1") process.exit(0);
46
+
17
47
  const msg = `
18
48
  ${c.bold}${c.cyan}🦁 Safari MCP installed${c.reset} ${c.dim}— 80 native browser tools for AI agents${c.reset}
19
49
 
@@ -21,6 +51,9 @@ ${c.bold}Next steps:${c.reset}
21
51
  1. Enable Safari → Develop → ${c.yellow}Allow JavaScript from Apple Events${c.reset}
22
52
  2. Add to your MCP client config:
23
53
  ${c.dim}{ "mcpServers": { "safari": { "command": "npx", "args": ["safari-mcp"] } } }${c.reset}
54
+ 3. ${c.bold}For native_click / native_keyboard${c.reset} (no focus stealing):
55
+ System Settings → Privacy & Security → ${c.yellow}Accessibility${c.reset} → add
56
+ ${c.dim}node_modules/safari-mcp/safari-helper${c.reset} ${c.dim}(or the global install path)${c.reset}
24
57
 
25
58
  ${c.bold}${c.magenta}⭐ Found this useful?${c.reset} A star helps others discover it:
26
59
  ${c.cyan}https://github.com/achiya-automation/safari-mcp${c.reset}