-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.py
More file actions
143 lines (111 loc) · 4.74 KB
/
server.py
File metadata and controls
143 lines (111 loc) · 4.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
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 = "/tmp/staging/recipes"
IMAGE_DIR = "/tmp/staging/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 with details.
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}

<!--
NANOBANANA HERO PROMPT:
{hero_prompt}
-->
## Ingredients
"""
for ing in ingredients:
md_content += f"- {ing}\n"
md_content += f"""

<!--
NANOBANANA PREP PROMPT:
{prep_prompt}
-->
"""
md_content += "\n## Steps\n"
for i, step in enumerate(steps, 1):
md_content += f"{i}. {step}\n"
# Return the markdown content directly so the client can write the file
return md_content
@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()