1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
2//
3// SPDX-License-Identifier: AGPL-3.0-or-later
4
5// Package notebooks provides the MCP resource handler for Lunatask notebooks.
6package notebooks
7
8import (
9 "context"
10 "encoding/json"
11 "fmt"
12
13 "git.secluded.site/lune/internal/mcp/shared"
14 "github.com/modelcontextprotocol/go-sdk/mcp"
15)
16
17// ResourceURI is the URI for the notebooks resource.
18const ResourceURI = "lunatask://notebooks"
19
20// ResourceDescription describes the notebooks resource for LLMs.
21const ResourceDescription = `Lists all configured Lunatask notebooks.
22
23Each notebook contains:
24- id: UUID to use when creating notes in this notebook
25- name: Human-readable notebook name
26- key: Short alias for CLI usage
27
28Use this resource to discover valid notebook IDs before creating or updating notes.`
29
30// Handler handles notebook resource requests.
31type Handler struct {
32 notebooks []shared.NotebookProvider
33}
34
35// NewHandler creates a new notebooks resource handler.
36func NewHandler(notebooks []shared.NotebookProvider) *Handler {
37 return &Handler{notebooks: notebooks}
38}
39
40// notebookInfo represents a notebook in the resource response.
41type notebookInfo struct {
42 ID string `json:"id"`
43 Name string `json:"name"`
44 Key string `json:"key"`
45}
46
47// HandleRead returns the configured notebooks.
48func (h *Handler) HandleRead(
49 _ context.Context,
50 _ *mcp.ReadResourceRequest,
51) (*mcp.ReadResourceResult, error) {
52 notebooksInfo := make([]notebookInfo, 0, len(h.notebooks))
53
54 for _, nb := range h.notebooks {
55 notebooksInfo = append(notebooksInfo, notebookInfo{
56 ID: nb.ID,
57 Name: nb.Name,
58 Key: nb.Key,
59 })
60 }
61
62 data, err := json.MarshalIndent(notebooksInfo, "", " ")
63 if err != nil {
64 return nil, fmt.Errorf("marshaling notebooks: %w", err)
65 }
66
67 return &mcp.ReadResourceResult{
68 Contents: []*mcp.ResourceContents{{
69 URI: ResourceURI,
70 MIMEType: "application/json",
71 Text: string(data),
72 }},
73 }, nil
74}