Install
openclaw skills install @chrischall/apple-icloud-mcpThis skill should be used when the user asks about Apple Music, their Apple Music playlists or library, iCloud Calendar, iCloud Contacts, iCloud Mail, Apple Maps directions or places, the weather (WeatherKit), podcasts, or iTunes/App Store search — from any OS, via Apple's web services. Unofficial; not affiliated with Apple. Triggers on phrases like "make an Apple Music playlist", "add this song to my playlist", "what's on my calendar", "schedule a meeting", "find free time", "what's Jane's number", "check my iCloud email", "directions to", "how long to drive", "will it rain", "top charts", "find a podcast".
openclaw skills install @chrischall/apple-icloud-mcpMCP server that reaches Apple Music, iCloud Calendar/Contacts/Mail, Apple Maps, WeatherKit and the iTunes
Search API over the network — no Mac needed. Unofficial; not affiliated with Apple. On a Mac, apple-swift-mcp
is a native companion that adds Reminders, Notes, Photos and Messages, and manages Music.app playlists locally
(rename, delete, remove/reorder tracks) with no tokens.
{
"mcpServers": {
"apple": {
"command": "npx",
"args": ["-y", "apple-icloud-mcp"],
"env": {
"ICLOUD_USERNAME": "you@icloud.com",
"ICLOUD_APP_PASSWORD": "abcd-efgh-ijkl-mnop",
"APPLE_MUSIC_WEB_USER_TOKEN": "<media-user-token cookie from music.apple.com>",
"DISPLAY_TZ": "America/New_York"
}
}
}
}
Each service turns on when its credentials are set — see the README's "Setting up credentials". Run
apple_healthcheck first: it says which services work and which variables are missing.
apple_healthcheck when anything fails or you are unsure what is configured.apple_music_search_catalog (or apple_itunes_search, whose
trackId is the same catalog id), then apple_music_create_playlist with those ids, or
apple_music_add_playlist_tracks to append. Read a playlist with apple_music_get_playlist before changing
it; removal/reorder tools take the LIBRARY track ids and positions that call returns.APPLE_MUSIC_WEB_USER_TOKEN); Apple's
official API cannot do these. Responses say which backend served them.revision from
apple_music_get_playlist (or from the previous write's result) as expectedRevision; a PLAYLIST_CHANGED
error means Apple has not caught up yet (or someone else edited it) — re-read and retry, never rebuild from
an older list.id from list/search verbatim. A recurring event's occurrence id ends in #occ=…;
pass span (thisEvent / futureEvents / allEvents) to update or delete. Times without an offset are
read in DISPLAY_TZ; all-day endDate is the LAST day (inclusive). Every event list states the window it
searched — nothing outside it was looked at. Lists are compact by default; view: "full" or
apple_calendar_get_event gives attendees, alarms and full notes.apple_contacts_get returns an entryId per email/phone/address; pass it to
apple_contacts_update to edit or remove exactly that entry.apple_mail_get_message never marks mail read; use apple_mail_update_flags (seen: true) for
that. Search one mailbox at a time (apple_mail_list_mailboxes for paths). To reply, pass inReplyTo
(mailbox, uid) to apple_mail_send; if the original has a different Reply-To, ask which address to answer.apple_maps_geocode first for a place name. Always show the Apple
Weather attribution the response includes.confirmToken: show the user the preview, get their explicit OK, then repeat the call with the token.returned/total/nextOffset/hasMore before the data; pass nextOffset as
offset for more. Never report "none" from a page that says hasMore: true.apple_healthcheck(services) — Check which Apple services (Apple Music, iCloud Calendar, Contacts, Mail, Apple Maps, WeatherKit, iTunes) are configured and reachable.apple_music_search_catalog(term, types, limit, offset, storefront, view) — Search Apple Music's catalog by text for songs, albums, artists, playlists, music videos or stations.apple_music_get_catalog_items(type, ids, isrc, upc, tracksLimit, tracksOffset, views, storefront, view) — Look up Apple Music catalog songs, albums, artists, playlists, music videos or stations by id — or songs/music videos by ISRC, albums by UPC.apple_music_get_charts(types, genre, chart, limit, offset, storefront, view) — Get Apple Music's top charts (most played songs, albums, playlists, music videos) for a storefront, optionally for one genre.apple_music_list_playlists(folderId, limit, offset, view) — List the playlists in your Apple Music library (alphabetical), or the contents of one playlist folder (folders and playlists).apple_music_get_playlist(playlistId, limit, offset, allTracks, storefront, view) — Read one playlist — a library playlist (p.…) or a catalog playlist (pl.…) — with its tracks in order.apple_music_list_folders(folderId) — List the playlist folders in your Apple Music library: the top level, or the sub-folders of one folder.apple_music_search_library(term, types, limit, offset, view) — Search YOUR Apple Music library (not the whole catalog) by text for songs, albums, artists, playlists or music videos.apple_music_list_library(kind, limit, offset, view) — List what is in your Apple Music library: all songs, albums, artists or music videos (alphabetical, paged), or recently-added items.apple_music_get_history(feed, limit, offset, view) — Your recent Apple Music listening: recently-played (albums, playlists, stations), recently-played-tracks (songs), recent-stations, or heavy-rotation.apple_music_get_recommendations(limit, offset, view) — Your personal Apple Music recommendations ("Made for You", "Recently Played" and similar groups), each with its title and the albums, playlists or stations in it (catalog ids).apple_music_get_replay(year, views, limit, view) — Apple Music Replay: your top songs, albums and artists for the latest Replay year, or for a given year (with play counts where Apple provides them).apple_music_get_ratings(type, ids) — Whether you have loved or disliked songs, albums, playlists, music videos or stations — catalog or library ids — returning love, dislike or none per id.apple_music_create_playlist(name, description, tracks, folderId, isPublic) — Create a new playlist in your Apple Music library, optionally with tracks (up to 500 catalog or library song ids; added 100 at a time), a description, a folder and public visibility (not in APPLE_WRITE_MODE=additive).apple_music_add_playlist_tracks(playlistId, tracks, skipDuplicates) — Append songs (up to 500 catalog or library ids) to the end of one of your library playlists.apple_music_create_folder(name, parentFolderId) — Create a playlist folder in your Apple Music library, at the top level or inside another folder.apple_music_add_to_library(songs, albums, playlists, musicVideos) — Add catalog songs, albums, playlists or music videos to your Apple Music library by catalog id (up to 100 per type).apple_music_add_favorites(songs, albums, playlists, artists, musicVideos) — Mark catalog songs, albums, playlists, artists or music videos as favorites (the star in Apple Music; favorite songs go to your Favorite Songs playlist), by catalog id, up to 100 per type.apple_music_set_rating(type, id, rating) — Set your rating on a song, album, playlist, music video or station (catalog or library id): love, dislike, or none to clear it.apple_music_update_playlist(playlistId, name, description, isPublic) (web-player mode) — Rename one of your Apple Music library playlists, change its description, or make it public/private.apple_music_remove_playlist_tracks(playlistId, trackIds, positions, expectedRevision) (web-player mode) — Remove tracks from one of your library playlists by library track id and/or 1-based position (from apple_music_get_playlist). — asks for confirmationapple_music_reorder_playlist(playlistId, operation, fromPosition, toPosition, count, by, descending, trackIds, expectedRevision) (web-player mode) — Reorder one of your library playlists: move tracks, sort (name, artist, album, release date, duration, date added), reverse, dedupe (keep the first copy of each song), or replace with a complete new order of its track ids (can drop tracks). — asks for confirmationapple_music_move_playlist(playlistId, folderId) (web-player mode) — Move one of your library playlists into a playlist folder, or back to the top level ("root").apple_music_delete_playlist(playlistId) (web-player mode) — Delete one of your library playlists (songs stay in your library). — asks for confirmationapple_music_remove_from_library(type, ids) (web-player mode) — Remove songs, albums, music videos or playlists from your Apple Music library by LIBRARY id (i.…, l.…, p.… from apple_music_list_library / apple_music_search_library), up to 50 at a time; the preview names each item. — asks for confirmationapple_music_remove_favorites(songs, albums, playlists, artists, musicVideos) (web-player mode) — Remove the favorite (star) from catalog songs, albums, playlists, artists or music videos, by catalog id, up to 100 per type.apple_calendar_list_calendars() — List your iCloud calendars (event calendars only): id, name, color, whether you can add events to it, whether it is shared (shared: with you by someone else; sharedByYou: by you with others), and which one new events go into by default.apple_calendar_list_events(fromDate, toDate, daysAhead, calendars, limit, offset, timeZone, view) — List iCloud Calendar events (appointments, meetings) in a date window, recurring events expanded into occurrences, sorted by start.apple_calendar_search_events(query, fromDate, toDate, daysAhead, calendars, limit, offset, timeZone, view) — Search iCloud Calendar events by text (case-insensitive match in title, location or notes) within a date window: fromDate (default today; may be in the past) + toDate or daysAhead (default 30), max 366 days.apple_calendar_get_event(eventId, includeIcs, timeZone) — Get one iCloud Calendar event in full (notes untruncated, attendees, alerts, recurrence rule in plain English) by the id list/search returned.apple_calendar_create_event(calendar, title, startDate, endDate, isAllDay, timeZone, location, notes, url, alarms, recurrence, attendees) — Create an iCloud Calendar event: title, startDate/endDate (timed default 1 hour; all-day endDate = last day), location, notes, url, alarms, recurrence, attendees. — asks for confirmation when attendees are involvedapple_calendar_update_event(eventId, span, title, startDate, endDate, isAllDay, timeZone, location, notes, url, alarms, attendees, calendar) — Change an iCloud Calendar event: title, startDate/endDate, isAllDay, location, notes, url ("" clears), alarms, attendees (full new list), calendar (moves it). — asks for confirmation when attendees are involvedapple_calendar_delete_event(eventId, span, timeZone) — Delete an iCloud Calendar event. Recurring: span thisEvent (default; the one occurrence an "#occ=" id names), futureEvents (it and all later ones) or allEvents (the whole series). — asks for confirmationapple_calendar_find_free_time(fromDate, toDate, daysAhead, minDurationMinutes, workdayStart, workdayEnd, weekdaysOnly, includeAllDay, calendars, timeZone) — Find free time in your iCloud calendars: open slots per day within working hours (workdayStart/workdayEnd, default 09:00–17:00, weekdays only by default) at least minDurationMinutes long (default 30).apple_contacts_search(query, group, limit, offset) — Search the user's iCloud Contacts (address book) by name, nickname, company, job title, email, or phone number digits — optionally only within one contact group.apple_contacts_get(contactId, timeZone) — Get one iCloud contact in full by id (from apple_contacts_search): names, organization, job title, emails, phones, postal addresses and URLs — each with its label and an entryId that apple_contacts_update can target — birthday, note, the…apple_contacts_list_groups() — List the contact groups in iCloud Contacts (e.g. Family, Work): each group's id, name and member count.apple_contacts_create(givenName, familyName, middleName, nickname, organization, department, jobTitle, note, birthday, emails, phones, urls, addresses) — Create a new contact in iCloud Contacts. Needs a givenName, familyName or organization; optional middleName, nickname, department, jobTitle, note, birthday (YYYY-MM-DD, or --MM-DD without a year), and lists of emails, phones, urls and po…apple_contacts_update(contactId, givenName, familyName, middleName, nickname, organization, department, jobTitle, note, birthday, emails, phones, urls, addresses) — Edit an existing iCloud contact in place. Scalar fields (givenName, familyName, middleName, nickname, organization, department, jobTitle, note, birthday) replace the current value; "" clears it.apple_contacts_delete(contactId) — Permanently delete one contact from iCloud Contacts (on every device) by id. — asks for confirmationapple_mail_list_mailboxes(counts) — List the iCloud Mail mailboxes (folders): path, name, special use (inbox, sent, drafts, trash, junk, archive) and, by default, message and unread counts.apple_mail_search(mailbox, from, to, subject, text, since, before, unread, flagged, limit, offset, timeZone) — Search emails in one iCloud Mail mailbox (default INBOX) by sender, recipient, subject, full text, received date range, unread and flagged state.apple_mail_get_message(mailbox, uid, uidValidity, maxChars, timeZone) — Read one iCloud Mail message by uid (from apple_mail_search): headers (from, to, cc, reply-to, date, subject, message-id), the body as plain text (HTML converted to readable text when there is no text part), a truncated flag, and attachm…apple_mail_send(to, cc, bcc, subject, body, inReplyTo, quoteOriginal, timeZone) — Send a plain-text email from your iCloud Mail address (to/cc/bcc, subject, body; no attachments). — asks for confirmationapple_mail_update_flags(mailbox, uids, uidValidity, seen, flagged) — Mark iCloud Mail messages read or unread, and flag or unflag them, by uid (1–100 uids from apple_mail_search, one mailbox).apple_mail_move(mailbox, uids, uidValidity, destination) — Move iCloud Mail messages (1–100 uids from apple_mail_search, one mailbox) to another mailbox: a path from apple_mail_list_mailboxes or an alias (inbox, archive, trash, junk, sent, drafts).apple_maps_geocode(address, limitToCountries, near, lang, view) — Turn an address or place name into coordinates with Apple Maps (geocoding).apple_maps_reverse_geocode(latitude, longitude, lang, view) — Find the street address at a latitude/longitude with Apple Maps (reverse geocoding) — e.g. "where is 37.33,-122.01?".apple_maps_search(query, near, categories, resultTypes, limitToCountries, lang, pageToken, view) — Search Apple Maps for places: businesses, points of interest, addresses, landmarks (e.g. "coffee", "EV charger", "Golden Gate Bridge").apple_maps_directions(origin, destination, transportType, departureDate, arrivalDate, timeZone, avoidTolls, alternateRoutes, near, lang, view) — Driving, walking or cycling directions between two places with Apple Maps (addresses or "lat,lng").apple_maps_etas(origin, destinations, transportType, departureDate, arrivalDate, timeZone, view) — Travel time and distance from one point to up to 10 destinations at once with Apple Maps — driving with live traffic, transit, walking or cycling (e.g. "which of these stores is closest by car?").apple_maps_lookup_place(placeIds, lang, view) — Look up Apple Maps places by place id — the id field from apple_maps_search, apple_maps_geocode or apple_maps_reverse_geocode results — 1 to 50 at once.apple_maps_snapshot_url(center, annotations, zoom, size, scale, mapType, colorScheme, showPointsOfInterest, lang, expiresInMinutes) — Make a signed link to a static Apple Maps image (PNG): centred on an address or "lat,lng", and/or with pins (each with an optional label, colour and one-character glyph; the map fits the pins when no center is given).apple_weather_get(latitude, longitude, dataSets, hours, days, timeZone, countryCode, units, lang, view) — Weather forecast for a place from Apple Weather (WeatherKit): current conditions, hourly (up to 240 h), daily (up to 10 days), next-hour rain, severe-weather alerts (need countryCode).apple_weather_get_alert(alertId, lang, timeZone, view) — Get one severe-weather alert's full official text from Apple Weather (WeatherKit), unmodified, by its id (the alerts[].id from apple_weather_get called with countryCode).apple_itunes_search(term, media, entity, attribute, country, limit, offset, explicit, lang, view) — Search Apple's iTunes Store catalog — songs, albums, artists, podcasts and podcast episodes, audiobooks, apps and ebooks — with no Apple account or key.apple_itunes_lookup(ids, upc, isbn, bundleId, entity, limit, offset, sort, country, view) — Look up iTunes Store items (no Apple account or key) by ids — 1–200 trackId/collectionId/artistId values, e.g. from apple_itunes_search or an Apple Music link — or by one UPC/EAN (album), ISBN (book) or bundleId (app).apple_charts_get(chart, storefront, limit, offset, view) — Apple's current top charts (no Apple account or key): most-played songs, albums, music videos and playlists on Apple Music; top podcasts, trending podcast episodes and top subscriber channels; top free/paid apps and books; top audiobooks.