Character
Build a party the engine can start. Every die — ability scores, hit points, starting gold — is rolled by osrlib's deterministic chargen CLI from a recorded seed, so the party is auditable and reproducible, never LLM-invented. Your job is to run the CLI, present what it returns verbatim, and collect the player's administrative build choices with AskUserQuestion.
Read the referee's constitution before doing anything else. It governs creation as well as play: the engine rolls every number (Article III.1), and AskUserQuestion is for administrative build choices only — never in-world play (Article I.5).
The CLI
Character creation runs off the play server, as a CLI (the once-per-campaign, pre-session shape — like compile-adventure's bundletool), so play sessions pay it zero standing schema. Invoke it with Bash:
uv run --project ${CLAUDE_PLUGIN_ROOT}/server python -m osrlib_referee_mcp.chargen <subcommand> …
The seed carries the whole roll state — there is no scratch file. roll emits the scores and the legal-class menu; build re-derives the same scores, then rolls HP and gold once the class is known, and finalizes. Same seed + same choices ⇒ byte-identical character. Pick a distinct seed per character (any integer — e.g. a timestamp or an incrementing counter); a "reroll" is simply a new seed, which is why it is auditable. osrlib offers no in-place single-ability reroll and no 4d6-drop-lowest / max-HP method — those are documented engine-limited gaps, not something to fake.
Building one character
Roll ability scores. chargen roll --seed S. Present the six scores and their modifiers (the modifier_legend in the payload says what each governs) to the player. Offer a reroll — that is a fresh roll with a new seed. The payload's eligible_classes is the legal-by-construction class menu; ineligible_classes carries the classes the scores lock out, with reasons (present them only if the player asks why a class is missing).
Choose class, alignment, adjustment, spell. AskUserQuestion, in this order:
- Class — present only
eligible_classes (the CLI's validate_class_choice is the gate; never re-derive eligibility yourself).
- Alignment — lawful, neutral, or chaotic.
- Adjustment (optional) — the creation-time two-for-one trade lowering STR/INT/WIS to raise a prime requisite. Offer it; most players skip it. Pass it as
--lower ABILITY=N --raise ABILITY=N.
- Starting spell — magic-user and elf only (their
caster is "arcane" in the class entry). One first-level arcane spell for the spell book; pass it as --spell SPELL_ID.
Reveal gold, then buy equipment. chargen build --seed S --class … --alignment … with those choices and no purchases reveals hit_points and starting_gold_gp. Present the gold total, then AskUserQuestion for equipment against that number: a standard class kit, or a manual pick. Weapons and armour buy one at a time (--buy sword); gear and ammunition buy in lots (--buy torch is one lot = six torches). Equip what should be worn/wielded with --equip.
Finalize. chargen build again with the equipment (--buy …, --equip …), the --name, and --out <path> to write the finished character document to a scratch file. If it returns {"ok": false, …} (an unaffordable basket, an illegal equip), surface the rejection's reason in plain language and re-ask — nothing was committed. On {"ok": true, …} deliver the HP, gold, and AC the CLI reports, verbatim.
Assembling the party
Build each member to its own scratch file, then assemble:
BUILD=$(mktemp -d)
uv run --project ${CLAUDE_PLUGIN_ROOT}/server python -m osrlib_referee_mcp.chargen build --seed 101 --class fighter --alignment lawful \
--buy sword --buy chainmail --equip sword --equip chainmail --name Brakka --out "$BUILD/brakka.json"
# …repeat for each member…
uv run --project ${CLAUDE_PLUGIN_ROOT}/server python -m osrlib_referee_mcp.chargen party --out heroes "$BUILD/brakka.json" "$BUILD/wynn.json"
chargen party --out <party_id> writes the stamped party document to <game-root>/parties/<party_id>.json (the game directory, ~/osr-games by default or wherever OSRLIB_REFEREE_GAME_ROOT points). Report the party_id back — that is what starts the adventure: the play/referee flow passes it as session_new(party_ref=<party_id>), so the whole party document never crosses the conversation wire. Members carry no entity ids yet; the engine assigns them when the session begins.
Tool reference
| Command |
Use |
chargen roll --seed S |
Roll ability scores; emit scores, modifiers, and the eligible-class menu. |
chargen build --seed S --class … --alignment … [--lower/--raise …] [--spell …] [--buy …] [--equip …] [--name …] [--out PATH] |
Roll HP + gold and finalize a character, or return structured rejections. |
chargen party --out PARTY_ID CHAR.json … |
Assemble finished character documents into a party in the game directory. |
1---2name: character3description: Create B/X (Basic/Expert) characters and assemble a party through the deterministic, seeded chargen CLI, where the osrlib engine rolls every ability score, hit-point total, and gold piece — never the LLM. Use when creating a new character, rolling up a PC, or building a party before starting an adventure.4---56# Character78Build a party the engine can start. Every die — ability scores, hit points, starting gold — is rolled by osrlib's deterministic `chargen` CLI from a recorded seed, so the party is auditable and reproducible, never LLM-invented. Your job is to run the CLI, present what it returns verbatim, and collect the player's *administrative* build choices with `AskUserQuestion`.910**Read [the referee's constitution](../referee/references/constitution.md) before doing anything else.** It governs creation as well as play: the engine rolls every number (Article III.1), and `AskUserQuestion` is for administrative build choices only — never in-world play (Article I.5).1112## The CLI1314Character creation runs off the play server, as a CLI (the once-per-campaign, pre-session shape — like `compile-adventure`'s `bundletool`), so play sessions pay it zero standing schema. Invoke it with `Bash`:1516```bash17uv run --project ${CLAUDE_PLUGIN_ROOT}/server python -m osrlib_referee_mcp.chargen <subcommand> …18```1920The **seed carries the whole roll state** — there is no scratch file. `roll` emits the scores and the legal-class menu; `build` re-derives the same scores, then rolls HP and gold once the class is known, and finalizes. Same seed + same choices ⇒ byte-identical character. Pick a distinct seed per character (any integer — e.g. a timestamp or an incrementing counter); a **"reroll" is simply a new seed**, which is why it is auditable. osrlib offers no in-place single-ability reroll and no 4d6-drop-lowest / max-HP method — those are documented engine-limited gaps, not something to fake.2122## Building one character23241. **Roll ability scores.** `chargen roll --seed S`. Present the six scores and their `modifiers` (the `modifier_legend` in the payload says what each governs) to the player. Offer a reroll — that is a fresh `roll` with a new seed. The payload's `eligible_classes` is the legal-by-construction class menu; `ineligible_classes` carries the classes the scores lock out, with reasons (present them only if the player asks why a class is missing).25262. **Choose class, alignment, adjustment, spell.** `AskUserQuestion`, in this order:27 - **Class** — present *only* `eligible_classes` (the CLI's `validate_class_choice` is the gate; never re-derive eligibility yourself).28 - **Alignment** — lawful, neutral, or chaotic.29 - **Adjustment** (optional) — the creation-time two-for-one trade lowering STR/INT/WIS to raise a prime requisite. Offer it; most players skip it. Pass it as `--lower ABILITY=N --raise ABILITY=N`.30 - **Starting spell** — magic-user and elf only (their `caster` is `"arcane"` in the class entry). One first-level arcane spell for the spell book; pass it as `--spell SPELL_ID`.31323. **Reveal gold, then buy equipment.** `chargen build --seed S --class … --alignment …` with those choices and **no purchases** reveals `hit_points` and `starting_gold_gp`. Present the gold total, then `AskUserQuestion` for equipment against that number: a standard class kit, or a manual pick. Weapons and armour buy one at a time (`--buy sword`); gear and ammunition buy in lots (`--buy torch` is one lot = six torches). Equip what should be worn/wielded with `--equip`.33344. **Finalize.** `chargen build` again with the equipment (`--buy …`, `--equip …`), the `--name`, and `--out <path>` to write the finished character document to a scratch file. If it returns `{"ok": false, …}` (an unaffordable basket, an illegal equip), surface the rejection's reason in plain language and re-ask — nothing was committed. On `{"ok": true, …}` deliver the HP, gold, and AC the CLI reports, verbatim.3536## Assembling the party3738Build each member to its own scratch file, then assemble:3940```bash41BUILD=$(mktemp -d)42uv run --project ${CLAUDE_PLUGIN_ROOT}/server python -m osrlib_referee_mcp.chargen build --seed 101 --class fighter --alignment lawful \43 --buy sword --buy chainmail --equip sword --equip chainmail --name Brakka --out "$BUILD/brakka.json"44# …repeat for each member…45uv run --project ${CLAUDE_PLUGIN_ROOT}/server python -m osrlib_referee_mcp.chargen party --out heroes "$BUILD/brakka.json" "$BUILD/wynn.json"46```4748`chargen party --out <party_id>` writes the stamped party document to `<game-root>/parties/<party_id>.json` (the game directory, `~/osr-games` by default or wherever `OSRLIB_REFEREE_GAME_ROOT` points). Report the `party_id` back — that is what starts the adventure: the `play`/`referee` flow passes it as `session_new(party_ref=<party_id>)`, so the whole party document never crosses the conversation wire. Members carry no entity ids yet; the engine assigns them when the session begins.4950## Tool reference5152| Command | Use |53|---|---|54| `chargen roll --seed S` | Roll ability scores; emit scores, modifiers, and the eligible-class menu. |55| `chargen build --seed S --class … --alignment … [--lower/--raise …] [--spell …] [--buy …] [--equip …] [--name …] [--out PATH]` | Roll HP + gold and finalize a character, or return structured rejections. |56| `chargen party --out PARTY_ID CHAR.json …` | Assemble finished character documents into a party in the game directory. |