Skip to main content
Glama

manage_condition

Track and modify D&D 5e conditions like blinded or poisoned on characters during gameplay. Add, remove, query status, or advance condition durations to manage combat effects.

Instructions

Manage D&D 5e conditions on targets (add, remove, query, tick duration)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
targetIdNo
encounterIdNo
operationNo
conditionNo
sourceNo
durationNo
saveDCNo
saveAbilityNo
exhaustionLevelsNo
roundNumberNo
batchNo

Implementation Reference

  • Core handler function for the manage_condition tool. Dispatches single or batch operations (add, remove, query, tick) on character conditions.
    export function manageCondition(input: ManageConditionInput | { batch: ManageConditionInput[] }): string { // Check if this is a batch operation if ('batch' in input && input.batch) { return handleBatchConditions(input.batch); } const singleInput = input as ManageConditionInput; const { targetId, operation } = singleInput; switch (operation) { case 'add': return handleAddCondition(targetId, singleInput); case 'remove': return handleRemoveCondition(targetId, singleInput); case 'query': return handleQueryConditions(targetId); case 'tick': return handleTickDuration(targetId, singleInput); default: throw new Error(`Unknown operation: ${operation}`); } }
  • Zod input schema definition for manage_condition tool, supporting single condition operations or batch arrays.
    // Single condition operation const singleConditionSchema = z.object({ targetId: z.string(), encounterId: z.string().optional(), operation: z.enum(['add', 'remove', 'query', 'tick']), // For add/remove condition: ConditionSchema.optional(), source: z.string().optional(), duration: z.union([ z.number(), // Rounds z.literal('concentration'), z.literal('until_dispelled'), z.literal('until_rest'), z.literal('save_ends'), ]).optional(), saveDC: z.number().optional(), saveAbility: AbilitySchema.optional(), // For exhaustion exhaustionLevels: z.number().min(1).optional(), // For tick roundNumber: z.number().optional(), }); // Support both single and batch operations export const manageConditionSchema = z.union([ singleConditionSchema, z.object({ batch: z.array(singleConditionSchema).min(1).max(20), }), ]); export type ManageConditionInput = z.infer<typeof singleConditionSchema>;
  • Static registration of manage_condition tool in the toolRegistry, converting Zod schema to JSON schema and providing async wrapper handler.
    manage_condition: { name: 'manage_condition', description: 'Manage D&D 5e conditions on targets (add, remove, query, tick duration)', inputSchema: toJsonSchema(manageConditionSchema), handler: async (args) => { try { const validated = manageConditionSchema.parse(args); const result = manageCondition(validated); return success(result); } catch (err) { if (err instanceof z.ZodError) { const messages = err.errors.map(e => `${e.path.join('.')}: ${e.message}`).join(', '); return error(`Validation failed: ${messages}`); } const message = err instanceof Error ? err.message : String(err); return error(message); } },
  • Supporting function to compute effective stats for characters under active conditions, used by character retrieval to show condition impacts.
    export function calculateEffectiveStats(characterId: string, baseStats: { maxHp: number; hp: number; speed: number; ac?: number; }): { maxHp: { base: number; effective: number; modified: boolean }; speed: { base: number; effective: number; modified: boolean }; ac?: { base: number; effective: number; modified: boolean }; conditionEffects: string[]; // Human-readable list of active effects } { const conditions = getActiveConditions(characterId); const result = { maxHp: { base: baseStats.maxHp, effective: baseStats.maxHp, modified: false }, speed: { base: baseStats.speed, effective: baseStats.speed, modified: false }, ac: baseStats.ac ? { base: baseStats.ac, effective: baseStats.ac, modified: false } : undefined, conditionEffects: [] as string[], }; // Apply each condition's mechanical effects for (const cond of conditions) { // Get mechanical effects (either custom or built-in) let effects = cond.mechanicalEffects; if (!effects && (cond.condition in CONDITION_EFFECTS || cond.condition === 'exhaustion')) { effects = getBuiltInMechanicalEffects(cond.condition, cond.exhaustionLevel); } if (!effects) continue; // Apply HP maximum modifier if (effects.maxHpMultiplier !== undefined) { result.maxHp.effective = Math.floor(result.maxHp.effective * effects.maxHpMultiplier); result.maxHp.modified = true; const condName = cond.condition === 'exhaustion' ? `Exhaustion ${cond.exhaustionLevel}` : String(cond.condition).charAt(0).toUpperCase() + String(cond.condition).slice(1); result.conditionEffects.push(`${condName}: HP max ×${effects.maxHpMultiplier}`); } if (effects.maxHpModifier !== undefined) { result.maxHp.effective += effects.maxHpModifier; result.maxHp.modified = true; result.conditionEffects.push(`HP max ${effects.maxHpModifier > 0 ? '+' : ''}${effects.maxHpModifier}`); } // Apply speed modifier if (effects.speedMultiplier !== undefined) { result.speed.effective = Math.floor(result.speed.effective * effects.speedMultiplier); result.speed.modified = true; const condName = cond.condition === 'exhaustion' ? `Exhaustion ${cond.exhaustionLevel}` : String(cond.condition).charAt(0).toUpperCase() + String(cond.condition).slice(1); result.conditionEffects.push(`${condName}: Speed ×${effects.speedMultiplier}`); } if (effects.speedModifier !== undefined) { result.speed.effective += effects.speedModifier; result.speed.modified = true; result.conditionEffects.push(`Speed ${effects.speedModifier > 0 ? '+' : ''}${effects.speedModifier}`); } if (effects.cannotMove) { result.speed.effective = 0; result.speed.modified = true; } // Apply AC modifier if (result.ac && effects.acModifier !== undefined) { result.ac.effective += effects.acModifier; result.ac.modified = true; result.conditionEffects.push(`AC ${effects.acModifier > 0 ? '+' : ''}${effects.acModifier}`); } // Track other effects (disadvantage, auto-fail, etc.) if (effects.disadvantageOn && effects.disadvantageOn.length > 0) { const condName = cond.condition === 'exhaustion' ? `Exhaustion ${cond.exhaustionLevel}` : String(cond.condition).charAt(0).toUpperCase() + String(cond.condition).slice(1); result.conditionEffects.push(`${condName}: Disadv. on ${effects.disadvantageOn.join(', ')}`); } if (effects.autoFailSaves && effects.autoFailSaves.length > 0) { result.conditionEffects.push(`Auto-fail ${effects.autoFailSaves.join(', ').toUpperCase()} saves`); } if (effects.incapacitated) { result.conditionEffects.push('Incapacitated'); } } return result; }

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/Mnehmos/ChatRPG'

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