feat: allow task updates without area_id change

Amolith and Crush created

Co-Authored-By: Crush <crush@charm.land>

Change summary

cmd/lunatask-mcp-server.go | 2 +-
lunatask/tasks.go          | 2 +-
tools/tasks.go             | 4 ++++
3 files changed, 6 insertions(+), 2 deletions(-)

Detailed changes

cmd/lunatask-mcp-server.go 🔗

@@ -261,7 +261,7 @@ func NewMCPServer(appConfig *Config) *server.MCPServer {
 			mcp.Required(),
 		),
 		mcp.WithString("area_id",
-			mcp.Description("New Area ID for the task. Must be a valid area_id from list_areas_and_goals tool. Only include if moving the task to a different area."),
+			mcp.Description("New Area ID for the task. Must be a valid area_id from list_areas_and_goals tool. Only include if moving the task to a different area. If omitted, the task will remain in its current area."),
 		),
 		mcp.WithString("goal_id",
 			mcp.Description("New Goal ID for the task. Must be a valid goal_id from list_areas_and_goals that belongs to the task's area (current or new). Only include if changing the goal association."),

lunatask/tasks.go 🔗

@@ -44,7 +44,7 @@ type Task struct {
 
 // CreateTaskRequest represents the request to create a task in Lunatask
 type CreateTaskRequest struct {
-	AreaID      string `json:"area_id" validate:"omitempty,uuid4"`
+	AreaID      string `json:"area_id,omitempty" validate:"omitempty,uuid4"`
 	GoalID      string `json:"goal_id,omitempty" validate:"omitempty,uuid4"` // Assuming GoalID remains optional for tasks
 	Name        string `json:"name" validate:"required,max=100"`
 	Note        string `json:"note,omitempty" validate:"omitempty"`

tools/tasks.go 🔗

@@ -200,6 +200,8 @@ func (h *Handlers) HandleUpdateTask(ctx context.Context, request mcp.CallToolReq
 		} else if !ok && areaIDArg != nil {
 			return reportMCPError("Invalid type for area_id argument: expected string.")
 		}
+		// If area_id is not provided or is empty, we don't set it in the updatePayload
+		// This will leave the task in its current area
 	}
 
 	if goalIDArg, exists := arguments["goal_id"]; exists {
@@ -219,6 +221,8 @@ func (h *Handlers) HandleUpdateTask(ctx context.Context, request mcp.CallToolReq
 			} else if areaIDProvided {
 				return reportMCPError("Internal error: area_id provided but area details not loaded for goal validation.")
 			}
+			// If area_id is not provided, we're not moving the task to a different area
+			// In this case, the goal validation should be skipped as we don't know the current area
 		} else if !ok && goalIDArg != nil {
 			return reportMCPError("Invalid type for goal_id argument: expected string.")
 		}