README.md

  1<!--
  2SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
  3
  4SPDX-License-Identifier: CC0-1.0
  5-->
  6
  7# lunatask-mcp-server
  8
  9_Interact with [Lunatask](https://lunatask.app) using `$PREFERRED_LLM`_
 10
 11[![scratchanitch.dev badge](https://img.shields.io/badge/scratchanitch-dev-FFC4B5)](https://scratchanitch.dev)
 12[![Go Report Card](https://goreportcard.com/badge/git.sr.ht/~amolith/lunatask-mcp-server)](https://goreportcard.com/report/git.sr.ht/~amolith/lunatask-mcp-server)
 13[![REUSE status](https://api.reuse.software/badge/git.sr.ht/~amolith/lunatask-mcp-server)](https://api.reuse.software/info/git.sr.ht/~amolith/lunatask-mcp-server)
 14
 15**Note:** lots of this was written by LLMs and I haven't reviewed it thoroughly
 16enough to be comfortable making it more public than unlisted. Please refrain
 17from sharing it around and do let me know if there are any issues.
 18
 19---
 20
 21## MCP server setup
 22
 23Ensure you have [the Go toolchain] installed.
 24
 25[the Go toolchain]: https://go.dev/doc/install
 26
 27```sh
 28git clone https://git.sr.ht/~amolith/lunatask-mcp-server
 29cd lunatask-mcp-server
 30# specify GOOS and GOARCH if cross-compiling
 31CGO_ENABLED=0 go build -o lunatask-mcp-server .
 32./lunatask-mcp-server
 33# it'll generate config.toml with default values
 34# fill them out with your preferred editor
 35./lunatask-mcp-server
 36```
 37
 38If you have [just], build with `just build` (supports `GOOS` and `GOARCH`). If
 39you also have [upx], compress the resulting binary with `just pack`. You can run
 40one after the other with `just build pack`.
 41
 42[just]: https://github.com/casey/just
 43[upx]: https://github.com/upx/upx
 44
 45Point [Home Assistant's MCP integration] at the `/sse` endpoint.
 46
 47[Home Assistant's MCP integration]: https://www.home-assistant.io/integrations/mcp/
 48
 49## Collaboration
 50
 51Patch requests are in [amolith/lunatask-mcp-server] on [pr.pico.sh]. You don't
 52need a new account to contribute, you don't need to fork this repo, you don't
 53need to fiddle with `git send-email`, you don't need to faff with your email
 54client to get `git request-pull` working...
 55
 56You just need:
 57
 58- Git
 59- SSH
 60- An SSH key
 61
 62```sh
 63# Clone this repo, make your changes, and commit them
 64# Create a new patch request with
 65git format-patch origin/main --stdout | ssh pr.pico.sh pr create amolith/lunatask-mcp-server
 66# After potential feedback, submit a revision to an existing patch request with
 67git format-patch origin/main --stdout | ssh pr.pico.sh pr add {prID}
 68# List patch requests
 69ssh pr.pico.sh pr list amolith/lunatask-mcp-server
 70```
 71
 72See "How do Patch Requests work?" on [pr.pico.sh]'s home page for a more
 73complete example workflow.
 74
 75[amolith/lunatask-mcp-server]: https://pr.pico.sh/r/amolith/lunatask-mcp-server
 76[pr.pico.sh]: https://pr.pico.sh
 77
 78I also accept patches to my public SourceHut inbox
 79([~amolith/public-inbox@lists.sr.ht][list], [web][listweb]) via `git send-email`
 80or `git request-pull` and over the Radicle network
 81(`rad:z2xbgGQHaDTVYjWKZLSXw1G4xBfUi`, [web][radrepo], [what is Radicle?][rad]).
 82
 83[list]: mailto:~amolith/public-inbox@lists.sr.ht
 84[listweb]: https://lists.sr.ht/~amolith/public-inbox
 85[radrepo]: https://radicle.secluded.site/nodes/seed.secluded.site/rad:z2xbgGQHaDTVYjWKZLSXw1G4xBfUi
 86[rad]: https://radicle.xyz
 87
 88## Models and prompts
 89
 90I'm currently using `google/gemini-2.5-flash` through [OpenRouter] with the
 91following system prompt:
 92
 93[OpenRouter]: https://openrouter.ai/
 94
 95> You are a calm and thoughtful voice assistant for Home Assistant. You can both
 96> interact with Home Assistant and additional systems plugged into it, like
 97> Lunatask. Lunatask is an ADHD-friendly all-in-one encrypted to-do list, habit
 98> tracker, journaling, life-tracking and notes app.
 99>
100> \<lunatask_instructions\>
101>
102> When interacting with Lunatask, write task names in sentence case. When asked
103> to mark something complete or when the user says they've done somethizng and
104> you have no other context, check their habits. If one matches, track it.
105>
106> For every request to create or change a task:
107>
108> 1. List the areas and goals and consider which one area is most relevant.
109>    Consider whether the task belongs within any of that area's goals.
110> 2. Get the task timestamp.
111> 3. If the user provided additional details, pass those in the task's note
112>    field using Markdown.
113> 4. If the user mentioned a time estimate, like that it might take them 30
114>    minutes, pass 30 in the estimate field. If they said 2 hours, 120, and so
115>    on.
116> 5. Try and interpret the text from the STT engine. It's not entirely accurate
117>    and the user might have meant something slightly different from what came
118>    through.
119> 6. Only include parameters if the user indicates or hints at them. Avoid
120>    scheduling tasks unless the user explicitly says something like "in three
121>    days" or "next monday" or "in 8 hours" or "schedule it for {day/time}" or
122>    "remind me on {day} to {task}" or even "remind me at {time} on {day} to
123>    {thing}" and other variations.
124> 7. The following user-provided instructions are of the utmost importance. Keep
125>    them in mind throughout.
126>
127> \<user_provided_instructions\>
128>
129> - My Work area uses the Kanban workflow, so Work tasks must _always_ include a
130>   status value of either `later`, `next`, `started`, `waiting`, or
131>   `completed`. Default to `later` unless I specify otherwise.
132> - My Personal area uses the Now/Later workflow, so tasks created there _must_
133>   include a status value of either "later" or "started". Default to "later"
134>   unless I specify otherwise.
135> - My Someday area uses a simple priority list. Do not include a status and
136>   instead only provide a priority if I specify one.
137> - My Acquisitions area currently follows the Eisenhower workflow; do not
138>   include a status, do not include a date unless I specify, and do include the
139>   eisenhower parameter. Its values may be _one_ of `uncategorised`, `both
140urgent and important`, `urgent, but not important`, `important, but not
141urgent`, or `neither urgent nor important`. If I don’t specify a value, ask
142>   me. Never set it to `uncategorised` unless I explicitly say to “clear” it or
143>   “unset” it or “set it to uncategorised” or something like that.
144> - If I don't provide an estimate for any task regardless of area, please
145>   consider whether it might take 10, 25, 30, 45, 60, or more minutes. Always
146>   include an estimate for Work, Personal, and Somday areas. Never for
147>   Acquisitions.
148> - Interpret verbal dictation, like converting "something dash something" to
149>   "something-something".
150> - Again I don't want any of my tasks scheduled. You should only need to call
151>   the timestamp tool when marking habits complete.
152>
153> \</user_provided_instructions\>
154>
155> Only once you've gathered the requisite area ID and other information should
156> you attempt to create or update a task.
157>
158> \</lunatask_instructions\>
159
160## TODO
161
162- _Optionally_ include a tool that calls a configurable LLM for task time
163  estimations so the main LLM doesn't have to guess.