Skip to main content
Glama

create_campaign

Create a new Dungeons & Dragons 5e campaign with configurable rules versions and interaction modes for text, audio, or voice-enabled gameplay.

Instructions

Create a new D&D campaign.

The rules_version parameter selects which edition of the D&D 5e rules to use for this campaign. '2024' uses the revised 2024 rules, '2014' uses the original 5th edition rules.

The interaction_mode parameter controls how the DM communicates:

  • classic: Text-only, no voice dependencies required.

  • narrated: DM responses delivered as TTS audio + text via WebSocket.

  • immersive: Narrated + player STT input from browser.

Interaction mode and model profile are independent axes — any combination is valid.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
nameYesCampaign name
descriptionYesBrief decription of the campaign, or a tagline
dm_nameNoDungeon Master name
settingNo Campaign setting - a full description of the setting of the campaign in markdown format, or the path to a `.txt` or `.md` file containing the same.
rules_versionNoD&D rules version: '2014' or '2024' (default: '2024')2024
interaction_modeNoInteraction mode: 'classic' (text-only), 'narrated' (TTS audio + text), 'immersive' (narrated + STT input). Default: 'classic'classic

Implementation Reference

  • DnDStorage.create_campaign method handles campaign creation logic by delegating to a split backend and initializing campaign-specific metadata and directory structures.
    def create_campaign(self, name: str, description: str, dm_name: str | None = None, setting: str | Path | None = None, rules_version: str = "2024", interaction_mode: str = "classic") -> Campaign:
        """Create a new campaign using split storage format.
    
        Args:
            name: Campaign name
            description: Campaign description
            dm_name: Dungeon Master name
            setting: Campaign setting
            rules_version: D&D rules version ('2014' or '2024', default '2024')
            interaction_mode: Interaction mode ('classic', 'narrated', or 'immersive', default 'classic')
        """
        logger.info(f"✨ Creating new campaign: '{name}' (rules: {rules_version}, mode: {interaction_mode})")
    
        # Use split backend to create the campaign
        campaign = self._split_backend.create_campaign(
            name=name,
            description=description,
            dm_name=dm_name,
            setting=setting
        )
    
        # Sync to main storage
        self._current_campaign = campaign
        self._current_format = StorageFormat.SPLIT
    
        # Store rules_version and interaction_mode in campaign metadata
        self._rules_version = rules_version
        self._interaction_mode = interaction_mode
    
        # Create rulebooks directory structure
        campaign_dir = self._split_backend._get_campaign_dir(name)
        rulebooks_dir = campaign_dir / "rulebooks"
        rulebooks_dir.mkdir(exist_ok=True)
        (rulebooks_dir / "custom").mkdir(exist_ok=True)
        logger.debug(f"📂 Created rulebooks directory structure at {rulebooks_dir}")
    
        # Save rules_version and interaction_mode to campaign.json metadata
        self._save_rules_version(campaign_dir, rules_version)
        self._save_interaction_mode(campaign_dir, interaction_mode)
    
        # Rebuild indexes for new campaign
        self._rebuild_character_index()
    
        # Update campaign hash
        self._campaign_hash = self._compute_campaign_hash()
    
        # Initialize library bindings for the new campaign
        self._library_bindings = LibraryBindings(campaign_id=campaign.id)
        logger.debug(f"📚 Created empty library bindings for campaign '{name}'")
    
        # Initialize discovery tracker for the new campaign
        self._discovery_tracker = DiscoveryTracker(campaign_dir)
        logger.debug(f"Initialized empty DiscoveryTracker for campaign '{name}'")
    
        logger.info(f"✅ Campaign '{name}' created and set as active using {self._current_format} format (rules: {rules_version}, mode: {interaction_mode}).")
        return campaign
  • SplitStorageBackend.create_campaign method performs the actual file system operations to create a new campaign directory and store initialized JSON files.
    def create_campaign(self, name: str, description: str, dm_name: str | None = None, setting: str | Path | None = None) -> Campaign:
        """Create a new campaign.
    
        Args:
            name: Campaign name
            description: Campaign description
            dm_name: Dungeon Master name
            setting: Campaign setting (string or path to file)
    
        Returns:
            New Campaign object
        """
        logger.info(f"✨ Creating new campaign: '{name}'")
    
        # Ensure directory structure exists
        self._ensure_campaign_structure(name)
    
        # Create campaign object
        game_state = GameState(campaign_name=name)
        campaign = Campaign(
            name=name,
            description=description,
            dm_name=dm_name,
            setting=setting,
            game_state=game_state
        )
    
        self._current_campaign = campaign
        self.save_all(force=True)  # Force save for new campaign
        logger.info(f"✅ Campaign '{name}' created and set as active.")
        return campaign
Install Server

Other Tools

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/Polloinfilzato/dm20-protocol'

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