@heznpc/imcp 0.1.0 → 0.6.0
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/LICENSE +21 -0
- package/README.ko.md +225 -57
- package/README.md +222 -30
- package/dist/calendar/prompts.d.ts +2 -0
- package/dist/calendar/prompts.js +43 -0
- package/dist/calendar/prompts.js.map +1 -0
- package/dist/calendar/scripts.d.ts +20 -0
- package/dist/calendar/scripts.js +283 -0
- package/dist/calendar/scripts.js.map +1 -0
- package/dist/calendar/tools.d.ts +3 -0
- package/dist/calendar/tools.js +252 -0
- package/dist/calendar/tools.js.map +1 -0
- package/dist/contacts/scripts.d.ts +22 -0
- package/dist/contacts/scripts.js +220 -0
- package/dist/contacts/scripts.js.map +1 -0
- package/dist/contacts/tools.d.ts +3 -0
- package/dist/contacts/tools.js +173 -0
- package/dist/contacts/tools.js.map +1 -0
- package/dist/cross/prompts.d.ts +2 -0
- package/dist/cross/prompts.js +177 -0
- package/dist/cross/prompts.js.map +1 -0
- package/dist/finder/scripts.d.ts +8 -0
- package/dist/finder/scripts.js +127 -0
- package/dist/finder/scripts.js.map +1 -0
- package/dist/finder/tools.d.ts +3 -0
- package/dist/finder/tools.js +134 -0
- package/dist/finder/tools.js.map +1 -0
- package/dist/index.js +38 -1
- package/dist/index.js.map +1 -1
- package/dist/intelligence/tools.d.ts +3 -0
- package/dist/intelligence/tools.js +74 -0
- package/dist/intelligence/tools.js.map +1 -0
- package/dist/mail/scripts.d.ts +9 -0
- package/dist/mail/scripts.js +214 -0
- package/dist/mail/scripts.js.map +1 -0
- package/dist/mail/tools.d.ts +3 -0
- package/dist/mail/tools.js +145 -0
- package/dist/mail/tools.js.map +1 -0
- package/dist/music/scripts.d.ts +9 -0
- package/dist/music/scripts.js +180 -0
- package/dist/music/scripts.js.map +1 -0
- package/dist/music/tools.d.ts +3 -0
- package/dist/music/tools.js +143 -0
- package/dist/music/tools.js.map +1 -0
- package/dist/notes/prompts.js +1 -6
- package/dist/notes/prompts.js.map +1 -1
- package/dist/notes/scripts.js +1 -11
- package/dist/notes/scripts.js.map +1 -1
- package/dist/notes/tools.js +1 -11
- package/dist/notes/tools.js.map +1 -1
- package/dist/photos/scripts.d.ts +7 -0
- package/dist/photos/scripts.js +142 -0
- package/dist/photos/scripts.js.map +1 -0
- package/dist/photos/tools.d.ts +3 -0
- package/dist/photos/tools.js +158 -0
- package/dist/photos/tools.js.map +1 -0
- package/dist/reminders/prompts.d.ts +2 -0
- package/dist/reminders/prompts.js +40 -0
- package/dist/reminders/prompts.js.map +1 -0
- package/dist/reminders/scripts.d.ts +21 -0
- package/dist/reminders/scripts.js +202 -0
- package/dist/reminders/scripts.js.map +1 -0
- package/dist/reminders/tools.d.ts +3 -0
- package/dist/reminders/tools.js +267 -0
- package/dist/reminders/tools.js.map +1 -0
- package/dist/safari/scripts.d.ts +8 -0
- package/dist/safari/scripts.js +120 -0
- package/dist/safari/scripts.js.map +1 -0
- package/dist/safari/tools.d.ts +3 -0
- package/dist/safari/tools.js +129 -0
- package/dist/safari/tools.js.map +1 -0
- package/dist/shared/esc.d.ts +10 -0
- package/dist/shared/esc.js +35 -0
- package/dist/shared/esc.js.map +1 -0
- package/dist/shared/jxa.js +1 -1
- package/dist/shared/jxa.js.map +1 -1
- package/dist/shared/prompt.d.ts +11 -0
- package/dist/shared/prompt.js +8 -0
- package/dist/shared/prompt.js.map +1 -0
- package/dist/shared/resources.d.ts +5 -0
- package/dist/shared/resources.js +81 -0
- package/dist/shared/resources.js.map +1 -0
- package/dist/shared/result.d.ts +15 -0
- package/dist/shared/result.js +14 -0
- package/dist/shared/result.js.map +1 -0
- package/dist/shared/setup.d.ts +2 -0
- package/dist/shared/setup.js +44 -0
- package/dist/shared/setup.js.map +1 -0
- package/dist/shared/swift.d.ts +2 -0
- package/dist/shared/swift.js +73 -0
- package/dist/shared/swift.js.map +1 -0
- package/dist/shortcuts/scripts.d.ts +4 -0
- package/dist/shortcuts/scripts.js +47 -0
- package/dist/shortcuts/scripts.js.map +1 -0
- package/dist/shortcuts/tools.d.ts +3 -0
- package/dist/shortcuts/tools.js +66 -0
- package/dist/shortcuts/tools.js.map +1 -0
- package/dist/system/scripts.d.ts +9 -0
- package/dist/system/scripts.js +124 -0
- package/dist/system/scripts.js.map +1 -0
- package/dist/system/tools.d.ts +3 -0
- package/dist/system/tools.js +179 -0
- package/dist/system/tools.js.map +1 -0
- package/package.json +39 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/shared/prompt.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,MAAM,UAAU,UAAU,CAAC,WAAmB,EAAE,IAAY;IAC1D,OAAO;QACL,WAAW;QACX,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,EAAE,CAAC;KAChF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { runJxa } from "./jxa.js";
|
|
3
|
+
import { listEventsScript } from "../calendar/scripts.js";
|
|
4
|
+
import { listRemindersScript } from "../reminders/scripts.js";
|
|
5
|
+
/**
|
|
6
|
+
* Register MCP resources that expose live Apple data for direct client reads.
|
|
7
|
+
*/
|
|
8
|
+
export function registerResources(server) {
|
|
9
|
+
// ── notes://recent — fixed resource: 10 most recently modified notes ──
|
|
10
|
+
server.registerResource("recent-notes", "notes://recent", {
|
|
11
|
+
description: "List of the 10 most recently modified Apple Notes",
|
|
12
|
+
mimeType: "application/json",
|
|
13
|
+
}, async (uri) => {
|
|
14
|
+
const notes = await fetchRecentNotes(10);
|
|
15
|
+
return {
|
|
16
|
+
contents: [{ uri: uri.href, mimeType: "application/json", text: JSON.stringify(notes, null, 2) }],
|
|
17
|
+
};
|
|
18
|
+
});
|
|
19
|
+
// ── notes://recent/{count} — template: configurable count ──
|
|
20
|
+
server.registerResource("recent-notes-count", new ResourceTemplate("notes://recent/{count}", { list: undefined }), {
|
|
21
|
+
description: "List of recently modified Apple Notes. Use {count} to control how many are returned (max 50).",
|
|
22
|
+
mimeType: "application/json",
|
|
23
|
+
}, async (uri, variables) => {
|
|
24
|
+
const raw = Array.isArray(variables.count) ? variables.count[0] : variables.count;
|
|
25
|
+
const count = Math.max(1, Math.min(Number(raw) || 10, 50));
|
|
26
|
+
const notes = await fetchRecentNotes(count);
|
|
27
|
+
return {
|
|
28
|
+
contents: [{ uri: uri.href, mimeType: "application/json", text: JSON.stringify(notes, null, 2) }],
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
// ── calendar://today — today's calendar events (reuses listEventsScript) ──
|
|
32
|
+
server.registerResource("today-events", "calendar://today", {
|
|
33
|
+
description: "Today's Apple Calendar events, sorted by start time",
|
|
34
|
+
mimeType: "application/json",
|
|
35
|
+
}, async (uri) => {
|
|
36
|
+
const today = new Date();
|
|
37
|
+
const start = new Date(today.getFullYear(), today.getMonth(), today.getDate()).toISOString();
|
|
38
|
+
const end = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1).toISOString();
|
|
39
|
+
const result = await runJxa(listEventsScript(start, end, 999, 0));
|
|
40
|
+
return {
|
|
41
|
+
contents: [{ uri: uri.href, mimeType: "application/json", text: JSON.stringify(result.events, null, 2) }],
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
// ── reminders://due — currently due or overdue reminders (reuses listRemindersScript) ──
|
|
45
|
+
server.registerResource("due-reminders", "reminders://due", {
|
|
46
|
+
description: "Apple Reminders that are currently due or overdue",
|
|
47
|
+
mimeType: "application/json",
|
|
48
|
+
}, async (uri) => {
|
|
49
|
+
const all = await runJxa(listRemindersScript(undefined, false));
|
|
50
|
+
const now = new Date();
|
|
51
|
+
const due = all
|
|
52
|
+
.filter((r) => r.dueDate && new Date(r.dueDate) <= now)
|
|
53
|
+
.sort((a, b) => new Date(a.dueDate).getTime() - new Date(b.dueDate).getTime());
|
|
54
|
+
return {
|
|
55
|
+
contents: [{ uri: uri.href, mimeType: "application/json", text: JSON.stringify(due, null, 2) }],
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
async function fetchRecentNotes(count) {
|
|
60
|
+
return runJxa(`
|
|
61
|
+
const Notes = Application('Notes');
|
|
62
|
+
const names = Notes.notes.name();
|
|
63
|
+
const ids = Notes.notes.id();
|
|
64
|
+
const modDates = Notes.notes.modificationDate();
|
|
65
|
+
const indices = Array.from({length: names.length}, (_, i) => i);
|
|
66
|
+
indices.sort((a, b) => modDates[b] - modDates[a]);
|
|
67
|
+
const top = indices.slice(0, ${count});
|
|
68
|
+
const result = top.map(i => {
|
|
69
|
+
const note = Notes.notes[i];
|
|
70
|
+
return {
|
|
71
|
+
id: ids[i],
|
|
72
|
+
name: names[i],
|
|
73
|
+
folder: note.container.name(),
|
|
74
|
+
modificationDate: modDates[i].toISOString(),
|
|
75
|
+
preview: note.plaintext().substring(0, 200)
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
JSON.stringify(result);
|
|
79
|
+
`);
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=resources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.js","sourceRoot":"","sources":["../../src/shared/resources.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Return a successful MCP tool response with JSON-formatted data. */
|
|
2
|
+
export declare function ok(data: unknown): {
|
|
3
|
+
content: {
|
|
4
|
+
type: "text";
|
|
5
|
+
text: string;
|
|
6
|
+
}[];
|
|
7
|
+
};
|
|
8
|
+
/** Return an MCP tool error response. */
|
|
9
|
+
export declare function err(message: string): {
|
|
10
|
+
content: {
|
|
11
|
+
type: "text";
|
|
12
|
+
text: string;
|
|
13
|
+
}[];
|
|
14
|
+
isError: boolean;
|
|
15
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Return a successful MCP tool response with JSON-formatted data. */
|
|
2
|
+
export function ok(data) {
|
|
3
|
+
return {
|
|
4
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
/** Return an MCP tool error response. */
|
|
8
|
+
export function err(message) {
|
|
9
|
+
return {
|
|
10
|
+
content: [{ type: "text", text: message }],
|
|
11
|
+
isError: true,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result.js","sourceRoot":"","sources":["../../src/shared/result.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,MAAM,UAAU,EAAE,CAAC,IAAa;IAC9B,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;KAC1E,CAAC;AACJ,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,GAAG,CAAC,OAAe;IACjC,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QACnD,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { runJxa } from "./jxa.js";
|
|
2
|
+
import { ok } from "./result.js";
|
|
3
|
+
const APPS = [
|
|
4
|
+
{ name: "Notes", script: "const Notes = Application('Notes'); JSON.stringify({app: 'Notes', accessible: true});" },
|
|
5
|
+
{ name: "Reminders", script: "const Reminders = Application('Reminders'); JSON.stringify({app: 'Reminders', accessible: true});" },
|
|
6
|
+
{ name: "Calendar", script: "const Calendar = Application('Calendar'); JSON.stringify({app: 'Calendar', accessible: true});" },
|
|
7
|
+
{ name: "Contacts", script: "const Contacts = Application('Contacts'); JSON.stringify({app: 'Contacts', accessible: true});" },
|
|
8
|
+
{ name: "Mail", script: "const Mail = Application('Mail'); JSON.stringify({app: 'Mail', accessible: true});" },
|
|
9
|
+
{ name: "Music", script: "const Music = Application('Music'); JSON.stringify({app: 'Music', accessible: true});" },
|
|
10
|
+
{ name: "Finder", script: "const Finder = Application('Finder'); JSON.stringify({app: 'Finder', accessible: true});" },
|
|
11
|
+
{ name: "Safari", script: "const Safari = Application('Safari'); JSON.stringify({app: 'Safari', accessible: true});" },
|
|
12
|
+
{ name: "System Events", script: "const SE = Application('System Events'); JSON.stringify({app: 'System Events', accessible: true});" },
|
|
13
|
+
{ name: "Photos", script: "const Photos = Application('Photos'); JSON.stringify({app: 'Photos', accessible: true});" },
|
|
14
|
+
];
|
|
15
|
+
export function registerSetupTools(server) {
|
|
16
|
+
server.registerTool("setup_permissions", {
|
|
17
|
+
title: "Setup Permissions",
|
|
18
|
+
description: "Trigger macOS permission prompts for all Apple apps used by iMcp. Run this once after installation to grant all permissions at once. Each app will show a one-time macOS permission dialog.",
|
|
19
|
+
inputSchema: {},
|
|
20
|
+
annotations: {
|
|
21
|
+
readOnlyHint: true,
|
|
22
|
+
destructiveHint: false,
|
|
23
|
+
idempotentHint: true,
|
|
24
|
+
openWorldHint: false,
|
|
25
|
+
},
|
|
26
|
+
}, async () => {
|
|
27
|
+
const results = [];
|
|
28
|
+
for (const app of APPS) {
|
|
29
|
+
try {
|
|
30
|
+
await runJxa(app.script);
|
|
31
|
+
results.push({ app: app.name, status: "granted" });
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
results.push({
|
|
35
|
+
app: app.name,
|
|
36
|
+
status: `failed: ${e instanceof Error ? e.message : String(e)}`,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const granted = results.filter((r) => r.status === "granted").length;
|
|
41
|
+
return ok({ total: APPS.length, granted, results });
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/shared/setup.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAEjC,MAAM,IAAI,GAAG;IACX,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,uFAAuF,EAAE;IAClH,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,mGAAmG,EAAE;IAClI,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,gGAAgG,EAAE;IAC9H,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,gGAAgG,EAAE;IAC9H,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,oFAAoF,EAAE;IAC9G,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,uFAAuF,EAAE;IAClH,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,0FAA0F,EAAE;IACtH,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,0FAA0F,EAAE;IACtH,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,oGAAoG,EAAE;IACvI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,0FAA0F,EAAE;CACvH,CAAC;AAEF,MAAM,UAAU,kBAAkB,CAAC,MAAiB;IAClD,MAAM,CAAC,YAAY,CACjB,mBAAmB,EACnB;QACE,KAAK,EAAE,mBAAmB;QAC1B,WAAW,EACT,6LAA6L;QAC/L,WAAW,EAAE,EAAE;QACf,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,KAAK;YACtB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,KAAK;SACrB;KACF,EACD,KAAK,IAAI,EAAE;QACT,MAAM,OAAO,GAA2C,EAAE,CAAC;QAC3D,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACzB,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;YACrD,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,CAAC,IAAI,CAAC;oBACX,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,MAAM,EAAE,WAAW,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;iBAChE,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;QACrE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IACtD,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { access } from "node:fs/promises";
|
|
3
|
+
import { resolve, dirname } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
const TIMEOUT_MS = 60_000; // 60s — LLM inference can be slow
|
|
6
|
+
const MAX_BUFFER = 10 * 1024 * 1024; // 10 MB
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const BINARY_PATH = resolve(__dirname, "../../swift/.build/release/ImcpBridge");
|
|
9
|
+
let bridgeChecked = false;
|
|
10
|
+
let bridgeError = null;
|
|
11
|
+
export async function checkSwiftBridge() {
|
|
12
|
+
if (bridgeChecked)
|
|
13
|
+
return bridgeError;
|
|
14
|
+
try {
|
|
15
|
+
await access(BINARY_PATH);
|
|
16
|
+
bridgeError = null;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
bridgeError = `Apple Intelligence requires macOS 26+ with Apple Silicon. Swift bridge binary not found at: ${BINARY_PATH}. Run 'npm run swift-build' to compile.`;
|
|
20
|
+
}
|
|
21
|
+
bridgeChecked = true;
|
|
22
|
+
return bridgeError;
|
|
23
|
+
}
|
|
24
|
+
export async function runSwift(command, input) {
|
|
25
|
+
const missing = await checkSwiftBridge();
|
|
26
|
+
if (missing)
|
|
27
|
+
throw new Error(missing);
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
const child = spawn(BINARY_PATH, [command], {
|
|
30
|
+
timeout: TIMEOUT_MS,
|
|
31
|
+
});
|
|
32
|
+
let stdout = "";
|
|
33
|
+
let stderr = "";
|
|
34
|
+
let size = 0;
|
|
35
|
+
child.stdout.on("data", (chunk) => {
|
|
36
|
+
size += chunk.length;
|
|
37
|
+
if (size > MAX_BUFFER) {
|
|
38
|
+
child.kill("SIGTERM");
|
|
39
|
+
reject(new Error(`Swift bridge output exceeded ${MAX_BUFFER} bytes`));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
stdout += chunk.toString();
|
|
43
|
+
});
|
|
44
|
+
child.stderr.on("data", (chunk) => {
|
|
45
|
+
stderr += chunk.toString();
|
|
46
|
+
});
|
|
47
|
+
child.on("close", (code, signal) => {
|
|
48
|
+
if (signal === "SIGTERM") {
|
|
49
|
+
reject(new Error(`Swift bridge timed out after ${TIMEOUT_MS / 1000}s`));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (code !== 0) {
|
|
53
|
+
reject(new Error(`Swift bridge exited with code ${code}: ${stderr || stdout}`));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const trimmed = stdout.trim();
|
|
57
|
+
if (!trimmed) {
|
|
58
|
+
reject(new Error("Swift bridge returned empty output"));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
resolve(JSON.parse(trimmed));
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
reject(new Error(`Swift bridge returned invalid JSON: ${trimmed.slice(0, 200)}`));
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
child.on("error", reject);
|
|
69
|
+
child.stdin.write(input);
|
|
70
|
+
child.stdin.end();
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=swift.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"swift.js","sourceRoot":"","sources":["../../src/shared/swift.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function listShortcutsScript(): string;
|
|
2
|
+
export declare function runShortcutScript(name: string, input?: string): string;
|
|
3
|
+
export declare function searchShortcutsScript(query: string): string;
|
|
4
|
+
export declare function getShortcutDetailScript(name: string): string;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// JXA scripts for macOS Shortcuts automation.
|
|
2
|
+
import { esc, escJxaShell } from "../shared/esc.js";
|
|
3
|
+
export function listShortcutsScript() {
|
|
4
|
+
return `
|
|
5
|
+
const app = Application.currentApplication();
|
|
6
|
+
app.includeStandardAdditions = true;
|
|
7
|
+
const output = app.doShellScript('shortcuts list');
|
|
8
|
+
const names = output.split('\\n').filter(n => n.length > 0);
|
|
9
|
+
JSON.stringify({total: names.length, shortcuts: names});
|
|
10
|
+
`;
|
|
11
|
+
}
|
|
12
|
+
export function runShortcutScript(name, input) {
|
|
13
|
+
const inputPart = input !== undefined
|
|
14
|
+
? ` --input-type text --input "${escJxaShell(input)}"`
|
|
15
|
+
: "";
|
|
16
|
+
return `
|
|
17
|
+
const app = Application.currentApplication();
|
|
18
|
+
app.includeStandardAdditions = true;
|
|
19
|
+
const output = app.doShellScript('shortcuts run "${escJxaShell(name)}"${inputPart}');
|
|
20
|
+
JSON.stringify({shortcut: '${esc(name)}', output: output});
|
|
21
|
+
`;
|
|
22
|
+
}
|
|
23
|
+
export function searchShortcutsScript(query) {
|
|
24
|
+
return `
|
|
25
|
+
const app = Application.currentApplication();
|
|
26
|
+
app.includeStandardAdditions = true;
|
|
27
|
+
const output = app.doShellScript('shortcuts list');
|
|
28
|
+
const names = output.split('\\n').filter(n => n.length > 0);
|
|
29
|
+
const q = '${esc(query)}'.toLowerCase();
|
|
30
|
+
const matches = names.filter(n => n.toLowerCase().includes(q));
|
|
31
|
+
JSON.stringify({total: matches.length, shortcuts: matches});
|
|
32
|
+
`;
|
|
33
|
+
}
|
|
34
|
+
export function getShortcutDetailScript(name) {
|
|
35
|
+
return `
|
|
36
|
+
const app = Application.currentApplication();
|
|
37
|
+
app.includeStandardAdditions = true;
|
|
38
|
+
let actions = '';
|
|
39
|
+
try {
|
|
40
|
+
actions = app.doShellScript('shortcuts view "${escJxaShell(name)}" 2>&1 || true');
|
|
41
|
+
} catch(e) {
|
|
42
|
+
actions = 'Details not available';
|
|
43
|
+
}
|
|
44
|
+
JSON.stringify({shortcut: '${esc(name)}', detail: actions});
|
|
45
|
+
`;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=scripts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scripts.js","sourceRoot":"","sources":["../../src/shortcuts/scripts.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAE9C,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,UAAU,mBAAmB;IACjC,OAAO;;;;;;GAMN,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,KAAc;IAC5D,MAAM,SAAS,GAAG,KAAK,KAAK,SAAS;QACnC,CAAC,CAAC,+BAA+B,WAAW,CAAC,KAAK,CAAC,GAAG;QACtD,CAAC,CAAC,EAAE,CAAC;IACP,OAAO;;;uDAG8C,WAAW,CAAC,IAAI,CAAC,IAAI,SAAS;iCACpD,GAAG,CAAC,IAAI,CAAC;GACvC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAa;IACjD,OAAO;;;;;iBAKQ,GAAG,CAAC,KAAK,CAAC;;;GAGxB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,OAAO;;;;;qDAK4C,WAAW,CAAC,IAAI,CAAC;;;;iCAIrC,GAAG,CAAC,IAAI,CAAC;GACvC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { runJxa } from "../shared/jxa.js";
|
|
3
|
+
import { ok, err } from "../shared/result.js";
|
|
4
|
+
import { listShortcutsScript, runShortcutScript, searchShortcutsScript, getShortcutDetailScript, } from "./scripts.js";
|
|
5
|
+
export function registerShortcutsTools(server, _config) {
|
|
6
|
+
server.registerTool("list_shortcuts", {
|
|
7
|
+
title: "List Shortcuts",
|
|
8
|
+
description: "List all available Siri Shortcuts on this Mac.",
|
|
9
|
+
inputSchema: {},
|
|
10
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
11
|
+
}, async () => {
|
|
12
|
+
try {
|
|
13
|
+
return ok(await runJxa(listShortcutsScript()));
|
|
14
|
+
}
|
|
15
|
+
catch (e) {
|
|
16
|
+
return err(`Failed to list shortcuts: ${e instanceof Error ? e.message : String(e)}`);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
server.registerTool("run_shortcut", {
|
|
20
|
+
title: "Run Shortcut",
|
|
21
|
+
description: "Run a Siri Shortcut by name. Optionally provide text input. Returns the shortcut's output. Note: shortcuts may trigger UI prompts or perform system actions.",
|
|
22
|
+
inputSchema: {
|
|
23
|
+
name: z.string().describe("Shortcut name (exact match)"),
|
|
24
|
+
input: z.string().optional().describe("Optional text input for the shortcut"),
|
|
25
|
+
},
|
|
26
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
27
|
+
}, async ({ name, input }) => {
|
|
28
|
+
try {
|
|
29
|
+
return ok(await runJxa(runShortcutScript(name, input)));
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
return err(`Failed to run shortcut: ${e instanceof Error ? e.message : String(e)}`);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
server.registerTool("search_shortcuts", {
|
|
36
|
+
title: "Search Shortcuts",
|
|
37
|
+
description: "Search Siri Shortcuts by name keyword.",
|
|
38
|
+
inputSchema: {
|
|
39
|
+
query: z.string().describe("Search keyword to match against shortcut names"),
|
|
40
|
+
},
|
|
41
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
42
|
+
}, async ({ query }) => {
|
|
43
|
+
try {
|
|
44
|
+
return ok(await runJxa(searchShortcutsScript(query)));
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
return err(`Failed to search shortcuts: ${e instanceof Error ? e.message : String(e)}`);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
server.registerTool("get_shortcut_detail", {
|
|
51
|
+
title: "Get Shortcut Detail",
|
|
52
|
+
description: "Get details about a Siri Shortcut including its actions.",
|
|
53
|
+
inputSchema: {
|
|
54
|
+
name: z.string().describe("Shortcut name (exact match)"),
|
|
55
|
+
},
|
|
56
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
57
|
+
}, async ({ name }) => {
|
|
58
|
+
try {
|
|
59
|
+
return ok(await runJxa(getShortcutDetailScript(name)));
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
return err(`Failed to get shortcut detail: ${e instanceof Error ? e.message : String(e)}`);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/shortcuts/tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function getClipboardScript(): string;
|
|
2
|
+
export declare function setClipboardScript(text: string): string;
|
|
3
|
+
export declare function getVolumeScript(): string;
|
|
4
|
+
export declare function setVolumeScript(volume?: number, muted?: boolean): string;
|
|
5
|
+
export declare function toggleDarkModeScript(): string;
|
|
6
|
+
export declare function getFrontmostAppScript(): string;
|
|
7
|
+
export declare function listRunningAppsScript(): string;
|
|
8
|
+
export declare function getScreenInfoScript(): string;
|
|
9
|
+
export declare function showNotificationScript(message: string, title?: string, subtitle?: string, sound?: string): string;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// JXA scripts for macOS system automation.
|
|
2
|
+
import { esc } from "../shared/esc.js";
|
|
3
|
+
export function getClipboardScript() {
|
|
4
|
+
return `
|
|
5
|
+
const app = Application.currentApplication();
|
|
6
|
+
app.includeStandardAdditions = true;
|
|
7
|
+
const text = app.theClipboard();
|
|
8
|
+
JSON.stringify({content: String(text)});
|
|
9
|
+
`;
|
|
10
|
+
}
|
|
11
|
+
export function setClipboardScript(text) {
|
|
12
|
+
return `
|
|
13
|
+
const app = Application.currentApplication();
|
|
14
|
+
app.includeStandardAdditions = true;
|
|
15
|
+
const text = '${esc(text)}';
|
|
16
|
+
app.setTheClipboardTo(text);
|
|
17
|
+
JSON.stringify({set: true, length: text.length});
|
|
18
|
+
`;
|
|
19
|
+
}
|
|
20
|
+
export function getVolumeScript() {
|
|
21
|
+
return `
|
|
22
|
+
const app = Application.currentApplication();
|
|
23
|
+
app.includeStandardAdditions = true;
|
|
24
|
+
const vol = app.getVolumeSettings();
|
|
25
|
+
JSON.stringify({
|
|
26
|
+
outputVolume: vol.outputVolume,
|
|
27
|
+
inputVolume: vol.inputVolume,
|
|
28
|
+
outputMuted: vol.outputMuted
|
|
29
|
+
});
|
|
30
|
+
`;
|
|
31
|
+
}
|
|
32
|
+
export function setVolumeScript(volume, muted) {
|
|
33
|
+
const parts = [];
|
|
34
|
+
if (volume !== undefined)
|
|
35
|
+
parts.push(`outputVolume: ${Math.max(0, Math.min(100, Math.round(volume)))}`);
|
|
36
|
+
if (muted !== undefined)
|
|
37
|
+
parts.push(`outputMuted: ${muted}`);
|
|
38
|
+
return `
|
|
39
|
+
const app = Application.currentApplication();
|
|
40
|
+
app.includeStandardAdditions = true;
|
|
41
|
+
app.setVolume(null, {${parts.join(", ")}});
|
|
42
|
+
const vol = app.getVolumeSettings();
|
|
43
|
+
JSON.stringify({
|
|
44
|
+
outputVolume: vol.outputVolume,
|
|
45
|
+
outputMuted: vol.outputMuted
|
|
46
|
+
});
|
|
47
|
+
`;
|
|
48
|
+
}
|
|
49
|
+
export function toggleDarkModeScript() {
|
|
50
|
+
return `
|
|
51
|
+
const se = Application('System Events');
|
|
52
|
+
const current = se.appearancePreferences.darkMode();
|
|
53
|
+
se.appearancePreferences.darkMode = !current;
|
|
54
|
+
JSON.stringify({darkMode: !current});
|
|
55
|
+
`;
|
|
56
|
+
}
|
|
57
|
+
export function getFrontmostAppScript() {
|
|
58
|
+
return `
|
|
59
|
+
const se = Application('System Events');
|
|
60
|
+
const procs = se.processes.whose({frontmost: true})();
|
|
61
|
+
if (procs.length === 0) throw new Error('No frontmost app found');
|
|
62
|
+
const proc = procs[0];
|
|
63
|
+
JSON.stringify({
|
|
64
|
+
name: proc.name(),
|
|
65
|
+
bundleIdentifier: proc.bundleIdentifier(),
|
|
66
|
+
pid: proc.unixId()
|
|
67
|
+
});
|
|
68
|
+
`;
|
|
69
|
+
}
|
|
70
|
+
export function listRunningAppsScript() {
|
|
71
|
+
return `
|
|
72
|
+
const se = Application('System Events');
|
|
73
|
+
const procs = se.applicationProcesses();
|
|
74
|
+
const result = [];
|
|
75
|
+
for (const p of procs) {
|
|
76
|
+
try {
|
|
77
|
+
result.push({
|
|
78
|
+
name: p.name(),
|
|
79
|
+
bundleIdentifier: p.bundleIdentifier(),
|
|
80
|
+
pid: p.unixId(),
|
|
81
|
+
visible: p.visible()
|
|
82
|
+
});
|
|
83
|
+
} catch(e) {}
|
|
84
|
+
}
|
|
85
|
+
JSON.stringify({total: result.length, apps: result});
|
|
86
|
+
`;
|
|
87
|
+
}
|
|
88
|
+
export function getScreenInfoScript() {
|
|
89
|
+
return `
|
|
90
|
+
const app = Application.currentApplication();
|
|
91
|
+
app.includeStandardAdditions = true;
|
|
92
|
+
const output = app.doShellScript('system_profiler SPDisplaysDataType -json');
|
|
93
|
+
const data = JSON.parse(output);
|
|
94
|
+
const displays = [];
|
|
95
|
+
for (const gpu of (data.SPDisplaysDataType || [])) {
|
|
96
|
+
for (const d of (gpu.spdisplays_ndrvs || [])) {
|
|
97
|
+
displays.push({
|
|
98
|
+
name: d._name,
|
|
99
|
+
resolution: d._spdisplays_resolution,
|
|
100
|
+
pixelWidth: d._spdisplays_pixels ? parseInt(d._spdisplays_pixels.split(' x ')[0]) : null,
|
|
101
|
+
pixelHeight: d._spdisplays_pixels ? parseInt(d._spdisplays_pixels.split(' x ')[1]) : null,
|
|
102
|
+
retina: d.spdisplays_retina === 'spdisplays_yes'
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
JSON.stringify({displays: displays});
|
|
107
|
+
`;
|
|
108
|
+
}
|
|
109
|
+
export function showNotificationScript(message, title, subtitle, sound) {
|
|
110
|
+
const opts = [];
|
|
111
|
+
if (title)
|
|
112
|
+
opts.push(`withTitle: '${esc(title)}'`);
|
|
113
|
+
if (subtitle)
|
|
114
|
+
opts.push(`subtitle: '${esc(subtitle)}'`);
|
|
115
|
+
if (sound)
|
|
116
|
+
opts.push(`soundName: '${esc(sound)}'`);
|
|
117
|
+
return `
|
|
118
|
+
const app = Application.currentApplication();
|
|
119
|
+
app.includeStandardAdditions = true;
|
|
120
|
+
app.displayNotification('${esc(message)}', {${opts.join(', ')}});
|
|
121
|
+
JSON.stringify({sent: true, message: '${esc(message)}'});
|
|
122
|
+
`;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=scripts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scripts.js","sourceRoot":"","sources":["../../src/system/scripts.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAE3C,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAEvC,MAAM,UAAU,kBAAkB;IAChC,OAAO;;;;;GAKN,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,OAAO;;;oBAGW,GAAG,CAAC,IAAI,CAAC;;;GAG1B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO;;;;;;;;;GASN,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAe,EAAE,KAAe;IAC9D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,MAAM,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,iBAAiB,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACxG,IAAI,KAAK,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,KAAK,EAAE,CAAC,CAAC;IAC7D,OAAO;;;2BAGkB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;GAMxC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO;;;;;GAKN,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO;;;;;;;;;;GAUN,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO;;;;;;;;;;;;;;;GAeN,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,OAAO;;;;;;;;;;;;;;;;;;GAkBN,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,OAAe,EAAE,KAAc,EAAE,QAAiB,EAAE,KAAc;IACvG,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,KAAK;QAAE,IAAI,CAAC,IAAI,CAAC,eAAe,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnD,IAAI,QAAQ;QAAE,IAAI,CAAC,IAAI,CAAC,cAAc,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACxD,IAAI,KAAK;QAAE,IAAI,CAAC,IAAI,CAAC,eAAe,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnD,OAAO;;;+BAGsB,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;4CACrB,GAAG,CAAC,OAAO,CAAC;GACrD,CAAC;AACJ,CAAC"}
|