Clone

git clone git@git.secluded.site:lunatask-mcp-server.git

README

lunatask-mcp-server

Interact with Lunatask using $PREFERRED_LLM

scratchanitch.dev badge Go Report Card REUSE status

Note: lots of this was written by LLMs and I haven't reviewed it thoroughly enough to be comfortable making it more public than unlisted. Please refrain from sharing it around and do let me know if there are any issues.


MCP server setup

Ensure you have the Go toolchain installed.

git clone https://git.sr.ht/~amolith/lunatask-mcp-server
cd lunatask-mcp-server
# specify GOOS and GOARCH if cross-compiling
CGO_ENABLED=0 go build -o lunatask-mcp-server .
./lunatask-mcp-server
# it'll generate config.toml with default values
# fill them out with your preferred editor
./lunatask-mcp-server

If you have just, build with just build (supports GOOS and GOARCH). If you also have upx, compress the resulting binary with just pack. You can run one after the other with just build pack.

Point Home Assistant's MCP integration at the /sse endpoint.

Available Tools

This MCP server provides several tools for interacting with Lunatask:

get_timestamp

Parses natural language dates into RFC3339 timestamps.

Parameters:

  • natural_language_date (string, required): A natural language description of a date/time (e.g., "today at 3pm", "next Monday", "in 2 hours")

list_areas_and_goals

Lists all configured areas and their goals in Lunatask.

Returns:

  • Text formatted as a list with area names and IDs, and their associated goal names and IDs

create_task

Creates a new task in Lunatask.

Parameters:

  • area_id (string, required): UUID of the area to create the task in
  • name (string, required): Name of the task (max 100 characters)
  • goal_id (string, optional): UUID of the goal to associate the task with
  • note (string, optional): Additional notes for the task in Markdown format
  • status (string, optional): Task status - one of "later", "next", "started", "waiting", or "completed"
  • motivation (string, optional): Motivation level - one of "must", "should", or "want"
  • estimate (integer, optional): Estimated time to complete task in minutes (0-720)
  • priority (string, optional): Task priority - one of "lowest", "low", "neutral", "high", or "highest"
  • eisenhower (string, optional): Eisenhower matrix categorization - one of "uncategorised", "both urgent and important", "urgent, but not important", "important, but not urgent", or "neither urgent nor important"
  • scheduled_on (string, optional): RFC3339 formatted timestamp for when the task is scheduled

update_task

Updates an existing task in Lunatask.

Parameters:

  • task_id (string, required): UUID of the task to update
  • area_id (string, optional): UUID of the area to move the task to
  • name (string, optional): New name for the task
  • goal_id (string, optional): UUID of the goal to associate the task with
  • note (string, optional): Additional notes for the task in Markdown format
  • status (string, optional): Task status - one of "later", "next", "started", "waiting", or "completed"
  • motivation (string, optional): Motivation level - one of "must", "should", or "want"
  • estimate (integer, optional): Estimated time to complete task in minutes (0-720)
  • priority (string, optional): Task priority - one of "lowest", "low", "neutral", "high", or "highest"
  • eisenhower (string, optional): Eisenhower matrix categorization - one of "uncategorised", "both urgent and important", "urgent, but not important", "important, but not urgent", or "neither urgent nor important"
  • scheduled_on (string, optional): RFC3339 formatted timestamp for when the task is scheduled

delete_task

Deletes a task from Lunatask.

Parameters:

  • task_id (string, required): UUID of the task to delete

list_habits_and_activities

Lists all configured habits in Lunatask.

Returns:

  • Text formatted as a list with habit names and IDs

track_habit_activity

Tracks an activity for a habit in Lunatask.

Parameters:

  • habit_id (string, required): UUID of the habit to track
  • performed_on (string, required): RFC3339 formatted timestamp of when the habit was performed

Collaboration

Patch requests are in amolith/llm-projects on pr.pico.sh. You don't need a new account to contribute, you don't need to fork this repo, you don't need to fiddle with git send-email, you don't need to faff with your email client to get git request-pull working...

You just need:

  • Git
  • SSH
  • An SSH key
# Clone this repo, make your changes, and commit them
# Create a new patch request with
git format-patch origin/main --stdout | ssh pr.pico.sh pr create amolith/llm-projects
# After potential feedback, submit a revision to an existing patch request with
git format-patch origin/main --stdout | ssh pr.pico.sh pr add {prID}
# List patch requests
ssh pr.pico.sh pr ls amolith/llm-projects

See "How do Patch Requests work?" on pr.pico.sh's home page for a more complete example workflow.

Models and prompts

I'm currently using google/gemini-2.5-flash through OpenRouter with the following system prompt:

You are a calm and thoughtful voice assistant for Home Assistant. You can both interact with Home Assistant and additional systems plugged into it, like Lunatask. Lunatask is an ADHD-friendly all-in-one encrypted to-do list, habit tracker, journaling, life-tracking and notes app.

<lunatask_instructions>

When interacting with Lunatask, write task names in sentence case. When asked to mark something complete or when the user says they've done somethizng and you have no other context, check their habits. If one matches, track it.

For every request to create or change a task:

  1. List the areas and goals and consider which one area is most relevant. Consider whether the task belongs within any of that area's goals.
  2. Get the task timestamp.
  3. If the user provided additional details, pass those in the task's note field using Markdown.
  4. If the user mentioned a time estimate, like that it might take them 30 minutes, pass 30 in the estimate field. If they said 2 hours, 120, and so on.
  5. Try and interpret the text from the STT engine. It's not entirely accurate and the user might have meant something slightly different from what came through.
  6. Only include parameters if the user indicates or hints at them. Avoid scheduling tasks unless the user explicitly says something like "in three days" or "next monday" or "in 8 hours" or "schedule it for {day/time}" or "remind me on {day} to {task}" or even "remind me at {time} on {day} to {thing}" and other variations.
  7. The following user-provided instructions are of the utmost importance. Keep them in mind throughout.

<user_provided_instructions>

  • My Work area uses the Kanban workflow, so Work tasks must always include a status value of either later, next, started, waiting, or completed. Default to later unless I specify otherwise.
  • My Personal area uses the Now/Later workflow, so tasks created there must include a status value of either "later" or "started". Default to "later" unless I specify otherwise.
  • My Someday area uses a simple priority list. Do not include a status and instead only provide a priority if I specify one.
  • My Acquisitions area currently follows the Eisenhower workflow; do not include a status, do not include a date unless I specify, and do include the eisenhower parameter. Its values may be one of uncategorised, both urgent and important, urgent, but not important, important, but not urgent, or neither urgent nor important. If I don’t specify a value, ask me. Never set it to uncategorised unless I explicitly say to “clear” it or “unset” it or “set it to uncategorised” or something like that.
  • If I don't provide an estimate for any task regardless of area, please consider whether it might take 10, 25, 30, 45, 60, or more minutes. Always include an estimate for Work, Personal, and Somday areas. Never for Acquisitions.
  • Interpret verbal dictation, like converting "something dash something" to "something-something".
  • Again I don't want any of my tasks scheduled. You should only need to call the timestamp tool when marking habits complete.

</user_provided_instructions>

Only once you've gathered the requisite area ID and other information should you attempt to create or update a task.

</lunatask_instructions>

TODO

  • Optionally include a tool that calls a configurable LLM for task time estimations so the main LLM doesn't have to guess.