{"_id":"@circuitwall/icloud-langchain","name":"@circuitwall/icloud-langchain","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@circuitwall/icloud-langchain","version":"0.1.0","description":"LangChain tools for iCloud Mail (IMAP) and iCloud Calendar / Reminders (CalDAV) — direct protocol calls, no MCP. Auth via Apple ID + app-specific password. Extracted from Jarela.","license":"Apache-2.0","author":{"name":"Andrew Ge Wu"},"homepage":"https://github.com/CircuitWall/jarela/tree/main/packages/icloud-langchain#readme","repository":{"type":"git","url":"git+https://github.com/CircuitWall/jarela.git","directory":"packages/icloud-langchain"},"bugs":{"url":"https://github.com/CircuitWall/jarela/issues"},"keywords":["icloud","apple","mail","imap","calendar","caldav","reminders","vtodo","langchain","langgraph","tool","tools","agent"],"type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./package.json":"./package.json"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"engines":{"node":">=20"},"scripts":{"build":"tsup","clean":"rimraf dist","test":"vitest run","typecheck":"tsc --noEmit"},"peerDependencies":{"@langchain/core":">=0.3.0","zod":">=3.23.0 <5"},"dependencies":{"ical.js":"^2.2.1","imapflow":"^1.4.2","tsdav":"^2.2.2"},"devDependencies":{"@langchain/core":"^1.1.46","@types/node":"^22.10.5","rimraf":"^6.0.1","tsup":"^8.3.5","typescript":"^5.7.2","vitest":"^4.1.7","zod":"^3.25.0"},"gitHead":"add320a712160690a1b45e546739360416eb1157","_id":"@circuitwall/icloud-langchain@0.1.0","_nodeVersion":"24.14.0","_npmVersion":"11.9.0","dist":{"integrity":"sha512-f1EeaooYR9UJLhWg4VIu8aL3uKRZwqyNmCvFbGXvM7m44vaKyL8DRAcvq1EG9g40hOkwiaOyOu5fPW0VVPm1FQ==","shasum":"da5433daad1baa905a935d1f26cdbf5145ffa23a","tarball":"https://registry.npmjs.org/@circuitwall/icloud-langchain/-/icloud-langchain-0.1.0.tgz","fileCount":10,"unpackedSize":311665,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIGn0/B3Iy25c5Qsi6vE4YymXyIBToZML+qllgguOcXMSAiAaOyt5xbW2gBWiqiUdE9Jdv2NxG4clZxLBF8Vbv6YWZw=="}]},"_npmUser":{"name":"andrew-ge-wu","email":"andrew.ge.wu@gmail.com"},"directories":{},"maintainers":[{"name":"andrew-ge-wu","email":"andrew.ge.wu@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/icloud-langchain_0.1.0_1781965823808_0.8889347972112724"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-20T14:30:23.636Z","0.1.0":"2026-06-20T14:30:23.954Z","modified":"2026-06-20T14:30:24.166Z"},"maintainers":[{"name":"andrew-ge-wu","email":"andrew.ge.wu@gmail.com"}],"description":"LangChain tools for iCloud Mail (IMAP) and iCloud Calendar / Reminders (CalDAV) — direct protocol calls, no MCP. Auth via Apple ID + app-specific password. Extracted from Jarela.","homepage":"https://github.com/CircuitWall/jarela/tree/main/packages/icloud-langchain#readme","keywords":["icloud","apple","mail","imap","calendar","caldav","reminders","vtodo","langchain","langgraph","tool","tools","agent"],"repository":{"type":"git","url":"git+https://github.com/CircuitWall/jarela.git","directory":"packages/icloud-langchain"},"author":{"name":"Andrew Ge Wu"},"bugs":{"url":"https://github.com/CircuitWall/jarela/issues"},"license":"Apache-2.0","readme":"# @circuitwall/icloud-langchain\r\n\r\nLangChain tools for **iCloud Mail** (IMAP), **iCloud Calendar**, and\r\n**iCloud Reminders** (CalDAV) — direct protocol calls, no MCP, no Apple\r\nSDK (there isn't one for end-user data). Extracted from\r\n[Jarela](https://github.com/CircuitWall/jarela) so any LangGraph /\r\nLangChain.js agent can give an LLM the same iCloud toolbelt without\r\nrunning the full Jarela stack.\r\n\r\n## Why\r\n\r\nApple does **not** ship an OAuth-protected REST API for a user's own\r\niCloud Mail / Calendar / Reminders. The only programmatic paths are the\r\ninternet standards Apple deliberately supports:\r\n\r\n- Mail → **IMAP** (`imap.mail.me.com:993`, TLS)\r\n- Calendar → **CalDAV** (`caldav.icloud.com`, PROPFIND principal\r\n  discovery)\r\n- Reminders → **CalDAV** (VTODO collections under the same principal)\r\n\r\nAuth = **Apple ID + an app-specific password** generated at\r\n<https://appleid.apple.com> (2FA must be on). \"Sign in with Apple\" is\r\nidentity-only and cannot grant Mail / Calendar access.\r\n\r\nThis package wraps [`imapflow`](https://imapflow.com),\r\n[`tsdav`](https://github.com/natelindev/tsdav), and\r\n[`ical.js`](https://github.com/mozilla-comm/ical.js) behind LangChain\r\ntool definitions, with a pluggable auth resolver so embedders can\r\nsupply credentials from their own vault.\r\n\r\n## Install\r\n\r\n```bash\r\nnpm i @circuitwall/icloud-langchain @langchain/core zod\r\n```\r\n\r\n`@langchain/core` and `zod` are peer dependencies — bring whichever\r\nversions your agent already uses (core ≥ 0.3, zod ≥ 3.23). `imapflow`,\r\n`tsdav`, and `ical.js` are runtime dependencies and install\r\nautomatically.\r\n\r\n## Quick start\r\n\r\n```ts\r\nimport {\r\n  setAuthResolver,\r\n  icloudTools,\r\n} from \"@circuitwall/icloud-langchain\";\r\n\r\n// Option A — env vars (default). No setup needed if these are set:\r\n//   ICLOUD_APPLE_ID=johnappleseed@icloud.com\r\n//   ICLOUD_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx\r\n\r\n// Option B — supply your own resolver (e.g. read from a secrets store):\r\nsetAuthResolver(async () => ({\r\n  appleId: \"johnappleseed@icloud.com\",\r\n  appPassword: await vault.read(\"icloud/app-password\"),\r\n}));\r\n\r\n// Hand the tools to your agent:\r\nimport { createReactAgent } from \"@langchain/langgraph/prebuilt\";\r\nconst agent = createReactAgent({\r\n  llm: yourModel,\r\n  tools: icloudTools,\r\n});\r\n```\r\n\r\nEach tool resolves auth lazily on every call, so it's safe to import\r\nthe tools at module load and configure the resolver later.\r\n\r\n## Generating the app-specific password\r\n\r\n1. Sign in at <https://appleid.apple.com>.\r\n2. Make sure **two-factor authentication is enabled** — the\r\n   \"App-Specific Passwords\" section only appears when 2FA is on.\r\n3. Open **Sign-In and Security → App-Specific Passwords →\r\n   Generate a password**.\r\n4. Name it (e.g. `Jarela`) and copy the 16-character value. It's\r\n   shown only once — store it in your vault before closing the page.\r\n5. Either set `ICLOUD_APP_PASSWORD` to that value, or pass it\r\n   through your custom `setAuthResolver()`.\r\n\r\nYou can revoke the password at any time from the same page — it\r\nimmediately invalidates this package's access without affecting any\r\nother client.\r\n\r\n## What's included (16 tools)\r\n\r\n### Mail (7)\r\n\r\n- `icloud_mail_list_folders` — folder tree with message and unread\r\n  counts, plus the IMAP SPECIAL-USE flag (`\\Drafts`, `\\Sent`,\r\n  `\\Trash`, `\\Junk`, `\\Archive`) for stable cross-locale lookup.\r\n- `icloud_mail_list_messages` — IMAP `SEARCH` over a folder\r\n  (`query`, `unseen_only`, `since`, `before`, `limit`), most-recent\r\n  first.\r\n- `icloud_mail_get_message` — full envelope, plain-text body\r\n  (HTML opt-in via `include_html`), and an attachments index.\r\n- `icloud_mail_create_draft` — IMAP `APPEND` into the Drafts\r\n  folder. **Drafts only** — this package intentionally does not\r\n  send mail on the user's behalf. Open the draft in Apple Mail to\r\n  review and send.\r\n- `icloud_mail_move_message`, `icloud_mail_flag_message`,\r\n  `icloud_mail_delete_message` — standard mailbox operations.\r\n  `delete_message` resolves the localised Trash folder via the\r\n  `\\Trash` SPECIAL-USE flag.\r\n\r\n### Calendar (6)\r\n\r\n- `icloud_calendar_list_calendars` — VEVENT calendar collections\r\n  with URL, display name, and color.\r\n- `icloud_calendar_list_events` — `time_min` / `time_max` window\r\n  via CalDAV `REPORT calendar-query`.\r\n- `icloud_calendar_get_event` — full event including raw\r\n  iCalendar source.\r\n- `icloud_calendar_create_event` — create a single event (or\r\n  all-day event with `all_day: true`).\r\n- `icloud_calendar_update_event` — patch summary / time /\r\n  location / description in place.\r\n- `icloud_calendar_delete_event` — delete by UID.\r\n\r\n### Reminders (3 + 1 lister)\r\n\r\n- `icloud_reminders_list_lists` — VTODO calendar collections.\r\n- `icloud_reminders_list` — items in a list, with\r\n  `include_completed`.\r\n- `icloud_reminders_create` — new VTODO with optional `due`.\r\n- `icloud_reminders_complete` — mark VTODO as `COMPLETED`.\r\n\r\nUse the convenience bundles `icloudMailTools`,\r\n`icloudCalendarTools`, `icloudReminderTools`, or `icloudTools` (all\r\nthree combined) to hand the lot to an agent.\r\n\r\n## Auth resolver\r\n\r\n```ts\r\nimport {\r\n  type ICloudAuth,\r\n  type AuthResolver,\r\n  setAuthResolver,\r\n  resolveICloudAuthFromEnv,\r\n} from \"@circuitwall/icloud-langchain\";\r\n\r\n// The default resolver reads ICLOUD_APPLE_ID + ICLOUD_APP_PASSWORD.\r\n// Replace it to plug in your own credential source:\r\nconst fromVault: AuthResolver = async () => {\r\n  const row = await db.getICloudCredential(currentUserId);\r\n  if (!row) return { error: \"iCloud credential not configured for this user.\" };\r\n  return { appleId: row.apple_id, appPassword: row.app_password };\r\n};\r\nsetAuthResolver(fromVault);\r\n```\r\n\r\nThe resolver may be sync or async. Whitespace, hyphens, and\r\nzero-width characters are stripped from the returned `appPassword`\r\nbefore use, so you can store the value either as Apple presents it\r\n(`xxxx-xxxx-xxxx-xxxx`) or pre-stripped.\r\n\r\n## Known limitations\r\n\r\n- **No SMTP / send-mail tool in this release** — by design. iCloud\r\n  drafts are written via IMAP `APPEND` and reviewed by the user in\r\n  Apple Mail before they go out. If you need send-on-behalf, layer\r\n  a separate `nodemailer` transport on top.\r\n- **No push notifications.** iCloud does not advertise CalDAV\r\n  WebPush or APNS for mail. Poll on whatever interval suits your\r\n  agent (every 5–15 minutes is the standard pattern).\r\n- **Recurring-event instance edits are not supported.** Updates\r\n  and deletes apply to the entire series. Per-instance edits\r\n  require `RECURRENCE-ID` + `EXDATE` plumbing that isn't in this\r\n  release.\r\n- **iCloud rate-limits aggressive IMAP IDLE.** Each tool call\r\n  opens a fresh connection and logs out, so this package is safe\r\n  by default; do not wrap it in a long-lived IDLE loop without\r\n  reading the iCloud server policy first.\r\n\r\n## License\r\n\r\nApache-2.0 — see [LICENSE](./LICENSE).\r\n","readmeFilename":"README.md","_rev":"1-4c224d3b3207cc0c51713bc69977097a"}