add_project
Create a project in Things 3 with title, notes, schedule, deadline, tags, area, and initial to-dos.
Instructions
Create a new project in Things
Args: title: Title of the project notes: Notes for the project when: When to schedule the project (today, tomorrow, evening, anytime, someday, or YYYY-MM-DD). Use YYYY-MM-DD@HH:MM format to add a reminder (e.g., 2024-01-15@14:30) deadline: Deadline for the project (YYYY-MM-DD) tags: Tags to apply to the project area_id: ID of area to add to area_title: Title of area to add to todos: Initial todos to create in the project
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| title | Yes | ||
| notes | No | ||
| when | No | ||
| deadline | No | ||
| tags | No | ||
| area_id | No | ||
| area_title | No | ||
| todos | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- src/things_mcp/server.py:391-426 (handler)MCP tool handler that creates a new project in Things by constructing and executing a Things URL. Decorated with @mcp.tool.
@mcp.tool async def add_project( title: str, notes: str = None, when: str = None, deadline: str = None, tags: List[str] = None, area_id: str = None, area_title: str = None, todos: List[str] = None ) -> str: """Create a new project in Things Args: title: Title of the project notes: Notes for the project when: When to schedule the project (today, tomorrow, evening, anytime, someday, or YYYY-MM-DD). Use YYYY-MM-DD@HH:MM format to add a reminder (e.g., 2024-01-15@14:30) deadline: Deadline for the project (YYYY-MM-DD) tags: Tags to apply to the project area_id: ID of area to add to area_title: Title of area to add to todos: Initial todos to create in the project """ url = url_scheme.add_project( title=title, notes=notes, when=when, deadline=deadline, tags=tags, area_id=area_id, area_title=area_title, todos=todos ) url_scheme.execute_url(url) return f"Created new project: {title}" - src/things_mcp/url_scheme.py:114-148 (schema)URL construction helper that builds a things:///add-project URL from project parameters, mapping arguments to URL query parameters.
def add_project(title: str, notes: Optional[str] = None, when: Optional[str] = None, deadline: Optional[str] = None, tags: Optional[list[str]] = None, area_id: Optional[str] = None, area_title: Optional[str] = None, todos: Optional[list[str]] = None) -> str: """Construct URL to add a new project. Args: title: Title of the project notes: Notes for the project when: Schedule the project. Accepts: - Keywords: "today", "tomorrow", "evening", "anytime", "someday" - Date: "yyyy-mm-dd" or natural language ("in 3 days", "next tuesday") - DateTime (adds reminder): "yyyy-mm-dd@HH:MM" (e.g., "2024-01-15@14:30") deadline: Deadline date (yyyy-mm-dd) tags: List of tag names area_id: UUID of area to add to area_title: Title of area to add to todos: List of todo titles to create in the project """ params = { 'title': title, 'notes': notes, 'when': when, 'deadline': deadline, 'area-id': area_id, 'area': area_title, # Change todos to be newline separated 'to-dos': '\n'.join(todos) if todos else None } # Handle tags separately since they need to be comma-separated if tags: params['tags'] = ','.join(tags) return construct_url('add-project', {k: v for k, v in params.items() if v is not None}) - src/things_mcp/server.py:391-391 (registration)The @mcp.tool decorator registers add_project as an MCP tool on the FastMCP server instance.
@mcp.tool - src/things_mcp/url_scheme.py:31-42 (helper)Helper that executes a Things URL via subprocess, used by the add_project handler to open the constructed URL.
def execute_url(url: str) -> None: """Execute a Things URL without bringing Things to the foreground. Security: validates the URL starts with 'things:///' before execution to prevent opening arbitrary URLs or executing unintended commands. Uses subprocess with argument list (no shell interpolation) to avoid command injection vectors. """ if not url.startswith("things:///"): raise ValueError(f"Invalid Things URL scheme: {url[:50]}") subprocess.run(['open', '-g', url], check=True, capture_output=True) - src/things_mcp/url_scheme.py:43-70 (helper)URL construction helper used by add_project to build the full things:///add-project URL with encoded parameters.
def construct_url(command: str, params: Dict[str, Any]) -> str: """Construct a Things URL from command and parameters.""" # Start with base URL url = f"things:///{command}" # Get authentication token if needed if command in ['update', 'update-project']: token = things.token() if token: params['auth-token'] = token # URL encode parameters if params: encoded_params = [] for key, value in params.items(): if value is None: continue # Handle boolean values if isinstance(value, bool): value = str(value).lower() # Handle lists (for tags, checklist items etc) elif isinstance(value, list): value = ','.join(str(v) for v in value) encoded_params.append(f"{key}={urllib.parse.quote(str(value))}") url += "?" + "&".join(encoded_params) return url