1<!--
2SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
3
4SPDX-License-Identifier: CC0-1.0
5-->
6
7# AGENTS.md
8
9MCP server exposing Lunatask to LLMs. Primary use case is letting the user say "remind me to call mom tomorrow" to their preferred MCP-supporting LLM, that LLM calls create_task, and the user sees the task in their desktop/mobile apps.
10
11If you know what doc-agent is, use it to check go module APIs often. You can check context7 for details on various libraries directly if the MCP tools are available:
12
13- [lunatask.app/api](https://lunatask.app/api) (`/websites/lunatask_app_api`) - Official Lunatask REST API documentation
14- [git.secluded.site/go-lunatask](https://git.secluded.site/go-lunatask) (`/websites/pkg_go_dev_git_secluded_site_go-lunatask`) - Go client for the Lunatask API
15- [github.com/charmbracelet/fang](https://github.com/charmbracelet/fang) (`/charmbracelet/fang`) - CLI starter kit with styled help, error handling, and version management for Cobra
16- [github.com/BurntSushi/toml](https://github.com/BurntSushi/toml) (`/burntsushi/toml`) - TOML parser and encoder for Go
17- [github.com/spf13/cobra](https://github.com/spf13/cobra) (`/websites/pkg_go_dev_github_com_spf13_cobra`) - CLI framework for Go
18- [github.com/markusmobius/go-dateparser](https://github.com/markusmobius/go-dateparser) (`/markusmobius/go-dateparser`) - Natural language date parsing supporting 200+ locales
19- [github.com/modelcontextprotocol/go-sdk](https://github.com/modelcontextprotocol/go-sdk) (`/modelcontextprotocol/go-sdk`) - Official Go SDK for the Model Context Protocol, providing APIs for constructing and using MCP clients and servers
20
21## Commands
22
23Run in order of most to least often
24
25```sh
26task fmt lint:fix test # frequently
27task # before committing
28```
29
30## Architecture
31
32```
33cmd/lunatask-mcp-server.go → Config, tool registration, SSE server
34tools/
35 ├── areas/ → list_areas_and_goals tool
36 ├── habits/ → list_habits, track_habit tools
37 ├── tasks/ → create/update/delete_task tools
38 ├── timestamp/ → get_timestamp tool
39 └── shared/ → Provider interfaces, error helpers
40```
41
42**Data flow**: SSE/STDIO request → MCP server → tool handler → lunatask client → Lunatask API
43
44**Domain model**: Areas contain Goals. Habits are separate. Tasks always belong to an Area and might belong to a Goal within that area.
45
46## Adding New Functionality
47
48**New MCP tool**:
49
501. Create package in `tools/` with `Handler` type and `NewHandler()` constructor
512. Add handler methods (`Handle`, `HandleCreate`, etc.) returning `(*mcp.CallToolResult, error)`
523. Put description constants in `prose.go` within the package
534. Register tool with `mcpServer.AddTool()` in `cmd/lunatask-mcp-server.go`
54
55## Key Patterns
56
57- **Tool descriptions are prompts**: The verbose `mcp.WithDescription()` strings guide the _calling_ LLM's behavior—they explain workflows, valid values, and when to use each tool
58- **Error returns**: Handlers return `(result, nil)` with `IsError: true`—application errors go in the result, not the Go error
59- **Enum translation**: Human strings (`"high"`) → API integers (`1`) in handlers before calling client
60- **Provider interfaces**: `tools/` defines interfaces (`AreaProvider`, etc.) that `cmd/` types implement, keeping packages decoupled
61
62## Gotchas
63
64- Area/goal/habit IDs are static in config, not fetched—Lunatask API has no list endpoint
65- `CreateTask` returns `(nil, nil)` on HTTP 204 (task already exists)—not an error
66- No tests exist yet
67- All files need appropriate SPDX headers based on content (`task reuse` checks this)