Skip to main content
Glama
study-flamingo

D&D MCP Server

create_character

Generate a new Dungeons & Dragons player character by specifying name, class, level, race, ability scores, and background details for campaign integration.

Instructions

Create a new player character.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
nameYesCharacter name
character_classYesCharacter class
class_levelYesClass level
raceYesCharacter race
player_nameNoThe name of the player in control of this character
descriptionNoA brief description of the character's appearance and demeanor.
bioNoThe character's backstory, personality, and motivations.
backgroundNoCharacter background
alignmentNoCharacter alignment
strengthNoStrength score
dexterityNoDexterity score
constitutionNoConstitution score
intelligenceNoIntelligence score
wisdomNoWisdom score
charismaNoCharisma score

Implementation Reference

  • The core handler function for the 'create_character' tool. It is registered via the @mcp.tool decorator. The function parameters with Annotated[Field] define the input schema. The logic constructs a Character model instance using provided parameters and persists it via storage.add_character.
    @mcp.tool
    def create_character(
        name: Annotated[str, Field(description="Character name")],
        character_class: Annotated[str, Field(description="Character class")],
        class_level: Annotated[int, Field(description="Class level", ge=1, le=20)],
        race: Annotated[str, Field(description="Character race")],
        player_name: Annotated[str | None, Field(description="The name of the player in control of this character")] = None,
        description: Annotated[str | None, Field(description="A brief description of the character's appearance and demeanor.")] = None,
        bio: Annotated[str | None, Field(description="The character's backstory, personality, and motivations.")] = None,
        background: Annotated[str | None, Field(description="Character background")] = None,
        alignment: Annotated[str | None, Field(description="Character alignment")] = None,
        strength: Annotated[int, Field(description="Strength score", ge=1, le=30)] = 10,
        dexterity: Annotated[int, Field(description="Dexterity score", ge=1, le=30)] = 10,
        constitution: Annotated[int, Field(description="Constitution score", ge=1, le=30)] = 10,
        intelligence: Annotated[int, Field(description="Intelligence score", ge=1, le=30)] = 10,
        wisdom: Annotated[int, Field(description="Wisdom score", ge=1, le=30)] = 10,
        charisma: Annotated[int, Field(description="Charisma score", ge=1, le=30)] = 10,
    ) -> str:
        """Create a new player character."""
        # Build ability scores
        abilities = {
            "strength": AbilityScore(score=strength),
            "dexterity": AbilityScore(score=dexterity),
            "constitution": AbilityScore(score=constitution),
            "intelligence": AbilityScore(score=intelligence),
            "wisdom": AbilityScore(score=wisdom),
            "charisma": AbilityScore(score=charisma),
        }
    
        character = Character(
            name=name,
            player_name=player_name,
            character_class=CharacterClass(name=character_class, level=class_level),
            race=Race(name=race),
            background=background,
            alignment=alignment,
            abilities=abilities,
            description=description,
            bio=bio,
        )
    
        storage.add_character(character)
        return f"Created character '{character.name}' (Level {character.character_class.level} {character.race.name} {character.character_class.name})"
  • Pydantic model for Character used internally by the create_character handler to structure the created character data.
    class CharacterClass(BaseModel):
        """Character class information."""
        name: str
        level: int = Field(ge=1, le=20)
        hit_dice: Annotated[str, "The type of hit dice for this character. E.g.. '1d8'"] = "1d4" # e.g., "1d8"
        subclass: Annotated[str | None, "The character's subclass."] = None
    
    
    class Race(BaseModel):
        """Character race information."""
        name: str
        subrace: str | None = None
        traits: list[str] = Field(default_factory=list)
    
    
    class Item(BaseModel):
        """Generic item model."""
        id: str = Field(default_factory=lambda: random(length=8))
        name: str
        description: str | None = None
        quantity: int = 1
        weight: float | None = None
        value: str | None = None  # e.g., "50 gp"
        item_type: str = "misc"  # weapon, armor, consumable, misc, etc.
        properties: dict[str, Any] = Field(default_factory=dict)
    
    
    class Spell(BaseModel):
        """Spell information."""
        id: str = Field(default_factory=lambda: random(length=8))
        name: str
        level: int = Field(ge=0, le=9)
        school: str
        casting_time: str
        range: int = Field(default=5, description="The range of the spell, in feet")
        duration: str
        components: list[str]  # V, S, M
        description: str
        material_components: str | None = None
        prepared: bool = False
    
    
    class Character(BaseModel):
  • Supporting Pydantic models (AbilityScore, CharacterClass, Race) used to construct the Character object in the handler.
    class AbilityScore(BaseModel):
        """D&D ability score with modifiers."""
        score: int = Field(ge=1, le=30, description="Raw ability score")
    
        @property
        def mod(self) -> int:
            """Calculate ability modifier."""
            return (self.score - 10) // 2
    
    
    class CharacterClass(BaseModel):
        """Character class information."""
        name: str
        level: int = Field(ge=1, le=20)
        hit_dice: Annotated[str, "The type of hit dice for this character. E.g.. '1d8'"] = "1d4" # e.g., "1d8"
        subclass: Annotated[str | None, "The character's subclass."] = None
    
    
    class Race(BaseModel):
        """Character race information."""
        name: str
        subrace: str | None = None
        traits: list[str] = Field(default_factory=list)
    
    
    class Item(BaseModel):
        """Generic item model."""
        id: str = Field(default_factory=lambda: random(length=8))
        name: str
        description: str | None = None
        quantity: int = 1
        weight: float | None = None
        value: str | None = None  # e.g., "50 gp"
        item_type: str = "misc"  # weapon, armor, consumable, misc, etc.
        properties: dict[str, Any] = Field(default_factory=dict)
    
    
    class Spell(BaseModel):
        """Spell information."""
        id: str = Field(default_factory=lambda: random(length=8))
        name: str
        level: int = Field(ge=0, le=9)
        school: str
        casting_time: str
        range: int = Field(default=5, description="The range of the spell, in feet")
        duration: str
        components: list[str]  # V, S, M
        description: str
        material_components: str | None = None
        prepared: bool = False
    
    
    class Character(BaseModel):
        """Complete character sheet."""
        # Basic Info
        id: str = Field(default_factory=lambda: random(length=8))
        name: str
        player_name: str | None = None
        character_class: CharacterClass
        race: Race
        background: str | None = None
        alignment: str | None = None
        description: str | None = None  # A brief description of the character's appearance and demeanor.
        bio: str | None = None  # The character's backstory, personality, and motivations.
    
        # Core Stats
        abilities: dict[str, AbilityScore] = Field(
            default_factory=lambda: {
                "strength": AbilityScore(score=10),
                "dexterity": AbilityScore(score=10),
                "constitution": AbilityScore(score=10),
                "intelligence": AbilityScore(score=10),
                "wisdom": AbilityScore(score=10),
                "charisma": AbilityScore(score=10),
            }
        )
    
        # Combat Stats
        armor_class: int = 10
        hit_points_max: int = 1
        hit_points_current: int = 1
        temporary_hit_points: int = 0
        hit_dice_remaining: str = "1d8"
        death_saves_success: int = Field(ge=0, le=3, default=0)
        death_saves_failure: int = Field(ge=0, le=3, default=0)
    
        # Skills & Proficiencies
        proficiency_bonus: int = 2
        skill_proficiencies: list[str] = Field(default_factory=list)
        saving_throw_proficiencies: list[str] = Field(default_factory=list)
    
        # Equipment
        inventory: list[Item] = Field(default_factory=list)
        equipment: dict[str, Item | None] = Field(
            default_factory=lambda: {
                "weapon_main": None,
                "weapon_off": None,
                "armor": None,
                "shield": None,
            }
        )
    
        # Spellcasting
        spellcasting_ability: str | None = None
        spell_slots: dict[int, int] = Field(default_factory=dict)  # level: max_slots
        spell_slots_used: dict[int, int] = Field(default_factory=dict)  # level: used_slots
        spells_known: list[Spell] = Field(default_factory=list)
    
        # Character Features
        features_and_traits: list[str] = Field(default_factory=list)
        languages: list[str] = Field(default_factory=list)
    
        # Misc
        inspiration: bool = False
        notes: str = ""
        created_at: datetime = Field(default_factory=datetime.now)
        updated_at: datetime = Field(default_factory=datetime.now)

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/study-flamingo/gamemaster-mcp'

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