๐ strands-icloud
One Strands tool for the entire Apple ecosystem. Mail, Calendar, Messages, Contacts, Photos, Notes, Reminders, Find My โ local-first on macOS, remote-capable via standard protocols, exposable over MCP.
Built for Strands Agents. Battle-tested inside devduck.
use_apple(action="messages.search", query="flight")
use_apple(action="mail.unread", limit=10)
use_apple(action="photos.search", query="drone") # โ returns REAL image blocks the model can SEE
use_apple(action="findmy.locate", device="iPhone")
Table of Contents
- Architecture
- Installation
- CLI
- Permissions Setup (macOS)
- Credentials & Keychain
- Action Reference
- MCP Server
- Parameter Reference
- Response Format
- Design Decisions
- Performance Notes
- Troubleshooting
- Security Model
- Known Limitations
Architecture
Two access layers, one dispatch surface:
flowchart TB
A["๐ use_apple(action=...)"]:::hub
A --> L
A --> R
A --> C
subgraph L["๐ฅ LOCAL ยท on-Mac ยท zero auth"]
direction TB
AS["AppleScript bridge<br/>Mail ยท Calendar ยท Contacts<br/>Notes ยท Reminders ยท Messages (send)"]
FS["Direct file access<br/>chat.db (SQLite, read-only)<br/>Photos library (osxphotos)"]
end
subgraph R["๐ REMOTE ยท anywhere ยท app-specific password โ"]
direction TB
IMAP["IMAP :993<br/>imap.mail.me.com"]
CAL["CalDAV<br/>caldav.icloud.com"]
CARD["CardDAV<br/>contacts.icloud.com"]
end
subgraph C["โ๏ธ CLOUD ยท pyicloud ยท real password + 2FA"]
FM["Find My<br/>devices ยท locate ยท play sound"]
end
classDef hub fill:#0a84ff,stroke:#0a84ff,color:#fff,font-weight:bold
classDef default fill:#1c1c1e,stroke:#3a3a3c,color:#f5f5f7
style L fill:#0e2a12,stroke:#32d74b,color:#f5f5f7
style R fill:#0b1f33,stroke:#0a84ff,color:#f5f5f7
style C fill:#2a0e1a,stroke:#ff375f,color:#f5f5f7
flowchart LR
subgraph clients["Consumers"]
DD["๐ฆ devduck<br/>(pipx inject)"]
SA["Strands Agent<br/>(pip install)"]
CC["Claude Code / Desktop<br/>Cursor ยท Kiro<br/>(MCP)"]
TERM["Terminal<br/>(uvx strands-icloud)"]
end
DD --> UA["use_apple"]
SA --> UA
CC -->|"strands-icloud-mcp<br/>stdio / HTTP"| UA
TERM -->|"CLI"| UA
classDef default fill:#1c1c1e,stroke:#3a3a3c,color:#f5f5f7
style UA fill:#0a84ff,stroke:#0a84ff,color:#fff,font-weight:bold
style clients fill:#000,stroke:#3a3a3c,color:#98989d
Why local-first? Your Mac already syncs everything via iCloud. Reading local data means zero auth, zero rate limits, zero Apple-breaking-the-API risk, and full history (Messages back to day one). Remote protocols are the fallback for headless/off-Mac deployments; pyicloud is only used where there is no local equivalent (Find My).
Module layout
strands_icloud/
โโโ __init__.py # exports use_apple
โโโ use_apple.py # @tool dispatch + all local backends (~850 lines)
โโโ remote.py # IMAP / CalDAV / CardDAV clients (stdlib imaplib + caldav + raw DAV)
โโโ mcp.py # MCP server entrypoint (strands-icloud-mcp)
โโโ cli.py # terminal CLI (strands-icloud / uvx strands-icloud)
Installation
Into devduck (pipx)
pipx inject devduck git+ssh://git@github.com/cagataycali/strands-icloud.git
# or from a local clone:
pipx inject devduck /path/to/strands-icloud
Register the tool (add to ~/.zshrc):
export DEVDUCK_TOOLS="$DEVDUCK_TOOLS;strands_icloud:use_apple"
Standalone (any Strands agent)
pip install git+ssh://git@github.com/cagataycali/strands-icloud.git
from strands import Agent
from strands_icloud import use_apple
agent = Agent(tools=[use_apple])
agent("what's on my calendar this week?")
Dependencies
| Package | Used for | Required? |
|---|---|---|
strands-agents |
@tool decorator |
yes |
osxphotos |
Photos library access | photos.* only |
pyicloud |
Find My | findmy.* only |
caldav |
CalDAV calendar client | caldav.* only |
keyring |
macOS Keychain credential lookup | optional (falls back to env) |
strands-mcp-server |
MCP entrypoint | MCP only |
Everything imports lazily โ a missing optional dep only disables its domain, never the whole tool.
CLI
Every action, straight from your terminal โ no agent required. Ships as the strands-icloud console script:
# zero-install via uv (private repo โ use --from git+ssh)
uvx --from git+ssh://git@github.com/cagataycali/strands-icloud.git strands-icloud reminders.list
# short alias once published to PyPI
uvx strands-icloud reminders.list
# or just use the installed script (pipx/pip)
strands-icloud messages.search --query flight
Examples
# Messages
strands-icloud messages.chats -n 10
strands-icloud messages.search -q "baklava"
strands-icloud messages.send --to "+15517274110" --text "hey from the terminal"
# Mail โ local (Mail.app) or remote (IMAP, faster on big inboxes)
strands-icloud mail.unread -n 10
strands-icloud imap.search -q invoice --folder INBOX -n 5
strands-icloud imap.read -q 4762 # read by message ID
# Calendar โ local or CalDAV (syncs to all devices)
strands-icloud calendar.events --days 14
strands-icloud caldav.create --title "Dentist" --start "2026-07-25 14:30" --calendar Home
# Photos โ save image files locally
strands-icloud photos.search --label dog -n 3 --save ./out
strands-icloud photos.recent -n 5 --no-images # metadata only
# Everything else
strands-icloud contacts.search -q mom
strands-icloud notes.read -q "meeting"
strands-icloud findmy.locate --device iPhone
strands-icloud actions # list every available action
strands-icloud mcp --http --port 8010 # start the MCP server
# Machine-readable output
strands-icloud reminders.list --json | jq '.content[0].text'
CLI flags
| Flag | Maps to | Notes |
|---|---|---|
--query / -q |
query |
search text or message/note ID |
--limit / -n |
limit |
default 20 |
--chat / --folder |
chat |
chat filter (messages) or IMAP folder |
--calendar |
calendar_name |
|
--save DIR |
โ | write photo images to disk |
--no-images |
with_images=False |
metadata only, saves tokens/time |
--json |
โ | structured output (image bytes omitted) |
| all others | same-named param | --to --text --subject --body --title --start --end --due --days --person --label --device --from-date --to-date |
Exit code is 0 on success, 1 on error โ safe for scripting.
Permissions Setup (macOS)
macOS gates each data source separately. You need:
1. Full Disk Access (required: Messages, speeds up Mail)
System Settings โ Privacy & Security โ Full Disk Access โ add the app that hosts the Python process:
- Running in Terminal/iTerm/Ghostty โ add that terminal app
- Running as a launchd service โ add the Python binary itself
- Running inside an IDE โ add the IDE
Restart the process after granting. Without FDA, messages.* fails with unable to open database file.
2. Automation permissions (per-app, auto-prompted)
First time you call each domain, macOS shows "...wants to control Mail.app" โ click OK. One prompt per (host app ร target app) pair. These land in System Settings โ Privacy & Security โ Automation.
If you accidentally denied one:
tccutil reset AppleEvents # resets ALL automation grants
3. Photos library access
osxphotos reads the Photos SQLite directly โ covered by Full Disk Access. Export of edited/iCloud-offloaded originals may trigger a Photos permission prompt on first use.
Credentials & Keychain
App-specific password (IMAP / CalDAV / CardDAV)
Generate at account.apple.com โ Sign-In and Security โ App-Specific Passwords. Format: xxxx-xxxx-xxxx-xxxx.
Store it in macOS Keychain (recommended):
security add-generic-password -a "you@icloud.com" -s "strands-icloud" -w "xxxx-xxxx-xxxx-xxxx"
Then only the username goes in your shell config:
# ~/.zshrc
export ICLOUD_USERNAME="you@icloud.com"
Credential resolution order for remote protocols:
ICLOUD_PASSWORDenv var (if set โ e.g. CI, containers)- Keychain service
strands-icloud(viakeyring) - Keychain service
pyicloud(legacy compat) - โ error with instructions
Real password (Find My only)
pyicloud drives the iCloud web API, which uses Apple's GSA/SRP handshake โ app-specific passwords do not work there. If you want Find My:
security add-generic-password -a "you@icloud.com" -s "strands-icloud-real" -w "YOUR_REAL_PASSWORD"
Resolution order: ICLOUD_PASSWORD_REAL env โ keychain strands-icloud-real โ keychain pyicloud.
First login triggers 2FA once (run any findmy.* action interactively, or use the icloud CLI that ships with pyicloud). The session cookie is cached in ~/.pyicloud and lasts ~weeks.
Action Reference
Every action returns {"status": "success"|"error", "content": [{"text": ...}, ...]}. Photos actions append image blocks after the text block.
๐ฌ Messages
Backend: direct SQLite read of ~/Library/Messages/chat.db (opened mode=ro โ never locks Messages.app), AppleScript for sending. Full history, fast, works even if Messages.app is closed.
| Action | Params | Description |
|---|---|---|
messages.list |
chat (optional filter: name/number/email substring), limit |
Recent messages, chronological. chat matches chat_identifier, display_name, or handle |
messages.search |
query (required), limit |
Full-text LIKE search over all message text, all time |
messages.chats |
limit |
Conversations sorted by most recent activity, with message counts |
messages.send |
to (phone/email), text |
Sends via Messages.app. Tries iMessage participant first, falls back to generic buddy (SMS relay if configured) |
use_apple(action="messages.list", chat="+31638236164", limit=50)
use_apple(action="messages.search", query="baklava")
use_apple(action="messages.send", to="cagataycali@icloud.com", text="hey from my agent")
Timestamps are converted from Apple epoch (nanoseconds since 2001-01-01) automatically.
๐ง Mail (local โ Mail.app)
Backend: AppleScript. Mail.app must be running (open -gja Mail launches it hidden/background).
| Action | Params | Description |
|---|---|---|
mail.unread |
limit |
Unread from inbox. Scans newestโoldest, capped at 400 most recent (see Performance) |
mail.search |
query (required), limit |
Subject OR sender contains query. Uses Mail's whose filter โ slow on huge inboxes |
mail.read |
query (subject substring) |
Full body (plain text) of first matching email |
mail.send |
to, subject, body |
Composes and sends immediately via default account |
use_apple(action="mail.unread", limit=10)
use_apple(action="mail.read", query="Run failed: CI")
use_apple(action="mail.send", to="x@y.com", subject="hi", body="sent by agent")
๐ Calendar (local โ Calendar.app)
Backend: AppleScript across all calendars.
| Action | Params | Description |
|---|---|---|
calendar.events |
days (default 7), limit |
Upcoming events across every calendar |
calendar.create |
title, start (YYYY-MM-DD HH:MM), end (optional, default +1h), calendar_name (optional, default first writable) |
Creates event |
use_apple(action="calendar.events", days=14)
use_apple(action="calendar.create", title="Dentist", start="2026-07-25 14:30", calendar_name="Home")
๐ค Contacts (local โ Contacts.app)
| Action | Params | Description |
|---|---|---|
contacts.search |
query (name substring), limit |
Name, all phones, all emails |
๐ผ Photos โ osxphotos with image blocks
Backend: osxphotos reading the Photos library database directly. The killer feature: results include Bedrock Converse-API image content blocks, so the model literally sees the photos (same mechanism as strands_tools.image_reader).
| Action | Params | Description |
|---|---|---|
photos.search |
query, person, label, from_date/to_date (YYYY-MM-DD), limit, with_images |
All filters AND-combined. query matches filename/title/description/labels/persons/albums. person = Photos face names. label = Apple's on-device ML labels (e.g. "Baklava", "Document", "Sea") |
photos.recent |
limit, with_images |
Newest photos |
photos.albums |
โ | All album names |
use_apple(action="photos.search", person="mom", from_date="2026-01-01")
use_apple(action="photos.search", label="dog", limit=5)
use_apple(action="photos.recent", limit=3, with_images=False) # metadata only
Image pipeline: export original โ if HEIC/oversized, convert via sips to JPEG (quality 80, max edge 1600px) โ attach as {"image": {"format": ..., "source": {"bytes": ...}}}. Hard caps: max 5 images per response, 4 MB per image (context window protection). Exports land in /tmp/apple_photos_export/.
๐ Notes โ Notes.app
| Action | Params | Description |
|---|---|---|
notes.list |
limit |
Titles + modification dates (default account) |
notes.read |
query (title substring) |
Full plaintext of first match |
notes.create |
title, body |
New note in default account |
โ๏ธ Reminders โ Reminders.app
| Action | Params | Description |
|---|---|---|
reminders.list |
limit |
Incomplete reminders with due dates |
reminders.create |
title, due (optional) |
New reminder. Due date support is limited by AppleScript date quirks โ title always works |
๐ฑ Find My โ pyicloud
Requires real Apple ID password (see Credentials). Session cached after first 2FA.
| Action | Params | Description |
|---|---|---|
findmy.devices |
โ | All devices: name, model, battery %, coordinates |
findmy.locate |
device (name substring) |
Coordinates + Apple Maps link + accuracy + timestamp |
findmy.play_sound |
device |
Ping the device (the classic "find my phone in the couch") |
use_apple(action="findmy.locate", device="iPhone")
# ๐ รaฤatay's iPhone: (52.37403, 4.88969)
# https://maps.apple.com/?ll=52.37403,4.88969
๐ IMAP (remote โ imap.mail.me.com)
Backend: Python stdlib imaplib, SSL port 993. Works from any machine โ Linux server, container, CI. App-specific password is sufficient.
| Action | Params | Description |
|---|---|---|
imap.folders |
โ | List all mailboxes (INBOX, Archive, Sent Messages, ...) |
imap.search |
query, chat (=folder, default INBOX), limit |
Searches SUBJECT OR FROM OR BODY. Returns message IDs for imap.read |
imap.unread |
chat (=folder), limit |
UNSEEN messages |
imap.read |
query (=message ID from search results), chat (=folder) |
Full body. Prefers text/plain, falls back to tag-stripped HTML. All fetches use BODY.PEEK โ never marks messages as read |
Note:
chatis reused as the folder parameter to keep the tool signature lean.
๐ CalDAV (remote โ caldav.icloud.com)
| Action | Params | Description |
|---|---|---|
caldav.calendars |
โ | List calendars |
caldav.events |
days, limit |
Upcoming events across all calendars, expanded recurrences |
caldav.create |
title, start, end, calendar_name |
Create event โ syncs to all your Apple devices in seconds |
๐ค CardDAV (remote โ contacts.icloud.com)
| Action | Params | Description |
|---|---|---|
carddav.contacts |
query (optional name filter), limit |
Full addressbook via raw DAV: PROPFIND principal discovery โ addressbook-home-set โ REPORT addressbook-query โ vCard parse (FN/TEL/EMAIL) |
MCP Server
Everything above, exposed over the Model Context Protocol โ usable from Claude Code, Claude Desktop, Kiro, Cursor, or any MCP client. Pattern borrowed from strands-cad.
strands-icloud-mcp # stdio (default โ for desktop clients)
strands-icloud-mcp --http --port 8010 # streamable HTTP (multi-client)
strands-icloud-mcp --http --stateless # stateless HTTP (horizontally scalable)
strands-icloud-mcp --agent-invocation # also expose invoke_agent (full conversations)
strands-icloud-mcp --debug # verbose logging (stderr)
Claude Code
claude mcp add apple -- strands-icloud-mcp
Claude Desktop
{
"mcpServers": {
"apple": {
"command": "strands-icloud-mcp"
}
}
}
If installed inside a pipx venv, use the absolute path:
~/.local/pipx/venvs/devduck/bin/strands-icloud-mcp.
Implementation notes (learned the hard way in strands-cad)
- stdout is sacred in stdio mode โ it's the protocol channel. All logging goes to stderr.
- The server calls the raw tool function (
mcp_server._tool_func), notagent.tool.mcp_server(...). Going throughagent.tool.*marks the agent as mid-invocation; since stdio blocks forever, every nested tool call would then be rejected by the SDK. --agent-invocationis off by default: tools-only surface. Enable it to let MCP clients run full agentic conversations against an embedded Strands agent.
Verified handshake
initialize โ serverInfo: strands-agent (1.27.x)
tools/list โ ["use_apple"]
tools/call use_apple(action="reminders.list")
โ โ๏ธ 3 open reminders: ...
Parameter Reference
Full signature โ every param is optional except action:
| Param | Type | Default | Used by |
|---|---|---|---|
action |
str | โ | everything (required) |
query |
str | None | search actions, mail.read, notes.read, imap.read (=msg ID) |
to |
str | None | messages.send, mail.send |
text |
str | None | messages.send |
subject, body |
str | None | mail.send, notes.create |
title |
str | None | calendar.create, notes.create, reminders.create, caldav.create |
chat |
str | None | messages.list (chat filter), imap.* (folder name) |
person, label |
str | None | photos.search |
device |
str | None | findmy.* |
calendar_name |
str | None | calendar.create, caldav.create |
start, end |
str | None | event creation, YYYY-MM-DD HH:MM |
due |
str | None | reminders.create |
from_date, to_date |
str | None | photos.search, YYYY-MM-DD |
days |
int | 7 | calendar.events, caldav.events |
limit |
int | 20 | all list/search actions |
with_images |
bool | True | photos.* โ set False for metadata-only (saves tokens) |
Response Format
# text-only actions
{
"status": "success",
"content": [{"text": "๐ง 5 unread:\n- [...] ..."}]
}
# photos with images โ text block first, then image blocks
{
"status": "success",
"content": [
{"text": "๐ผ 3 photos:\n- IMG_4321.HEIC | 2026-07-21 12:59 | labels: Baklava, ..."},
{"image": {"format": "jpeg", "source": {"bytes": b"..."}}},
...
]
}
# errors are never raised โ always structured
{
"status": "error",
"content": [{"text": "chat.db not found at ..."}]
}
Design Decisions
- One mega-tool, dot-namespaced actions (
use_apple(action="messages.search")) instead of 25 separate tools. Keeps the agent's tool list small, matches theuse_aws/use_spotify/adbconvention, and lets one docstring teach the model the entire surface. - Local-first, remote-fallback. AppleScript + direct file reads beat any network API for latency, history depth, and reliability. Remote protocols exist for off-Mac deployment of the same tool.
- Read-only by default at the storage layer. chat.db opens with
?mode=ro; IMAP fetches useBODY.PEEK. Writes only happen through explicit send/create actions via Apple's own apps/APIs. - Graceful degradation. Optional deps import lazily inside the action branch. No osxphotos? Photos actions error cleanly with install instructions; everything else works.
- Structured errors, never exceptions. The agent can read the failure and route around it (e.g., fall back from
mail.unreadtoimap.unread). - Image budget. Max 5 images ร โค4 MB, auto-downscaled to 1600px JPEG q80. A photo dump should never blow up the context window.
Performance Notes
| Operation | Cost | Notes |
|---|---|---|
messages.* (read) |
~10 ms | Direct SQLite, indexed |
mail.unread |
2โ30 s | AppleScript iteration, newest-first, capped at 400 recent messages. The naive whose read status is false filter took >120 s on a 16k inbox โ that's why it scans instead |
mail.search |
10 sโ3 min | Uses Mail's whose filter (server-side in Mail), acceptable but not instant on big inboxes. Prefer imap.search for speed |
imap.search |
1โ3 s | iCloud does the searching |
calendar.events |
5โ60 s | AppleScript iterates every calendar; slow with many calendars. caldav.events is usually faster |
photos.search |
5โ30 s first call | osxphotos loads the library DB once per call; big libraries pay upfront. Filtering itself is in-memory and fast |
caldav/carddav |
1โ5 s | Plain HTTPS |
Rules of thumb: Messages โ local always. Mail search โ IMAP. Calendar list โ CalDAV. Photos โ local (only option). Sends โ local (Apple handles delivery).
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
unable to open database file on messages.* |
No Full Disk Access | Grant FDA to host app, restart the process |
Timeout on mail.* |
Mail.app not running or gigantic inbox | open -gja Mail, wait for index; use imap.* instead |
Not authorized to send Apple events |
Automation permission denied | System Settings โ Automation, or tccutil reset AppleEvents |
PyiCloudFailedLoginException on findmy.* |
Using app-specific password | pyicloud needs the real password (keychain strands-icloud-real) |
| 2FA loop on findmy | Expired session | Re-auth interactively once; check ~/.pyicloud is writable |
imap.* AUTHENTICATIONFAILED |
Bad/revoked app-specific password | Regenerate at account.apple.com, update keychain entry |
| Photos export returns nothing | Original offloaded to iCloud ("Optimize Mac Storage") | Tool retries with use_photos_export=True (slower, downloads); ensure disk space |
| Keychain prompt blocks headless run | keyring needs UI unlock | security unlock-keychain in session, or use env vars for that host |
| MCP client sees no tools | stdout polluted by a print | Run with --debug, check nothing but JSON-RPC goes to stdout |
Nuclear option for AppleScript weirdness: quit and relaunch the target app.
Security Model
- App-specific password (keychain
strands-icloud): grants mail/calendar/contacts via legacy protocols. Revocable at account.apple.com anytime without touching your real password. Cannot be used to log into iCloud web, change account settings, or access Find My. - Real password (keychain
strands-icloud-real, optional): only needed for Find My. Never written to disk by this tool; keychain access requires your login session. - No plaintext secrets in dotfiles: only
ICLOUD_USERNAMElives in~/.zshrc. - Local data never leaves the machine except as tool results into your model provider (mind what you query if using a cloud LLM โ that's the actual data boundary here).
- chat.db is opened read-only; the tool physically cannot modify or delete message history.
Known Limitations
- macOS only for local actions (AppleScript, chat.db, osxphotos). Remote actions (
imap.*,caldav.*,carddav.*) run anywhere Python does. reminders.createdue dates: AppleScript date construction is unreliable across locales; reminders are created without due dates for now.messages.sendrequires Messages.app signed in; SMS relay needs an iPhone with Text Message Forwarding enabled.mail.unreadscans the 400 most recent inbox messages โ unread mail older than that won't appear (useimap.unreadfor exhaustive).- Group chat display names in Messages may be empty (falls back to chat identifier).
- pyicloud is an unofficial client of a private API โ Apple can (and occasionally does) break it. Local + DAV paths are unaffected.
- HEIC โ JPEG conversion via
sipsloses HDR/depth metadata (irrelevant for model vision).
Development
git clone git@github.com:cagataycali/strands-icloud.git
cd strands-icloud
uv venv && source .venv/bin/activate
uv pip install -e .
# smoke test without an agent
python -c "
from strands_icloud.use_apple import use_apple
fn = getattr(use_apple, '_tool_func', use_apple)
print(fn(action='reminders.list', limit=3))
"
# reinject into devduck after changes
pipx inject devduck . --force
License
MIT ยฉ รaฤatay รalฤฑ
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file strands_icloud-0.1.0.tar.gz.
File metadata
- Download URL: strands_icloud-0.1.0.tar.gz
- Upload date:
- Size: 26.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bf558718002e0122caf399d34af30a5f0cc4e1b858513fcdb34a8b7c7f0c193f
|
|
| MD5 |
e7c9aa7c3796232eb9498102da920261
|
|
| BLAKE2b-256 |
99384c132bf666fd7f2108234f9589ed4116fa90b9a29db28ea5f1dd2d313acb
|
File details
Details for the file strands_icloud-0.1.0-py3-none-any.whl.
File metadata
- Download URL: strands_icloud-0.1.0-py3-none-any.whl
- Upload date:
- Size: 28.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0fa5f166616bb323671e881728df16c386e566ebfd0f0727022d26e947e6d90e
|
|
| MD5 |
dd3d1d54629af76edee06439b7977b30
|
|
| BLAKE2b-256 |
2563853a11c36e1cac58eb49e6c8e14b2f96004922fe5645afc7d5704303a8bb
|