icloud-mcp 2.5.0 → 2.5.1

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.
Files changed (3) hide show
  1. package/index.js +7 -3
  2. package/lib/smtp.js +8 -3
  3. package/package.json +1 -1
package/index.js CHANGED
@@ -88,7 +88,7 @@ function resolveMailbox(name, creds) {
88
88
 
89
89
  async function main() {
90
90
  const server = new Server(
91
- { name: 'icloud-mail', version: '2.5.0' },
91
+ { name: 'icloud-mail', version: '2.5.1' },
92
92
  { capabilities: { tools: {} } }
93
93
  );
94
94
 
@@ -728,7 +728,10 @@ async function main() {
728
728
  body: { type: 'string', description: 'Plain text body (used as fallback when html is also provided)' },
729
729
  html: { type: 'string', description: 'HTML body. If provided without body, plain text is auto-generated. If provided with body, saves multipart/alternative.' },
730
730
  cc: { type: 'string', description: 'CC recipient(s)' },
731
- bcc: { type: 'string', description: 'BCC recipient(s)' }
731
+ bcc: { type: 'string', description: 'BCC recipient(s)' },
732
+ inReplyTo: { type: 'string', description: 'Message-ID of the email being replied to — sets In-Reply-To header for threading' },
733
+ references: { type: 'string', description: 'Space-separated Message-IDs for the References header — enables full thread linking' },
734
+ account: { type: 'string', description: 'Account whose Drafts folder to save into (e.g. "umd", "personal", "alt"). Defaults to iCloud.' }
732
735
  },
733
736
  required: ['to', 'subject']
734
737
  }
@@ -1147,7 +1150,7 @@ async function main() {
1147
1150
  } else if (name === 'save_draft') {
1148
1151
  const creds = resolveCreds(args.account);
1149
1152
  result = await withTimeout('save_draft', TIMEOUT.FETCH, () =>
1150
- saveDraft(args.to, args.subject, args.body, { html: args.html, cc: args.cc, bcc: args.bcc }, creds)
1153
+ saveDraft(args.to, args.subject, args.body, { html: args.html, cc: args.cc, bcc: args.bcc, inReplyTo: args.inReplyTo, references: args.references }, creds)
1151
1154
  );
1152
1155
  // ── CardDAV / Contacts (FETCH tier 30s) ──
1153
1156
  } else if (name === 'list_contacts') {
@@ -1219,6 +1222,7 @@ async function main() {
1219
1222
  }
1220
1223
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
1221
1224
  } catch (error) {
1225
+ process.stderr.write(`[tool-error] ${name}: ${error.responseText ?? error.message}\n`);
1222
1226
  return { content: [{ type: 'text', text: `Error: ${friendlyError(error)}` }], isError: true };
1223
1227
  }
1224
1228
  });
package/lib/smtp.js CHANGED
@@ -178,8 +178,12 @@ export async function saveDraft(to, subject, body, opts = {}, creds = null) {
178
178
 
179
179
  const mailOptions = { from: user, to: normalizeAddresses(to), subject };
180
180
  applyBody(mailOptions, body, opts.html);
181
- if (opts.cc) mailOptions.cc = normalizeAddresses(opts.cc);
182
- if (opts.bcc) mailOptions.bcc = normalizeAddresses(opts.bcc);
181
+ if (opts.cc) mailOptions.cc = normalizeAddresses(opts.cc);
182
+ if (opts.bcc) mailOptions.bcc = normalizeAddresses(opts.bcc);
183
+ if (opts.inReplyTo) mailOptions.inReplyTo = opts.inReplyTo;
184
+ if (opts.references) mailOptions.references = Array.isArray(opts.references)
185
+ ? opts.references.join(' ')
186
+ : opts.references;
183
187
 
184
188
  // Use nodemailer stream transport to produce raw MIME bytes without sending
185
189
  const streamTransport = nodemailer.createTransport({ streamTransport: true, buffer: true });
@@ -204,7 +208,8 @@ export async function saveDraft(to, subject, body, opts = {}, creds = null) {
204
208
  await client.append(draftMailbox, rawMessage, ['\\Draft', '\\Seen']);
205
209
  } catch (err) {
206
210
  // Folder might have a different name — scan the list for the \Drafts attribute
207
- if (err.message?.includes('NONEXISTENT') || err.message?.includes('does not exist') || err.message?.includes('NO ')) {
211
+ const r = err.responseText ?? err.message ?? '';
212
+ if (r.includes('NONEXISTENT') || r.includes('does not exist') || r.includes("doesn't exist") || r.includes('TRYCREATE') || r.includes('NO ') || r.includes('Failure')) {
208
213
  const mailboxes = await client.list();
209
214
  const draftMb = mailboxes.find(mb => mb.flags?.has('\\Drafts'));
210
215
  draftMailbox = draftMb?.path ?? 'Drafts';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "icloud-mcp",
3
- "version": "2.5.0",
3
+ "version": "2.5.1",
4
4
  "description": "A Model Context Protocol (MCP) server for iCloud Mail",
5
5
  "main": "index.js",
6
6
  "bin": {