Skip to main content
Glama

Build dialogue tree

build_dialogue_tree

Compile nested dialogue, choices, cutscenes, and game-flow nodes into correctly indented RPG Maker MV event commands; optionally insert them into an event page to avoid manual indents and terminators.

Instructions

Compiles a nested tree of nodes into correctly indented event commands and optionally inserts it into an event page, so you never hand-write indents, block terminators or move-route rows. Covers dialogue, branching, switches and variables, cutscenes (screen effects, audio, pictures, animations, move routes) and game flow (battles, shops, items, gold, party, scenes, labels). With mapId + eventId the commands are inserted at indent 0 before the page's end (or at index), like add_event_command; without them, or with dryRun, nothing is written and the compiled commands are returned in preview. tree is an array of nodes; every node is an object with one main key, and unknown keys are rejected. choices, if and battle bodies nest at most 8 levels deep (each body counts as a level). A node that is invalid anywhere in the tree fails the whole call and nothing is written. Node vocabulary, in three groups. (1) MESSAGES AND FLOW: {say: string | string[], face?: {name, index}, background?: 0|1|2, position?: 0|1|2} (4 lines per message box; "\n" splits lines; control codes like \C[2] are kept as written); {choices: [{label, then?: Node[]}] (1-6), cancel?: "disallow" (default) | "branch" | choiceIndex}; {if: Condition, then?: Node[], else?: Node[]} with Condition = {switch, is?} | {variable, op: "eq"|"ne"|"gt"|"gte"|"lt"|"lte", value} | {selfSwitch: "A".."D", is?} | {gold} (party has at least) | {item} (party has item); {setSwitch: {id, value}} | {setVariable: {id, op: "set"|"add"|"sub", value}} | {setSelfSwitch: {ch, value}} | {transfer: {mapId, x, y, direction?: 0|2|4|6|8, fade?: 0|1|2}} | {raw: [{code, indent?, parameters?}]} (indent is relative to the node's position). Example: [{"say":"Will you help?","face":{"name":"Actor1","index":0}},{"choices":[{"label":"Yes","then":[{"setSwitch":{"id":5,"value":true}},{"say":"Thank you!"}]},{"label":"No","then":[{"say":"A pity."}]}],"cancel":"branch"}]. (2) CUTSCENE, where target is "player" | "this" (the running event) | a positive event id: {wait: 1-6000} (frames; 60 = 1 second) | {fade: "out"|"in"} | {tint: {r, g, b: -255..255, gray: 0-255, frames?: 1-600 (60), wait?: true}} | {flash: {r, g, b: 0-255, intensity: 0-255, frames?: 1-600 (60), wait?: true}} | {shake: {power?: 1-9 (5), speed?: 1-9 (5), frames?: 1-600 (30), wait?: true}} | {weather: {type: "none"|"rain"|"storm"|"snow", power?: 1-9 (5), frames?: 1-600 (60), wait?: false}} | {playAudio: {kind: "bgm"|"bgs"|"me"|"se", name (use "" to stop that channel), volume?: 0-100 (90), pitch?: 50-150 (100), pan?: -100..100 (0)}} | {fadeAudio: {kind: "bgm"|"bgs", seconds: 1-60}} | {showPicture: {id: 1-100, name, origin?: "upperLeft"|"center", x, y, scaleX?: 0-2000 (100), scaleY?: 0-2000 (100), opacity?: 0-255 (255), blend?: "normal"|"add"|"multiply"|"screen"}} | {erasePicture: 1-100} | {animation: {target, animationId, wait?: true}} | {balloon: {target, balloonId: 1-10, wait?: true}} | {moveRoute: {target, steps: 1-100 steps, repeat?: false, skippable?: false, wait?: true}} (compiles to command 205 plus one 505 row per step). A route step is one of the strings down, left, right, up, turnDown, turnLeft, turnRight, turnUp, walkAnimOn, walkAnimOff, stepAnimOn, stepAnimOff, dirFixOn, dirFixOff, throughOn, throughOff, transparentOn, transparentOff, or an object {jump: {x, y}} (relative tiles, -1000..1000) | {wait: 1-999} | {switchOn: id} | {switchOff: id} | {speed: 1-6} | {frequency: 1-5}. A repeating route never finishes, so with repeat: true wait defaults to false and an explicit wait: true is rejected. Example: [{"fade":"out"},{"playAudio":{"kind":"bgm","name":"Theme1"}},{"moveRoute":{"target":"player","steps":["up","up",{"wait":10},"turnLeft"]}},{"fade":"in"}]. (3) GAME FLOW: {battle: {troopId, canEscape?: false, canLose?: false, onWin?: Node[], onEscape?: Node[] (needs canEscape: true), onLose?: Node[] (needs canLose: true)}} (like the editor, branches are written only when canEscape or canLose is true or onWin has nodes: then 601, plus 602 with canEscape and 603 with canLose even when empty, and the closer 604; with neither, just the battle command is written and what follows runs after the battle; a body for a branch whose box is off is rejected) | {shop: {goods: [{type: "item"|"weapon"|"armor", id, price?}] (1-40; omit price for the database price), purchaseOnly?: false}} | {callCommon: commonEventId} | {label: name} | {jump: label name} (jump to a label in the same list) | {exit: true} (stop this event) | {comment: string | string[]} (not shown in game) | {gold: n} (positive gives, negative takes; not 0) | {item: {kind: "item"|"weapon"|"armor", id, count}} (positive adds, negative removes, not 0, |count| <= 99; weapons/armors only change the inventory, not equipped gear) | {party: {actorId, action: "add"|"remove", initialize?: false}} (initialize resets the actor when added) | {learnSkill: {actorId, skillId, forget?: false}} | {recoverAll: true} (full HP/MP/states for the whole party) | {nameInput: {actorId, maxChars: 1-16}} | {plugin: "Command arg1 arg2"} (plugin command) | {scene: "menu"|"save"|"gameOver"|"title"}. Example: [{"battle":{"troopId":3,"canLose":true,"onWin":[{"gold":200},{"item":{"kind":"item","id":1,"count":2}}],"onLose":[{"say":"Defeated..."},{"scene":"gameOver"}]}},{"shop":{"goods":[{"type":"item","id":1},{"type":"weapon","id":2,"price":300}]}}]. Returns { commands, inserted?, problems, preview? }; preview is included for dry runs and for trees of up to 40 commands.

Input Schema

NameRequiredDescriptionDefault
treeYesDialogue nodes, in order
indexNoPosition in the page's command list to insert at; defaults to the end (before the terminator). Positions inside a conditional, choice or battle body (the branch markers 402, 403, 404, 411, 412, 413, 601, 602, 603, 604 count as inside), or on a continuation line of a multi-line command (text, comment, move route, script or shop lines: 401, 405, 408, 505, 605, 655), are refused
mapIdNoMap to insert into; omit (with eventId) for a dry run
dryRunNoCompile and validate only; never touches the project files
eventIdNoEvent to insert into; omit (with mapId) for a dry run
pageIndexNoWhich event page (0-based)

Schema Changelog

Changes observed during successful MCP inspections.

  1. Addedv0.5.1

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden and does it well: unknown keys rejected, nesting capped at 8 levels for choices/if/battle bodies, any invalid node fails the whole call and nothing is written, insertion positions inside branch markers or continuation lines are refused, and the return shape { commands, inserted?, problems, preview? } with preview only for dry runs or trees up to 40 commands. That is exactly the destructive/mutation context an agent needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose and insertion semantics, then organized into three labeled node groups with worked examples, which is the right structure for this vocabulary. It is very long and does repeat some schema-enumerated bounds (1-6000, 0-255, etc.), which is wasted text, but the bulk of the length is load-bearing node semantics.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema, yet the description documents the return object and when `preview` appears. Given the enormous input schema and absence of annotations, the description supplies the missing pieces: failure atomicity, insert-position refusals, depth limits, and node vocabulary with examples. Nothing essential to calling it correctly is absent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds semantics the schema cannot: 60 frames = 1 second, defaults for volume/pitch/pan/frames/power, that a repeating move route never finishes so wait: true is rejected, that weapons/armors only change inventory not equipped gear, and that 'initialize' resets an added actor. These are real behavioral defaults, not restatements of ranges.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (compiles) and resource (nested tree of nodes → indented event commands), plus insertion scope. The opening line 'so you never hand-write indents, block terminators or move-route rows' plus the explicit comparison to add_event_command separates it from the sibling command-insertion tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly defines the two operating modes: with mapId + eventId commands are inserted at indent 0 (or at `index`) like add_event_command; without them or with dryRun nothing is written and output goes to `preview`. That is clear routing context, but it never states when an agent should prefer this over add_event_command or add_dialogue for a single-line case, so no true exclusions are given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.