mcpField
M
mjucius-cozi_mcp

mjucius-cozi_mcp

远程服务
github.com/mjucius生产力62 周前更新
代码仓库

关于 mjucius-cozi_mcp

mjucius-cozi_mcp 是非官方 MCP 服务,让 AI 助手读取和更新 Cozi 家庭日历与清单。每位用户在本机运行自己的实例,凭据保存在客户端安全配置中;还可启用只读模式。

主要功能

  1. 01读取家庭成员与清单
  2. 02创建和管理清单项目
  3. 03查看及搜索日历
  4. 04创建、更新和删除日程
  5. 05支持只读工具模式

适用场景

  1. 01查询家庭成员的日程安排
  2. 02维护购物清单和待办事项
  3. 03添加或调整家庭活动
  4. 04仅开放日历与清单读取权限

MCP 相关

该 MCP 服务向客户端提供 Cozi 家庭成员、清单和日历工具,并可执行日程与清单更新。设置只读模式后,仅暴露读取工具。

配置

远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。

服务地址https://server.smithery.ai/@mjucius/cozi_mcp/mcp
一键复制安装命令
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。

全部服务地址
Streamable HTTPhttps://server.smithery.ai/@mjucius/cozi_mcp/mcp需要授权

工具

详细介绍

Cozi MCP 徽标

Cozi MCP 服务

一个非官方的 Model Context Protocol 服务,可让 Claude 等 AI 助手读取和更新你的 Cozi Family Organizer 清单和日历。

每位用户都使用自己的 Cozi 账户运行独立实例。你的凭据存储在 MCP 客户端的安全配置中(Claude Desktop 的操作系统钥匙串或本地环境),不会离开你的设备——本服务的作者无法访问你的数据。

安装

1. MCPB(推荐用于 Claude Desktop)

从 Releases 页面下载最新的 .mcpb,然后双击在 Claude Desktop 中安装。系统会提示你输入 Cozi 用户名和密码——它们会安全地存储在操作系统钥匙串中。

此方式无需在设备上安装 Node、npm 或 Python。

2. npx(适用于其他 MCP 客户端)

将以下内容添加到 Claude Desktop 的 claude_desktop_config.json(或其他 MCP 客户端配置文件)中:

{
  "mcpServers": {
    "cozi": {
      "command": "npx",
      "args": ["-y", "@mjucius/cozi-mcp"],
      "env": {
        "COZI_USERNAME": "[email protected]",
        "COZI_PASSWORD": "your-password",
        "COZI_READ_ONLY": "true"
      }
    }
  }
}

需要 Node 20+。首次运行时会下载该软件包。

设置 COZI_READ_ONLY=true 可仅开放读取操作。在只读模式下,服务会注册 family_members、get_lists、get_list_items、get_calendar、search_calendar 和 today;创建、更新或 删除 Cozi 数据的工具不会向 MCP 客户端开放。若要使用默认的读写工具集,请省略此变量,或将其设置为除 1、true、yes 或 on 以外的任意值。

故障排除

修改密码后,工具仍提示“Authentication failed”

COZI_USERNAME 和 COZI_PASSWORD 只会在服务进程启动时读取一次。在 MCP 客户端的设置中修改它们,只会更新已存储的配置,无法传递给已经运行的服务——在服务重新启动之前,它会继续使用旧凭据。

完全退出并重新启动 MCP 客户端(在 macOS 上,请按 Cmd-Q,而不是关闭窗口)。重新加载、重新连接或关闭后再启用扩展通常都不够。

如何确认当前实际运行的是哪个版本?

运行中的服务会在 MCP 握手时声明其版本;客户端会显示该版本(Claude Desktop:Settings > Extensions)。这与工作目录中的版本无关——安装 MCPB 时,安装的是 .mcpb 文件中的内容,而其内容是否最新取决于最近一次运行 npm run bundle:mcpb 的时间。请在安装前立即构建安装包,或从 GitHub 发布版本安装。

多次失败后,开始提示“Too many failed login attempts”

同一用户名连续 5 次认证失败会触发指数退避,最长为 15 分钟;提示信息会说明剩余等待时间。计数器保存在进程内存中,因此重启客户端即可清除。

信任与安全

Cozi 不支持 OAuth——用户名和密码认证是其 API 唯一支持的方式。本服务如实处理这一情况:

  • 架构上按用户隔离。 每位用户都使用自己的 Cozi 账户运行独立实例。没有共享后端、代理或多租户数据库。本服务的作者永远无法看到任何人的凭据或数据。
  • 凭据只存储在 MCP 客户端的安全配置中。 Claude Desktop 会将凭据存储在操作系统钥匙串中。npx 方式会从你自行设置的环境变量中读取凭据。本服务不会记录日志、写入磁盘,也不会将凭据发送到 https://rest.cozi.com 以外的任何位置。
  • API 接口范围受限。 本服务只会访问 rest.cozi.com,且仅使用 Cozi 网页应用所用的相同端点(认证、清单、日历、家庭成员)。所有请求和响应代码都位于 src/cozi/ 中,约 500 行 TypeScript 代码,可供你自行审查。
  • 开源,采用 MIT 许可证。 如果你需要稳定版本,可固定到特定版本(@mjucius/[email protected]);如果希望完全避免供应链信任问题,也可以复刻代码仓库并自行构建。
安全与信任模型

这是一个专为单用户设计的服务。Cozi 凭据持有者就是主体——没有单独的逐调用方身份验证关卡,因为每位用户都使用自己的 Cozi 账户运行自己的实例。具体来说:

  • **stdio(npx / MCPB)信任本地用户。**能够启动进程并读取已配置的 COZI_USERNAME / COZI_PASSWORD(或操作系统钥匙串条目)的任何人,都会被视为账户所有者。信任边界是你的机器及其用户账户。
  • **不支持多租户。**每位用户都使用自己的 Cozi 账户配置自己的实例。没有共享后端,也没有可被攻破的租户隔离机制;除持有有效 Cozi 凭据外,不进行逐调用方身份验证——这与 Cozi 网页应用本身采用的访问模型相同。

两项防御措施可缩小该模型下的影响范围:

  • **凭据缓存有时效限制。**经过身份验证的客户端只会在有限时长内缓存,因此轮换或撤销 Cozi 密码后,该密码会停止生效,而不会因过时的缓存会话而被无限期接受。
  • **限制登录失败频率。**对重复的身份验证失败尝试进行频率限制,以遏制针对 Cozi 端点的凭据猜测攻击。

工具

默认情况下,该服务会公开 15 个工具;启用 COZI_READ_ONLY=true(或 MCPB 只读设置)时,则会公开 6 个只读工具。返回值是精简的字典,会省略值为 null 或空的字段。

家庭
  • family_members() → [{id, name, color?}] — 先调用此工具,以获取预约所需的参与者 ID。
列表
  • get_lists(list_type?) → [{id, title, type, item_count, completed_count}] — list_type 是可选参数,可为 'shopping' 或 'todo'。
  • get_list_items(list_id, include_completed=false) → [{id, text, status, position?, header?}] — header: true 表示这是分区标题(例如“PRODUCE”),而不是条目。
  • create_list(name, list_type) → {id, title, type}。
  • rename_list(list_id, title) → {id, title, type} — 条目保持不变。
  • delete_list(list_id) → boolean。

只读模式下会隐藏 create_list、rename_list 和 delete_list。

条目
  • add_item(list_id, text, position=0) → {id, text}。
  • update_item(list_id, item_id, text?, completed?) → {id, text, status} — 可传入其中一个或两个参数。同时传入两个参数时不是原子操作:先更新文本,再更新状态。
  • remove_items(list_id, item_ids) → boolean。

只读模式下会隐藏所有条目工具。

日历
  • today() → {date, weekday, time, timezone} — 你设备上的当前本地时间。每个工具结果也会在末尾单独附上这一行,这样助手就能根据你的时钟,而不是自己的时钟(通常为 UTC),来判断“明天”。如果服务运行在其他设备上,请设置标准的 TZ 环境变量(例如 TZ=America/New_York)。
  • get_calendar(year, month) → [{id, subject, day, all_day, start?, end?, end_day?, attendees?, location?, notes?, reminders?, kind?, read_only?, source?, recurring?, recurrence?, series_start?, series_end?, skipped_days?}]。day 是日程发生的日期;只有跨多天的事件才会显示 end_day。Cozi 会在事件涉及的每个月中列出该事件,因此 day 可能不在你查询的月份内。每月的重复系列会按 Cozi 实际展开的日期逐次列出:每条记录都有系列 id、对应的 day(以及跨天时的 end_day)、series_start 和 recurrence(Cozi 对重复规则的描述)。在 Cozi 应用中删除的重复项不会列出,而会记录在 skipped_days 中;如果某个系列当月没有剩余重复项,则不会列出。kind 用于标记生日等非约会事项;read_only 事项(节假日、订阅日历中的事项,其名称由 source 指明)无法更改。reminders 表示开始前多少分钟提醒。
  • search_calendar(query) → {appointments: [...same fields, last_day?, next_days?], more?} — 使用 Cozi 自带的跨月搜索。对于重复系列,会返回最近一次过去的重复项和接下来的十次。Cozi 会从几年前开始搜索,新建的日程可能需要几秒钟才会显示。
  • create_appointment(subject, start, end, attendees?, all_day=false, notes='', location?, repeat?, reminders?, notify?) — start 和 end 是 ISO 日期时间(例如 '2026-06-15T10:00:00')。全天事件(all_day=true)也接受单独的日期(例如 '2026-06-15'),且 end 可以与 start 相同;定时事件使用单独的日期会报错。跨天事件的 end 必须设为较晚的日期;结果会通过 end_day 报告持续日期范围。end 早于 start 会报错。repeat 用于创建重复系列:{frequency: 'daily'|'weekly'|'monthly'|'yearly', interval?, weekdays?, monthly_by?: 'day_of_month'|'weekday', until?}(不设置 until 则会永远重复)。reminders 表示开始前多少分钟提醒,例如 [30, 1440]。
  • update_appointment(appointment_id, year, month, ...) — 通过先获取再合并进行部分更新:传入 (appointment_id, year, month) 以及需要更改的字段。未传入的字段会保留。若要将定时日程改为全天日程,请传入 all_day=true;若要改为定时日程,请传入新的 start/end。传入 end 会根据(可能是新设置的)开始日期重新计算事件跨度,因此将 end 设为较晚日期会使事件跨天,设为开始日期则会将其改回单日;只传入 start 会移动事件并保留其时长。若事件为全天事件或将改为全天事件,start/end 可使用单独的日期;定时事件使用单独的日期会报错。重复系列需要设置 scope:'this' 只更改 occurrence_day 当天的重复项(Cozi 会将更改后的副本存为单独的日程并返回),'this_and_following' 会更改该重复项及后续所有重复项(Cozi 会拆分该系列),'series' 会更改所有重复项。repeat 会替换系列的重复规则,或将一次性日程改为重复系列;reminders 会替换现有提醒([] 会清除提醒)。
  • delete_appointment(appointment_id, year, month, scope?, occurrence_day?, notify?) → boolean。如果该 ID 不在 (year, month) 对应的页面上,则会报错。重复系列需要设置 scope:'this' 会删除 occurrence_day 当天的重复项,'this_and_following' 会在该日期之前结束系列,'series' 会删除所有重复项。删除单次重复项后,会重新读取数据以确认 Cozi 已应用更改。 update_appointment 和 delete_appointment 不允许修改节假日、订阅的日历和生日。在任何日历写入操作中设置 notify=true,都会向已开启通知的参与者发送 Cozi 的变更通知(类似 Cozi 应用中的“通知”选项);默认关闭。

在只读模式下,create_appointment、update_appointment 和 delete_appointment 会被隐藏。

工作流提示

创建或更新包含特定参与者的日程时,请先调用 family_members(),并在 attendees 参数中使用返回的 id 值。日历工具的作用范围限于 (year, month) 页面——从该页面更新或删除日程时,请传入相同的 year/month。

从 v1(Python)迁移

v2.0 是对先前 Python 实现的 Node/TypeScript 重写版,以 MCPB 和 npx 形式分发。运行时发生了变化,工具接口也进行了整合——如果你有针对 v1 编写的提示词,请按以下方式更新:

v1(Python,14 个工具)v2(Node,12 个工具)
get_family_membersfamily_members
get_lists_by_type(t)get_lists(list_type=t)
update_item_text(...) + mark_item(...)update_item(text?, completed?)(已合并)
add_item(list_id, item_text, ...)add_item(list_id, text, ...)(参数已重命名)
update_appointment(appointment_obj)update_appointment(appointment_id, year, month, ...partial)
update_list(重新排列项目)已移除
delete_appointment(id)delete_appointment(id, year, month)
get_lists 返回嵌套项目现在仅返回摘要——通过 get_list_items(list_id) 获取项目

旧版 v1 Python 源代码保留在 Git 标签 v1.0.0 中,以供参考。

开发

需要 Node 20+(参见 .nvmrc)。

nvm use
npm install
npm test               # vitest, mocked at the CoziClient boundary; no credentials
npm run test:live      # live conformance suite against real Cozi (creds.env); required before a release
npm run typecheck
npm run build          # tsup → dist/
npm run dev            # local stdio dev with COZI_USERNAME / COZI_PASSWORD env vars
npm run bundle:mcpb    # produces cozi-mcp.mcpb at repo root

仓库布局:

cozi_mcp/
├── src/
│   ├── server.ts              # MCP server factory
│   ├── bin.ts                 # npx + MCPB stdio entry point
│   ├── instructions.ts
│   ├── cozi/                  # Inlined Cozi HTTP client (no separate npm package)
│   └── tools/                 # 13 MCP tools
├── tests/                     # vitest, mocks CoziClient at the boundary
├── manifest.json              # MCPB manifest (Claude Desktop)
└── package.json

Cozi HTTP 客户端直接内置于 src/cozi/ 中,而非作为单独的 npm 包发布——它体积小,仅对此 MCP 服务有用,而且这样可以避免引入单独依赖所带来的供应链风险。如果你希望在自己的项目中使用 Python 等效版本,请参见 py-cozi-client。

致谢

  • Cozi 认证端点要求使用 ?apikey=coziwc|v…_production,这一信息是 Wetzel402/py-cozi PR #3 通过逆向分析线上 my.cozi.com 网页包发现的。若没有这一发现,从服务器环境发起的每次登录尝试都会失败并返回误导性的 401,无论凭据是否有效。
  • 基于 Anthropic 的 Model Context Protocol 及其 TypeScript SDK 构建。

商标与关联关系

Cozi 和 Cozi 徽标是 Cozi Group Inc. 的商标。本项目为非官方项目,与 Cozi Group Inc. 无关联,也未获得其认可或赞助。使用 Cozi API 的风险由你自行承担,并受 Cozi 服务条款约束。

许可证

MIT——参见 LICENSE。

贡献

欢迎提交 PR。提交前请运行 npm test 和 npm run typecheck。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。