Local Schedule MCP Server
by xifeng0716
README.md
# Local Schedule · 本地日程
让 iPhone 原生日历/提醒事项、Muse 和本地 AI 共用一份日程。数据保存在自己的机器上,AI 通过六个 HTTP/MCP 操作读写,手机通过 CalDAV 同步。
这是从个人 Mac mini 部署整理出的轻量开源版本:中文界面、东八区时间、单用户。演示数据全部虚构,仓库不含个人课表、运行数据库、凭据、证书或实际节点地址。
```mermaid
flowchart LR
Phone[iPhone / Mac 日历与提醒事项] <-->|CalDAV HTTPS · tailnet| DAV[Radicale]
Muse[Muse · 云端 Agent] -->|HTTP API · Bearer token · tailnet| API[本地日程服务]
Companion[陪伴线程 / Codex] -->|Streamable HTTP MCP · 独立 token| API
API <-->|实时 CalDAV + ETag| DAV
API --> DB[(SQLite 元数据)]
DAV --> Files[(iCalendar 文件 + Git 历史)]
```
Radicale 保存手机可见的日程与待办;SQLite 保存日常模板、打卡、编号、审计和回收站。回收站/审计中保留恢复用的原文,但没有另一套供手机同步的活动条目表。HTTP、MCP、定时任务共用一个服务进程。
| 能力 | 说明 |
| --- | --- |
| 六个操作 | `schedule`、`find`、`add`、`update`、`done`、`remove` |
| 默认列表 | 课程、安排;待办、以后、日常 |
| 每日视图 | 时间线、到期/逾期、后续 DDL、作息内空档、重叠提示 |
| 日常 | 模板生成今天及未来三天的单次提醒,收集手机勾选,记录漏打卡 |
| 恢复 | 删除进回收站;恢复、撤销最近修改/完成;ETag 防覆盖 |
| 运维 | 每调用方独立 token、操作审计、Radicale Git 历史、在线备份与恢复 |
## 本机跑起来
需要 Python 3.12、Git;已在 Apple Silicon 的 macOS 实测。建议把服务目录放在 `~/Services` 或 Application Support,避免系统后台任务访问 Documents 的隐私权限问题。
```sh
git clone https://github.com/xifeng0716/local-schedule.git
cd local-schedule
python3.12 -m venv .venv
.venv/bin/python -m pip install -r requirements.lock
.venv/bin/python -m pip install -e . --no-deps
.venv/bin/python -m local_schedule.admin init
.venv/bin/python -m radicale --config runtime/radicale.conf
```
保持 Radicale 运行,在另一个终端进入同一项目目录:
```sh
# 只建五个空列表
.venv/bin/python -m local_schedule.admin collections
# 可选:导入虚构演示数据;须在日程 API 启动前执行
# .venv/bin/python -m local_schedule.admin seed
.venv/bin/python -m local_schedule
```
```sh
curl http://127.0.0.1:8123/health
# {"ok":true,...}
```
初次初始化在 `runtime/secrets.json` 生成随机密码和三个独立 token,文件权限 600、运行目录 700。`password` 用于 CalDAV;`tokens.muse`、`tokens.companion`、`tokens.codex` 分别供调用方使用。请从本地凭据文件取值,不要提交它。可用 `SCHEDULE_CONFIG=/absolute/path/secrets.json` 指定其他运行配置。
## 接入方式
| 调用方 | 协议和地址 | 认证 |
| --- | --- | --- |
| iPhone / Mac | `https://<node>.<tailnet>.ts.net:8443/schedule/` | 用户名 `schedule` + `password`,SSL 开启 |
| Muse | `http://<tailnet-ip>:8123/api/<operation>` | `Bearer <tokens.muse>` |
| 陪伴 / Codex | `http://127.0.0.1:8123/mcp` | 各自的 Bearer token |
以上远程地址是部署后的例子。默认两个服务都只听回环,必须先配置 tailnet 入站/HTTPS;克隆仓库不会自动配置 VPN。
- [接入文档](docs/integrations.md):iPhone 手动添加、Muse HTTP 示例、标准 MCP 配置。
- [部署与实际环境](docs/deployment.md):Mac mini、SFM/sing-box 内置 Tailscale、HTTPS、launchd、备份及排查。
- [接口与数据约定](docs/api.md):完整参数、时间/优先级语义、冲突及恢复。
Muse 在这里是独立的云端 AI 调用方,不是本仓库运行依赖。它只需要能访问 tailnet 服务并发送 HTTP 请求;没有绑定特定 Muse SDK,也不包含 Muse 的私有实现。
## 验证与边界
```sh
.venv/bin/python -m pytest -q
```
测试启动临时 Radicale/API,使用随机回环端口与临时数据,覆盖 HTTP/MCP、外部编辑和删除、ETag、日常、导入幂等和备份恢复。原部署中,用户已确认 iPhone 手动添加账户成功、Muse 接入成功;尚不等同于所有设备通知和整机重启场景都验收完成。
目前适合个人使用:一个 API 进程、一个写入方;token 区分调用方但都拥有完整读写权限,不能当成多租户权限系统。时间固定 `Asia/Shanghai`;未带时区的输入按 UTC+08:00 处理。支持 POSIX 信号,Windows 未适配。CalDAV 是拉取同步,不能保证系统通知及时性。删除的列表需先重建后再恢复条目。
## 许可证
[GPL-3.0-only](LICENSE)。本项目直接调用 Radicale 的存储锁接口进行备份,采用 GPLv3;第三方组件继续遵循各自许可证。详见 [依赖说明](THIRD_PARTY.md)。
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues