mcp: rename preview_recipe_text to extract_into_recipe

Amolith created

Change summary

internal/mcp/server.go      | 54 +++++++++++++++++++-------------------
internal/mcp/server_test.go | 24 ++++++++--------
2 files changed, 39 insertions(+), 39 deletions(-)

Detailed changes

internal/mcp/server.go 🔗

@@ -22,7 +22,7 @@ const (
 	serverName                 = "Cooked"
 	maxShoppingListTextItems   = 30
 	readToolName               = "read"
-	previewRecipeTextToolName  = "preview_recipe_text"
+	extractIntoRecipeToolName  = "extract_into_recipe"
 	saveRecipeToolName         = "save_recipe"
 	deleteRecipeToolName       = "delete_recipe"
 	changeShoppingListToolName = "change_shopping_list"
@@ -63,7 +63,7 @@ func NewServer(backend Backend, version string) *Server {
 	server := &Server{backend: backend}
 	server.sdk = sdk.NewServer(&sdk.Implementation{Name: serverName, Title: serverName, Version: version}, nil)
 	sdk.AddTool(server.sdk, readTool(), server.callReadTool)
-	sdk.AddTool(server.sdk, previewRecipeTextTool(), server.callPreviewRecipeTextTool)
+	sdk.AddTool(server.sdk, extractIntoRecipeTool(), server.callExtractIntoRecipeTool)
 	sdk.AddTool(server.sdk, saveRecipeTool(), server.callSaveRecipeTool)
 	sdk.AddTool(server.sdk, deleteRecipeTool(), server.callDeleteRecipeTool)
 	sdk.AddTool(server.sdk, changeShoppingListTool(), server.callChangeShoppingListTool)
@@ -214,28 +214,28 @@ func (s *Server) readRecipeCards(
 	return recipes, "", nil
 }
 
-func (s *Server) callPreviewRecipeTextTool(
+func (s *Server) callExtractIntoRecipeTool(
 	ctx context.Context,
 	_ *sdk.CallToolRequest,
-	arguments PreviewRecipeTextArguments,
-) (*sdk.CallToolResult, PreviewRecipeTextOutput, error) {
+	arguments ExtractIntoRecipeArguments,
+) (*sdk.CallToolResult, ExtractIntoRecipeOutput, error) {
 	title := strings.TrimSpace(arguments.Title)
 	if title == "" {
-		return nil, PreviewRecipeTextOutput{}, fmt.Errorf("title is required")
+		return nil, ExtractIntoRecipeOutput{}, fmt.Errorf("title is required")
 	}
 	if strings.TrimSpace(arguments.Text) == "" {
-		return nil, PreviewRecipeTextOutput{}, fmt.Errorf("text is required")
+		return nil, ExtractIntoRecipeOutput{}, fmt.Errorf("text is required")
 	}
 
-	preview, err := s.backend.PreviewRecipeText(ctx, title, arguments.Text)
+	extraction, err := s.backend.PreviewRecipeText(ctx, title, arguments.Text)
 	if err != nil {
-		return nil, PreviewRecipeTextOutput{}, err
+		return nil, ExtractIntoRecipeOutput{}, err
 	}
 
-	output := PreviewRecipeTextOutput{
-		Title:    preview.Title,
-		Markdown: preview.Markdown,
-		Portions: preview.Portions,
+	output := ExtractIntoRecipeOutput{
+		Title:    extraction.Title,
+		Markdown: extraction.Markdown,
+		Portions: extraction.Portions,
 	}
 
 	return newToolResult(formatRecipeTextPreview(output), output), output, nil
@@ -646,14 +646,14 @@ func readTool() *sdk.Tool {
 	}
 }
 
-func previewRecipeTextTool() *sdk.Tool {
+func extractIntoRecipeTool() *sdk.Tool {
 	openWorld := true
 	return &sdk.Tool{
-		Name:        previewRecipeTextToolName,
-		Title:       "Preview recipe text",
-		Description: "Preview raw recipe text as Cooked recipe markdown and portions without saving or updating a recipe.",
+		Name:        extractIntoRecipeToolName,
+		Title:       "Extract raw recipe text into Cooked recipe",
+		Description: "Extract raw recipe text into Cooked recipe markdown and portions without saving or updating a recipe. Extraction rewrites ingredients and steps and infers portions; review the result before saving. If the extracted result is incorrect, save the correct version with source=prepared and your own markdown and portions.",
 		Annotations: &sdk.ToolAnnotations{
-			Title:         "Preview recipe text",
+			Title:         "Extract raw recipe text into Cooked recipe",
 			ReadOnlyHint:  true,
 			OpenWorldHint: &openWorld,
 		},
@@ -1010,14 +1010,14 @@ func formatRecipe(recipe RecipeDetail) string {
 	return strings.TrimRight(builder.String(), "\n")
 }
 
-func formatRecipeTextPreview(preview PreviewRecipeTextOutput) string {
+func formatRecipeTextPreview(preview ExtractIntoRecipeOutput) string {
 	title := preview.Title
 	if title == "" {
-		title = "(untitled preview)"
+		title = "(untitled extraction)"
 	}
 
 	var builder strings.Builder
-	builder.WriteString("Recipe text preview: ")
+	builder.WriteString("Extracted recipe text: ")
 	builder.WriteString(title)
 	builder.WriteByte('\n')
 	fmt.Fprintf(&builder, "Portions: %s\n", formatPortions(preview.Portions))
@@ -1108,14 +1108,14 @@ type RecipeDetail struct {
 	Portions float64 `json:"portions"`
 }
 
-// PreviewRecipeTextArguments contains preview_recipe_text tool arguments.
-type PreviewRecipeTextArguments struct {
-	Title string `json:"title" jsonschema:"Recipe title for the preview."`
-	Text  string `json:"text"  jsonschema:"Raw recipe text to preview without saving."`
+// ExtractIntoRecipeArguments contains extract_into_recipe tool arguments.
+type ExtractIntoRecipeArguments struct {
+	Title string `json:"title" jsonschema:"Recipe title for the extraction."`
+	Text  string `json:"text"  jsonschema:"Raw recipe text to extract into Cooked recipe markdown without saving."`
 }
 
-// PreviewRecipeTextOutput is the structured output for preview_recipe_text.
-type PreviewRecipeTextOutput struct {
+// ExtractIntoRecipeOutput is the structured output for extract_into_recipe.
+type ExtractIntoRecipeOutput struct {
 	Title    string  `json:"title"`
 	Markdown string  `json:"markdown"`
 	Portions float64 `json:"portions"`

internal/mcp/server_test.go 🔗

@@ -225,13 +225,13 @@ func TestCallToolACIDRecipesPreviewText1And4_1PreviewsRawText(t *testing.T) {
 	}}
 	server := NewServer(backend, "test")
 
-	result, output, err := server.callPreviewRecipeTextTool(
+	result, output, err := server.callExtractIntoRecipeTool(
 		context.Background(),
 		nil,
-		PreviewRecipeTextArguments{Title: " Pasta ", Text: "  Boil pasta.\n"},
+		ExtractIntoRecipeArguments{Title: " Pasta ", Text: "  Boil pasta.\n"},
 	)
 	if err != nil {
-		t.Fatalf("callPreviewRecipeTextTool() error = %v", err)
+		t.Fatalf("callExtractIntoRecipeTool() error = %v", err)
 	}
 
 	if backend.previewCalls != 1 {
@@ -245,39 +245,39 @@ func TestCallToolACIDRecipesPreviewText1And4_1PreviewsRawText(t *testing.T) {
 	}
 	if output.Title != "Pasta with Tomato Sauce" || output.Markdown != "# Pasta\n\n1. Boil pasta." ||
 		output.Portions != 2.5 {
-		t.Fatalf("preview output = %#v, want title/markdown/portions", output)
+		t.Fatalf("extraction output = %#v, want title/markdown/portions", output)
 	}
 	requireStructuredContent(t, result, output)
 }
 
-func TestCallToolACIDToolsPreviewRecipeTextTool1RequiresTitle(t *testing.T) {
+func TestCallToolACIDToolsExtractIntoRecipeTool1RequiresTitle(t *testing.T) {
 	backend := &fakeBackend{}
 	server := NewServer(backend, "test")
 
-	_, _, err := server.callPreviewRecipeTextTool(
+	_, _, err := server.callExtractIntoRecipeTool(
 		context.Background(),
 		nil,
-		PreviewRecipeTextArguments{Title: "   ", Text: "Boil pasta."},
+		ExtractIntoRecipeArguments{Title: "   ", Text: "Boil pasta."},
 	)
 	if err == nil {
-		t.Fatal("callPreviewRecipeTextTool() error = nil, want missing title error")
+		t.Fatal("callExtractIntoRecipeTool() error = nil, want missing title error")
 	}
 	if backend.previewCalls != 0 {
 		t.Fatalf("preview calls = %d, want none", backend.previewCalls)
 	}
 }
 
-func TestCallToolACIDToolsPreviewRecipeTextTool2RequiresText(t *testing.T) {
+func TestCallToolACIDToolsExtractIntoRecipeTool2RequiresText(t *testing.T) {
 	backend := &fakeBackend{}
 	server := NewServer(backend, "test")
 
-	_, _, err := server.callPreviewRecipeTextTool(
+	_, _, err := server.callExtractIntoRecipeTool(
 		context.Background(),
 		nil,
-		PreviewRecipeTextArguments{Title: "Pasta", Text: "   "},
+		ExtractIntoRecipeArguments{Title: "Pasta", Text: "   "},
 	)
 	if err == nil {
-		t.Fatal("callPreviewRecipeTextTool() error = nil, want missing text error")
+		t.Fatal("callExtractIntoRecipeTool() error = nil, want missing text error")
 	}
 	if backend.previewCalls != 0 {
 		t.Fatalf("preview calls = %d, want none", backend.previewCalls)