OmniFocus

io.github.steveardis由 GitHub 账号 steveardis 发布v0.2.1更新于 Oct 24, 2026

Full CRUD MCP server for OmniFocus via Omni Automation — tasks, projects, folders, tags, recurrence.

已验证STDIO仅桌面效率与工作流

概览

AI 生成的概览

让助手在 macOS 上通过 Omni Automation 读取和修改 OmniFocus 的任务、项目、文件夹与标签。

可以做什么
通过完整的 Omni Automation JavaScript API 将 OmniFocus 暴露给助手,借助 osascript 在应用内运行 OmniJS 片段。读取类工具可列出和获取项目、任务、文件夹与标签,支持筛选和数量限制,并提供 resolve_name 将名称映射为稳定 ID。写入类工具可创建、编辑、完成、丢弃、删除和移动任务、项目、文件夹与标签,涵盖日期、标签、旗标、预计分钟数和重复规则。
适用场景
适合让助手管理 Mac 上真实的 OmniFocus 数据库:收集和整理任务、查看项目、调整截止或推迟日期、清理文件夹与标签。适合希望用对话方式操作 OmniFocus 而非手动点击的用户。
运行要求
仅限 macOS,需在同一台机器上安装并运行 OmniFocus,且需要 Node.js 20 或更高版本。npm 包 @scardis/omnifocus-mcp 通过 stdio 在本地运行;未声明账号、API 密钥或环境变量。
安装前请注意
写入类工具会改动真实数据:delete_task、delete_project、delete_folder 和 delete_tag 会永久删除条目及其子项,完成、丢弃和移动操作也会修改现有记录。名称可能重复,写入前应使用 resolve_name 并请用户确认。集成测试会针对真实数据库运行并创建临时夹具,若启用同步,夹具可能同步到其他设备。

安装

在 SourceWeft 中

  1. 打开 控制台中的 OmniFocus,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。

其他 MCP 客户端

参照 仓库 中的启动说明。

README

omnifocus-mcp

An MCP server for OmniFocus that exposes the full Omni Automation JavaScript API to LLM callers.

macOS only. Requires OmniFocus running on the same machine. The entire implementation runs OmniJS snippets inside OmniFocus via osascript -l JavaScript — no AppleScript string generation, no scripting dictionary limitations.

Prerequisites

  • macOS (Omni Automation is macOS-only; the server will not start on other platforms)
  • OmniFocus installed and running
  • Node.js ≥ 20

Install

The package is published to npm as @scardis/omnifocus-mcp.

Via npx (no install required)

Add to your MCP client config (e.g. Claude Desktop claude_desktop_config.json):

json
{  "mcpServers": {    "omnifocus": {      "command": "npx",      "args": ["-y", "@scardis/omnifocus-mcp"]    }  }}

From source

bash
git clone https://github.com/steveardis/omnifocus-mcp.gitcd omnifocus-mcpnpm installnpm run build

Then configure your MCP client:

json
{  "mcpServers": {    "omnifocus": {      "command": "node",      "args": ["/absolute/path/to/omnifocus-mcp/dist/server.js"]    }  }}

Available Tools

Read

ToolDescription
list_projectsProjects with optional filtering by status, folderId, flagged. Default excludes done/dropped. Limit (default 100).
get_projectFull project detail by stable ID
list_tasksTasks scoped by projectId, folderId, inbox: true, or all: true with optional status/tag/due/flagged filters. Limit (default 200).
get_taskFull task detail by stable ID — includes defer/planned/due dates, tags, repetition rule, parentTaskId
list_foldersFolders with optional status filter. Limit (default 200).
get_folderFull folder detail by stable ID, including child folder and project IDs
list_tagsTags with optional status filter. Limit (default 200).
get_tagFull tag detail by stable ID, including child tag IDs
resolve_nameResolve a name to stable ID candidates — never silently disambiguates; returns all matches

Write

ToolDescription
create_taskCreate a task in inbox, project, or as subtask. Supports defer/planned/due dates, tags, flagged, estimated minutes, and repetition rules.
edit_taskEdit any task field. Pass null to clear dates or repetition. Omitted fields are unchanged.
complete_taskMark a task complete
drop_taskMark a task dropped
delete_taskPermanently delete a task and all subtasks
create_projectCreate a project, optionally in a folder. Supports type, status, review interval, tags.
edit_projectEdit project fields
complete_projectMark a project complete
drop_projectMark a project dropped
delete_projectPermanently delete a project and all its tasks
create_folderCreate a folder, optionally nested
edit_folderRename a folder
delete_folderPermanently delete a folder and entire subtree
create_tagCreate a tag, optionally nested
edit_tagEdit tag name or status
delete_tagPermanently delete a tag and child tags
move_taskMove a task to a project or make it a subtask of another task
move_projectMove a project to a folder or to top level

Addressing model

Every entity returned by this server includes a stable id field (id.primaryKey from OmniFocus). Use this ID in subsequent calls rather than names. Names can be ambiguous; IDs are not.

If you have a name but not an ID, use resolve_name. It returns a list — if multiple candidates are returned, inspect the path field and ask the user to disambiguate before proceeding with any write operation.

Comparison with other OmniFocus MCP servers

Two notable alternatives exist: themotionmachine/OmniFocus-MCP and jqlts1/omnifocus-mcp-enhanced (a fork of the above with additional tools).

Scripting API. The alternatives use the JXA scripting dictionary or AppleScript to drive OmniFocus. This server makes a single JXA call — Application('OmniFocus').evaluateJavascript() — and runs all logic as OmniJS (Omni Automation) inside OmniFocus. This gives access to the full Omni Automation API surface (recurrence rules, review intervals, perspectives, forecast, attachments, URL automation, etc.) rather than the more limited scripting dictionary.

Argument injection. The alternatives construct osascript commands via string interpolation, which can break on apostrophes, quotes, backslashes, and unicode in names. This server serializes all arguments with JSON.stringify into a JS literal.

Entity addressing. The alternatives address entities primarily by name. This server returns a stable id (id.primaryKey) for every entity and provides resolve_name to map a name to ID candidates — returning all matches with full paths rather than silently picking one when names are ambiguous.

Full CRUD. This server supports creating, editing, completing, dropping, deleting, and moving tasks, projects, folders, and tags — plus repetition rules and OmniFocus 4's planned date.

Development

bash
# Type-check without buildingnpm run typecheck
# Run unit tests (no OmniFocus required)npm test
# Build (compiles TypeScript and copies snippets into dist/)npm run build

Publishing a new version is documented in RELEASING.md.

Testing

Unit tests (no OmniFocus required)

bash
npm test

Integration tests

⚠️ Integration tests run against your real OmniFocus database.

Each test run creates a temporary top-level folder named __MCP_TEST_<uuid>__ and deletes it on teardown. If a test run is interrupted before teardown, run the cleanup script:

bash
npm run test:cleanup-fixtures

⚠️ Sync warning: By default, integration tests refuse to run if OmniFocus sync is enabled, to prevent test fixtures from propagating to your other devices. Disable OmniFocus sync first, or set MCP_TEST_ALLOW_SYNC=1 to opt in (fixtures will sync):

bash
# Default (refuses if sync enabled)npm run test:integration
# With sync enabled (use carefully)MCP_TEST_ALLOW_SYNC=1 npm run test:integration

Clean up stale test fixtures

bash
npm run test:cleanup-fixtures

This removes any __MCP_TEST_*__ folders and orphaned __mcp_*__ projects/tags left in OmniFocus from interrupted test runs.

Contributing

Contributions are welcome! Here's how to get started:

  1. Fork and clone the repo
  2. Install dependencies: npm install
  3. Run unit tests (no OmniFocus needed): npm test
  4. Run integration tests (requires macOS + OmniFocus): npm run test:integration

Before submitting a PR

  • npm run typecheck — must pass with no errors
  • npm test — all unit tests must pass
  • npm run test:integration — all integration tests must pass (macOS only)
  • Keep changes focused — one feature or fix per PR

Architecture overview

The server runs OmniJS snippets inside OmniFocus via osascript -l JavaScript. Each tool has three layers:

  • Schema (src/schemas/shapes.ts) — Zod schemas for input validation and output parsing
  • Snippet (src/snippets/*.js) — OmniJS code that runs inside OmniFocus. Plain ES5 JavaScript (no imports, no TypeScript). Arguments are injected via __ARGS__ placeholder.
  • Tool handler (src/tools/*.ts) — Validates input, calls runSnippet(), parses the result

When adding a new tool:

  1. Define input/output schemas in src/schemas/shapes.ts and export from src/schemas/index.ts
  2. Create the OmniJS snippet in src/snippets/
  3. Add the snippet name to ALLOWED_SNIPPETS in src/runtime/snippetLoader.ts
  4. Create the tool handler in src/tools/ and register it in src/tools/index.ts
  5. Add unit tests for schemas and integration tests that run against OmniFocus

Writing OmniJS snippets

Snippets run inside OmniFocus's JavaScript runtime, not Node.js. Key constraints:

  • ES5-style JavaScript — use var, function(){}, no arrow functions in older OmniFocus versions
  • No imports — all OmniJS globals (flattenedTasks, flattenedProjects, moveTasks, etc.) are available directly
  • Return JSON — always return JSON.stringify({ ok: true, data: ... })
  • Error pattern — throw named errors (NotFoundError, ValidationError) which the bridge catches and wraps

License

MIT

来源:README.md,提交 738bb19

工具

0
SourceWeft 尚未在沙箱中启动过该软件包,因此其工具未知。

版本历史

1
  1. v0.2.1最新Sep 16, 2026

评分

已满足适用检查项的 50%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通25 分

    请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。

  • 已声明认证方式10 分

    请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。

  • 已列出工具15 分

    请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。

  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分