create.go

  1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
  2//
  3// SPDX-License-Identifier: AGPL-3.0-or-later
  4
  5// Package journal provides MCP tools for Lunatask journal operations.
  6package journal
  7
  8import (
  9	"context"
 10
 11	"git.secluded.site/go-lunatask"
 12	"git.secluded.site/lune/internal/dateutil"
 13	"git.secluded.site/lune/internal/mcp/shared"
 14	"github.com/modelcontextprotocol/go-sdk/mcp"
 15)
 16
 17// CreateToolName is the name of the create journal entry tool.
 18const CreateToolName = "add_journal_entry"
 19
 20// CreateToolDescription describes the create journal entry tool for LLMs.
 21const CreateToolDescription = `Creates a journal entry in Lunatask for daily reflection.
 22
 23Optional:
 24- content: Markdown content for the entry
 25- name: Entry title (defaults to weekday name if omitted)
 26- date: Entry date (YYYY-MM-DD or natural language, default: today)
 27
 28Entries are date-keyed. If no date is provided, uses today.
 29Content supports Markdown formatting.
 30
 31Common uses:
 32- End-of-day summaries
 33- Reflection on completed work
 34- Recording thoughts or learnings`
 35
 36// CreateInput is the input schema for creating a journal entry.
 37type CreateInput struct {
 38	Content *string `json:"content,omitempty"`
 39	Name    *string `json:"name,omitempty"`
 40	Date    *string `json:"date,omitempty"`
 41}
 42
 43// CreateOutput is the output schema for creating a journal entry.
 44type CreateOutput struct {
 45	ID   string `json:"id"`
 46	Date string `json:"date"`
 47}
 48
 49// Handler handles journal-related MCP tool requests.
 50type Handler struct {
 51	client *lunatask.Client
 52}
 53
 54// NewHandler creates a new journal handler.
 55func NewHandler(accessToken string) *Handler {
 56	return &Handler{
 57		client: lunatask.NewClient(accessToken, lunatask.UserAgent("lune-mcp/1.0")),
 58	}
 59}
 60
 61// HandleCreate creates a new journal entry.
 62func (h *Handler) HandleCreate(
 63	ctx context.Context,
 64	_ *mcp.CallToolRequest,
 65	input CreateInput,
 66) (*mcp.CallToolResult, CreateOutput, error) {
 67	dateStr := ""
 68	if input.Date != nil {
 69		dateStr = *input.Date
 70	}
 71
 72	date, err := dateutil.Parse(dateStr)
 73	if err != nil {
 74		return shared.ErrorResult(err.Error()), CreateOutput{}, nil
 75	}
 76
 77	builder := h.client.NewJournalEntry(date)
 78
 79	if input.Content != nil {
 80		builder.WithContent(*input.Content)
 81	}
 82
 83	if input.Name != nil {
 84		builder.WithName(*input.Name)
 85	}
 86
 87	entry, err := builder.Create(ctx)
 88	if err != nil {
 89		return shared.ErrorResult(err.Error()), CreateOutput{}, nil
 90	}
 91
 92	formattedDate := date.Format("2006-01-02")
 93
 94	return &mcp.CallToolResult{
 95			Content: []mcp.Content{&mcp.TextContent{
 96				Text: "Journal entry created for " + formattedDate,
 97			}},
 98		}, CreateOutput{
 99			ID:   entry.ID,
100			Date: formattedDate,
101		}, nil
102}