Skip to main content
Glama

build_prompt

Generate Stable Diffusion prompts from character names by analyzing Gelbooru tag frequency data to create accurate image generation strings.

Instructions

Given a character name, returns a ready-to-use image-generation prompt string like 'misty (pokemon), green eyes, orange hair, side ponytail, ...'. Internally calls get_character_tags with caching, then assembles the prompt with tags ordered by frequency (eye → hair → other).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
character_nameYesThe Gelbooru tag for the character, e.g. 'misty_(pokemon)'. Use underscores as Gelbooru does.
max_imagesNoPosts to analyse (default 300). Cached after first fetch.
include_otherNoWhether to include non-eye/hair tags (clothing, accessories, etc.) in the prompt. Default true.

Implementation Reference

  • Main handler function _build_prompt that executes the tool logic: fetches character tags via _fetch_character_tags, orders them (eye → hair → other tags), and assembles a ready-to-use image-generation prompt string.
    def _build_prompt(character_name: str, max_images: int, include_other: bool) -> Dict[str, Any]:
        """
        Calls _fetch_character_tags and assembles a ready-to-use image-gen prompt string.
        Tags are ordered: character name → eye → hair → other (highest frequency first).
        """
        tags_result = _fetch_character_tags(character_name, max_images)
        if "error" in tags_result:
            return tags_result
    
        ct = tags_result["character_tags"]
    
        # Human-readable character name: strip _(series) suffix for the label
        display_name = character_name.replace("_", " ")
    
        parts: List[str] = [display_name]
        parts.extend(e["tag"] for e in ct["eye"])
        parts.extend(h["tag"] for h in ct["hair"])
        if include_other:
            parts.extend(o["tag"] for o in ct["other"])
    
        prompt_string = ", ".join(parts)
    
        return {
            "prompt": {
                "character": display_name,
                "posts_analysed": ct["posts_analysed"],
                "cache_hit": ct.get("cache_hit", False),
                "prompt_string": prompt_string,
                "tags": {
                    "eye":   [e["tag"] for e in ct["eye"]],
                    "hair":  [h["tag"] for h in ct["hair"]],
                    "other": [o["tag"] for o in ct["other"]] if include_other else [],
                },
            }
        }
  • Tool registration definition: declares the build_prompt tool with its name, description, and JSON input schema defining three parameters (character_name, max_images, include_other).
    Tool(
        name="build_prompt",
        description=(
            "Given a character name, returns a ready-to-use image-generation prompt "
            "string like 'misty (pokemon), green eyes, orange hair, side ponytail, ...'. "
            "Internally calls get_character_tags with caching, then assembles the prompt "
            "with tags ordered by frequency (eye → hair → other)."
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "character_name": {
                    "type": "string",
                    "description": (
                        "The Gelbooru tag for the character, e.g. 'misty_(pokemon)'. "
                        "Use underscores as Gelbooru does."
                    ),
                },
                "max_images": {
                    "type": "integer",
                    "description": "Posts to analyse (default 300). Cached after first fetch.",
                    "default": 300,
                    "minimum": 10,
                },
                "include_other": {
                    "type": "boolean",
                    "description": (
                        "Whether to include non-eye/hair tags (clothing, accessories, etc.) "
                        "in the prompt. Default true."
                    ),
                    "default": True,
                },
            },
            "required": ["character_name"],
        },
    ),
  • The list_tools() decorated function that registers all tools with the MCP server, including build_prompt in the list of available tools.
    @server.list_tools()
    async def list_tools() -> list[Tool]:
        return [
            Tool(
                name="search_posts",
                description=(
                    "Search Gelbooru posts by tags, page, limit, or ID. "
                    "Supports all Gelbooru tag syntax: AND (tag1 tag2), OR ({t1~t2}), "
                    "NOT (-tag), wildcards (*tag / tag*), meta-tags like "
                    "rating:safe/questionable/explicit, score:>=N, width:>=N, "
                    "user:name, sort:random, sort:score:desc, etc."
                ),
                inputSchema={
                    "type": "object",
                    "properties": {
                        "tags": {
                            "type": "string",
                            "description": (
                                "Tag query string. Examples: 'cat_ears blue_eyes', "
                                "'touhou -rating:explicit', 'score:>=50 sort:score:desc'"
                            ),
                        },
                        "limit": {
                            "type": "integer",
                            "description": "Number of posts to return (default 20, max 100).",
                            "default": 20,
                            "minimum": 1,
                            "maximum": 100,
                        },
                        "pid": {
                            "type": "integer",
                            "description": "Page number (0-indexed).",
                            "default": 0,
                        },
                        "id": {
                            "type": "integer",
                            "description": "Fetch a single post by its Gelbooru ID.",
                        },
                        "cid": {
                            "type": "integer",
                            "description": "Fetch posts by change ID (Unix timestamp).",
                        },
                    },
                },
            ),
            Tool(
                name="get_deleted_posts",
                description=(
                    "Retrieve deleted posts. Pass last_id to get everything deleted "
                    "above that post ID."
                ),
                inputSchema={
                    "type": "object",
                    "properties": {
                        "last_id": {
                            "type": "integer",
                            "description": "Return deleted posts whose ID is above this value.",
                        },
                        "limit": {"type": "integer", "default": 20, "minimum": 1, "maximum": 100},
                    },
                },
            ),
            Tool(
                name="search_tags",
                description=(
                    "Search Gelbooru tags by name, pattern, or ID. "
                    "Useful for autocomplete, tag counts, and tag type lookup."
                ),
                inputSchema={
                    "type": "object",
                    "properties": {
                        "name": {
                            "type": "string",
                            "description": "Exact tag name to look up.",
                        },
                        "names": {
                            "type": "string",
                            "description": "Space-separated list of tag names, e.g. 'cat dog fox'.",
                        },
                        "name_pattern": {
                            "type": "string",
                            "description": (
                                "Wildcard tag search using SQL LIKE syntax. "
                                "Use % for multi-char wildcard, _ for single-char. "
                                "Example: '%choolgirl%'"
                            ),
                        },
                        "id": {
                            "type": "integer",
                            "description": "Look up a tag by its database ID.",
                        },
                        "after_id": {
                            "type": "integer",
                            "description": "Return tags whose ID is greater than this value.",
                        },
                        "limit": {"type": "integer", "default": 20, "minimum": 1, "maximum": 100},
                        "order": {
                            "type": "string",
                            "enum": ["ASC", "DESC"],
                            "description": "Sort direction.",
                        },
                        "orderby": {
                            "type": "string",
                            "enum": ["date", "count", "name"],
                            "description": "Field to sort by.",
                        },
                    },
                },
            ),
            Tool(
                name="search_users",
                description="Search Gelbooru users by name or name pattern.",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "name": {
                            "type": "string",
                            "description": "Exact username to search for.",
                        },
                        "name_pattern": {
                            "type": "string",
                            "description": "Wildcard username search (SQL LIKE syntax).",
                        },
                        "limit": {"type": "integer", "default": 20, "minimum": 1, "maximum": 100},
                        "pid": {"type": "integer", "default": 0},
                    },
                },
            ),
            Tool(
                name="get_comments",
                description="Retrieve comments for a specific Gelbooru post.",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "post_id": {
                            "type": "integer",
                            "description": "The post ID whose comments you want to retrieve.",
                        },
                    },
                    "required": ["post_id"],
                },
            ),
            Tool(
                name="get_character_tags",
                description=(
                    "Given a character name (e.g. 'misty_(pokemon)'), fetches the top "
                    "highest-scored general/solo posts across multiple pages and returns "
                    "the most frequently occurring tags split into three semantic buckets: "
                    "eye colour/shape, hair colour/style, and other character traits. "
                    "Each tag includes a frequency score. Results are cached to disk for 24 hours."
                ),
                inputSchema={
                    "type": "object",
                    "properties": {
                        "character_name": {
                            "type": "string",
                            "description": (
                                "The Gelbooru tag for the character, e.g. 'misty_(pokemon)', "
                                "'rem_(re:zero)', 'saber_(fate)'. Use underscores as Gelbooru does."
                            ),
                        },
                        "max_images": {
                            "type": "integer",
                            "description": (
                                "How many top-scored posts to analyse across all pages "
                                "(default 300). More images = slower but more reliable results. "
                                "Fetched in pages of 100."
                            ),
                            "default": 300,
                            "minimum": 10,
                        },
                    },
                    "required": ["character_name"],
                },
            ),
            Tool(
                name="build_prompt",
                description=(
                    "Given a character name, returns a ready-to-use image-generation prompt "
                    "string like 'misty (pokemon), green eyes, orange hair, side ponytail, ...'. "
                    "Internally calls get_character_tags with caching, then assembles the prompt "
                    "with tags ordered by frequency (eye → hair → other)."
                ),
                inputSchema={
                    "type": "object",
                    "properties": {
                        "character_name": {
                            "type": "string",
                            "description": (
                                "The Gelbooru tag for the character, e.g. 'misty_(pokemon)'. "
                                "Use underscores as Gelbooru does."
                            ),
                        },
                        "max_images": {
                            "type": "integer",
                            "description": "Posts to analyse (default 300). Cached after first fetch.",
                            "default": 300,
                            "minimum": 10,
                        },
                        "include_other": {
                            "type": "boolean",
                            "description": (
                                "Whether to include non-eye/hair tags (clothing, accessories, etc.) "
                                "in the prompt. Default true."
                            ),
                            "default": True,
                        },
                    },
                    "required": ["character_name"],
                },
            ),
        ]
  • Routing/dispatch logic in call_tool() that handles build_prompt requests: extracts arguments from the request and calls _build_prompt via the executor.
    elif name == "build_prompt":
        character_name = arguments["character_name"]
        max_images = arguments.get("max_images", 300)
        include_other = arguments.get("include_other", True)
        result = await loop.run_in_executor(
            None, _build_prompt, character_name, max_images, include_other
        )

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/citronlegacy/gelbooru-mcp'

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