@@ -20,6 +20,7 @@ import (
taskrs "git.secluded.site/lune/internal/mcp/resources/task"
"git.secluded.site/lune/internal/mcp/shared"
"git.secluded.site/lune/internal/mcp/tools/habit"
+ "git.secluded.site/lune/internal/mcp/tools/journal"
"git.secluded.site/lune/internal/mcp/tools/task"
"git.secluded.site/lune/internal/mcp/tools/timestamp"
"github.com/modelcontextprotocol/go-sdk/mcp"
@@ -137,6 +138,31 @@ func registerTools(
}, tsHandler.Handle)
}
+ registerTaskTools(mcpServer, tools, accessToken, areaProviders)
+
+ if tools.TrackHabit {
+ habitHandler := habit.NewHandler(accessToken, habitProviders)
+ mcp.AddTool(mcpServer, &mcp.Tool{
+ Name: habit.TrackToolName,
+ Description: habit.TrackToolDescription,
+ }, habitHandler.HandleTrack)
+ }
+
+ if tools.CreateJournal {
+ journalHandler := journal.NewHandler(accessToken)
+ mcp.AddTool(mcpServer, &mcp.Tool{
+ Name: journal.CreateToolName,
+ Description: journal.CreateToolDescription,
+ }, journalHandler.HandleCreate)
+ }
+}
+
+func registerTaskTools(
+ mcpServer *mcp.Server,
+ tools *config.ToolsConfig,
+ accessToken string,
+ areaProviders []shared.AreaProvider,
+) {
taskHandler := task.NewHandler(accessToken, areaProviders)
if tools.CreateTask {
@@ -173,14 +199,6 @@ func registerTools(
Description: task.ShowToolDescription,
}, taskHandler.HandleShow)
}
-
- if tools.TrackHabit {
- habitHandler := habit.NewHandler(accessToken, habitProviders)
- mcp.AddTool(mcpServer, &mcp.Tool{
- Name: habit.TrackToolName,
- Description: habit.TrackToolDescription,
- }, habitHandler.HandleTrack)
- }
}
func runStdio(mcpServer *mcp.Server) error {
@@ -0,0 +1,102 @@
+// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+// Package journal provides MCP tools for Lunatask journal operations.
+package journal
+
+import (
+ "context"
+
+ "git.secluded.site/go-lunatask"
+ "git.secluded.site/lune/internal/dateutil"
+ "git.secluded.site/lune/internal/mcp/shared"
+ "github.com/modelcontextprotocol/go-sdk/mcp"
+)
+
+// CreateToolName is the name of the create journal entry tool.
+const CreateToolName = "add_journal_entry"
+
+// CreateToolDescription describes the create journal entry tool for LLMs.
+const CreateToolDescription = `Creates a journal entry in Lunatask for daily reflection.
+
+Optional:
+- content: Markdown content for the entry
+- name: Entry title (defaults to weekday name if omitted)
+- date: Entry date (YYYY-MM-DD or natural language, default: today)
+
+Entries are date-keyed. If no date is provided, uses today.
+Content supports Markdown formatting.
+
+Common uses:
+- End-of-day summaries
+- Reflection on completed work
+- Recording thoughts or learnings`
+
+// CreateInput is the input schema for creating a journal entry.
+type CreateInput struct {
+ Content *string `json:"content,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Date *string `json:"date,omitempty"`
+}
+
+// CreateOutput is the output schema for creating a journal entry.
+type CreateOutput struct {
+ ID string `json:"id"`
+ Date string `json:"date"`
+}
+
+// Handler handles journal-related MCP tool requests.
+type Handler struct {
+ client *lunatask.Client
+}
+
+// NewHandler creates a new journal handler.
+func NewHandler(accessToken string) *Handler {
+ return &Handler{
+ client: lunatask.NewClient(accessToken, lunatask.UserAgent("lune-mcp/1.0")),
+ }
+}
+
+// HandleCreate creates a new journal entry.
+func (h *Handler) HandleCreate(
+ ctx context.Context,
+ _ *mcp.CallToolRequest,
+ input CreateInput,
+) (*mcp.CallToolResult, CreateOutput, error) {
+ dateStr := ""
+ if input.Date != nil {
+ dateStr = *input.Date
+ }
+
+ date, err := dateutil.Parse(dateStr)
+ if err != nil {
+ return shared.ErrorResult(err.Error()), CreateOutput{}, nil
+ }
+
+ builder := h.client.NewJournalEntry(date)
+
+ if input.Content != nil {
+ builder.WithContent(*input.Content)
+ }
+
+ if input.Name != nil {
+ builder.WithName(*input.Name)
+ }
+
+ entry, err := builder.Create(ctx)
+ if err != nil {
+ return shared.ErrorResult(err.Error()), CreateOutput{}, nil
+ }
+
+ formattedDate := date.Format("2006-01-02")
+
+ return &mcp.CallToolResult{
+ Content: []mcp.Content{&mcp.TextContent{
+ Text: "Journal entry created for " + formattedDate,
+ }},
+ }, CreateOutput{
+ ID: entry.ID,
+ Date: formattedDate,
+ }, nil
+}