from mcp.server.fastmcp import FastMCP from PIL import Image, ImageDraw, ImageFont import os import textwrap # Initialize the FastMCP server mcp = FastMCP("recipe-maker") # Constants RECIPE_DIR = "recipes" IMAGE_DIR = "recipes/images" # Ensure directories exist os.makedirs(RECIPE_DIR, exist_ok=True) os.makedirs(IMAGE_DIR, exist_ok=True) def create_placeholder(text: str, file_path: str, color: str = "lightgray"): """Creates a simple placeholder image with text.""" width, height = 1024, 1024 img = Image.new('RGB', (width, height), color=color) d = ImageDraw.Draw(img) # Simple text centering logic try: # Try to load a font, otherwise fallback to default font = ImageFont.load_default() # Scale up text if possible (rudimentary) # In a real app we'd load a TTF except: font = None text_lines = textwrap.wrap(text, width=40) y_text = height // 2 - (len(text_lines) * 15) for line in text_lines: d.text((width // 2, y_text), line, fill="black", anchor="mm", font=font) y_text += 30 img.save(file_path) def generate_nanobanana_hero_prompt(title: str, description: str) -> str: return ( f"Photorealistic hero shot of {title}, {description}. " "Professional food photography, high detailed, appetizing, 4k resolution, soft natural lighting." ) def generate_nanobanana_prep_prompt(title: str, ingredients: list[str]) -> str: ing_list = ", ".join(ingredients[:5]) # Top 5 ingredients return ( f"Photorealistic overhead shot of ingredients for {title}, including {ing_list}. " "Kitchen workspace with bowls, mixers, and utensils. Clean, organized, bright lighting." ) @mcp.tool() def create_recipe(title: str, description: str, ingredients: list[str], steps: list[str], servings: str) -> str: """ Creates a recipe as a Markdown file with placeholder images. Args: title: The title of the recipe. description: A brief description. ingredients: List of ingredient strings (e.g. "1 cup flour"). steps: List of cooking steps. servings: Serving size information. """ safe_title = "".join(c for c in title if c.isalnum() or c in (' ', '_')).replace(' ', '_').lower() recipe_filename = os.path.join(RECIPE_DIR, f"{safe_title}.md") hero_img_name = f"{safe_title}_hero.png" prep_img_name = f"{safe_title}_prep.png" hero_img_path = os.path.join(IMAGE_DIR, hero_img_name) prep_img_path = os.path.join(IMAGE_DIR, prep_img_name) # Generate prompts hero_prompt = generate_nanobanana_hero_prompt(title, description) prep_prompt = generate_nanobanana_prep_prompt(title, ingredients) # Create placeholders create_placeholder(f"HERO: {title}\nPrompt: {hero_prompt}", hero_img_path, color="lightblue") create_placeholder(f"PREP: {title}\nPrompt: {prep_prompt}", prep_img_path, color="lightgreen") # Create Markdown content md_content = f"""# {title} **Servings:** {servings} ## Description {description} ![Hero Image of {title}](images/{hero_img_name}) ## Ingredients """ for ing in ingredients: md_content += f"- {ing}\n" md_content += "\n## Steps\n" for i, step in enumerate(steps, 1): md_content += f"{i}. {step}\n" md_content += f""" ![Ingredients and Prep for {title}](images/{prep_img_name}) """ with open(recipe_filename, "w") as f: f.write(md_content) return f"Recipe created at {recipe_filename}" @mcp.tool() def create_hero_image(title: str, description: str) -> str: """Generates a hero image placeholder and prompt.""" safe_title = "".join(c for c in title if c.isalnum() or c in (' ', '_')).replace(' ', '_').lower() img_name = f"{safe_title}_hero_custom.png" img_path = os.path.join(IMAGE_DIR, img_name) prompt = generate_nanobanana_hero_prompt(title, description) create_placeholder(f"HERO: {title}\nPrompt: {prompt}", img_path, color="lightblue") return f"Created placeholder at {img_path}. Prompt: {prompt}" @mcp.tool() def create_prep_image(title: str, ingredients: list[str]) -> str: """Generates a prep image placeholder and prompt.""" safe_title = "".join(c for c in title if c.isalnum() or c in (' ', '_')).replace(' ', '_').lower() img_name = f"{safe_title}_prep_custom.png" img_path = os.path.join(IMAGE_DIR, img_name) prompt = generate_nanobanana_prep_prompt(title, ingredients) create_placeholder(f"PREP: {title}\nPrompt: {prompt}", img_path, color="lightgreen") return f"Created placeholder at {img_path}. Prompt: {prompt}" if __name__ == "__main__": mcp.run()