list.go

 1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
 2//
 3// SPDX-License-Identifier: AGPL-3.0-or-later
 4
 5package habit
 6
 7import (
 8	"context"
 9	"fmt"
10	"strings"
11
12	"github.com/modelcontextprotocol/go-sdk/mcp"
13)
14
15// ListToolName is the name of the list habits tool.
16const ListToolName = "list_habits"
17
18// ListToolDescription describes the list habits tool for LLMs.
19const ListToolDescription = `Lists configured habits. Fallback for lunatask://habits resource.
20
21Returns habit metadata (id, name, key) from config.
22Use the lunatask://habits resource if your client supports MCP resources.`
23
24// ListInput is the input schema for listing habits.
25type ListInput struct{}
26
27// Summary represents a habit in the list output.
28type Summary struct {
29	ID   string `json:"id"`
30	Name string `json:"name"`
31	Key  string `json:"key"`
32}
33
34// ListOutput is the output schema for listing habits.
35type ListOutput struct {
36	Habits []Summary `json:"habits"`
37	Count  int       `json:"count"`
38}
39
40// HandleList lists configured habits.
41func (h *Handler) HandleList(
42	_ context.Context,
43	_ *mcp.CallToolRequest,
44	_ ListInput,
45) (*mcp.CallToolResult, ListOutput, error) {
46	summaries := make([]Summary, 0, len(h.habits))
47
48	for _, habit := range h.habits {
49		summaries = append(summaries, Summary{
50			ID:   habit.ID,
51			Name: habit.Name,
52			Key:  habit.Key,
53		})
54	}
55
56	output := ListOutput{
57		Habits: summaries,
58		Count:  len(summaries),
59	}
60
61	text := formatListText(summaries)
62
63	return &mcp.CallToolResult{
64		Content: []mcp.Content{&mcp.TextContent{Text: text}},
65	}, output, nil
66}
67
68func formatListText(habits []Summary) string {
69	if len(habits) == 0 {
70		return "No habits configured"
71	}
72
73	var text strings.Builder
74
75	text.WriteString(fmt.Sprintf("Found %d habit(s):\n", len(habits)))
76
77	for _, h := range habits {
78		text.WriteString(fmt.Sprintf("- %s: %s (%s)\n", h.Key, h.Name, h.ID))
79	}
80
81	return text.String()
82}