safari-mcp 2.15.6 → 2.15.7
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/index.js +23 -13
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -210,19 +210,21 @@ function _startMemoryMonitor() {
|
|
|
210
210
|
|
|
211
211
|
// Cleanup on exit
|
|
212
212
|
let _cleaningUp = false;
|
|
213
|
+
async function _shutdown() {
|
|
214
|
+
if (_cleaningUp) return;
|
|
215
|
+
_cleaningUp = true;
|
|
216
|
+
// Restore the user's clipboard synchronously FIRST — if a native paste is mid-flight, its
|
|
217
|
+
// 2s restore timer would never fire once we exit, leaving the tool's text on the clipboard.
|
|
218
|
+
try { safari.flushClipboardRestore(); } catch {}
|
|
219
|
+
// Cap tab cleanup — if the daemon/Safari is wedged at shutdown (exactly when a SIGTERM
|
|
220
|
+
// tends to arrive), listTabs/closeTab can each block for their full timeout; never let
|
|
221
|
+
// that hang the exit past 3s.
|
|
222
|
+
await Promise.race([_cleanupTabs(), new Promise(r => setTimeout(r, 3000))]);
|
|
223
|
+
process.exit(0);
|
|
224
|
+
}
|
|
225
|
+
|
|
213
226
|
for (const sig of ["SIGINT", "SIGTERM", "SIGHUP"]) {
|
|
214
|
-
process.on(sig,
|
|
215
|
-
if (_cleaningUp) return; // Prevent double-exit on rapid signal repeat
|
|
216
|
-
_cleaningUp = true;
|
|
217
|
-
// Restore the user's clipboard synchronously FIRST — if a native paste is mid-flight, its
|
|
218
|
-
// 2s restore timer would never fire once we exit, leaving the tool's text on the clipboard.
|
|
219
|
-
try { safari.flushClipboardRestore(); } catch {}
|
|
220
|
-
// Cap tab cleanup — if the daemon/Safari is wedged at shutdown (exactly when a SIGTERM
|
|
221
|
-
// tends to arrive), listTabs/closeTab can each block for their full timeout; never let
|
|
222
|
-
// that hang the exit past 3s.
|
|
223
|
-
await Promise.race([_cleanupTabs(), new Promise(r => setTimeout(r, 3000))]);
|
|
224
|
-
process.exit(0);
|
|
225
|
-
});
|
|
227
|
+
process.on(sig, _shutdown);
|
|
226
228
|
}
|
|
227
229
|
process.on("exit", () => {
|
|
228
230
|
if (_openedTabs.size > 0) {
|
|
@@ -2420,4 +2422,12 @@ _startMemoryMonitor();
|
|
|
2420
2422
|
|
|
2421
2423
|
// Transport is chosen at runtime: default stdio (unchanged), or a shared HTTP instance when
|
|
2422
2424
|
// SAFARI_MCP_HTTP=1 (many Claude sessions → one process). buildServer is the per-session factory.
|
|
2423
|
-
await startTransport(buildServer, process.env);
|
|
2425
|
+
const transportHandle = await startTransport(buildServer, process.env);
|
|
2426
|
+
|
|
2427
|
+
if (transportHandle.kind === "stdio") {
|
|
2428
|
+
// A client can disappear without delivering a signal. Treat its pipe closing as the stdio
|
|
2429
|
+
// server's lifecycle boundary, while leaving the opt-in HTTP daemon independent of stdin.
|
|
2430
|
+
process.stdin.once("end", _shutdown);
|
|
2431
|
+
process.stdin.once("close", _shutdown);
|
|
2432
|
+
if (process.stdin.readableEnded || process.stdin.destroyed) void _shutdown();
|
|
2433
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "safari-mcp",
|
|
3
|
-
"version": "2.15.
|
|
3
|
+
"version": "2.15.7",
|
|
4
4
|
"mcpName": "io.github.achiya-automation/safari-mcp",
|
|
5
5
|
"description": "Safari browser automation for AI agents — native macOS, zero Chrome overhead. 96 tools via AppleScript + JavaScript.",
|
|
6
6
|
"type": "module",
|