get_headings
Retrieve headings from Things projects to view their sections. Optionally filter by project UUID.
Instructions
Get headings from Things
Args: project_uuid: Optional UUID of a specific project to get headings from
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| project_uuid | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- src/things_mcp/server.py:249-268 (handler)The main handler for the get_headings tool. Accepts an optional project_uuid, validates it if provided, fetches headings via the 'things' library, formats them using format_heading(), and returns as a string.
@mcp.tool async def get_headings(project_uuid: str = None) -> str: """Get headings from Things Args: project_uuid: Optional UUID of a specific project to get headings from """ if project_uuid: project = things.get(project_uuid) if not project or project.get('type') != 'project': return f"Error: Invalid project UUID '{project_uuid}'" headings = things.tasks(type='heading', project=project_uuid) else: headings = things.tasks(type='heading') if not headings: return "No headings found" formatted_headings = [format_heading(heading) for heading in headings] return "\n\n---\n\n".join(formatted_headings) - src/things_mcp/server.py:249-249 (registration)The @mcp.tool decorator registers get_headings as a tool on the FastMCP server instance.
@mcp.tool - src/things_mcp/formatters.py:251-296 (helper)Helper function that formats a single heading dictionary into a human-readable string. Includes title, UUID, type, project info, dates with age calculation, notes, and optionally tasks under the heading.
def format_heading(heading: dict, include_items: bool = False) -> str: """Helper function to format a single heading.""" heading_text = f"Title: {heading['title']}\nUUID: {heading['uuid']}" heading_text += f"\nType: heading" # Add project info if present if heading.get('project'): if heading.get('project_title'): heading_text += f"\nProject: {heading['project_title']}" else: try: project = things.get(heading['project']) if project: heading_text += f"\nProject: {project['title']}" except Exception: pass # Add dates if heading.get('created'): heading_text += f"\nCreated: {heading['created']}" try: age_text = _calculate_age(heading['created']) heading_text += f"\nAge: {age_text}" except (ValueError, TypeError): pass if heading.get('modified'): heading_text += f"\nModified: {heading['modified']}" try: modified_age = _calculate_age(heading['modified']) heading_text += f"\nLast modified: {modified_age}" except (ValueError, TypeError): pass # Add notes if present if heading.get('notes'): heading_text += f"\nNotes: {heading['notes']}" if include_items: # Get todos under this heading todos = things.todos(heading=heading['uuid']) if todos: heading_text += "\n\nTasks under heading:" for todo in todos: heading_text += f"\n- {todo['title']}" return heading_text - src/things_mcp/server.py:267-268 (handler)The get_headings handler imports format_heading from .formatters (line 6 of server.py: 'from .formatters import ... format_heading').
formatted_headings = [format_heading(heading) for heading in headings] return "\n\n---\n\n".join(formatted_headings)