handler.go

 1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
 2//
 3// SPDX-License-Identifier: AGPL-3.0-or-later
 4
 5// Package areas provides the areas MCP resource for listing areas and goals.
 6package areas
 7
 8import (
 9	"context"
10	"encoding/json"
11
12	"github.com/modelcontextprotocol/go-sdk/mcp"
13
14	"git.secluded.site/lunatask-mcp-server/tools/shared"
15)
16
17// ResourceURI is the URI for the areas resource.
18const ResourceURI = "lunatask://areas"
19
20// Handler handles area-related MCP resource requests.
21type Handler struct {
22	areas []shared.AreaProvider
23}
24
25// NewHandler creates a new areas Handler.
26func NewHandler(areas []shared.AreaProvider) *Handler {
27	return &Handler{areas: areas}
28}
29
30// AreaInfo represents an area with its goals for JSON serialization.
31type AreaInfo struct {
32	Key   string     `json:"key"`
33	Name  string     `json:"name"`
34	ID    string     `json:"id"`
35	Goals []GoalInfo `json:"goals,omitempty"`
36}
37
38// GoalInfo represents a goal for JSON serialization.
39type GoalInfo struct {
40	Key  string `json:"key"`
41	Name string `json:"name"`
42	ID   string `json:"id"`
43}
44
45// HandleRead handles the areas resource read request.
46func (h *Handler) HandleRead(
47	_ context.Context,
48	_ *mcp.ReadResourceRequest,
49) (*mcp.ReadResourceResult, error) {
50	areasInfo := make([]AreaInfo, 0, len(h.areas))
51
52	for _, area := range h.areas {
53		areaInfo := AreaInfo{
54			Key:   area.GetKey(),
55			Name:  area.GetName(),
56			ID:    area.GetID(),
57			Goals: make([]GoalInfo, 0, len(area.GetGoals())),
58		}
59
60		for _, goal := range area.GetGoals() {
61			areaInfo.Goals = append(areaInfo.Goals, GoalInfo{
62				Key:  goal.GetKey(),
63				Name: goal.GetName(),
64				ID:   goal.GetID(),
65			})
66		}
67
68		areasInfo = append(areasInfo, areaInfo)
69	}
70
71	data, err := json.MarshalIndent(areasInfo, "", "  ")
72	if err != nil {
73		return nil, err
74	}
75
76	return &mcp.ReadResourceResult{
77		Contents: []*mcp.ResourceContents{{
78			URI:      ResourceURI,
79			MIMEType: "application/json",
80			Text:     string(data),
81		}},
82	}, nil
83}