mcp-icloud 2.1.2 → 2.1.3

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/PRIVACY.md ADDED
@@ -0,0 +1,55 @@
1
+ # Privacy policy
2
+
3
+ Effective 10 August 2026. Applies to the mcp-icloud server (the software you
4
+ run), not to any AI client you connect it to.
5
+
6
+ ## The short version
7
+
8
+ mcp-icloud runs on your machine and works for you. It has no servers of its
9
+ own, no analytics, no telemetry, and no way to see your data. The author
10
+ never receives anything.
11
+
12
+ ## What the software touches, and where it goes
13
+
14
+ When a connected AI client (Claude Desktop, for example) calls a tool, the
15
+ server reads or writes data in your Apple services: mail, calendar events,
16
+ contacts, reminders, notes, messages, and Safari tabs. Two things happen
17
+ with that data, and nothing else.
18
+
19
+ First, tool results are returned to the AI client that asked for them. What
20
+ that client does with the data is governed by its own privacy policy, not
21
+ this one. Nothing is sent anywhere unless a client you connected asks.
22
+
23
+ Second, in cloud mode the server talks to Apple's servers on your behalf
24
+ (imap.mail.me.com, smtp.mail.me.com, caldav.icloud.com,
25
+ contacts.icloud.com), over TLS, authenticated with credentials you
26
+ provided. In local mode the server makes no network connections at all; it
27
+ drives the apps already on your Mac, and macOS asks for your consent per
28
+ app before any of that works. You can revoke that consent at any time in
29
+ System Settings under Privacy and Security.
30
+
31
+ ## Credentials
32
+
33
+ Cloud mode needs your iCloud address and an app-specific password. You
34
+ store them yourself, either in a local .env file or in the macOS Keychain
35
+ when you install the desktop extension. The server reads them once at
36
+ startup, sends them only to Apple, and never writes them to any log.
37
+ Diagnostics print a fixed mask instead of the value. Local mode needs no
38
+ credentials at all.
39
+
40
+ ## What is kept
41
+
42
+ Nothing. The server is stateless: no database, no cache, no files written.
43
+ When it stops, nothing of yours remains in it.
44
+
45
+ ## Third parties
46
+
47
+ There are none. No data is sold, shared, or transferred to anyone. The only
48
+ parties that ever see your data are Apple (which already has it) and the AI
49
+ client you chose to connect.
50
+
51
+ ## Changes and contact
52
+
53
+ Changes to this policy are made in this file, in the open, with the
54
+ repository's history as the record. Questions and concerns:
55
+ https://github.com/MrGo2/icloud-mcp/issues
package/README.md CHANGED
@@ -34,7 +34,9 @@ Credentials are never logged. `ICLOUD_APP_PASSWORD` is read once at startup and
34
34
 
35
35
  Every tool argument is validated against a zod schema before the handler runs. Arguments are also coerced at each AppleScript interpolation site, so a value that is not a number cannot reach a script template.
36
36
 
37
- The server collects nothing and keeps nothing: no telemetry, no analytics, no state on disk. The full policy is in [PRIVACY.md](PRIVACY.md).
37
+ ## Privacy Policy
38
+
39
+ The server collects nothing and keeps nothing: no telemetry, no analytics, no state on disk. Your data moves only between your machine, the AI client you connect and Apple's services. The full policy, covering collection, storage, third-party sharing, retention and contact, is in [PRIVACY.md](PRIVACY.md).
38
40
 
39
41
  ## Tools
40
42
 
@@ -115,7 +117,7 @@ Reading requires the [`imsg`](https://github.com/steipete/imsg) CLI and Full Dis
115
117
 
116
118
  ### Tool annotations (MCP hints)
117
119
 
118
- Every tool declares its behaviour explicitly instead of relying on the spec defaults, which are deliberately pessimistic. All `list-*`, `read-*`, `search-*` and `get-*` tools, plus `about` and `check-auth-status`, are marked read-only. The four destructive tools (`delete-event`, `delete-contact`, `delete-reminder`, `close-safari-tab`) carry `destructiveHint`. Tools that reach the network or another person carry `openWorldHint`: all Email and Calendar tools, `send-message`, `react-message` and `open-safari-url`. The read-only tools plus `mark-as-read`, `complete-reminder`, `update-reminder`, `update-event` and `set-mode` are marked idempotent.
120
+ Every tool declares its behaviour explicitly instead of relying on the spec defaults, which are deliberately pessimistic. All `list-*`, `read-*`, `search-*` and `get-*` tools, plus `about` and `check-auth-status`, are marked read-only. Nine tools carry `destructiveHint`: the four deletions (`delete-event`, `delete-contact`, `delete-reminder`, `close-safari-tab`), the three that reach another person irrevocably (`send-email`, `send-message`, `react-message`) and the two in-place updates (`update-event`, `update-reminder`). Tools that reach the network or another person carry `openWorldHint`: all Email and Calendar tools, `send-message`, `react-message` and `open-safari-url`. The read-only tools plus `mark-as-read`, `complete-reminder`, `update-reminder`, `update-event` and `set-mode` are marked idempotent.
119
121
 
120
122
  ## Installation
121
123
 
package/calendar/index.js CHANGED
@@ -218,7 +218,7 @@ const calendarTools = [
218
218
  description: z.string().optional().describe('New description (optional)'),
219
219
  location: z.string().optional().describe('New location (optional)')
220
220
  },
221
- annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true},
221
+ annotations: {"readOnlyHint":false,"destructiveHint":true,"idempotentHint":true,"openWorldHint":true},
222
222
  handler: withErrorHandler(handleUpdateEvent, 'update-event')
223
223
  },
224
224
  {
package/contacts/index.js CHANGED
@@ -309,7 +309,7 @@ const contactsTools = [
309
309
  {
310
310
  name: 'delete-contact',
311
311
  title: 'Delete Contact',
312
- description: 'Permanently deletes a contact from the user\'s address book. Takes the handle returned by list-contacts or search-contacts; confirm the target with read-contact first, because there is no undo through this server.',
312
+ description: 'Permanently deletes a contact from the user\'s address book. Takes the handle returned by list-contacts or search-contacts; there is no undo through this server.',
313
313
  inputSchema: {
314
314
  contactUrl: z.string().describe('URL or ID of the contact to delete (from list-contacts output)')
315
315
  },
package/email/index.js CHANGED
@@ -225,7 +225,7 @@ const emailTools = [
225
225
  body: z.string().describe('Email body content'),
226
226
  isHtml: z.boolean().optional().describe('Whether the body is HTML (default: false)')
227
227
  },
228
- annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":true},
228
+ annotations: {"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":true},
229
229
  handler: withErrorHandler(handleSendEmail, 'send-email')
230
230
  },
231
231
  {
package/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * iCloud MCP Server v2.1.1
4
+ * iCloud MCP Server
5
5
  *
6
6
  * Provides Claude with access to Apple services:
7
7
  * - Email (via IMAP/SMTP or Mail.app)
@@ -21,6 +21,7 @@ const { McpServer } = require('@modelcontextprotocol/server');
21
21
  const { serveStdio } = require('@modelcontextprotocol/server/stdio');
22
22
 
23
23
  const config = require('./config');
24
+ const { version } = require('./package.json');
24
25
  const { getMode, onModeChange } = require('./mode');
25
26
 
26
27
  // Import all modules - tools are always available, handlers check mode
@@ -56,7 +57,7 @@ function buildServer() {
56
57
  const server = new McpServer(
57
58
  {
58
59
  name: 'icloud-mcp',
59
- version: '2.1.1',
60
+ version,
60
61
  title: 'iCloud MCP'
61
62
  },
62
63
  {
@@ -98,7 +99,7 @@ mode returns an error. Use set-mode to switch without restarting.`
98
99
  return server;
99
100
  }
100
101
 
101
- console.error('[icloud-mcp] Starting iCloud MCP server v2.1.1...');
102
+ console.error(`[icloud-mcp] Starting iCloud MCP server v${version}...`);
102
103
  console.error(`[icloud-mcp] Initial mode: ${getMode().toUpperCase()}`);
103
104
  console.error(`[icloud-mcp] Tools available: ${TOOLS.length}`);
104
105
 
package/messages/index.js CHANGED
@@ -110,13 +110,13 @@ const messagesTools = [
110
110
  {
111
111
  name: 'send-message',
112
112
  title: 'Send Message',
113
- description: 'Send an iMessage or SMS. IMPORTANT: Always confirm with user before sending.',
113
+ description: 'Sends an iMessage or SMS to a phone number or email handle, with an optional file attachment. The message is delivered as soon as the tool runs; there is no draft step and no recall.',
114
114
  inputSchema: {
115
115
  to: z.string().describe('Recipient phone number (with country code) or email'),
116
116
  body: z.string().describe('Message content'),
117
117
  file: z.string().optional().describe('Path to file attachment (optional)')
118
118
  },
119
- annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":true},
119
+ annotations: {"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":true},
120
120
  handler: withErrorHandler(async ({ to, body, file }) => {
121
121
  const modeError = requireLocalMode('send-message');
122
122
  if (modeError) return modeError;
@@ -144,7 +144,7 @@ const messagesTools = [
144
144
  chatId: z.number().int().describe('Chat ID'),
145
145
  type: z.enum(['love', 'like', 'dislike', 'laugh', 'emphasis', 'question']).describe('Reaction type')
146
146
  },
147
- annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":true},
147
+ annotations: {"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":true},
148
148
  handler: withErrorHandler(async ({ chatId, type }) => {
149
149
  const modeError = requireLocalMode('react-message');
150
150
  if (modeError) return modeError;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mcp-icloud",
3
3
  "mcpName": "io.github.MrGo2/icloud-mcp",
4
- "version": "2.1.2",
4
+ "version": "2.1.3",
5
5
  "description": "MCP server for Apple services - Email, Calendar, Contacts, Reminders, Notes, Messages and Safari - with dual local (AppleScript) and cloud (IMAP/CalDAV/CardDAV) modes",
6
6
  "main": "index.js",
7
7
  "bin": {
@@ -22,6 +22,7 @@
22
22
  "utils/",
23
23
  "LICENSE",
24
24
  "README.md",
25
+ "PRIVACY.md",
25
26
  "DISCLOSURE"
26
27
  ],
27
28
  "scripts": {
@@ -115,7 +115,7 @@ const remindersTools = [
115
115
  dueDate: z.string().optional().describe('New due date in ISO format'),
116
116
  priority: z.number().int().min(0).max(9).optional().describe('New priority level')
117
117
  },
118
- annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},
118
+ annotations: {"readOnlyHint":false,"destructiveHint":true,"idempotentHint":true,"openWorldHint":false},
119
119
  handler: async ({ reminderId, ...updates }) => {
120
120
  const modeError = requireLocalMode('update-reminder');
121
121
  if (modeError) return modeError;