Manage your family's calendars and lists in Cozi. View, create, and update appointments; organize…
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent — or use 1-click editor setup below.
We haven't yet run this listing's install command through our automated sandbox check. This isn't a red flag — we're steadily working through the catalog.
💡 Paste the JSON block into your client's configuration file under mcpServers, then restart the application.
An unofficial Model Context Protocol server that lets AI assistants like Claude read and update your Cozi Family Organizer lists and calendar.
Each user runs their own instance against their own Cozi account. Your credentials are stored in your MCP client's secure config (Claude Desktop's OS keychain, Smithery's encrypted session config, or your local environment) and never leave your machine — the author of this server has no access to your data.
Download the latest .mcpb from the Releases page and double-click to install in Claude Desktop. You'll be prompted for your Cozi username and password — they're stored securely in your OS keychain.
This path requires no Node, npm, or Python install on your machine.
For Cursor, ChatGPT-style clients, or web agents that connect to Smithery-hosted servers:
Configure your Cozi credentials in the Smithery UI; each session runs in isolation with its own credential set.
Add this to your Claude Desktop claude_desktop_config.json (or any other MCP client config file):
Requires Node 20+. The package will be downloaded on first run.
Set COZI_READ_ONLY=true to expose only read operations. In read-only mode, the server registers
family_members, get_lists, get_list_items, and get_calendar; tools that create, update, or
delete Cozi data are hidden from MCP clients. Omit the variable, or set it to any value other than
1, true, yes, or on, for the default read-write tool surface.
COZI_USERNAME and COZI_PASSWORD are read once, when the server process
starts. Editing them in your MCP client's settings updates the stored config but
does not reach a server that is already running — it keeps presenting the old
credentials until it is respawned.
Fully quit and relaunch your MCP client (on macOS, Cmd-Q rather than closing the window). Reloading, reconnecting, or toggling the extension off and on is usually not enough.
The running server advertises its version in the MCP handshake; your client
displays it (Claude Desktop: Settings > Extensions). That is independent of what
is in your working tree — installing an MCPB installs whatever is inside the
.mcpb file, which is only as current as the last npm run bundle:mcpb. Build
the bundle immediately before installing it, or install from a GitHub release.
Five consecutive failed authentications for a username trigger an exponential backoff, capped at 15 minutes; the message states the remaining wait. The counter lives in process memory, so restarting the client clears it.
Cozi has no OAuth — username/password authentication is the only way the API supports. This server handles that fact honestly:
https://rest.cozi.com.rest.cozi.com for the same endpoints the Cozi web app uses (auth, lists, calendar, family members). The full request/response code lives in src/cozi/ — about 500 lines of TypeScript you can audit yourself.@mjucius/cozi-mcp@2.0.0) if you want a stable target, or fork the repo and run your own build if you want zero supply-chain trust.This is a single-user server by design. The Cozi credential holder is the principal — there is no separate per-caller authentication gate, because each user runs their own instance against their own Cozi account. Concretely:
COZI_USERNAME / COZI_PASSWORD (or the OS keychain entry) is treated as the account owner. The trust boundary is your machine and its user account.Two defensive measures narrow the blast radius of that model:
The server exposes 12 tools by default, or 4 read-only tools when COZI_READ_ONLY=true (or
Smithery/MCPB read-only config) is enabled. Returns are slim dicts with null/empty fields omitted.
family_members() → [{id, name, color?}] — call this first to get attendee IDs for appointments.get_lists(list_type?) → [{id, title, type, item_count, completed_count}] — list_type is optional, 'shopping' or 'todo'.get_list_items(list_id, include_completed=false) → [{id, text, status, position?}].create_list(name, list_type) → {id, title, type}.delete_list(list_id) → boolean.create_list and delete_list are hidden in read-only mode.
add_item(list_id, text, position=0) → {id, text}.update_item(list_id, item_id, text?, completed?) → {id, text, status} — pass either or both. Non-atomic when both are passed: the text is updated first, then the status.remove_items(list_id, item_ids) → boolean.All item tools are hidden in read-only mode.
get_calendar(year, month) → [{id, subject, day, all_day, start?, end?, end_day?, attendees?, location?, notes?}]. day is always the start day; end_day appears only on multi-day events, which Cozi lists in every month they overlap (so day may fall outside the month you asked for).create_appointment(subject, start, end, attendees?, all_day=false, notes='', location?) — start and end are ISO datetimes (e.g. '2026-06-15T10:00:00'). For all-day events (all_day=true) a bare date (e.g. '2026-06-15') is also accepted and end may equal start; a bare date on a timed event is an error. Put end on a later date for a multi-day event; the result reports the span as end_day. An end before start is an error.update_appointment(appointment_id, year, month, ...) — partial update via fetch-then-merge: pass (appointment_id, year, month) plus any fields to change. Omitted fields are preserved. To switch a timed appointment to all-day pass all_day=true; to switch to timed pass new start/end. Passing end re-spans the event against its (possibly newly set) start day, so an end on a later date makes it multi-day and one on the start day collapses it back; passing start alone moves the event and keeps its length. A bare date is accepted for start/end when the event is, or is being made, all-day; on a timed event it is an error.delete_appointment(appointment_id, year, month) → boolean.create_appointment, update_appointment, and delete_appointment are hidden in read-only mode.
When creating or updating appointments with specific attendees, call family_members() first and use those id values in the attendees arg. Calendar tools are scoped to a (year, month) page — pass the same year/month back when updating or deleting an appointment from that page.
v2.0 is a Node/TypeScript rewrite of the previous Python implementation, distributed as MCPB / npx / Smithery. The runtime changed AND the tool surface was consolidated — if you have prompts written against v1, update them as follows:
| v1 (Python, 14 tools) | v2 (Node, 12 tools) |
|---|---|
get_family_members | family_members |
get_lists_by_type(t) | get_lists(list_type=t) |
update_item_text(...) + mark_item(...) | update_item(text?, completed?) (merged) |
add_item(list_id, item_text, ...) | add_item(list_id, text, ...) (param renamed) |
update_appointment(appointment_obj) | update_appointment(appointment_id, year, month, ...partial) |
update_list (item reordering) | removed |
delete_appointment(id) | delete_appointment(id, year, month) |
get_lists returned nested items | now summary only — fetch items via get_list_items(list_id) |
Factual signals from GitHub, npm, and our automated checks — not a rating.
No reviews yet — be the first to share how this listing worked for you.
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/mjucius-cozi-mcp)<a href="https://allmcps.com/mcp/mjucius-cozi-mcp"><img src="https://allmcps.com/api/badge/mjucius-cozi-mcp?style=directory" alt="Mjucius Cozi MCP on AllMCPs" /></a>