关于 OmniFocus
OmniFocus 是面向 macOS 用户的 MCP 服务,可让大模型管理 OmniFocus 数据。它通过 Omni Automation 提供任务、项目、文件夹和标签的读取及完整增删改操作,并以稳定 ID 定位实体。
主要功能
- 01读取任务、项目、文件夹和标签
- 02创建、编辑、完成及删除项目
- 03移动任务和项目
- 04管理日期、标签和重复规则
- 05将名称解析为稳定 ID 候选项
适用场景
- 01按项目、状态或截止日期查看任务
- 02创建并更新项目和任务
- 03用文件夹和标签整理任务
- 04修改数据前区分同名实体
MCP 相关
该服务向 MCP 客户端提供 OmniFocus 读取和写入工具。它通过 `osascript -l JavaScript` 在正在运行的 macOS OmniFocus 应用内执行 OmniJS 代码。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
27收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| limit | integer | 否 | 返回项目的最大数量。默认值为 100。 |
| filter | object | 否 | 可选筛选条件。所有字段按 AND 组合。未指定 status 时,默认排除已完成和已丢弃的项目。 |
| filter.status | array | 否 | |
| filter.flagged | boolean | 否 | |
| filter.folderId | string | 否 |
详细介绍
omnifocus-mcp
一个面向 OmniFocus 的 MCP 服务,可向 LLM 调用方开放完整的 Omni Automation JavaScript API。
仅支持 macOS。 要求 OmniFocus 在同一台机器上运行。整个实现通过 osascript -l JavaScript 在 OmniFocus 内运行 OmniJS 片段——无需生成 AppleScript 字符串,也不受脚本字典限制。
先决条件
- macOS(Omni Automation 仅支持 macOS;服务无法在其他平台上启动)
- 已安装并且正在运行 OmniFocus
- Node.js ≥ 20
安装
此软件包已发布到 npm,名称为 @scardis/omnifocus-mcp。
通过 npx(无需安装)
添加到 MCP 客户端配置中(例如 Claude Desktop 的 claude_desktop_config.json):
{
"mcpServers": {
"omnifocus": {
"command": "npx",
"args": ["-y", "@scardis/omnifocus-mcp"]
}
}
}
从源代码安装
git clone https://github.com/steveardis/omnifocus-mcp.git
cd omnifocus-mcp
npm install
npm run build
然后配置 MCP 客户端:
{
"mcpServers": {
"omnifocus": {
"command": "node",
"args": ["/absolute/path/to/omnifocus-mcp/dist/server.js"]
}
}
}
可用工具
读取
| 工具 | 描述 |
|---|---|
list_projects | 列出项目,可按状态、folderId、是否标记进行筛选。默认不包含已完成或已放弃的项目。数量上限(默认 100)。 |
get_project | 根据稳定 ID 获取完整的项目详情 |
list_tasks | 列出任务,可按 projectId、folderId、inbox: true 或 all: true 指定范围,并可按状态、标签、到期时间、是否标记进行筛选。数量上限(默认 200)。 |
get_task | 根据稳定 ID 获取完整的任务详情,包括延后/计划/到期日期、标签、重复规则、parentTaskId |
list_folders | 列出文件夹,可按状态筛选。数量上限(默认 200)。 |
get_folder | 根据稳定 ID 获取完整的文件夹详情,包括子文件夹和项目 ID |
list_tags | 列出标签,可按状态筛选。数量上限(默认 200)。 |
get_tag | 根据稳定 ID 获取完整的标签详情,包括子标签 ID |
resolve_name | 将名称解析为稳定 ID 候选项——绝不会静默消歧;返回所有匹配项 |
写入
| 工具 | 描述 |
|---|---|
create_task | 在收件箱或项目中创建任务,或创建子任务。支持延后/计划/到期日期、标签、标记、预估分钟数和重复规则。 |
edit_task | 编辑任意任务字段。传入 null 可清除日期或重复规则。未提供的字段保持不变。 |
complete_task | 将任务标记为已完成 |
drop_task | 将任务标记为已放弃 |
delete_task | 永久删除任务及其所有子任务 |
create_project | 创建项目,可选择放入文件夹。支持类型、状态、复查间隔和标签。 |
edit_project | 编辑项目字段 |
complete_project | 将项目标记为已完成 |
drop_project | 将项目标记为已放弃 |
delete_project | 永久删除项目及其所有任务 |
create_folder | 创建文件夹,可选择嵌套放置 |
edit_folder | 重命名文件夹 |
delete_folder | 永久删除文件夹及其整个子树 |
create_tag | 创建标签,可选择嵌套放置 |
edit_tag | 编辑标签名称或状态 |
delete_tag | 永久删除标签及其子标签 |
move_task | 将任务移至某个项目,或设为另一任务的子任务 |
move_project | 将项目移至某个文件夹或顶层 |
寻址模型
此服务返回的每个实体都包含稳定的 id 字段(OmniFocus 的 id.primaryKey)。后续调用时请使用此 ID,而非名称。名称可能存在歧义;ID 不会。
如果知道名称但没有 ID,请使用 resolve_name。它会返回一个列表——如果返回多个候选项,请检查 path 字段,并在执行任何写入操作前让用户确认具体对象。
与其他 OmniFocus MCP 服务的比较
有两个值得关注的替代方案: themotionmachine/OmniFocus-MCP 和 jqlts1/omnifocus-mcp-enhanced(前者的一个分支,提供了额外的工具)。
脚本 API。 这些替代方案使用 JXA 脚本字典或 AppleScript 驱动 OmniFocus。本服务只进行一次 JXA 调用 — Application('OmniFocus').evaluateJavascript() — 并在 OmniFocus 内部以 OmniJS(Omni Automation)运行所有逻辑。这样即可使用完整的 Omni Automation API(重复规则、审核间隔、视图、预测、附件、URL 自动化等),而非功能更有限的脚本字典。
参数注入。 这些替代方案通过字符串插值构造 osascript 命令,名称中的撇号、引号、反斜杠和 Unicode 字符可能导致问题。本服务使用 JSON.stringify 将所有参数序列化为 JS 字面量。
实体寻址。 这些替代方案主要通过名称寻址实体。本服务会为每个实体返回稳定的 id(id.primaryKey),并提供 resolve_name 将名称映射为候选 ID — 返回包含完整路径的所有匹配项,而不会在名称有歧义时悄悄选取其中一个。
完整的 CRUD。 本服务支持创建、编辑、完成、放弃、删除和移动任务、项目、文件夹和标签 — 还支持重复规则以及 OmniFocus 4 的计划日期。
开发
# Type-check without building
npm run typecheck
# Run unit tests (no OmniFocus required)
npm test
# Build (compiles TypeScript and copies snippets into dist/)
npm run build
发布新版本的说明见 RELEASING.md。
测试
单元测试(无需 OmniFocus)
npm test
集成测试
⚠️ 集成测试会针对你的真实 OmniFocus 数据库运行。
每次测试运行都会创建一个名为
__MCP_TEST_<uuid>__的临时顶级文件夹,并在清理时将其删除。如果测试运行在清理前中断,请运行清理脚本:npm run test:cleanup-fixtures
⚠️ 同步警告: 默认情况下,如果启用了 OmniFocus 同步,集成测试将拒绝运行,以防测试数据传播到你的其他设备。请先禁用 OmniFocus 同步,或设置
MCP_TEST_ALLOW_SYNC=1选择加入(测试数据将会同步):
# Default (refuses if sync enabled)
npm run test:integration
# With sync enabled (use carefully)
MCP_TEST_ALLOW_SYNC=1 npm run test:integration
清理过期的测试数据
npm run test:cleanup-fixtures
此操作会从 OmniFocus 中移除所有 __MCP_TEST_*__ 文件夹,以及因测试运行中断而遗留的孤立 __mcp_*__ 项目/标签。
贡献
欢迎贡献!以下是开始的方法:
- 复刻并克隆仓库
- 安装依赖项:
npm install - 运行单元测试(无需 OmniFocus):
npm test - 运行集成测试(需要 macOS + OmniFocus):
npm run test:integration
提交 PR 前
npm run typecheck— 必须通过,且无错误npm test— 所有单元测试都必须通过npm run test:integration— 所有集成测试都必须通过(仅限 macOS)- 修改范围应保持聚焦 — 每个 PR 只包含一项功能或修复
架构概览
服务通过 osascript -l JavaScript 在 OmniFocus 内部运行 OmniJS 代码片段。每个工具分为三层:
- Schema(
src/schemas/shapes.ts)— 用于输入验证和输出解析的 Zod schema - 代码片段(
src/snippets/*.js)— 在 OmniFocus 内部运行的 OmniJS 代码。使用纯 ES5 JavaScript(无导入、无 TypeScript)。参数通过__ARGS__占位符注入。 - 工具处理器(
src/tools/*.ts)— 验证输入、调用runSnippet()并解析结果
添加新工具时:
- 在
src/schemas/shapes.ts中定义输入/输出 schema,并从src/schemas/index.ts导出 - 在
src/snippets/中创建 OmniJS 代码片段 - 将代码片段名称添加到
src/runtime/snippetLoader.ts中的ALLOWED_SNIPPETS - 在
src/tools/中创建工具处理器,并在src/tools/index.ts中注册 - 为 schema 添加单元测试,并添加针对 OmniFocus 运行的集成测试
编写 OmniJS 代码片段
代码片段在 OmniFocus 的 JavaScript 运行时中运行,而非 Node.js。主要限制:
- ES5 风格的 JavaScript — 使用
var、function(){};较旧版本的 OmniFocus 不支持箭头函数 - 不使用导入 — 所有 OmniJS 全局变量(
flattenedTasks、flattenedProjects、moveTasks等)均可直接使用 - 返回 JSON — 始终
return JSON.stringify({ ok: true, data: ... }) - 错误模式 — 抛出命名错误(
NotFoundError、ValidationError),由桥接程序捕获并封装
许可证
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。