Skip to main content
Glama

build_encounter

Calculate balanced D&D 5e encounters by determining XP budgets for different difficulty levels and suggesting monster combinations based on party size and level.

Instructions

Build balanced D&D 5e encounters. Given party size and level, calculates XP budgets for each difficulty and suggests monster combinations.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
party_sizeYesNumber of party members (1-10)
party_levelYesAverage party level (1-20)
difficultyNoTarget difficulty. If omitted, shows budgets and suggestions for all difficulties.
monster_cr_minNoMinimum monster CR to consider (numeric, e.g. 0.25 for 1/4)
monster_cr_maxNoMaximum monster CR to consider (numeric)

Implementation Reference

  • The handler function for the build_encounter MCP tool, which takes party details and monster CR constraints to generate and format balanced encounter suggestions.
    async ({ party_size, party_level, difficulty, monster_cr_min, monster_cr_max }) => {
      const budgets = calculatePartyBudget(party_size, party_level);
    
      const crMin = monster_cr_min ?? 0;
      const crMax = monster_cr_max ?? party_level + 3;
      const monsters = getMonstersByCrRange(db, crMin, crMax);
    
      const lines: string[] = [];
      lines.push(`# Encounter Builder`);
      lines.push('');
      lines.push(`**Party:** ${party_size} characters at level ${party_level}`);
      lines.push(`**Monster CR range:** ${crMin}–${crMax}`);
      lines.push('');
    
      // XP budget table
      lines.push('## XP Budgets');
      lines.push('');
      lines.push('| Difficulty | XP Budget |');
      lines.push('|------------|-----------|');
      for (const d of DIFFICULTIES) {
        const marker = difficulty === d ? ' ←' : '';
        lines.push(`| ${d.charAt(0).toUpperCase() + d.slice(1)} | ${budgets[d].toLocaleString()} XP${marker} |`);
      }
      lines.push('');
    
      if (monsters.length === 0) {
        lines.push('*No SRD monsters found in the specified CR range.*');
        return {
          content: [{ type: 'text' as const, text: lines.join('\n') }],
        };
      }
    
      // Suggest groups for target difficulties
      const targetDifficulties: Difficulty[] = difficulty ? [difficulty] : DIFFICULTIES;
    
      for (const d of targetDifficulties) {
        const budget = budgets[d];
        lines.push(`## ${d.charAt(0).toUpperCase() + d.slice(1)} Encounters (${budget.toLocaleString()} XP)`);
        lines.push('');
    
        const groups = findMonsterGroups(monsters, budget, 5);
        if (groups.length === 0) {
          lines.push('*No suitable monster combinations found for this budget and CR range. Try widening the CR range.*');
        } else {
          groups.forEach((group, i) => {
            lines.push(`**Option ${i + 1}:**`);
            lines.push(formatGroup(group));
            lines.push('');
          });
        }
        lines.push('');
      }
    
      lines.push('---');
      lines.push('*Adjusted XP uses DMG encounter multipliers based on monster count. The actual difficulty may vary based on terrain, tactics, and party composition.*');
    
      return {
        content: [{ type: 'text' as const, text: lines.join('\n') }],
      };
    },
  • Zod-based schema for the build_encounter tool input parameters.
    {
      description:
        'Build balanced D&D 5e encounters. Given party size and level, calculates XP budgets for each difficulty and suggests monster combinations.',
      inputSchema: {
        party_size: z.number().min(1).max(10).describe('Number of party members (1-10)'),
        party_level: z.number().min(1).max(20).describe('Average party level (1-20)'),
        difficulty: z
          .enum(['easy', 'medium', 'hard', 'deadly'])
          .optional()
          .describe('Target difficulty. If omitted, shows budgets and suggestions for all difficulties.'),
        monster_cr_min: z
          .number()
          .optional()
          .describe('Minimum monster CR to consider (numeric, e.g. 0.25 for 1/4)'),
        monster_cr_max: z
          .number()
          .optional()
          .describe('Maximum monster CR to consider (numeric)'),
      },
    },
  • The registration function for the build_encounter MCP tool.
    export function registerBuildEncounter(
      server: McpServer,
      db: Database.Database,
    ): void {
      server.registerTool(
        'build_encounter',

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/gregario/dnd-oracle'

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