@zyx1121/apple-contacts-mcp 0.1.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.md +47 -0
- package/dist/applescript.d.ts +5 -0
- package/dist/applescript.js +29 -0
- package/dist/applescript.js.map +1 -0
- package/dist/helpers.d.ts +19 -0
- package/dist/helpers.js +25 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +11 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/contacts.d.ts +2 -0
- package/dist/tools/contacts.js +239 -0
- package/dist/tools/contacts.js.map +1 -0
- package/package.json +38 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 zyx1121
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# @zyx1121/apple-mail-mcp
|
|
2
|
+
|
|
3
|
+
MCP server for Apple Mail — read, search, and manage emails via Claude Code.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
claude mcp add apple-mail -- npx @zyx1121/apple-mail-mcp
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
|
|
13
|
+
- macOS with Apple Mail configured
|
|
14
|
+
- Node.js >= 18
|
|
15
|
+
- First run will prompt for Automation permission (System Settings > Privacy & Security > Automation)
|
|
16
|
+
|
|
17
|
+
## Tools
|
|
18
|
+
|
|
19
|
+
| Tool | Description |
|
|
20
|
+
|------|-------------|
|
|
21
|
+
| `mail_get_accounts` | List all accounts and their mailboxes |
|
|
22
|
+
| `mail_count_unread` | Count unread messages per account/mailbox |
|
|
23
|
+
| `mail_list_messages` | List messages with filters (account, mailbox, date range, unread) |
|
|
24
|
+
| `mail_read_message` | Read full content of a message by ID |
|
|
25
|
+
| `mail_search` | Search by subject, sender, or both |
|
|
26
|
+
| `mail_mark_read` | Mark a message as read |
|
|
27
|
+
|
|
28
|
+
## Examples
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
"List my mail accounts" → mail_get_accounts
|
|
32
|
+
"Show unread count" → mail_count_unread
|
|
33
|
+
"Yesterday's emails" → mail_list_messages { date_from: "2026-03-26" }
|
|
34
|
+
"Search for GitHub emails" → mail_search { query: "GitHub" }
|
|
35
|
+
"Read message 12345" → mail_read_message { message_id: 12345 }
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Limitations
|
|
39
|
+
|
|
40
|
+
- macOS only (uses AppleScript via `osascript`)
|
|
41
|
+
- Subject search is case-sensitive (AppleScript limitation)
|
|
42
|
+
- Sender/body search fetches recent messages and filters in JS (last 30 days, max 500)
|
|
43
|
+
- Mail.app must be running
|
|
44
|
+
|
|
45
|
+
## License
|
|
46
|
+
|
|
47
|
+
MIT
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
const TIMEOUT_MS = 60_000;
|
|
3
|
+
export class AppleMailError extends Error {
|
|
4
|
+
constructor(message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = "AppleMailError";
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export async function runAppleScript(script) {
|
|
10
|
+
return new Promise((resolve, reject) => {
|
|
11
|
+
execFile("osascript", ["-e", script], { timeout: TIMEOUT_MS }, (err, stdout, stderr) => {
|
|
12
|
+
if (err) {
|
|
13
|
+
const msg = stderr || err.message;
|
|
14
|
+
if (msg.includes("not running") || msg.includes("-600"))
|
|
15
|
+
return reject(new AppleMailError("Apple Mail is not running. Please open Mail.app and try again."));
|
|
16
|
+
if (msg.includes("not allowed") || msg.includes("not permitted"))
|
|
17
|
+
return reject(new AppleMailError("Permission denied. Grant automation access in System Settings > Privacy & Security > Automation."));
|
|
18
|
+
if (msg.includes("timed out") || err.code === "ETIMEDOUT")
|
|
19
|
+
return reject(new AppleMailError("AppleScript execution timed out."));
|
|
20
|
+
return reject(new AppleMailError(msg.trim()));
|
|
21
|
+
}
|
|
22
|
+
resolve(stdout.trimEnd());
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
export function escapeForAppleScript(str) {
|
|
27
|
+
return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=applescript.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applescript.js","sourceRoot":"","sources":["../src/applescript.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,MAAM,UAAU,GAAG,MAAM,CAAC;AAE1B,MAAM,OAAO,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,MAAc;IACjD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,QAAQ,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YACrF,IAAI,GAAG,EAAE,CAAC;gBACR,MAAM,GAAG,GAAG,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC;gBAClC,IAAI,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC;oBACrD,OAAO,MAAM,CAAC,IAAI,cAAc,CAAC,gEAAgE,CAAC,CAAC,CAAC;gBACtG,IAAI,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAC;oBAC9D,OAAO,MAAM,CAAC,IAAI,cAAc,CAAC,kGAAkG,CAAC,CAAC,CAAC;gBACxI,IAAI,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAK,GAA6B,CAAC,IAAI,KAAK,WAAW;oBAClF,OAAO,MAAM,CAAC,IAAI,cAAc,CAAC,kCAAkC,CAAC,CAAC,CAAC;gBACxE,OAAO,MAAM,CAAC,IAAI,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAChD,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACzD,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare function success(data: unknown): {
|
|
2
|
+
content: {
|
|
3
|
+
type: "text";
|
|
4
|
+
text: string;
|
|
5
|
+
}[];
|
|
6
|
+
};
|
|
7
|
+
export declare function error(message: string): {
|
|
8
|
+
content: {
|
|
9
|
+
type: "text";
|
|
10
|
+
text: string;
|
|
11
|
+
}[];
|
|
12
|
+
isError: true;
|
|
13
|
+
};
|
|
14
|
+
export declare function withErrorHandling<T extends Record<string, unknown>>(fn: (args: T) => Promise<ReturnType<typeof success | typeof error>>): (args: T) => Promise<{
|
|
15
|
+
content: {
|
|
16
|
+
type: "text";
|
|
17
|
+
text: string;
|
|
18
|
+
}[];
|
|
19
|
+
}>;
|
package/dist/helpers.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { AppleMailError } from "./applescript.js";
|
|
2
|
+
export function success(data) {
|
|
3
|
+
return {
|
|
4
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
export function error(message) {
|
|
8
|
+
return {
|
|
9
|
+
content: [{ type: "text", text: JSON.stringify({ error: message }) }],
|
|
10
|
+
isError: true,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export function withErrorHandling(fn) {
|
|
14
|
+
return async (args) => {
|
|
15
|
+
try {
|
|
16
|
+
return await fn(args);
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
if (e instanceof AppleMailError)
|
|
20
|
+
return error(e.message);
|
|
21
|
+
throw e;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,MAAM,UAAU,OAAO,CAAC,IAAa;IACnC,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,MAAM,UAAU,KAAK,CAAC,OAAe;IACnC,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;QAC9E,OAAO,EAAE,IAAa;KACvB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,EAAmE;IAEnE,OAAO,KAAK,EAAE,IAAO,EAAE,EAAE;QACvB,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,YAAY,cAAc;gBAAE,OAAO,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YACzD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { createServer } from "./server.js";
|
|
4
|
+
if (process.platform !== "darwin") {
|
|
5
|
+
console.error("apple-contacts-mcp requires macOS with Apple Contacts.");
|
|
6
|
+
process.exit(1);
|
|
7
|
+
}
|
|
8
|
+
const server = createServer();
|
|
9
|
+
const transport = new StdioServerTransport();
|
|
10
|
+
await server.connect(transport);
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;IAClC,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;IACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;AAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
|
package/dist/server.d.ts
ADDED
package/dist/server.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { registerContactTools } from "./tools/contacts.js";
|
|
3
|
+
export function createServer() {
|
|
4
|
+
const server = new McpServer({
|
|
5
|
+
name: "apple-contacts",
|
|
6
|
+
version: "0.1.0",
|
|
7
|
+
});
|
|
8
|
+
registerContactTools(server);
|
|
9
|
+
return server;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAE7B,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { runAppleScript, escapeForAppleScript } from "../applescript.js";
|
|
3
|
+
import { success, error, withErrorHandling } from "../helpers.js";
|
|
4
|
+
const RS = "\u001e"; // ASCII 30 Record Separator
|
|
5
|
+
function parseContact(line) {
|
|
6
|
+
const [id, name, firstName, lastName, org, phones, emails] = line.split("\t");
|
|
7
|
+
return {
|
|
8
|
+
id,
|
|
9
|
+
name,
|
|
10
|
+
firstName: firstName || null,
|
|
11
|
+
lastName: lastName || null,
|
|
12
|
+
organization: org || null,
|
|
13
|
+
phones: phones ? phones.split(",").filter(Boolean).map((p) => {
|
|
14
|
+
const [label, ...rest] = p.split(":");
|
|
15
|
+
return { label, value: rest.join(":") };
|
|
16
|
+
}) : [],
|
|
17
|
+
emails: emails ? emails.split(",").filter(Boolean).map((e) => {
|
|
18
|
+
const [label, ...rest] = e.split(":");
|
|
19
|
+
return { label, value: rest.join(":") };
|
|
20
|
+
}) : [],
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function parseContacts(raw) {
|
|
24
|
+
if (!raw)
|
|
25
|
+
return [];
|
|
26
|
+
return raw.split(RS).filter(Boolean).map(parseContact);
|
|
27
|
+
}
|
|
28
|
+
const CONTACT_FIELDS = `
|
|
29
|
+
set phoneList to ""
|
|
30
|
+
repeat with ph in phones of p
|
|
31
|
+
set phoneList to phoneList & (label of ph) & ":" & (value of ph) & ","
|
|
32
|
+
end repeat
|
|
33
|
+
set emailList to ""
|
|
34
|
+
repeat with em in emails of p
|
|
35
|
+
set emailList to emailList & (label of em) & ":" & (value of em) & ","
|
|
36
|
+
end repeat
|
|
37
|
+
set fn to ""
|
|
38
|
+
try
|
|
39
|
+
if first name of p is not missing value then set fn to first name of p
|
|
40
|
+
end try
|
|
41
|
+
set ln to ""
|
|
42
|
+
try
|
|
43
|
+
if last name of p is not missing value then set ln to last name of p
|
|
44
|
+
end try
|
|
45
|
+
set org to ""
|
|
46
|
+
try
|
|
47
|
+
if organization of p is not missing value then set org to organization of p
|
|
48
|
+
end try`;
|
|
49
|
+
export function registerContactTools(server) {
|
|
50
|
+
// List all contacts
|
|
51
|
+
server.registerTool("contacts_list", {
|
|
52
|
+
description: "List all contacts",
|
|
53
|
+
inputSchema: z.object({
|
|
54
|
+
limit: z.coerce.number().default(50).describe("Max contacts to return (default 50)"),
|
|
55
|
+
}),
|
|
56
|
+
}, withErrorHandling(async ({ limit }) => {
|
|
57
|
+
const raw = await runAppleScript(`
|
|
58
|
+
tell application "Contacts"
|
|
59
|
+
set output to ""
|
|
60
|
+
set cnt to 0
|
|
61
|
+
repeat with p in every person
|
|
62
|
+
if cnt >= ${limit} then exit repeat
|
|
63
|
+
${CONTACT_FIELDS}
|
|
64
|
+
set output to output & (id of p) & "\\t" & (name of p) & "\\t" & fn & "\\t" & ln & "\\t" & org & "\\t" & phoneList & "\\t" & emailList & (ASCII character 30)
|
|
65
|
+
set cnt to cnt + 1
|
|
66
|
+
end repeat
|
|
67
|
+
return output
|
|
68
|
+
end tell`);
|
|
69
|
+
return success(parseContacts(raw));
|
|
70
|
+
}));
|
|
71
|
+
// Search contacts
|
|
72
|
+
server.registerTool("contacts_search", {
|
|
73
|
+
description: "Search contacts by name, phone, or email",
|
|
74
|
+
inputSchema: z.object({
|
|
75
|
+
query: z.string().min(1).describe("Search keyword"),
|
|
76
|
+
}),
|
|
77
|
+
}, withErrorHandling(async ({ query }) => {
|
|
78
|
+
const esc = escapeForAppleScript(query);
|
|
79
|
+
const raw = await runAppleScript(`
|
|
80
|
+
tell application "Contacts"
|
|
81
|
+
set output to ""
|
|
82
|
+
set nameMatches to every person whose name contains "${esc}"
|
|
83
|
+
set emailMatches to every person whose emails contains "${esc}"
|
|
84
|
+
set phoneMatches to every person whose phones contains "${esc}"
|
|
85
|
+
set seen to {}
|
|
86
|
+
repeat with grp in {nameMatches, emailMatches, phoneMatches}
|
|
87
|
+
repeat with p in grp
|
|
88
|
+
set pid to id of p
|
|
89
|
+
if pid is not in seen then
|
|
90
|
+
set end of seen to pid
|
|
91
|
+
${CONTACT_FIELDS}
|
|
92
|
+
set output to output & pid & "\\t" & (name of p) & "\\t" & fn & "\\t" & ln & "\\t" & org & "\\t" & phoneList & "\\t" & emailList & (ASCII character 30)
|
|
93
|
+
end if
|
|
94
|
+
end repeat
|
|
95
|
+
end repeat
|
|
96
|
+
return output
|
|
97
|
+
end tell`);
|
|
98
|
+
return success(parseContacts(raw));
|
|
99
|
+
}));
|
|
100
|
+
// Get contact by ID
|
|
101
|
+
server.registerTool("contacts_get", {
|
|
102
|
+
description: "Get full details of a contact by ID",
|
|
103
|
+
inputSchema: z.object({
|
|
104
|
+
id: z.string().describe("Contact ID"),
|
|
105
|
+
}),
|
|
106
|
+
}, withErrorHandling(async ({ id }) => {
|
|
107
|
+
const esc = escapeForAppleScript(id);
|
|
108
|
+
const raw = await runAppleScript(`
|
|
109
|
+
tell application "Contacts"
|
|
110
|
+
set p to person id "${esc}"
|
|
111
|
+
${CONTACT_FIELDS}
|
|
112
|
+
set addrList to ""
|
|
113
|
+
repeat with a in addresses of p
|
|
114
|
+
set addrList to addrList & (label of a) & ":" & (street of a) & ";"
|
|
115
|
+
end repeat
|
|
116
|
+
set urlList to ""
|
|
117
|
+
repeat with u in urls of p
|
|
118
|
+
set urlList to urlList & (label of u) & ":" & (value of u) & ","
|
|
119
|
+
end repeat
|
|
120
|
+
set bd to ""
|
|
121
|
+
try
|
|
122
|
+
if birth date of p is not missing value then set bd to (birth date of p as string)
|
|
123
|
+
end try
|
|
124
|
+
return (id of p) & "\\t" & (name of p) & "\\t" & fn & "\\t" & ln & "\\t" & org & "\\t" & phoneList & "\\t" & emailList & "\\t" & addrList & "\\t" & urlList & "\\t" & bd
|
|
125
|
+
end tell`);
|
|
126
|
+
if (!raw)
|
|
127
|
+
return error("Contact not found");
|
|
128
|
+
const parts = raw.split("\t");
|
|
129
|
+
const [cid, name, firstName, lastName, organization, phones, emails, addresses, urls, birthDate] = parts;
|
|
130
|
+
return success({
|
|
131
|
+
id: cid,
|
|
132
|
+
name,
|
|
133
|
+
firstName: firstName || null,
|
|
134
|
+
lastName: lastName || null,
|
|
135
|
+
organization: organization || null,
|
|
136
|
+
phones: phones ? phones.split(",").filter(Boolean).map((p) => {
|
|
137
|
+
const [label, ...rest] = p.split(":");
|
|
138
|
+
return { label, value: rest.join(":") };
|
|
139
|
+
}) : [],
|
|
140
|
+
emails: emails ? emails.split(",").filter(Boolean).map((e) => {
|
|
141
|
+
const [label, ...rest] = e.split(":");
|
|
142
|
+
return { label, value: rest.join(":") };
|
|
143
|
+
}) : [],
|
|
144
|
+
addresses: addresses ? addresses.split(";").filter(Boolean).map((a) => {
|
|
145
|
+
const [label, ...rest] = a.split(":");
|
|
146
|
+
return { label, street: rest.join(":") };
|
|
147
|
+
}) : [],
|
|
148
|
+
urls: urls ? urls.split(",").filter(Boolean).map((u) => {
|
|
149
|
+
const [label, ...rest] = u.split(":");
|
|
150
|
+
return { label, value: rest.join(":") };
|
|
151
|
+
}) : [],
|
|
152
|
+
birthDate: birthDate || null,
|
|
153
|
+
});
|
|
154
|
+
}));
|
|
155
|
+
// Create contact
|
|
156
|
+
server.registerTool("contacts_create", {
|
|
157
|
+
description: "Create a new contact",
|
|
158
|
+
inputSchema: z.object({
|
|
159
|
+
first_name: z.string().optional().describe("First name"),
|
|
160
|
+
last_name: z.string().optional().describe("Last name"),
|
|
161
|
+
organization: z.string().optional().describe("Company/organization"),
|
|
162
|
+
phone: z.string().optional().describe("Phone number"),
|
|
163
|
+
phone_label: z.string().default("mobile").describe("Phone label (mobile, home, work, etc.)"),
|
|
164
|
+
email: z.string().optional().describe("Email address"),
|
|
165
|
+
email_label: z.string().default("work").describe("Email label (work, home, etc.)"),
|
|
166
|
+
}),
|
|
167
|
+
}, withErrorHandling(async ({ first_name, last_name, organization, phone, phone_label, email, email_label }) => {
|
|
168
|
+
if (!first_name && !last_name && !organization)
|
|
169
|
+
return error("Provide at least first_name, last_name, or organization");
|
|
170
|
+
const props = [];
|
|
171
|
+
if (first_name)
|
|
172
|
+
props.push(`first name:"${escapeForAppleScript(first_name)}"`);
|
|
173
|
+
if (last_name)
|
|
174
|
+
props.push(`last name:"${escapeForAppleScript(last_name)}"`);
|
|
175
|
+
if (organization)
|
|
176
|
+
props.push(`organization:"${escapeForAppleScript(organization)}"`);
|
|
177
|
+
const phoneCmd = phone
|
|
178
|
+
? `make new phone at end of phones of newPerson with properties {label:"${escapeForAppleScript(phone_label)}", value:"${escapeForAppleScript(phone)}"}`
|
|
179
|
+
: "";
|
|
180
|
+
const emailCmd = email
|
|
181
|
+
? `make new email at end of emails of newPerson with properties {label:"${escapeForAppleScript(email_label)}", value:"${escapeForAppleScript(email)}"}`
|
|
182
|
+
: "";
|
|
183
|
+
const raw = await runAppleScript(`
|
|
184
|
+
tell application "Contacts"
|
|
185
|
+
set newPerson to make new person with properties {${props.join(", ")}}
|
|
186
|
+
${phoneCmd}
|
|
187
|
+
${emailCmd}
|
|
188
|
+
save
|
|
189
|
+
return (id of newPerson) & "\\t" & (name of newPerson)
|
|
190
|
+
end tell`);
|
|
191
|
+
const [id, name] = raw.split("\t");
|
|
192
|
+
return success({ id, name, created: true });
|
|
193
|
+
}));
|
|
194
|
+
// Update contact
|
|
195
|
+
server.registerTool("contacts_update", {
|
|
196
|
+
description: "Update an existing contact",
|
|
197
|
+
inputSchema: z.object({
|
|
198
|
+
id: z.string().describe("Contact ID"),
|
|
199
|
+
first_name: z.string().optional().describe("New first name"),
|
|
200
|
+
last_name: z.string().optional().describe("New last name"),
|
|
201
|
+
organization: z.string().optional().describe("New organization"),
|
|
202
|
+
}),
|
|
203
|
+
}, withErrorHandling(async ({ id, first_name, last_name, organization }) => {
|
|
204
|
+
const esc = escapeForAppleScript(id);
|
|
205
|
+
const updates = [];
|
|
206
|
+
if (first_name !== undefined)
|
|
207
|
+
updates.push(`set first name of p to "${escapeForAppleScript(first_name)}"`);
|
|
208
|
+
if (last_name !== undefined)
|
|
209
|
+
updates.push(`set last name of p to "${escapeForAppleScript(last_name)}"`);
|
|
210
|
+
if (organization !== undefined)
|
|
211
|
+
updates.push(`set organization of p to "${escapeForAppleScript(organization)}"`);
|
|
212
|
+
if (!updates.length)
|
|
213
|
+
return error("No fields to update");
|
|
214
|
+
await runAppleScript(`
|
|
215
|
+
tell application "Contacts"
|
|
216
|
+
set p to person id "${esc}"
|
|
217
|
+
${updates.join("\n ")}
|
|
218
|
+
save
|
|
219
|
+
end tell`);
|
|
220
|
+
return success({ id, updated: true });
|
|
221
|
+
}));
|
|
222
|
+
// Delete contact
|
|
223
|
+
server.registerTool("contacts_delete", {
|
|
224
|
+
description: "Delete a contact",
|
|
225
|
+
inputSchema: z.object({
|
|
226
|
+
id: z.string().describe("Contact ID"),
|
|
227
|
+
}),
|
|
228
|
+
}, withErrorHandling(async ({ id }) => {
|
|
229
|
+
const esc = escapeForAppleScript(id);
|
|
230
|
+
await runAppleScript(`
|
|
231
|
+
tell application "Contacts"
|
|
232
|
+
set p to person id "${esc}"
|
|
233
|
+
delete p
|
|
234
|
+
save
|
|
235
|
+
end tell`);
|
|
236
|
+
return success({ id, deleted: true });
|
|
237
|
+
}));
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=contacts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contacts.js","sourceRoot":"","sources":["../../src/tools/contacts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElE,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,4BAA4B;AAEjD,SAAS,YAAY,CAAC,IAAY;IAChC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC9E,OAAO;QACL,EAAE;QACF,IAAI;QACJ,SAAS,EAAE,SAAS,IAAI,IAAI;QAC5B,QAAQ,EAAE,QAAQ,IAAI,IAAI;QAC1B,YAAY,EAAE,GAAG,IAAI,IAAI;QACzB,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YAC3D,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACtC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1C,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;QACP,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YAC3D,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACtC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1C,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;KACR,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,GAAW;IAChC,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,OAAO,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;YAoBX,CAAC;AAEb,MAAM,UAAU,oBAAoB,CAAC,MAAiB;IACpD,oBAAoB;IACpB,MAAM,CAAC,YAAY,CACjB,eAAe,EACf;QACE,WAAW,EAAE,mBAAmB;QAChC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,qCAAqC,CAAC;SACrF,CAAC;KACH,EACD,iBAAiB,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;QACpC,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC;;;;;gBAKvB,KAAK;MACf,cAAc;;;;;SAKX,CAAC,CAAC;QACL,OAAO,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;IACrC,CAAC,CAAC,CACH,CAAC;IAEF,kBAAkB;IAClB,MAAM,CAAC,YAAY,CACjB,iBAAiB,EACjB;QACE,WAAW,EAAE,0CAA0C;QACvD,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,gBAAgB,CAAC;SACpD,CAAC;KACH,EACD,iBAAiB,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;QACpC,MAAM,GAAG,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC;;;yDAGkB,GAAG;4DACA,GAAG;4DACH,GAAG;;;;;;;UAOrD,cAAc;;;;;;SAMf,CAAC,CAAC;QACL,OAAO,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;IACrC,CAAC,CAAC,CACH,CAAC;IAEF,oBAAoB;IACpB,MAAM,CAAC,YAAY,CACjB,cAAc,EACd;QACE,WAAW,EAAE,qCAAqC;QAClD,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC;SACtC,CAAC;KACH,EACD,iBAAiB,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE;QACjC,MAAM,GAAG,GAAG,oBAAoB,CAAC,EAAE,CAAC,CAAC;QACrC,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC;;wBAEf,GAAG;IACvB,cAAc;;;;;;;;;;;;;;SAcT,CAAC,CAAC;QACL,IAAI,CAAC,GAAG;YAAE,OAAO,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC;QACzG,OAAO,OAAO,CAAC;YACb,EAAE,EAAE,GAAG;YACP,IAAI;YACJ,SAAS,EAAE,SAAS,IAAI,IAAI;YAC5B,QAAQ,EAAE,QAAQ,IAAI,IAAI;YAC1B,YAAY,EAAE,YAAY,IAAI,IAAI;YAClC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC3D,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACtC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1C,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;YACP,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC3D,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACtC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1C,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;YACP,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBACpE,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACtC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3C,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;YACP,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBACrD,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACtC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1C,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;YACP,SAAS,EAAE,SAAS,IAAI,IAAI;SAC7B,CAAC,CAAC;IACL,CAAC,CAAC,CACH,CAAC;IAEF,iBAAiB;IACjB,MAAM,CAAC,YAAY,CACjB,iBAAiB,EACjB;QACE,WAAW,EAAE,sBAAsB;QACnC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC;YACxD,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC;YACtD,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;YACpE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC;YACrD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,wCAAwC,CAAC;YAC5F,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC;YACtD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,gCAAgC,CAAC;SACnF,CAAC;KACH,EACD,iBAAiB,CAAC,KAAK,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE;QAC1G,IAAI,CAAC,UAAU,IAAI,CAAC,SAAS,IAAI,CAAC,YAAY;YAAE,OAAO,KAAK,CAAC,yDAAyD,CAAC,CAAC;QACxH,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,UAAU;YAAE,KAAK,CAAC,IAAI,CAAC,eAAe,oBAAoB,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAC/E,IAAI,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,cAAc,oBAAoB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAC5E,IAAI,YAAY;YAAE,KAAK,CAAC,IAAI,CAAC,iBAAiB,oBAAoB,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QACrF,MAAM,QAAQ,GAAG,KAAK;YACpB,CAAC,CAAC,wEAAwE,oBAAoB,CAAC,WAAW,CAAC,aAAa,oBAAoB,CAAC,KAAK,CAAC,IAAI;YACvJ,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,QAAQ,GAAG,KAAK;YACpB,CAAC,CAAC,wEAAwE,oBAAoB,CAAC,WAAW,CAAC,aAAa,oBAAoB,CAAC,KAAK,CAAC,IAAI;YACvJ,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC;;sDAEe,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;IAClE,QAAQ;IACR,QAAQ;;;SAGH,CAAC,CAAC;QACL,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACnC,OAAO,OAAO,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,CAAC,CAAC,CACH,CAAC;IAEF,iBAAiB;IACjB,MAAM,CAAC,YAAY,CACjB,iBAAiB,EACjB;QACE,WAAW,EAAE,4BAA4B;QACzC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC;YACrC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC;YAC5D,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC;YAC1D,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;SACjE,CAAC;KACH,EACD,iBAAiB,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,EAAE,EAAE;QACtE,MAAM,GAAG,GAAG,oBAAoB,CAAC,EAAE,CAAC,CAAC;QACrC,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,IAAI,UAAU,KAAK,SAAS;YAAE,OAAO,CAAC,IAAI,CAAC,2BAA2B,oBAAoB,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAC3G,IAAI,SAAS,KAAK,SAAS;YAAE,OAAO,CAAC,IAAI,CAAC,0BAA0B,oBAAoB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACxG,IAAI,YAAY,KAAK,SAAS;YAAE,OAAO,CAAC,IAAI,CAAC,6BAA6B,oBAAoB,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QACjH,IAAI,CAAC,OAAO,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACzD,MAAM,cAAc,CAAC;;wBAEH,GAAG;IACvB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;;SAEf,CAAC,CAAC;QACL,OAAO,OAAO,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,CAAC,CAAC,CACH,CAAC;IAEF,iBAAiB;IACjB,MAAM,CAAC,YAAY,CACjB,iBAAiB,EACjB;QACE,WAAW,EAAE,kBAAkB;QAC/B,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC;SACtC,CAAC;KACH,EACD,iBAAiB,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE;QACjC,MAAM,GAAG,GAAG,oBAAoB,CAAC,EAAE,CAAC,CAAC;QACrC,MAAM,cAAc,CAAC;;wBAEH,GAAG;;;SAGlB,CAAC,CAAC;QACL,OAAO,OAAO,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,CAAC,CAAC,CACH,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zyx1121/apple-contacts-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for Apple Contacts — search, read, create, and manage contacts via Claude Code",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"apple-contacts-mcp": "dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"prepublishOnly": "npm run build"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"mcp",
|
|
20
|
+
"apple-contacts",
|
|
21
|
+
"claude",
|
|
22
|
+
"contacts",
|
|
23
|
+
"macos"
|
|
24
|
+
],
|
|
25
|
+
"author": "zyx1121",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=18"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
32
|
+
"zod": "^3.25.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^20.0.0",
|
|
36
|
+
"typescript": "^5.0.0"
|
|
37
|
+
}
|
|
38
|
+
}
|