safari-mcp 2.21.1 → 2.21.2

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/index.js +3 -3
  2. package/package.json +1 -1
  3. package/response.js +21 -0
package/index.js CHANGED
@@ -11,7 +11,7 @@ import { startTransport } from "./transport.js";
11
11
  import { currentSessionId } from "./session-context.js";
12
12
  import { z } from "zod";
13
13
  import * as safari from "./safari.js";
14
- import { textResult, jsonResult, imageResult, errorResult } from "./response.js";
14
+ import { textResult, jsonResult, imageResult, errorResult, evalResult } from "./response.js";
15
15
  import {
16
16
  OWNERSHIP_DIR, BLANK_TAB_SENTINEL,
17
17
  _openedTabs, _ownedTabURLs,
@@ -2982,7 +2982,7 @@ server.tool(
2982
2982
  return safari.evaluate(args);
2983
2983
  }
2984
2984
  );
2985
- return { content: [{ type: "text", text: (typeof result === 'string' ? result : JSON.stringify(result)) || "(no return value)" }] };
2985
+ return evalResult(result);
2986
2986
  }
2987
2987
  );
2988
2988
 
@@ -2993,7 +2993,7 @@ server.tool(
2993
2993
  async (args) => {
2994
2994
  const script = readFileSync(args.path, "utf8");
2995
2995
  const result = await extensionOrFallback("evaluate", { script }, () => safari.evaluate({ script }));
2996
- return { content: [{ type: "text", text: (typeof result === "string" ? result : JSON.stringify(result)) || "(no return value)" }] };
2996
+ return evalResult(result);
2997
2997
  }
2998
2998
  );
2999
2999
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "safari-mcp",
3
- "version": "2.21.1",
3
+ "version": "2.21.2",
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",
package/response.js CHANGED
@@ -28,3 +28,24 @@ export const errorResult = (msg) => ({
28
28
  content: [{ type: "text", text: msg }],
29
29
  isError: true,
30
30
  });
31
+
32
+ /**
33
+ * `safari_evaluate` / `safari_eval_file` result text.
34
+ *
35
+ * Distinct from `textResult`: only these two tools surface a *script's* return value,
36
+ * so they need to say "the script returned nothing" — and the old form said it with a
37
+ * falsy check, `(… || "(no return value)")`. That collapsed three different outcomes
38
+ * into one string: a script returning `undefined` (nothing), a script returning `""`
39
+ * (a real value), and an injection that never ran at all (a failure). An empty return
40
+ * is a legitimate result and must stay distinguishable from no return.
41
+ */
42
+ export const evalResult = (r) => {
43
+ let text;
44
+ if (typeof r === "string") {
45
+ text = r === "" ? '""' : r;
46
+ } else {
47
+ const json = JSON.stringify(r); // undefined for undefined/function/symbol
48
+ text = json === undefined ? "(no return value)" : json;
49
+ }
50
+ return { content: [{ type: "text", text }] };
51
+ };