Spaces:
Sleeping
Sleeping
Sandra Sanchez commited on
Commit ·
3c635cb
1
Parent(s): bcade95
Improve prompts for real adaptation, separate tools to follow generate_story_base, adapt and translate, and then image generation and audio
Browse files- app.py +89 -32
- mcp_server/server.py +25 -9
- mcp_server/templates/dentist.json +1 -1
- mcp_server/templates/doctor.json +1 -1
- mcp_server/templates/first_day_school.json +1 -1
- mcp_server/templates/haircut.json +1 -1
- mcp_server/templates/loud_events.json +1 -1
- mcp_server/templates/new_food.json +1 -1
- mcp_server/templates/new_place.json +1 -1
- mcp_server/templates/physical_education.json +1 -1
- mcp_server/templates/pickup_from_school.json +1 -1
- mcp_server/templates/social_situations.json +1 -1
app.py
CHANGED
|
@@ -30,39 +30,66 @@ GENERATED_IMAGES_DIR.mkdir(exist_ok=True)
|
|
| 30 |
TEMP_DIR = Path(__file__).resolve().parent / "temp"
|
| 31 |
TEMP_DIR.mkdir(exist_ok=True)
|
| 32 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
|
| 34 |
def load_scenarios():
|
| 35 |
return [p.stem for p in TEMPLATES_DIR.glob("*.json")]
|
| 36 |
|
| 37 |
-
def
|
| 38 |
filepath = TEMPLATES_DIR / f"{scenario_name}.json"
|
| 39 |
if not filepath.exists():
|
| 40 |
return "Template not found."
|
| 41 |
template = json.loads(filepath.read_text())
|
| 42 |
story_prompt = (
|
| 43 |
-
f"Rewrite the following scenario into a simple, autism-friendly social story for
|
| 44 |
-
|
| 45 |
-
f"
|
| 46 |
-
"
|
| 47 |
-
"
|
| 48 |
-
|
| 49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
story_resp = client.chat.completions.create(
|
| 51 |
model="gpt-4o-mini",
|
| 52 |
messages=[{"role": "user", "content": story_prompt}]
|
| 53 |
)
|
| 54 |
return story_resp.choices[0].message.content.strip()
|
| 55 |
|
| 56 |
-
def generate_image(scenario_name: str, culture="default", age="7", gender="female", vibe="Cartoon", comfort_character="Koala"):
|
| 57 |
filepath = TEMPLATES_DIR / f"{scenario_name}.json"
|
| 58 |
if not filepath.exists():
|
| 59 |
return None
|
| 60 |
template = json.loads(filepath.read_text())
|
|
|
|
| 61 |
image_prompt = (
|
| 62 |
-
f"
|
| 63 |
-
f"
|
| 64 |
-
f"
|
| 65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
)
|
| 67 |
img = client.images.generate(
|
| 68 |
model="gpt-image-1",
|
|
@@ -70,6 +97,7 @@ def generate_image(scenario_name: str, culture="default", age="7", gender="femal
|
|
| 70 |
output_format="png",
|
| 71 |
size="1024x1024"
|
| 72 |
)
|
|
|
|
| 73 |
image_bytes = base64.b64decode(img.data[0].b64_json)
|
| 74 |
image = Image.open(io.BytesIO(image_bytes))
|
| 75 |
return image
|
|
@@ -78,14 +106,26 @@ def show_selected(scenario_name):
|
|
| 78 |
return f"You selected: {scenario_name}"
|
| 79 |
|
| 80 |
|
| 81 |
-
async def
|
|
|
|
|
|
|
| 82 |
server = await create_mcp_server()
|
| 83 |
context = {}
|
| 84 |
-
result = await server.request_handlers["
|
| 85 |
return result["adapted_story"]
|
| 86 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
async def call_voice_tool(story, language):
|
| 88 |
-
|
|
|
|
|
|
|
| 89 |
context = {}
|
| 90 |
result = await server.request_handlers["generate_voice"](context, story, language)
|
| 91 |
return result.get("audio", None)
|
|
@@ -95,12 +135,13 @@ def show_translation(story, language, culture):
|
|
| 95 |
|
| 96 |
def format_story(story):
|
| 97 |
# Texto grande y claro, sin asteriscos
|
|
|
|
| 98 |
return f"<div style='font-size:1.5em; line-height:1.6; font-weight:400'>{story}</div>"
|
| 99 |
|
| 100 |
def main():
|
| 101 |
print("Loading scenarios...")
|
| 102 |
scenarios = load_scenarios()
|
| 103 |
-
print("Scenarios loaded
|
| 104 |
|
| 105 |
with gr.Blocks() as demo:
|
| 106 |
gr.Markdown("# 🧸 Comfortool\n### Social stories with comforting illustrations to support autistic kids with daily challenges")
|
|
@@ -115,15 +156,15 @@ def main():
|
|
| 115 |
language_input = gr.Textbox(label="Translate to my language (e.g., 'es', 'fr')", value="en")
|
| 116 |
culture_input = gr.Textbox(label="My Community/Culture (e.g., 'Latino', 'Roma', 'Muslim')", value="default")
|
| 117 |
age_input = gr.Textbox(label="My age (e.g., '7')", value="7")
|
| 118 |
-
gender_input = gr.Textbox(label="Gender identity (e.g., 'boy', 'girl', 'non-binary')", value="
|
| 119 |
vibe_input = gr.Dropdown(
|
| 120 |
choices=["Comic", "Kawaii", "Pictorial", "Basic B&W", "Cartoon", "Soft Pastel"],
|
| 121 |
label="Vibe / illustration style",
|
| 122 |
value="Cartoon"
|
| 123 |
)
|
| 124 |
-
comfort_character_input = gr.Textbox(label="Favourite animal or character (e.g., 'Koala', '
|
| 125 |
|
| 126 |
-
generate_btn = gr.Button("
|
| 127 |
|
| 128 |
# Resultados en dos columnas
|
| 129 |
with gr.Row():
|
|
@@ -131,21 +172,38 @@ def main():
|
|
| 131 |
image_out = gr.Image(label="Illustration")
|
| 132 |
|
| 133 |
def on_generate(scenario_name, language, culture, age, gender, vibe, comfort_character):
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 141 |
|
| 142 |
generate_btn.click(
|
| 143 |
fn=on_generate,
|
| 144 |
-
inputs=[dropdown, language_input, culture_input, age_input,
|
| 145 |
-
outputs=[story_out, image_out, story_state]
|
|
|
|
| 146 |
)
|
| 147 |
|
| 148 |
-
|
| 149 |
def on_voice(story, language):
|
| 150 |
if not story or story.strip() == "":
|
| 151 |
return None
|
|
@@ -157,7 +215,7 @@ def main():
|
|
| 157 |
return audio_path
|
| 158 |
else:
|
| 159 |
return None
|
| 160 |
-
|
| 161 |
voice_btn = gr.Button("Listen to the story")
|
| 162 |
voice_out = gr.Audio(label="Story audio", type="filepath")
|
| 163 |
|
|
@@ -167,7 +225,6 @@ def main():
|
|
| 167 |
outputs=voice_out
|
| 168 |
)
|
| 169 |
|
| 170 |
-
|
| 171 |
print("Gradio app initialized.")
|
| 172 |
return demo
|
| 173 |
|
|
|
|
| 30 |
TEMP_DIR = Path(__file__).resolve().parent / "temp"
|
| 31 |
TEMP_DIR.mkdir(exist_ok=True)
|
| 32 |
|
| 33 |
+
VIBE_DESCRIPTIONS = {
|
| 34 |
+
"Comic": "comic-style illustration, bold outlines, dynamic poses, speech bubbles, vibrant colors",
|
| 35 |
+
"Kawaii": "kawaii-style illustration, pastel colors, cute rounded characters, big eyes",
|
| 36 |
+
"Pictorial": "pictorial illustration, as if it had been painted with a brush, gentle and calm atmosphere",
|
| 37 |
+
"Basic B&W": "black and white illustration, simple lines, no colors, like a coloring book. Only use black and white, no colours.",
|
| 38 |
+
"Cartoon": "cartoon-style illustration, exaggerated features, bright colors, playful mood",
|
| 39 |
+
"Soft Pastel": "soft pastel illustration, gentle colors, smooth textures, calming feeling"
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
|
| 43 |
def load_scenarios():
|
| 44 |
return [p.stem for p in TEMPLATES_DIR.glob("*.json")]
|
| 45 |
|
| 46 |
+
def generate_story_base(scenario_name: str, language="en", culture="default", age="7", gender="female",vibe="Cartoon", comfort_character="Koala"):
|
| 47 |
filepath = TEMPLATES_DIR / f"{scenario_name}.json"
|
| 48 |
if not filepath.exists():
|
| 49 |
return "Template not found."
|
| 50 |
template = json.loads(filepath.read_text())
|
| 51 |
story_prompt = (
|
| 52 |
+
f" Rewrite the following scenario into a simple, autism-friendly social story for an autistic child of age {age}, gender {gender}, from {culture}."
|
| 53 |
+
"<Use a maximum of 3 to 5 short and direct paragraphs.>"
|
| 54 |
+
f"{scenario_name}: {template}"
|
| 55 |
+
f"The story must include {comfort_character} as a friend to cope in the situation. Do not invent or mention any other character or animal."
|
| 56 |
+
"Use only a few short, direct sentences. Each sentence should describe one step or idea. Do not use long paragraphs."
|
| 57 |
+
"Do not use exclamation marks. Do not mention 'comfort character'."
|
| 58 |
+
"Use simple sentences and a gentle and calm tone."
|
| 59 |
+
# f"Rewrite the following scenario into a simple, autism-friendly social story for a child of age {age} "
|
| 60 |
+
# f"who identifies as {gender}, from {culture} culture, in {language} language. "
|
| 61 |
+
# f"Use the illustration style '{vibe}'. Include the comfort character '{comfort_character}' in the story if it makes sense but do not use the phrase 'comfort character'."
|
| 62 |
+
# f"Use the correct grammatical gender and pronouns for {gender} in {language}. "
|
| 63 |
+
# "Use short sentences, gentle tone, clear structure, supportive language, and separate each idea with a newline. "
|
| 64 |
+
# "Avoid exclamation marks. Do NOT use Markdown, asterisks, or any formatting symbols. Do NOT return JSON. Return only plain story text.\n\n"
|
| 65 |
+
# f"Scenario data:\n{json.dumps(template, indent=2)}"
|
| 66 |
+
)
|
| 67 |
story_resp = client.chat.completions.create(
|
| 68 |
model="gpt-4o-mini",
|
| 69 |
messages=[{"role": "user", "content": story_prompt}]
|
| 70 |
)
|
| 71 |
return story_resp.choices[0].message.content.strip()
|
| 72 |
|
| 73 |
+
def generate_image(scenario_name: str, culture="default", age="7", gender="female", vibe="Cartoon", comfort_character="Koala", story_text=None):
|
| 74 |
filepath = TEMPLATES_DIR / f"{scenario_name}.json"
|
| 75 |
if not filepath.exists():
|
| 76 |
return None
|
| 77 |
template = json.loads(filepath.read_text())
|
| 78 |
+
vibe_desc = VIBE_DESCRIPTIONS.get(vibe, vibe)
|
| 79 |
image_prompt = (
|
| 80 |
+
f"Based on the following story: {story_text}, create an illustration that clearly shows the child and {comfort_character} together. Do not include any other animals."
|
| 81 |
+
f"Context: {template['title']},"
|
| 82 |
+
f"CHILD DETAILS: the protagonist is a kid of age {age}, gender {gender}"
|
| 83 |
+
|
| 84 |
+
f"CULTURAL CONTEXT: Represented with visual motifs from {culture} only if pertinent. Never use flags"
|
| 85 |
+
f"ILLUSTRATION STYLE: Draw this in the style of {vibe}: {vibe_desc}."
|
| 86 |
+
"Key features: 3–5 visual features of that style"
|
| 87 |
+
"TONE AND MOOD: Gentle, supportive, calming. Friendly characters"
|
| 88 |
+
|
| 89 |
+
# f"Create a {vibe_desc} illustration for a social story about: {template['title']}, "
|
| 90 |
+
# f"for a child of age {age} from {culture} culture. "
|
| 91 |
+
# f"Include the comfort character '{comfort_character} and no flags of any country'. "
|
| 92 |
+
# "Use gentle colors, simple shapes, friendly characters, minimal details, no text."
|
| 93 |
)
|
| 94 |
img = client.images.generate(
|
| 95 |
model="gpt-image-1",
|
|
|
|
| 97 |
output_format="png",
|
| 98 |
size="1024x1024"
|
| 99 |
)
|
| 100 |
+
# Decodifica la imagen desde base64
|
| 101 |
image_bytes = base64.b64decode(img.data[0].b64_json)
|
| 102 |
image = Image.open(io.BytesIO(image_bytes))
|
| 103 |
return image
|
|
|
|
| 106 |
return f"You selected: {scenario_name}"
|
| 107 |
|
| 108 |
|
| 109 |
+
async def call_adapt_tool(story, culture, age, gender, vibe, comfort_character):
|
| 110 |
+
print(f"\n[TOOL] Adapt story called with:\nCulture: {culture}, Age: {age}, Gender: {gender}, Vibe: {vibe}, Comfort Character: {comfort_character}\nStory:\n{story}\n")
|
| 111 |
+
|
| 112 |
server = await create_mcp_server()
|
| 113 |
context = {}
|
| 114 |
+
result = await server.request_handlers["adapt_story"](context, story, culture, age, gender, vibe, comfort_character)
|
| 115 |
return result["adapted_story"]
|
| 116 |
|
| 117 |
+
async def call_translate_tool(story, language):
|
| 118 |
+
print(f"\n[TOOL] Translate story called with:\nLanguage: {language}\nStory:\n{story}\n")
|
| 119 |
+
|
| 120 |
+
server = await create_mcp_server()
|
| 121 |
+
context = {}
|
| 122 |
+
result = await server.request_handlers["translate_story"](context, story, language)
|
| 123 |
+
return result["translated_story"]
|
| 124 |
+
|
| 125 |
async def call_voice_tool(story, language):
|
| 126 |
+
print(f"\n[TOOL] Generate voice called with:\nLanguage: {language}\nStory:\n{story}\n")
|
| 127 |
+
|
| 128 |
+
server = await create_mcp_server()
|
| 129 |
context = {}
|
| 130 |
result = await server.request_handlers["generate_voice"](context, story, language)
|
| 131 |
return result.get("audio", None)
|
|
|
|
| 135 |
|
| 136 |
def format_story(story):
|
| 137 |
# Texto grande y claro, sin asteriscos
|
| 138 |
+
story = story.replace("*", "").replace("\n", "<br>").replace("#", "")
|
| 139 |
return f"<div style='font-size:1.5em; line-height:1.6; font-weight:400'>{story}</div>"
|
| 140 |
|
| 141 |
def main():
|
| 142 |
print("Loading scenarios...")
|
| 143 |
scenarios = load_scenarios()
|
| 144 |
+
print("Scenarios loaded")
|
| 145 |
|
| 146 |
with gr.Blocks() as demo:
|
| 147 |
gr.Markdown("# 🧸 Comfortool\n### Social stories with comforting illustrations to support autistic kids with daily challenges")
|
|
|
|
| 156 |
language_input = gr.Textbox(label="Translate to my language (e.g., 'es', 'fr')", value="en")
|
| 157 |
culture_input = gr.Textbox(label="My Community/Culture (e.g., 'Latino', 'Roma', 'Muslim')", value="default")
|
| 158 |
age_input = gr.Textbox(label="My age (e.g., '7')", value="7")
|
| 159 |
+
gender_input = gr.Textbox(label="Gender identity (e.g., 'boy', 'girl', 'non-binary')", value="female")
|
| 160 |
vibe_input = gr.Dropdown(
|
| 161 |
choices=["Comic", "Kawaii", "Pictorial", "Basic B&W", "Cartoon", "Soft Pastel"],
|
| 162 |
label="Vibe / illustration style",
|
| 163 |
value="Cartoon"
|
| 164 |
)
|
| 165 |
+
comfort_character_input = gr.Textbox(label="Favourite animal or character (e.g., 'Koala', 'Robot')", value="Koala")
|
| 166 |
|
| 167 |
+
generate_btn = gr.Button("Step 1: Create Story")
|
| 168 |
|
| 169 |
# Resultados en dos columnas
|
| 170 |
with gr.Row():
|
|
|
|
| 172 |
image_out = gr.Image(label="Illustration")
|
| 173 |
|
| 174 |
def on_generate(scenario_name, language, culture, age, gender, vibe, comfort_character):
|
| 175 |
+
# 1. Genera la historia base en inglés
|
| 176 |
+
story_base = generate_story_base(
|
| 177 |
+
scenario_name,
|
| 178 |
+
language,
|
| 179 |
+
culture,
|
| 180 |
+
age,
|
| 181 |
+
gender,
|
| 182 |
+
vibe,
|
| 183 |
+
comfort_character
|
| 184 |
+
)
|
| 185 |
+
print("\n--- Historia base (EN) ---\n", story_base)
|
| 186 |
+
# 2. Adapta la historia
|
| 187 |
+
adapted_story = asyncio.run(call_adapt_tool(story_base, culture, age, gender, vibe, comfort_character))
|
| 188 |
+
print("\n--- Historia adaptada (EN) ---\n", adapted_story)
|
| 189 |
+
# 3. Traduce la historia adaptada (solo si el idioma no es inglés)
|
| 190 |
+
if language != "en":
|
| 191 |
+
final_story = asyncio.run(call_translate_tool(adapted_story, language))
|
| 192 |
+
print(f"\n--- Historia traducida ({language}) ---\n", final_story)
|
| 193 |
+
else:
|
| 194 |
+
final_story = adapted_story
|
| 195 |
+
print("\n--- Historia final (EN, sin traducción) ---\n", final_story)
|
| 196 |
+
# 4. Genera la imagen usando la historia final como contexto
|
| 197 |
+
image = generate_image(scenario_name, culture, age, gender, vibe, comfort_character, story_text=final_story)
|
| 198 |
+
return format_story(final_story), image, final_story
|
| 199 |
|
| 200 |
generate_btn.click(
|
| 201 |
fn=on_generate,
|
| 202 |
+
inputs=[dropdown, language_input, culture_input, age_input, gender_input, vibe_input, comfort_character_input],
|
| 203 |
+
outputs=[story_out, image_out, story_state],
|
| 204 |
+
show_progress=True
|
| 205 |
)
|
| 206 |
|
|
|
|
| 207 |
def on_voice(story, language):
|
| 208 |
if not story or story.strip() == "":
|
| 209 |
return None
|
|
|
|
| 215 |
return audio_path
|
| 216 |
else:
|
| 217 |
return None
|
| 218 |
+
|
| 219 |
voice_btn = gr.Button("Listen to the story")
|
| 220 |
voice_out = gr.Audio(label="Story audio", type="filepath")
|
| 221 |
|
|
|
|
| 225 |
outputs=voice_out
|
| 226 |
)
|
| 227 |
|
|
|
|
| 228 |
print("Gradio app initialized.")
|
| 229 |
return demo
|
| 230 |
|
mcp_server/server.py
CHANGED
|
@@ -19,13 +19,13 @@ async def create_mcp_server():
|
|
| 19 |
if hasattr(server, "set_version"):
|
| 20 |
server.set_version("0.1.0")
|
| 21 |
|
| 22 |
-
# Tool:
|
| 23 |
-
async def
|
| 24 |
prompt = (
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
)
|
| 30 |
openai_api_key = os.environ.get("OPENAI_API_KEY")
|
| 31 |
client = OpenAI(api_key=openai_api_key)
|
|
@@ -36,6 +36,22 @@ async def create_mcp_server():
|
|
| 36 |
adapted_story = response.choices[0].message.content.strip()
|
| 37 |
return {"adapted_story": adapted_story}
|
| 38 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
# Tool: TTS
|
| 40 |
async def generate_voice(context, story, language="en"):
|
| 41 |
openai_api_key = os.environ.get("OPENAI_API_KEY")
|
|
@@ -50,6 +66,7 @@ async def create_mcp_server():
|
|
| 50 |
# Añade más según tus pruebas y preferencias
|
| 51 |
}
|
| 52 |
voice = voice_map.get(language, "nova") # Por defecto "nova"
|
|
|
|
| 53 |
response = client.audio.speech.create(
|
| 54 |
model="tts-1",
|
| 55 |
voice=voice,
|
|
@@ -60,11 +77,10 @@ async def create_mcp_server():
|
|
| 60 |
return {"audio": audio_bytes}
|
| 61 |
|
| 62 |
|
| 63 |
-
server.request_handlers["
|
| 64 |
-
|
| 65 |
server.request_handlers["generate_voice"] = generate_voice
|
| 66 |
|
| 67 |
-
|
| 68 |
return server
|
| 69 |
|
| 70 |
|
|
|
|
| 19 |
if hasattr(server, "set_version"):
|
| 20 |
server.set_version("0.1.0")
|
| 21 |
|
| 22 |
+
# Tool: Adapt a story for autism and culture
|
| 23 |
+
async def adapt_story(context, story, culture="default", age="7", gender="female", vibe="Cartoon", comfort_character="Koala"):
|
| 24 |
prompt = (
|
| 25 |
+
f"Adapt the following story for an autistic child of age {age}, gender {gender}, from {culture} culture. "
|
| 26 |
+
f"Include '{comfort_character}' as a supportive friend, use the style '{vibe}', and make the story concrete, supportive, and easy to understand. "
|
| 27 |
+
"Do not translate. Return only the adapted story in English."
|
| 28 |
+
f"\n\nStory:\n{story}"
|
| 29 |
)
|
| 30 |
openai_api_key = os.environ.get("OPENAI_API_KEY")
|
| 31 |
client = OpenAI(api_key=openai_api_key)
|
|
|
|
| 36 |
adapted_story = response.choices[0].message.content.strip()
|
| 37 |
return {"adapted_story": adapted_story}
|
| 38 |
|
| 39 |
+
# Tool: Translate a story
|
| 40 |
+
async def translate_story(context, story, language="en"):
|
| 41 |
+
prompt = (
|
| 42 |
+
f"Translate the following story to {language}. Use correct grammatical gender and pronouns. "
|
| 43 |
+
"Return only the translated story."
|
| 44 |
+
f"\n\nStory:\n{story}"
|
| 45 |
+
)
|
| 46 |
+
openai_api_key = os.environ.get("OPENAI_API_KEY")
|
| 47 |
+
client = OpenAI(api_key=openai_api_key)
|
| 48 |
+
response = client.chat.completions.create(
|
| 49 |
+
model="gpt-4o-mini",
|
| 50 |
+
messages=[{"role": "user", "content": prompt}]
|
| 51 |
+
)
|
| 52 |
+
translated_story = response.choices[0].message.content.strip()
|
| 53 |
+
return {"translated_story": translated_story}
|
| 54 |
+
|
| 55 |
# Tool: TTS
|
| 56 |
async def generate_voice(context, story, language="en"):
|
| 57 |
openai_api_key = os.environ.get("OPENAI_API_KEY")
|
|
|
|
| 66 |
# Añade más según tus pruebas y preferencias
|
| 67 |
}
|
| 68 |
voice = voice_map.get(language, "nova") # Por defecto "nova"
|
| 69 |
+
print(voice)
|
| 70 |
response = client.audio.speech.create(
|
| 71 |
model="tts-1",
|
| 72 |
voice=voice,
|
|
|
|
| 77 |
return {"audio": audio_bytes}
|
| 78 |
|
| 79 |
|
| 80 |
+
server.request_handlers["adapt_story"] = adapt_story
|
| 81 |
+
server.request_handlers["translate_story"] = translate_story
|
| 82 |
server.request_handlers["generate_voice"] = generate_voice
|
| 83 |
|
|
|
|
| 84 |
return server
|
| 85 |
|
| 86 |
|
mcp_server/templates/dentist.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
{
|
| 2 |
-
"id": "
|
| 3 |
"title": "Going to the Dentist",
|
| 4 |
"story": "Today I am going to the dentist. The dentist helps keep my teeth clean and healthy. First, I will enter the quiet waiting room. Then, someone will call my name. I will sit in a big chair that goes up and down. The dentist will look at my teeth and might clean them. Some sounds may be loud, but they are safe. If I need a break, I can ask for one. When it is finished, I can go home feeling proud.",
|
| 5 |
"sensory": ["bright light", "whirring sounds"],
|
|
|
|
| 1 |
{
|
| 2 |
+
"id": "going to the dentist",
|
| 3 |
"title": "Going to the Dentist",
|
| 4 |
"story": "Today I am going to the dentist. The dentist helps keep my teeth clean and healthy. First, I will enter the quiet waiting room. Then, someone will call my name. I will sit in a big chair that goes up and down. The dentist will look at my teeth and might clean them. Some sounds may be loud, but they are safe. If I need a break, I can ask for one. When it is finished, I can go home feeling proud.",
|
| 5 |
"sensory": ["bright light", "whirring sounds"],
|
mcp_server/templates/doctor.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
{
|
| 2 |
-
"id": "
|
| 3 |
"title": "Going to the Doctor",
|
| 4 |
"story": "Today I am visiting the doctor. The doctor keeps my body healthy. I will check in and wait until my name is called. The doctor may ask questions and gently check parts of my body. Sometimes, the doctor might use tools like a stethoscope. If I need a moment, I can say 'please wait.' After the visit, I can go home knowing I took good care of myself."
|
| 5 |
}
|
|
|
|
| 1 |
{
|
| 2 |
+
"id": "going to the doctor",
|
| 3 |
"title": "Going to the Doctor",
|
| 4 |
"story": "Today I am visiting the doctor. The doctor keeps my body healthy. I will check in and wait until my name is called. The doctor may ask questions and gently check parts of my body. Sometimes, the doctor might use tools like a stethoscope. If I need a moment, I can say 'please wait.' After the visit, I can go home knowing I took good care of myself."
|
| 5 |
}
|
mcp_server/templates/first_day_school.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
{
|
| 2 |
-
"id": "
|
| 3 |
"title": "First Day of School",
|
| 4 |
"story": "Today is my first day of school. I will meet teachers and classmates. I will learn where my classroom is and where I can take breaks. There will be new routines, and that is okay. If things feel confusing, I can ask a teacher for help. Each day will feel more familiar."
|
| 5 |
}
|
|
|
|
| 1 |
{
|
| 2 |
+
"id": "first day of school",
|
| 3 |
"title": "First Day of School",
|
| 4 |
"story": "Today is my first day of school. I will meet teachers and classmates. I will learn where my classroom is and where I can take breaks. There will be new routines, and that is okay. If things feel confusing, I can ask a teacher for help. Each day will feel more familiar."
|
| 5 |
}
|
mcp_server/templates/haircut.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
{
|
| 2 |
-
"id": "
|
| 3 |
"title": "Getting a Haircut",
|
| 4 |
"story": "Today I am getting a haircut. The hairdresser helps my hair look nice. First, I will sit in a chair. Someone may touch my hair or use scissors. Scissors make small sounds, but they are safe. Hair may fall on my skin and feel tickly, but it can be brushed away. After the haircut, my head will feel lighter and fresh."
|
| 5 |
}
|
|
|
|
| 1 |
{
|
| 2 |
+
"id": "getting a haircut",
|
| 3 |
"title": "Getting a Haircut",
|
| 4 |
"story": "Today I am getting a haircut. The hairdresser helps my hair look nice. First, I will sit in a chair. Someone may touch my hair or use scissors. Scissors make small sounds, but they are safe. Hair may fall on my skin and feel tickly, but it can be brushed away. After the haircut, my head will feel lighter and fresh."
|
| 5 |
}
|
mcp_server/templates/loud_events.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
{
|
| 2 |
-
"id": "
|
| 3 |
"title": "Loud and Crowded Places",
|
| 4 |
"story": "Today I might be in a loud or busy place. There may be many people and sounds. If it feels too loud, I can use headphones or take a break. I can stay close to someone I trust. I do not have to talk if I don’t want to. When the event is over, I can rest somewhere quiet."
|
| 5 |
}
|
|
|
|
| 1 |
{
|
| 2 |
+
"id": "loud and crowded events",
|
| 3 |
"title": "Loud and Crowded Places",
|
| 4 |
"story": "Today I might be in a loud or busy place. There may be many people and sounds. If it feels too loud, I can use headphones or take a break. I can stay close to someone I trust. I do not have to talk if I don’t want to. When the event is over, I can rest somewhere quiet."
|
| 5 |
}
|
mcp_server/templates/new_food.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
{
|
| 2 |
-
"id": "
|
| 3 |
"title": "Trying a New Food",
|
| 4 |
"story": "Today I might try a new food. New food has a new smell, texture, or taste. I can look at the food first, smell it, touch it, or lick it. If I don’t like it, that is okay. Trying is already a success."
|
| 5 |
}
|
|
|
|
| 1 |
{
|
| 2 |
+
"id": "trying a new food",
|
| 3 |
"title": "Trying a New Food",
|
| 4 |
"story": "Today I might try a new food. New food has a new smell, texture, or taste. I can look at the food first, smell it, touch it, or lick it. If I don’t like it, that is okay. Trying is already a success."
|
| 5 |
}
|
mcp_server/templates/new_place.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
{
|
| 2 |
-
"id": "
|
| 3 |
"title": "Visiting a New Place",
|
| 4 |
"story": "Today I will go somewhere I have not been before. New places can feel exciting or scary. I can look around slowly and learn what is there. I can stay close to someone I trust. When I’m ready, I can explore more. Every new place becomes familiar after a while."
|
| 5 |
}
|
|
|
|
| 1 |
{
|
| 2 |
+
"id": "visiting a new place",
|
| 3 |
"title": "Visiting a New Place",
|
| 4 |
"story": "Today I will go somewhere I have not been before. New places can feel exciting or scary. I can look around slowly and learn what is there. I can stay close to someone I trust. When I’m ready, I can explore more. Every new place becomes familiar after a while."
|
| 5 |
}
|
mcp_server/templates/physical_education.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
{
|
| 2 |
-
"id": "
|
| 3 |
"title": "PE Class",
|
| 4 |
"story": "In PE class, I will move my body and try fun activities. There may be loud sounds like balls bouncing or whistles. I can follow instructions at my own pace. If an activity feels too fast or confusing, I can ask for a pause. PE is for having fun and learning new skills."
|
| 5 |
}
|
|
|
|
| 1 |
{
|
| 2 |
+
"id": "physical education class",
|
| 3 |
"title": "PE Class",
|
| 4 |
"story": "In PE class, I will move my body and try fun activities. There may be loud sounds like balls bouncing or whistles. I can follow instructions at my own pace. If an activity feels too fast or confusing, I can ask for a pause. PE is for having fun and learning new skills."
|
| 5 |
}
|
mcp_server/templates/pickup_from_school.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
{
|
| 2 |
-
"id": "
|
| 3 |
"title": "Getting Picked Up From School",
|
| 4 |
"story": "When school is over, someone comes to pick me up. If I am playing, stopping can feel hard. I will get a reminder before it’s time to go. I can take one last turn or finish my activity. When I’m ready, I will leave calmly and go home."
|
| 5 |
}
|
|
|
|
| 1 |
{
|
| 2 |
+
"id": "getting picked up",
|
| 3 |
"title": "Getting Picked Up From School",
|
| 4 |
"story": "When school is over, someone comes to pick me up. If I am playing, stopping can feel hard. I will get a reminder before it’s time to go. I can take one last turn or finish my activity. When I’m ready, I will leave calmly and go home."
|
| 5 |
}
|
mcp_server/templates/social_situations.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
{
|
| 2 |
-
"id": "
|
| 3 |
"title": "Social Situations",
|
| 4 |
"story": "Sometimes I will be around people and talk to them. I don’t have to talk a lot. I can use short words or gestures. If I need space, I can step away for a moment. Everyone communicates in different ways, and that is okay. Being myself is enough."
|
| 5 |
}
|
|
|
|
| 1 |
{
|
| 2 |
+
"id": "social situations",
|
| 3 |
"title": "Social Situations",
|
| 4 |
"story": "Sometimes I will be around people and talk to them. I don’t have to talk a lot. I can use short words or gestures. If I need space, I can step away for a moment. Everyone communicates in different ways, and that is okay. Being myself is enough."
|
| 5 |
}
|