AGENTS.md

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:

  1. Add handler method to tools/ (on Handlers struct)
  2. Register tool with mcpServer.AddTool() in cmd/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) with IsError: 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.) that cmd/ types implement, keeping packages decoupled

Gotchas

  • Area/goal/habit IDs are static in config, not fetched—Lunatask API has no list endpoint
  • CreateTask returns (nil, nil) on HTTP 204 (task already exists)—not an error
  • update_task MCP tool requires name even for partial updates
  • No tests exist yet
  • All files need SPDX headers (just reuse checks this)

Contributing

Patches via pr.pico.sh:

git format-patch origin/main --stdout | ssh pr.pico.sh pr create amolith/llm-projects