@zyx1121/apple-messages-mcp 0.1.0 → 0.2.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/README.md +4 -1
- package/dist/helpers.js +1 -1
- package/dist/tools/messages.js +38 -5
- package/dist/tools/messages.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -39,6 +39,7 @@ claude mcp add apple-messages -- npx @zyx1121/apple-messages-mcp
|
|
|
39
39
|
| `messages_list_chats` | List recent chats/conversations |
|
|
40
40
|
| `messages_read` | Read recent messages from a specific chat or contact |
|
|
41
41
|
| `messages_search` | Search messages by keyword |
|
|
42
|
+
| `messages_delete` | Delete a specific chat/conversation |
|
|
42
43
|
|
|
43
44
|
## Examples
|
|
44
45
|
|
|
@@ -47,13 +48,15 @@ claude mcp add apple-messages -- npx @zyx1121/apple-messages-mcp
|
|
|
47
48
|
"Show my recent chats" → messages_list_chats {}
|
|
48
49
|
"Read messages from John" → messages_read { contact: "john@example.com" }
|
|
49
50
|
"Search for 'meeting'" → messages_search { query: "meeting" }
|
|
51
|
+
"Delete chat with +886912345678" → messages_delete { contact: "+886912345678" }
|
|
50
52
|
```
|
|
51
53
|
|
|
52
54
|
## Limitations
|
|
53
55
|
|
|
54
56
|
- macOS only (uses AppleScript via `osascript` and `sqlite3`)
|
|
55
57
|
- Sending uses AppleScript — Messages.app must be running
|
|
56
|
-
- Reading uses `~/Library/Messages/chat.db` — requires Full Disk Access
|
|
58
|
+
- Reading/deleting uses `~/Library/Messages/chat.db` — requires Full Disk Access
|
|
59
|
+
- Deleting quits Messages.app temporarily to safely modify the database
|
|
57
60
|
|
|
58
61
|
## License
|
|
59
62
|
|
package/dist/helpers.js
CHANGED
package/dist/tools/messages.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { runAppleScript, runSqlite, escapeForAppleScript, success, withErrorHandling } from "../helpers.js";
|
|
2
|
+
import { runAppleScript, runSqlite, escapeForAppleScript, success, error, withErrorHandling } from "../helpers.js";
|
|
3
3
|
const DB_PATH = `${process.env.HOME}/Library/Messages/chat.db`;
|
|
4
4
|
export function registerMessagesTools(server) {
|
|
5
5
|
server.tool("messages_send", "Send an iMessage to a phone number or email", {
|
|
@@ -41,8 +41,8 @@ LIMIT ${limit};`;
|
|
|
41
41
|
chatFilter = `cmj.chat_id = ${parseInt(chat_id, 10)}`;
|
|
42
42
|
}
|
|
43
43
|
else {
|
|
44
|
-
const escaped = contact.replace(/'/g, "''");
|
|
45
|
-
chatFilter = `cmj.chat_id IN (SELECT ROWID FROM chat WHERE chat_identifier LIKE '%${escaped}%')`;
|
|
44
|
+
const escaped = contact.replace(/'/g, "''").replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
45
|
+
chatFilter = `cmj.chat_id IN (SELECT ROWID FROM chat WHERE chat_identifier LIKE '%${escaped}%' ESCAPE '\\')`;
|
|
46
46
|
}
|
|
47
47
|
const query = `
|
|
48
48
|
SELECT m.text, m.is_from_me,
|
|
@@ -62,7 +62,7 @@ LIMIT ${limit};`;
|
|
|
62
62
|
query: z.string().describe("Search keyword"),
|
|
63
63
|
limit: z.number().optional().default(20).describe("Max number of results to return"),
|
|
64
64
|
}, withErrorHandling(async ({ query: keyword, limit }) => {
|
|
65
|
-
const escaped = keyword.replace(/'/g, "''");
|
|
65
|
+
const escaped = keyword.replace(/'/g, "''").replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
66
66
|
const sql = `
|
|
67
67
|
SELECT m.text, m.is_from_me,
|
|
68
68
|
datetime(m.date/1000000000 + 978307200, 'unixepoch', 'localtime') as date,
|
|
@@ -71,12 +71,45 @@ FROM message m
|
|
|
71
71
|
LEFT JOIN handle h ON m.handle_id = h.ROWID
|
|
72
72
|
JOIN chat_message_join cmj ON m.ROWID = cmj.message_id
|
|
73
73
|
JOIN chat c ON cmj.chat_id = c.ROWID
|
|
74
|
-
WHERE m.text LIKE '%${escaped}%'
|
|
74
|
+
WHERE m.text LIKE '%${escaped}%' ESCAPE '\\'
|
|
75
75
|
ORDER BY m.date DESC
|
|
76
76
|
LIMIT ${limit};`;
|
|
77
77
|
const raw = await runSqlite(DB_PATH, sql);
|
|
78
78
|
const messages = raw ? JSON.parse(raw) : [];
|
|
79
79
|
return success(messages);
|
|
80
80
|
}));
|
|
81
|
+
server.tool("messages_delete", "Delete a specific chat/conversation by selecting it and using keyboard shortcut", {
|
|
82
|
+
chat_id: z.string().optional().describe("Chat ROWID from messages_list_chats"),
|
|
83
|
+
contact: z.string().optional().describe("Phone number, email, or chat_identifier to match"),
|
|
84
|
+
}, withErrorHandling(async ({ chat_id, contact }) => {
|
|
85
|
+
if (!chat_id && !contact)
|
|
86
|
+
throw new Error("Provide either chat_id or contact");
|
|
87
|
+
let identifier;
|
|
88
|
+
if (chat_id) {
|
|
89
|
+
const raw = await runSqlite(DB_PATH, `SELECT chat_identifier FROM chat WHERE ROWID = ${parseInt(chat_id, 10)};`);
|
|
90
|
+
const rows = raw ? JSON.parse(raw) : [];
|
|
91
|
+
if (rows.length === 0)
|
|
92
|
+
return error("Chat not found");
|
|
93
|
+
identifier = rows[0].chat_identifier;
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
identifier = contact;
|
|
97
|
+
}
|
|
98
|
+
// Verify chat exists
|
|
99
|
+
const escaped = identifier.replace(/'/g, "''");
|
|
100
|
+
const check = await runSqlite(DB_PATH, `SELECT ROWID, chat_identifier, display_name FROM chat WHERE chat_identifier = '${escaped}' OR ROWID = ${parseInt(chat_id || "0", 10)};`);
|
|
101
|
+
const rows = check ? JSON.parse(check) : [];
|
|
102
|
+
if (rows.length === 0)
|
|
103
|
+
return error("Chat not found");
|
|
104
|
+
const rowId = rows[0].ROWID;
|
|
105
|
+
// Quit Messages, delete from db, reopen
|
|
106
|
+
await runAppleScript('tell application "Messages" to quit');
|
|
107
|
+
await new Promise((r) => setTimeout(r, 1000));
|
|
108
|
+
await runSqlite(DB_PATH, `DELETE FROM chat_message_join WHERE chat_id = ${rowId};`);
|
|
109
|
+
await runSqlite(DB_PATH, `DELETE FROM message WHERE ROWID NOT IN (SELECT message_id FROM chat_message_join);`);
|
|
110
|
+
await runSqlite(DB_PATH, `DELETE FROM chat WHERE ROWID = ${rowId};`);
|
|
111
|
+
await runAppleScript('tell application "Messages" to activate');
|
|
112
|
+
return success({ deleted: rows[0].chat_identifier, display_name: rows[0].display_name || null });
|
|
113
|
+
}));
|
|
81
114
|
}
|
|
82
115
|
//# sourceMappingURL=messages.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/tools/messages.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,oBAAoB,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/tools/messages.ts"],"names":[],"mappings":"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"}
|