AGENTS.md
MCP server exposing Lunatask (task/habit tracker) to LLMs via SSE. Primary use case: Home Assistant voice assistant says "remind me to call mom tomorrow" → HA's LLM calls this server's create_task tool → task appears in Lunatask.
Commands
just # Run all checks (fmt, lint, staticcheck, test, vuln, reuse)
just build # Build with version info
just run # Build and run
Architecture
cmd/lunatask-mcp-server.go → Config, tool registration, SSE server
tools/ → MCP tool handlers
lunatask/ → HTTP client for Lunatask API
Data flow: SSE request → MCP server → tool handler → lunatask client → Lunatask API
Domain model: Areas contain Goals. Habits are separate. Tasks belong to an Area and optionally a Goal.
Adding New Functionality
New MCP tool:
- Add handler method to
tools/(onHandlersstruct) - Register tool with
mcpServer.AddTool()incmd/lunatask-mcp-server.go
New API endpoint: Add method to lunatask/Client with request/response types
Key Patterns
- 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 - Error returns: Handlers return
(result, nil)withIsError: true—application errors go in the result, not the Go error - Enum translation: Human strings (
"high") → API integers (1) in handlers before calling client - Provider interfaces:
tools/defines interfaces (AreaProvider, etc.) thatcmd/types implement, keeping packages decoupled
Gotchas
- Area/goal/habit IDs are static in config, not fetched—Lunatask API has no list endpoint
CreateTaskreturns(nil, nil)on HTTP 204 (task already exists)—not an errorupdate_taskMCP tool requiresnameeven for partial updates- No tests exist yet
- All files need SPDX headers (
just reusechecks this)
Contributing
Patches via pr.pico.sh:
git format-patch origin/main --stdout | ssh pr.pico.sh pr create amolith/llm-projects