added all mcp

This commit is contained in:
liph22
2025-12-19 23:59:54 +01:00
parent edfffd76e1
commit 14bc398915
6240 changed files with 2421602 additions and 0 deletions

View File

@@ -0,0 +1,305 @@
import json
import logging
import traceback
from typing import List, Optional
from mcp.server.fastmcp import FastMCP
from mealie import MealieFetcher
from models.recipe import Recipe, RecipeIngredient, RecipeInstruction, RecipeNutrition
from utils import format_error_response
logger = logging.getLogger("mealie-mcp")
def register_recipe_tools(mcp: FastMCP, mealie: MealieFetcher) -> None:
"""Register all recipe-related tools with the MCP server."""
@mcp.tool()
def get_recipes(
search: Optional[str] = None,
page: Optional[int] = None,
per_page: Optional[int] = None,
categories: Optional[List[str]] = None,
tags: Optional[List[str]] = None,
) -> str:
"""Provides a paginated list of recipes with optional filtering.
Args:
search: Filters recipes by name or description.
page: Page number for pagination.
per_page: Number of items per page.
categories: Filter by specific recipe categories.
tags: Filter by specific recipe tags.
Returns:
str: Recipe summaries with details like ID, name, description, and image information.
"""
try:
logger.info(
{
"message": "Fetching recipes",
"search": search,
"page": page,
"per_page": per_page,
"categories": categories,
"tags": tags,
}
)
result = mealie.get_recipes(
search=search,
page=page,
per_page=per_page,
categories=categories,
tags=tags,
)
return json.dumps(result, indent=2)
except Exception as e:
error_msg = f"Error fetching recipes: {str(e)}"
logger.error({"message": error_msg})
logger.debug(
{"message": "Error traceback", "traceback": traceback.format_exc()}
)
return format_error_response(error_msg)
@mcp.tool()
def get_recipe_detailed(slug: str) -> str:
"""Retrieve a specific recipe by its slug identifier. Use this when to get full recipe
details for tasks like updating or displaying the recipe.
Args:
slug: The unique text identifier for the recipe, typically found in recipe URLs
or from get_recipes results.
Returns:
str: Comprehensive recipe details including ingredients, instructions,
nutrition information, notes, and associated metadata.
"""
try:
logger.info({"message": "Fetching recipe", "slug": slug})
result = mealie.get_recipe(slug)
return json.dumps(result, indent=2)
except Exception as e:
error_msg = f"Error fetching recipe with slug '{slug}': {str(e)}"
logger.error({"message": error_msg})
logger.debug(
{"message": "Error traceback", "traceback": traceback.format_exc()}
)
return format_error_response(error_msg)
@mcp.tool()
def get_recipe_concise(slug: str) -> str:
"""Retrieve a concise version of a specific recipe by its slug identifier. Use this when you only
need a summary of the recipe, such as for when mealplaning.
Args:
slug: The unique text identifier for the recipe, typically found in recipe URLs
or from get_recipes results.
"""
try:
logger.info({"message": "Fetching recipe", "slug": slug})
recipe_json = mealie.get_recipe(slug)
recipe = Recipe.model_validate(recipe_json)
return json.dumps(recipe.model_dump(
include={
"name",
"slug",
"recipeServings",
"recipeYieldQuantity",
"recipeYield",
"totalTime",
"rating",
"recipeIngredient",
"lastMade",
},
exclude_none=True,
), indent=2)
except Exception as e:
error_msg = f"Error fetching recipe with slug '{slug}': {str(e)}"
logger.error({"message": error_msg})
logger.debug(
{"message": "Error traceback", "traceback": traceback.format_exc()}
)
return format_error_response(error_msg)
@mcp.tool()
def create_recipe(
name: str,
ingredients: list[str],
instructions: list[str],
prep_time: Optional[str] = None,
cook_time: Optional[str] = None,
total_time: Optional[str] = None,
recipe_yield: Optional[str] = None,
servings: Optional[int] = None,
description: Optional[str] = None,
calories: Optional[str] = None,
protein: Optional[str] = None,
carbohydrates: Optional[str] = None,
fat: Optional[str] = None,
fiber: Optional[str] = None,
sugar: Optional[str] = None,
sodium: Optional[str] = None,
) -> str:
"""Create a new recipe
Args:
name: The name of the new recipe to be created.
ingredients: A list of ingredients for the recipe include quantities and units.
instructions: A list of instructions for preparing the recipe.
prep_time: Preparation time (e.g., "30min", "1h", "1h 30min")
cook_time: Cooking time (e.g., "45min", "1h 15min")
total_time: Total time (e.g., "90min", "2h")
recipe_yield: What the recipe yields (e.g., "4 servings", "12 cookies")
servings: Number of servings as integer
description: A brief description of the recipe
calories: Calories per serving (e.g., "350")
protein: Protein content (e.g., "25g")
carbohydrates: Carbohydrate content (e.g., "40g")
fat: Fat content (e.g., "15g")
fiber: Fiber content (e.g., "5g")
sugar: Sugar content (e.g., "8g")
sodium: Sodium content (e.g., "600mg")
Returns:
str: Confirmation message or details about the created recipe.
"""
try:
logger.info({"message": "Creating recipe", "name": name})
slug = mealie.create_recipe(name)
recipe_json = mealie.get_recipe(slug)
recipe = Recipe.model_validate(recipe_json)
recipe.recipeIngredient = [RecipeIngredient(note=i) for i in ingredients]
recipe.recipeInstructions = [
RecipeInstruction(text=i) for i in instructions
]
# Set time information if provided
if prep_time:
recipe.prepTime = prep_time
if cook_time:
recipe.cookTime = cook_time
if total_time:
recipe.totalTime = total_time
if recipe_yield:
recipe.recipeYield = recipe_yield
if servings:
recipe.recipeServings = servings
if description:
recipe.description = description
# Set nutrition information if provided
if any([calories, protein, carbohydrates, fat, fiber, sugar, sodium]):
nutrition = RecipeNutrition()
if calories:
nutrition.calories = calories
if protein:
nutrition.proteinContent = protein
if carbohydrates:
nutrition.carbohydrateContent = carbohydrates
if fat:
nutrition.fatContent = fat
if fiber:
nutrition.fiberContent = fiber
if sugar:
nutrition.sugarContent = sugar
if sodium:
nutrition.sodiumContent = sodium
recipe.nutrition = nutrition
result = mealie.update_recipe(slug, recipe.model_dump(exclude_none=True))
return json.dumps(result, indent=2)
except Exception as e:
error_msg = f"Error creating recipe '{name}': {str(e)}"
logger.error({"message": error_msg})
logger.debug(
{"message": "Error traceback", "traceback": traceback.format_exc()}
)
return format_error_response(error_msg)
@mcp.tool()
def update_recipe(
slug: str,
ingredients: Optional[list[str]] = None,
instructions: Optional[list[str]] = None,
prep_time: Optional[str] = None,
cook_time: Optional[str] = None,
total_time: Optional[str] = None,
recipe_yield: Optional[str] = None,
servings: Optional[int] = None,
description: Optional[str] = None,
calories: Optional[str] = None,
protein: Optional[str] = None,
carbohydrates: Optional[str] = None,
fat: Optional[str] = None,
fiber: Optional[str] = None,
sugar: Optional[str] = None,
sodium: Optional[str] = None,
) -> str:
"""Update an existing recipe with new information.
Args:
slug: The unique text identifier for the recipe to be updated.
ingredients: A list of ingredients for the recipe include quantities and units.
instructions: A list of instructions for preparing the recipe.
prep_time: Preparation time (e.g., "PT15M" for 15 minutes in ISO 8601 format)
cook_time: Cooking time (e.g., "PT30M" for 30 minutes)
total_time: Total time (e.g., "PT45M" for 45 minutes)
recipe_yield: What the recipe yields (e.g., "4 servings")
servings: Number of servings as integer
description: A brief description of the recipe
Returns:
str: Confirmation message or details about the updated recipe.
"""
try:
logger.info({"message": "Updating recipe", "slug": slug})
recipe_json = mealie.get_recipe(slug)
recipe = Recipe.model_validate(recipe_json)
if ingredients:
recipe.recipeIngredient = [RecipeIngredient(note=i) for i in ingredients]
if instructions:
recipe.recipeInstructions = [
RecipeInstruction(text=i) for i in instructions
]
if prep_time:
recipe.prepTime = prep_time
if cook_time:
recipe.cookTime = cook_time
if total_time:
recipe.totalTime = total_time
if recipe_yield:
recipe.recipeYield = recipe_yield
if servings:
recipe.recipeServings = servings
if description:
recipe.description = description
if any([calories, protein, carbohydrates, fat, fiber, sugar, sodium]):
if not recipe.nutrition:
recipe.nutrition = RecipeNutrition()
if calories:
recipe.nutrition.calories = calories
if protein:
recipe.nutrition.proteinContent = protein
if carbohydrates:
recipe.nutrition.carbohydrateContent = carbohydrates
if fat:
recipe.nutrition.fatContent = fat
if fiber:
recipe.nutrition.fiberContent = fiber
if sugar:
recipe.nutrition.sugarContent = sugar
if sodium:
recipe.nutrition.sodiumContent = sodium
result = mealie.update_recipe(slug, recipe.model_dump(exclude_none=True))
return json.dumps(result, indent=2)
except Exception as e:
error_msg = f"Error updating recipe '{slug}': {str(e)}"
logger.error({"message": error_msg})
logger.debug(
{"message": "Error traceback", "traceback": traceback.format_exc()}
)
return format_error_response(error_msg)