Skip to content

Commit 9ef61c6

Browse files
committed
refactor(tools): rename query_omnifocus to search and get_tree to browse
Rename tools for clarity and consistency: - query_omnifocus → search - get_tree → browse New features added during refactor: - folderPath field: Returns folder hierarchy as an array - available filter: Filter projects to Active + not deferred - task_filters parameter in browse: Full task filtering when include_tasks=True Both tools now use shared JS modules via the includes mechanism, reducing code duplication by ~160 lines.
1 parent dbfa83c commit 9ef61c6

8 files changed

Lines changed: 468 additions & 807 deletions

File tree

src/omnifocus_mcp/mcp_tools/projects/tree.py renamed to src/omnifocus_mcp/mcp_tools/projects/browse.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
1-
"""Get tree tool - hierarchical view of folders, projects, and tasks."""
1+
"""Browse tool - hierarchical view of folders, projects, and tasks."""
22

33
import json
44
from typing import Any
55

66
from ...omnijs import execute_omnijs_with_params
77

8+
# Shared JS modules for browse script
9+
BROWSE_INCLUDES = [
10+
"common/status_maps",
11+
"common/filters",
12+
"common/field_mappers",
13+
]
814

9-
async def get_tree(
15+
16+
async def browse(
1017
parent_id: str | None = None,
1118
parent_name: str | None = None,
1219
filters: dict[str, Any] | None = None,
20+
task_filters: dict[str, Any] | None = None,
1321
include_completed: bool = False,
1422
max_depth: int | None = None,
1523
include_root_projects: bool = True,
@@ -20,7 +28,7 @@ async def get_tree(
2028
include_tasks: bool = False,
2129
) -> str:
2230
"""
23-
Get a hierarchical tree of folders, projects, and tasks.
31+
Browse the hierarchical tree of folders, projects, and tasks.
2432
2533
Returns a tree structure showing the folder/project/task hierarchy in OmniFocus.
2634
Supports filtering by various criteria and starting from a specific folder.
@@ -38,15 +46,22 @@ async def get_tree(
3846
- due_within: Projects due within N days from today
3947
- deferred_until: Projects deferred becoming available within N days
4048
- has_note: Filter by note presence (boolean)
49+
- available: Filter to Active projects that are not deferred (boolean)
50+
task_filters: Optional filters for tasks when include_tasks=True (all AND logic):
51+
- flagged: Filter by flagged status (boolean)
52+
- tags: Filter by tag names (list, OR logic)
53+
- status: Filter by task status (list, OR logic)
54+
- due_within: Tasks due within N days from today
55+
- planned_within: Tasks planned within N days from today
4156
include_completed: Include completed/dropped projects and tasks (default: False)
4257
max_depth: Maximum folder depth to traverse (None = unlimited)
4358
include_root_projects: Include projects at root level (not in any folder) (default: True)
4459
summary: If True, return only counts (projectCount, folderCount, taskCount) without tree
4560
fields: Specific project/task fields to return (reduces response size).
4661
Project fields: id, name, status, sequential, flagged, dueDate, deferDate,
47-
estimatedMinutes, taskCount, tagNames.
62+
estimatedMinutes, taskCount, tagNames, folderPath.
4863
Task fields: id, name, flagged, dueDate, deferDate, estimatedMinutes, tagNames,
49-
completed, note.
64+
completed, note, folderPath.
5065
If not specified, returns all fields.
5166
include_folders: Include folder nodes in the tree (default: True)
5267
include_projects: Include project nodes in the tree (default: True)
@@ -75,11 +90,12 @@ async def get_tree(
7590
"""
7691
try:
7792
result = await execute_omnijs_with_params(
78-
"tree",
93+
"browse",
7994
{
8095
"parent_id": parent_id,
8196
"parent_name": parent_name,
8297
"filters": filters or {},
98+
"task_filters": task_filters or {},
8399
"include_completed": include_completed,
84100
"max_depth": max_depth,
85101
"include_root_projects": include_root_projects,
@@ -89,6 +105,7 @@ async def get_tree(
89105
"include_projects": include_projects,
90106
"include_tasks": include_tasks,
91107
},
108+
includes=BROWSE_INCLUDES,
92109
)
93110
return json.dumps(result, indent=2)
94111
except Exception as e:
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""Query tools for OmniFocus."""
22

3-
from .query import query_omnifocus
3+
from .search import search
44

5-
__all__ = ["query_omnifocus"]
5+
__all__ = ["search"]

src/omnifocus_mcp/mcp_tools/query/query.py renamed to src/omnifocus_mcp/mcp_tools/query/search.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
1-
"""Query OmniFocus database tool."""
1+
"""Search OmniFocus database tool."""
22

33
import json
44
from typing import Any
55

66
from ...omnijs import execute_omnijs_with_params
77

8+
# Shared JS modules for search script
9+
SEARCH_INCLUDES = [
10+
"common/status_maps",
11+
"common/filters",
12+
"common/field_mappers",
13+
]
814

9-
async def query_omnifocus(
15+
16+
async def search(
1017
entity: str,
1118
filters: dict[str, Any] | None = None,
1219
fields: list[str] | None = None,
@@ -17,7 +24,7 @@ async def query_omnifocus(
1724
summary: bool = False,
1825
) -> str:
1926
"""
20-
Query OmniFocus database with powerful filters.
27+
Search OmniFocus database with powerful filters.
2128
2229
Much faster than dump_database for targeted queries.
2330
@@ -34,8 +41,9 @@ async def query_omnifocus(
3441
- deferred_until: Items deferred becoming available within N days
3542
- planned_within: Tasks planned within N days from today (OmniFocus 4.7+)
3643
- has_note: Filter by note presence
44+
- available: For projects, filter to Active + not deferred
3745
fields: Specific fields to return (reduces response size). Task fields include:
38-
plannedDate, effectivePlannedDate, effectiveDueDate, effectiveDeferDate
46+
plannedDate, effectivePlannedDate, effectiveDueDate, effectiveDeferDate, folderPath
3947
limit: Maximum number of items to return
4048
sort_by: Field to sort by (name, dueDate, deferDate, plannedDate, modificationDate, etc.)
4149
sort_order: Sort order: 'asc' or 'desc' (default: 'asc')
@@ -47,7 +55,7 @@ async def query_omnifocus(
4755
"""
4856
try:
4957
result = await execute_omnijs_with_params(
50-
"query",
58+
"search",
5159
{
5260
"entity": entity,
5361
"filters": filters or {},
@@ -58,6 +66,7 @@ async def query_omnifocus(
5866
"include_completed": include_completed,
5967
"summary": summary,
6068
},
69+
includes=SEARCH_INCLUDES,
6170
)
6271
return json.dumps(result, indent=2)
6372
except Exception as e:

0 commit comments

Comments
 (0)