friedafetch
Health Warn
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 5 GitHub stars
Code Fail
- rm -rf — Recursive force deletion command in .github/workflows/release.yml
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
Frieda – MCP connector for iCloud: calendars, contacts, mail and notes for Home Assistant (HACS integration)
English · Deutsch
Frieda – MCP connector for iCloud
Frieda (technical name friedafetch) is a Home Assistant integration (HACS) that connects Apple iCloud with an app-specific password and exposes
calendars, contacts, e-mail and notes as tools for LLMs. The tools are registered as a Home Assistant
LLM API, so they are available to every conversation agent that enables the API (Assist, Google Generative AI,
OpenAI, Ollama …) and to any MCP client (Claude, ChatGPT connectors, local agents) through Home Assistant's
MCP Server integration or the integration's own MCP endpoint. Inbox rules, push delivery and a daily overview
come with the separate extension Frieda Postfach.
The project is named after the maintainer's dog Frieda, who looks out of the cloud in the logo.
Features
| Area | Protocol | Read | Write |
|---|---|---|---|
| Calendar | CalDAV | list calendars, search/read events (recurrences expanded) | create, update (incl. RRULE) and delete events |
| Contacts | CardDAV | search (name, mail, phone, company …) and read contacts | create, update and delete contacts |
| IMAP + SMTP | mailboxes, search/filter, read mail (text, attachment list) | send/reply, mark read/flagged, move, trash – many uids at once | |
| Notes | IMAP folder Notes |
list/search/read notes | create, update and delete notes |
| Rules | – | with the extension Frieda Postfach | inbox rules, push, daily overview |
| Insights | all of the above | mailbox statistics, free time slots, birthdays, duplicate contacts | unsubscribe from newsletters, store attachments (receipts) |
Important note on Notes
Apple offers no interface for modern iCloud Notes (CloudKit, the default since iOS 9 / "upgraded notes") that
works with an app-specific password. The integration can therefore only read and write notes stored in the
IMAP folder Notes of the iCloud mail account (classic IMAP notes). If that folder does not exist, the note tools
say so. The other areas use official, stable protocols (CalDAV, CardDAV, IMAP, SMTP) and are fully usable.
Requirements
- Home Assistant 2026.10 or newer (the integration uses the current
llm.ToolAPI withprobatioschemas; older
2025 releases work through the built-involuptuousfallback but are untested). - An Apple ID with two-factor authentication and an app-specific password
(appleid.apple.com → Sign-In and Security → App-Specific Passwords). - iCloud Mail must be enabled for the Apple ID if you want e-mail and notes.
- Optional: Home Assistant's Model Context Protocol Server integration (
mcp_server) if you prefer it over the
built-in endpoint.
Installation
HACS (recommended)
- HACS → Integrations → ⋮ → Custom repositories → URL of this repository, category Integration.
- Install "Frieda" and restart Home Assistant.
Manual
Copy custom_components/friedafetch into the custom_components directory of your Home Assistant configuration and
restart Home Assistant.
Upgrading to 2.0
Frieda 2.0 is a pure connector: inbox rules, push delivery, the daily overview and the birthday sensor moved to the
separate integration Frieda Postfach. Install it via HACS and add
it for your account; existing rules, hit counters, run history and automation settings are picked up automatically.
Until then Frieda shows a repair notice for accounts with stored rules, and no rules run. The rule tools
(icloud_*_rule, icloud_run_rules, icloud_daily_overview) appear again as soon as Frieda Postfach is set up.
Upgrading from “iCloud MCP” (versions up to 1.0.x)
The project was renamed to Frieda with version 1.1.0; the integration domain changed from icloud_mcp tofriedafetch. Remove the old integration (Settings → Devices & services → iCloud MCP → Delete), update the HACS
custom repository to https://github.com/nadeo360/friedafetch, install Frieda and add it again with the Apple ID
and app-specific password. Rules and options are not migrated; MCP clients need the new endpoint/api/friedafetch. The tool names (icloud_*) are unchanged. If an old custom_components/icloud_mcp folder is left
behind, Home Assistant may keep loading it instead of the current version (both declare the domain friedafetch);
Frieda detects this at startup and shows a repair issue – delete the folder named there and restart Home Assistant.
Setup
- Settings → Devices & services → Add integration → "Frieda".
- Enter the Apple ID and the app-specific password. Credentials are validated against CalDAV (mandatory) and IMAP
(optional – if IMAP fails, the mail and note tools start disabled). - Connect an MCP client, either via the built-in endpoint (see below) or via the core
Model Context Protocol Server integration: there, under Configure, enable "all LLM APIs" or select
"iCloud (Calendar, Contacts, Mail, Notes)" in addition to Assist. - Optional for voice assistants: enable the iCloud LLM API in the conversation integration (e.g. Google Generative
AI) under "Control Home Assistant".
Note on
mcp_server_http_transport(hass-mcp-server): that HACS integration ships its own fixed tool set and
does not forward Home Assistant LLM APIs, so the iCloud tools do not appear there. Use the built-in endpoint
or the core MCP Server integration instead; both can run side by side.
Options (Configure)
The options dialog has three sections: Tools and account, Security and guard rails and Approvals.
| Option | Effect |
|---|---|
| Calendar / Contact / E-mail / Note tools | show or hide tool groups |
| Read-only mode | hides every create/update/delete/send tool |
| Allow sending e-mails | hides icloud_send_mail when disabled |
| Allow deleting | hides all icloud_delete_* tools (except rule deletion) when disabled |
| Default maximum number of results | default list limit (1–200) |
| Sender address | From: for outgoing mail (default: Apple ID; must be an iCloud alias) |
| Attachment folder | where icloud_save_attachments (and Frieda Postfach rules) store files (default <media>/frieda; must be an allowed path) |
| Account label | short name used as tool suffix when several accounts are configured |
| Security section | quotas, recipient policy, protected calendars/mailboxes, hidden mailboxes (see Security) |
All tools carry MCP annotations (readOnlyHint, destructiveHint) so that clients in read-only mode can drop the
writing tools automatically.
Capabilities you switch off are not hidden silently: the LLM prompt (and the instructions of the built-in MCP
endpoint) lists what the administrator disabled, so the assistant can tell the user why it cannot send or delete
and where to enable it (Settings → Devices & services → Frieda → Configure). Likewise, active approvals are
announced so that an approval_required result is explained as "waiting for approval", not as an error.
Built-in MCP endpoint
The integration serves its tools directly at POST /api/friedafetch (MCP Streamable HTTP, stateless) and
authenticates with Home Assistant access tokens – no additional integration required.
- In Home Assistant open your profile → Security → Long-lived access tokens → Create token.
- Configure the client with the URL
https://<your-home-assistant>/api/friedafetchand the headerAuthorization: Bearer <token>.
For Claude Code (~/.claude.json) or Claude Desktop (claude_desktop_config.json) this looks like:
{
"mcpServers": {
"icloud": {
"type": "http",
"url": "https://<your-home-assistant>/api/friedafetch",
"headers": { "Authorization": "Bearer <token>" }
}
}
}
GET /api/friedafetch answers with a short status (name, version, tool count). Server-initiated streams and
sessions are not needed; every POST is handled on its own.
Several iCloud accounts
Add the integration once per Apple ID. The first account keeps the plain tool names (icloud_list_events); every
further account gets a suffix derived from its account label (option) or the local part of its Apple ID, for
example icloud_list_events_work. The LLM APIs are registered the same way (friedafetch, friedafetch_work), and
the panel offers an account selector. Each account has its own options.
Tools
| Tool | Description |
|---|---|
icloud_list_calendars |
calendars with ids |
icloud_list_events |
events in a time range (recurrences expanded), optional text filter |
icloud_get_event |
one event with details |
icloud_create_event |
create an event (all-day or timed, optional RRULE) |
icloud_update_event |
change fields of an event (duration kept when only start changes) |
icloud_delete_event |
delete an event |
icloud_search_contacts |
search contacts (empty query = alphabetical list) |
icloud_get_contact |
contact by uid |
icloud_create_contact |
create a contact |
icloud_update_contact |
change a contact (list fields replace the existing list) |
icloud_delete_contact |
delete a contact |
icloud_list_mailboxes |
mailboxes/folders |
icloud_search_mail |
filter mail (sender, subject, full text, date range, unseen, flagged) |
icloud_get_mail |
read a mail (text, optional HTML, attachment list, optional raw headers) |
icloud_send_mail |
send or reply (quote, In-Reply-To, copy in the sent folder) |
icloud_mark_mail |
read/unread, flagged/unflagged – one or many uids (uids) at once |
icloud_move_mail |
move to another folder – one or many uids with a single IMAP command |
icloud_delete_mail |
move to trash (or delete permanently when already in trash) – one or many uids |
icloud_approval_status |
outcome of an action that required human approval |
icloud_mailbox_stats |
top senders/domains, unread and newsletter share, rule coverage and rule suggestions |
icloud_unsubscribe |
unsubscribe from a newsletter (one-click https or unsubscribe e-mail) |
icloud_save_attachments |
store the attachments of a mail in <folder>/<subfolder>/<YYYY-MM>/ |
icloud_find_free_time |
free slots of a given length within working hours |
icloud_upcoming_birthdays |
birthdays of the contacts in the coming days (with age, if known) |
icloud_find_duplicate_contacts |
probable duplicates (same e-mail, phone or name) |
icloud_list_notes |
list/search notes |
icloud_get_note |
read a note |
icloud_create_note |
create a note |
icloud_update_note |
replace a note (it gets a new uid) |
icloud_delete_note |
delete a note |
Times are ISO 8601; naive times are interpreted in the Home Assistant time zone. All-day events use dates
(YYYY-MM-DD) with an inclusive end date. The mail tools icloud_mark_mail, icloud_move_mail andicloud_delete_mail accept a uids list (up to 500) and process it with a single IMAP command, so cleaning up spam
is one call instead of one per message.
Panel
The integration adds "Frieda" to the Home Assistant sidebar (admins only, German/English following the HA
language):
- Overview: whether the MCP endpoint is active (both URLs to copy – for the local address and, if set up, the
external address and Home Assistant Cloud –, number of reading and writing tools, token rule), the MCP clients that connected recently (name and version from the MCP handshake), whether the LLM API is
exposed by Home Assistant's own MCP server, and the state of Frieda Postfach (running, installed but not linked,
not installed). - Usage: tool calls today, in 7 and 30 days and in total, split into reading and writing, a 14-day chart, the most
used tools, where the calls came from (Frieda endpoint, HA MCP server, Assist agents) and the hourly quotas. Only
counters are stored, never arguments or results. - Approvals: pending and decided requests (approve or deny with one tap, also from the companion app; the request
shows "Sending …" until the result is in). - Change log: everything Frieda changed in iCloud as a table grouped by day (e.g. "Mail moved · 3 messages ·
→ Archive"), with search, filters for area and trigger, a result switch and selectable columns; a click on a row
shows the error and the raw parameters, and for runs of Frieda Postfach the messages with a link to their timeline.
Tabs and widgets: three tabs keep the panel tidy – Overview (with the usage), Approvals (shown when
approvals are on or there are entries; the tab counts the pending ones, so they stand out from the other tabs too) and
Change log. On the overview, Arrange in the title bar lets you drag the cards by the handle (or move them
with the arrows), switch them between full and half width and hide them; tables offer a Columns menu. Rare
actions such as clearing the log sit in a small ⋮ menu and always ask for confirmation. The layout and the last tab
are stored per Home Assistant user in Home Assistant itself, so they survive restarts and follow you to other
devices.
Live: the tables follow changes right away (new change-log entries, approvals, runs), without reloading the page;
new rows light up briefly. After an update the panel offers a reload when it still runs the old code.
Pages: long tables show 5, 10, 25, 50 or all entries per page (remembered per table); search and filters
always cover all entries.
Frieda UI: both panels use one shared design library (/friedafetch_static/ui.js): colours from the Home
Assistant theme, buttons, chips, tables, menus, dialogs and widgets. Frieda Postfach loads it from Frieda, so every
module looks and behaves the same. It also covers accessibility: the focus stays in place when a panel redraws,
dialogs keep the focus inside, notices and search hits are read out, symbols have names for screen readers, and
coloured text keeps WCAG AA contrast in light and dark themes.
The panel has no external dependencies and talks to the integration via WebSocket commands (friedafetch/accounts,friedafetch/overview, friedafetch/usage/reset, friedafetch/approvals/*, friedafetch/audit/*).
Attachments and unsubscribing
- Attachments:
icloud_save_attachmentsstores the attachments of a mail below the attachment folder, sorted by
month and named<date>_<sender>_<file>. Identical files are not stored twice, small images (logos, signatures)
are skipped. Home Assistant must allow the folder (media folders are allowed by default, others go intoallowlist_external_dirs). - Unsubscribe:
icloud_unsubscribeuses theList-Unsubscribeheader: one-click https (RFC 8058) first, then an
unsubscribe e-mail (only when sending is allowed; it counts against the sending quota and needs approval if
sending does). Links that require a web page are returned for you to open.
Extensions
Frieda only acts when an AI client or you call it. Everything that runs on its own lives in extensions that attach to
a Frieda account, reuse its connection and guard rails, and add their tools to it:
- Frieda Postfach (
friedafetch_mail): inbox rules with push
delivery (IMAP IDLE), receipts via rules, the daily overview, a birthday sensor and the rule tools.
Security
- Only an app-specific password is used; it can be revoked at Apple any time and is redacted in diagnostics.
Connections go exclusively over TLS to Apple endpoints; there is no telemetry. - The MCP endpoint and the panel are protected by Home Assistant tokens and admin rights; tool groups, read-only
mode, sending and deleting can be switched off individually. - Guard rails (options → Security): hourly quotas per account for mail moves/deletions/flag changes, sent mails
and deleted events/contacts/notes; a recipient policy for sending (any address, known contacts, or an allowlist of
addresses/domains) with a recipient cap and optional BCC ban; protected calendars and mailboxes that AI clients may
only read, and hidden mailboxes that are not exposed at all. Blocked calls returncode: "blocked". - Change log: every writing tool call and every rule run with hits or errors (marked manual or automatic) is recorded (time, client, Home Assistant user, tool,
shortened parameters without message bodies, result) in the "Change log" card of the panel and fired as the eventfriedafetch_action, so an automation can notify you, e.g. when more than ten mails are deleted at once. - Approvals (human in the loop, options → Approvals): sending, deleting and mass mail actions above a threshold
can be parked instead of executed. Home Assistant shows a notification (optionally an actionable push on your phone
with Approve/Deny) and the "Approvals" card in the panel lists the request; after approval Home Assistant runs the
action and the AI reads the outcome withicloud_approval_status. Requests expire after a configurable time. - Delayed sending (options → Approvals, default off): e-mails from assistants wait a few seconds (e.g. 60) before
they go out. Until then the "Approvals" card shows them with "Send now" and "Cancel", and the notification has a
Cancel button. Recipients and quotas are checked at once and again when the mail is sent. Without effect when sending
needs approval anyway. - Persistent state: the hourly quotas, active injection locks and the list of approvals survive restarts and
reloads, so a restart neither refills a quota nor lifts a lock. Requests that were still open at a restart cannot
be executed afterwards: they are closed as expired (a delayed mail as cancelled, i.e. not sent). - Endpoint profiles: besides
/api/friedafetchthere is/api/friedafetch/readonly, which serves only tools that
cannot change anything – the right endpoint for experiments or less trusted agents. The option "MCP endpoint only
for administrator tokens" refuses non-admin tokens; request bodies are capped at 1 MiB. - Prompt-injection defence: subjects, bodies, notes and event texts are stripped of invisible/bidi characters,
marked as third-party content in the tool results, and scanned for typical injection patterns; hits are flagged
withsuspicious: trueandwarnings. The LLM prompt instructs the model never to follow instructions found in
such content. - Injection lock (options → Security, default on): once a tool returned such flagged content, the same caller
(platform and Home Assistant user) may not send, delete, unsubscribe or create deleting/moving rules for a while
(default 15 minutes): the call is parked for approval, or blocked if approvals are off. The panel overview shows
active locks. This stops the classic attack where a mail says “forward everything to …”. - Rules are mass actions too: with Frieda Postfach, rules that delete or move and real runs over the whole
mailbox follow the approvals (“approve deleting”, mass threshold). Unattended runs (timer, push) and runs requested
by an AI change at most 100 messages (50 deletions) per run and count against the hourly quota for mail changes;
the rest follows in the next run. AI sorting counts against the same quota. - Supply chain: every commit runs tests, Ruff with the Bandit rule set, Bandit, CodeQL, pip-audit, hassfest and
HACS validation; GitHub Actions are pinned to commit SHAs, themainbranch is protected, OpenSSF Scorecard rates
the repository continuously, Dependabot and GitHub security alerts are enabled. Releases are built by GitHub
Actions and published with signed build provenance (Sigstore) and a CycloneDX SBOM; HACS installs exactly this
signed package (gh attestation verify friedafetch.zip --repo nadeo360/friedafetch). Details and the disclosure process: SECURITY.md.
Example automation on the audit event:
automation:
- alias: Warn on mass deletion by AI
triggers:
- trigger: event
event_type: friedafetch_action
conditions:
- "{{ trigger.event.data.action == 'delete' and (trigger.event.data.details.count | default(1)) > 10 }}"
actions:
- action: notify.mobile_app_iphone
data:
message: "{{ trigger.event.data.client }} deleted {{ trigger.event.data.details.count }} mails"
Technical notes
- Credentials live only in the config entry; the password is redacted in diagnostics.
- CalDAV/CardDAV are implemented directly on
aiohttp(principal discovery,calendar-query,addressbook-multiget, ETag-protected updates). Contacts are cached locally and synchronised incrementally via
CTag/ETag. - Recurring events are expanded with
python-dateutil(RRULE, EXDATE, RDATE, moved occurrences). - vCards are handled by a small lossless parser: unknown fields (photo, Apple extensions) survive updates.
- IMAP via
aioimaplib(one serialised connection with automatic reconnect), SMTP viaaiosmtplib(STARTTLS, 587). - Packages that Home Assistant ships itself (
icalendar,aioimaplib,aiosmtplib,mcp,anyio) are declared
as minimum versions and follow the HA release, as hassfest requires.
Development
How to report bugs, suggest ideas and send pull requests: CONTRIBUTING.md.
The architecture of Frieda and Frieda Postfach is described in the arc42 document docs/architecture.md.
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements_dev.txt
pytest
ruff check . && ruff format .
Home Assistant 2026.10 requires Python ≥ 3.14.2.
Releases
scripts/release.py VERSION --notes NOTES.md releases from a clean dev: it stops if origin/main has commitsdev lacks, sets the version in the manifest, runs ruff and the tests, moves main on by fast-forward and pushes
it, waits until every CI run of that commit has passed, creates the GitHub release with the notes (German, ---,
English), and then checks the zip the release workflow attached – checksum, version and every file against the
tagged source. --dry-run only checks and tests; --draft prints a notes skeleton from the commits since the last
release.
Artwork
assets/*.svg are the sources; scripts/build_icons.py renders every PNG variant (icon, @2x, light/dark logo) intoassets/ and into custom_components/friedafetch/brand/, from where Home Assistant (2026.3+) and HACS load the
integration's icon directly. --check verifies in CI that the files are current.
About the use of AI
This integration was developed with substantial help from an AI coding assistant (Anthropic's Claude), working from
the maintainer's requirements and decisions. Every change is covered by the automated test suite and the security
checks described above, and all releases were reviewed and tested by the maintainer against a real iCloud account.
Please report bugs and ideas via GitHub issues – they are read by a human.
Legal notices
Apple, iCloud, iPhone, iPad, Mac and macOS are trademarks of Apple Inc.; Home Assistant is a trademark of the Open
Home Foundation; "Model Context Protocol" and "Claude" are trademarks of Anthropic, PBC. This is an independent
community project and is not affiliated with, endorsed or supported by Apple, the Open Home Foundation, Nabu Casa,
Anthropic or HACS. Using iCloud through this integration is subject to Apple's iCloud terms; you are responsible
for complying with them. The software comes without warranty, reads and changes personal data on your behalf and
hands it to the AI clients you connect. Full notices, third-party licenses (including the GPL-3.0 licensedaioimaplib) and the liability disclaimer: NOTICE.md.
License
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found