Skip to main content
Glama
cookbook.py7.76 kB
"""Pydantic models for Cookbook app responses.""" from typing import List, Optional, Union from pydantic import BaseModel, ConfigDict, Field from .base import BaseResponse, IdResponse, StatusResponse class Nutrition(BaseModel): """Nutrition information following schema.org/NutritionInformation.""" type: str = Field( default="NutritionInformation", alias="@type", description="Schema.org object type", ) calories: Optional[str] = Field(None, description="Calories (e.g., '650 kcal')") carbohydrateContent: Optional[str] = Field( None, description="Carbohydrates (e.g., '300 g')" ) cholesterolContent: Optional[str] = Field( None, description="Cholesterol (e.g., '10 g')" ) fatContent: Optional[str] = Field(None, description="Fat (e.g., '45 g')") fiberContent: Optional[str] = Field(None, description="Fiber (e.g., '50 g')") proteinContent: Optional[str] = Field(None, description="Protein (e.g., '80 g')") saturatedFatContent: Optional[str] = Field( None, description="Saturated fat (e.g., '5 g')" ) servingSize: Optional[str] = Field( None, description="Serving size description (e.g., 'One plate')" ) sodiumContent: Optional[str] = Field(None, description="Sodium (e.g., '10 mg')") sugarContent: Optional[str] = Field(None, description="Sugar (e.g., '5 g')") transFatContent: Optional[str] = Field(None, description="Trans fat (e.g., '10 g')") unsaturatedFatContent: Optional[str] = Field( None, description="Unsaturated fat (e.g., '40 g')" ) model_config = ConfigDict(populate_by_name=True) class RecipeStub(BaseModel): """Stub of a recipe with basic information.""" id: str = Field(description="Recipe ID as string") recipe_id: int = Field(description="Recipe ID as integer (deprecated)") name: str = Field(description="Recipe name") keywords: Optional[str] = Field(default="", description="Comma-separated keywords") dateCreated: str = Field(description="Creation date (ISO8601)") dateModified: Optional[str] = Field( None, description="Last modified date (ISO8601)" ) imageUrl: str = Field(default="", description="URL of the recipe image") imagePlaceholderUrl: str = Field(default="", description="URL of placeholder image") class Recipe(BaseModel): """Full recipe following schema.org/Recipe specification.""" type: str = Field(default="Recipe", alias="@type", description="Schema.org type") id: Optional[str] = Field(None, description="Recipe ID") name: str = Field(description="Recipe name") description: str = Field(default="", description="Recipe description") url: str = Field(default="", description="Original recipe URL") image: str = Field(default="", description="URL of original recipe image") imageUrl: Optional[str] = Field( None, description="URL of the recipe image in Nextcloud" ) imagePlaceholderUrl: Optional[str] = Field( None, description="URL of placeholder image" ) keywords: str = Field(default="", description="Comma-separated keywords") dateCreated: Optional[str] = Field(None, description="Creation date (ISO8601)") dateModified: Optional[str] = Field( None, description="Last modified date (ISO8601)" ) prepTime: Optional[str] = Field(None, description="Preparation time (ISO8601)") cookTime: Optional[str] = Field(None, description="Cooking time (ISO8601)") totalTime: Optional[str] = Field(None, description="Total time (ISO8601)") recipeYield: Union[int, str] = Field(default=1, description="Number of servings") recipeCategory: str = Field(default="", description="Recipe category") tool: List[str] = Field(default_factory=list, description="Required tools") recipeIngredient: List[str] = Field( default_factory=list, description="List of ingredients" ) recipeInstructions: List[str] = Field( default_factory=list, description="Cooking instructions" ) nutrition: Optional[Nutrition] = Field(None, description="Nutrition information") model_config = ConfigDict(populate_by_name=True, extra="allow") class Category(BaseModel): """A recipe category.""" name: str = Field(description="Category name") recipe_count: int = Field(description="Number of recipes in category") class Keyword(BaseModel): """A recipe keyword/tag.""" name: str = Field(description="Keyword name") recipe_count: int = Field(description="Number of recipes with this keyword") class VisibleInfoBlocks(BaseModel): """Configuration for visible information blocks in the UI.""" preparation_time: Optional[bool] = Field( None, alias="preparation-time", description="Show preparation time" ) cooking_time: Optional[bool] = Field( None, alias="cooking-time", description="Show cooking time" ) total_time: Optional[bool] = Field( None, alias="total-time", description="Show total time" ) nutrition_information: Optional[bool] = Field( None, alias="nutrition-information", description="Show nutrition info" ) tools: Optional[bool] = Field(None, description="Show tools list") model_config = ConfigDict(populate_by_name=True) class CookbookConfig(BaseModel): """Cookbook app configuration.""" folder: Optional[str] = Field(None, description="Recipe folder path") update_interval: Optional[int] = Field( None, description="Auto-rescan interval in minutes" ) print_image: Optional[bool] = Field(None, description="Print images with recipes") visibleInfoBlocks: Optional[VisibleInfoBlocks] = Field( None, description="Visible info blocks configuration" ) class APIVersion(BaseModel): """API version information.""" epoch: int = Field(description="API epoch") major: int = Field(description="Major version") minor: int = Field(description="Minor version") class Version(BaseModel): """Version information for Cookbook app and API.""" cookbook_version: List[int] = Field(description="Cookbook app version") api_version: APIVersion = Field(description="API version") # Response models for MCP tools class ImportRecipeResponse(BaseResponse): """Response model for recipe import.""" recipe: Recipe = Field(description="The imported recipe") recipe_id: str = Field(description="ID of the imported recipe") class CreateRecipeResponse(IdResponse): """Response model for recipe creation.""" pass class UpdateRecipeResponse(IdResponse): """Response model for recipe update.""" pass class DeleteRecipeResponse(StatusResponse): """Response model for recipe deletion.""" deleted_id: int = Field(description="ID of deleted recipe") class ListRecipesResponse(BaseResponse): """Response model for listing recipes.""" recipes: List[RecipeStub] = Field(description="List of recipe stubs") total_count: int = Field(description="Total number of recipes") class SearchRecipesResponse(BaseResponse): """Response model for recipe search.""" recipes: List[RecipeStub] = Field(description="Matching recipes") query: str = Field(description="Search query used") total_found: int = Field(description="Number of recipes found") class ListCategoriesResponse(BaseResponse): """Response model for listing categories.""" categories: List[Category] = Field(description="List of categories") class ListKeywordsResponse(BaseResponse): """Response model for listing keywords.""" keywords: List[Keyword] = Field(description="List of keywords") class ReindexResponse(StatusResponse): """Response model for reindex operation.""" pass

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/No-Smoke/nextcloud-mcp-comprehensive'

If you have feedback or need assistance with the MCP directory API, please join our Discord server