Spaces:
Sleeping
Sleeping
File size: 5,779 Bytes
c7d933a 4f79b3e c7d933a 4f79b3e c7d933a 4f79b3e c7d933a 4f79b3e c7d933a 4f79b3e c7d933a 4f79b3e c7d933a 4f79b3e c7d933a 4f79b3e c7d933a 4f79b3e c7d933a 4f79b3e c7d933a 4f79b3e c7d933a 4f79b3e c7d933a 4f79b3e c7d933a 4f79b3e c7d933a 4f79b3e c7d933a 4f79b3e c7d933a 4f79b3e c7d933a 4f79b3e c7d933a 4f79b3e c7d933a | 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 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | """
Comfortool MCP Server
Provides tools for creating autism-friendly social stories with cultural adaptation
"""
from fastmcp import FastMCP
from openai import OpenAI
import os
from dotenv import load_dotenv
import base64
import io
from PIL import Image
from pathlib import Path
import json
# Load environment variables
load_dotenv()
# Initialize FastMCP server
mcp = FastMCP("comfortool")
# Constants
TEMPLATES_DIR = Path(__file__).resolve().parent / "mcp_server" / "templates"
GENERATED_IMAGES_DIR = Path(__file__).resolve().parent / "generated_images"
GENERATED_IMAGES_DIR.mkdir(exist_ok=True)
# Vibe descriptions for image generation (exported for use in app.py)
VIBE_DESCRIPTIONS = {
"Comic": "comic-style illustration, comic strip format with exactly 4 panels, bold outlines, dynamic poses, speech bubbles, vibrant colors. If there is text, translate it to the selected language with perfect ortography",
"Kawaii": "kawaii-style illustration, pastel colors, cute rounded characters, big eyes.",
"Pictorial": "pictorial illustration, painted with a brush, gentle and calm atmosphere",
"Basic B&W": "black and white illustration, simple lines, no other colors allowed, like a coloring book.Absolutely only use black and white.",
"Cartoon": "cartoon-style illustration, exaggerated features, bright colors, playful mood",
"Soft Pastel": "Only use soft pastel colours, smooth textures, calming feeling"
}
# Valid OpenAI voices for TTS (exported for use in app.py)
VALID_VOICES = {"nova", "shimmer", "echo", "onyx", "fable", "alloy", "ash", "sage", "coral"}
# Initialize OpenAI client
def get_openai_client():
api_key = os.environ.get("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables")
return OpenAI(api_key=api_key)
# Helper functions (not exposed as tools)
def _adapt_story_impl(
story: str,
culture: str = "default",
age: str = "7",
gender: str = "female",
vibe: str = "Cartoon",
comfort_character: str = "Koala"
) -> str:
"""Internal implementation of adapt_story"""
prompt = (
f"Adapt the following story for an autistic child of age {age}, gender {gender}, from {culture} culture. "
f"Include '{comfort_character}' as a supportive friend, use the style '{vibe}', and make the story concrete, supportive, and easy to understand. "
"Avoid excessive emotion and exclamation marks. "
"Adapt language according to age, simpler sentences for smaller (ages 2 to 4) kids. "
"The absolute max length is 640 characters. "
"Do not mention any info related to format, like pages, panels or scenes. It is just one story. "
"Do not translate. Return only the adapted story in English."
f"\n\nStory:\n{story}"
)
client = get_openai_client()
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}]
)
return response.choices[0].message.content.strip()
def _translate_story_impl(
story: str,
language: str = "en",
gender: str = "female"
) -> str:
"""Internal implementation of translate_story"""
if language.lower() == "en":
return story
prompt = (
f"Translate the following story to {language} and the corresponding regional or cultural variant if mentioned. "
f"Use correct grammatical gender and pronouns, adapted to the selected gender of the kid ('{gender}'). "
"If the story mentions an animal or character, translate its name to the most culturally and linguistically appropriate version for the target language and region. "
"For example, if the story mentions 'fox', translate it as 'zorro' for Spanish from Spain. "
"Return only the translated story, using the regional variety requested."
f"\n\nStory:\n{story}"
)
client = get_openai_client()
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}]
)
return response.choices[0].message.content.strip()
@mcp.tool()
def adapt_story(
story: str,
culture: str = "default",
age: str = "7",
gender: str = "female",
vibe: str = "Cartoon",
comfort_character: str = "Koala"
) -> str:
"""
Adapts a story for an autistic child based on culture, age, gender, and comfort character.
Args:
story: The original story text to adapt
culture: Cultural context (e.g., 'Latino', 'Roma', 'Muslim', 'default')
age: Child's age (e.g., '7')
gender: Gender identity (e.g., 'boy', 'girl', 'non-binary')
vibe: Illustration style for the story
comfort_character: Supportive character/animal (e.g., 'Koala', 'Robot')
Returns:
The adapted story in English
"""
return _adapt_story_impl(story, culture, age, gender, vibe, comfort_character)
@mcp.tool()
def translate_story(
story: str,
language: str = "en",
gender: str = "female"
) -> str:
"""
Translates a story to the selected language with proper grammatical gender.
Args:
story: The story text to translate
language: Target language (e.g., 'Spanish from Spain', 'en', 'fr')
gender: Gender for grammatical agreement (e.g., 'boy', 'girl', 'non-binary')
Returns:
The translated story
"""
return _translate_story_impl(story, language, gender)
# Helper function to list available scenarios
@mcp.tool()
def list_scenarios() -> list[str]:
"""
Lists all available scenario templates.
Returns:
List of scenario names
"""
return [p.stem.replace("_", " ") for p in TEMPLATES_DIR.glob("*.json")]
|