D2R modding toolkit — YAML character builder and data pipeline with MCP server exposing D2R game data lookup tools
Server exposes 23 tools with basic descriptions and minimal parameter documentation. Most lookup tools (1-7) have single string parameters with descriptions, but lack structured output schemas. Save/chargen/mod tools (8-23) have better parameter coverage but descriptions are often terse or missing context. No tool annotations (readOnlyHint/destructiveHint) despite clear risk levels. Error handling is absent from descriptions. Output schemas are not documented, LLMs cannot predict response structure. Naming is verb-noun compliant but descriptions average ~100 chars, below the 194-char baseline for A+ tools.
Build and deploy a character to the live saves directory. Structurally enforces CLAUDE.md rules #3, #4, #10, #17: backs up the live save, builds to a temp file, runs the scanner on the temp, and only promotes the temp to the live save if the scanner passes. Live save is untouched on scanner failure.
Import a server-synced .d2s save into chars/<name>.yaml.
List character names defined in chars/*.yaml.
Validate a character YAML and optionally run a dry-run binary build.
Look up a D2R base item by 3-char code or name. Searches item_bases.py data. Returns dimensions, requirements, sockets. Supports substring matching on names.
Look up a D2R runeword by name or numeric ID. Searches runewords.py data. Returns runes, valid bases, stats. Supports substring matching.
No output schemas documented. Lookup tools (1-7) return strings; save/chargen/mod tools return dicts. LLMs cannot predict response structure, forcing them to guess field names for downstream operations.
Mod tools (16-23) have minimal descriptions (<50 chars). Parameters like 'warn_conflicts', 'no_regen', 'game_dir' lack context. LLMs cannot determine when to set these flags or what they control.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | F | 48 | 2026-07-28+ | v2 |
Look up a D2R set item by name or numeric ID. Searches set_items.py data. Returns item info + set membership. Supports substring matching.
Look up a D2R skill by name or numeric ID. Searches skills.py data. Returns skill ID and class. Supports substring matching.
Look up a D2R stat by ID, canonical name, or YAML alias. Searches item_stat_cost.py data. Returns encoding info (save bits, save add, param bits, value shift) needed for binary stat encoding.
Look up a D2R unique item by name or numeric UID. Searches unique_items.py data. Returns item info + stats. Supports substring matching (e.g. "harlequin" finds Harlequin Crest).
Audit vanilla skills and items; write markdown reports.
Build mod from vanilla + overlays + scripts into build/.
Remove build/ and reset chargen data.
Build + deploy mod to the game mod folder (runs CASC injection by default).
Compare vanilla/ vs build/ tables. Returns list of changed files.
Extract vanilla data from CASC archive into vanilla/.
Remove mod from the game.
Full recovery pipeline: extract → build → deploy.
Compare two .d2s files and return structural differences.
Summarize a .d2s save: class, level, stats, progression, merc. No scanner pass — use d2r_save_scan for validation.
List items on disk in a .d2s save, optionally filtered by location.
Run d2rdoctor scanner on a .d2s save file. Returns a structured result with checksum/size status, item counts, and any scanner errors or warnings. status == "error" iff errors is non-empty. Deployment-blocker rule: never deploy a save that this tool flags as error (see CLAUDE.md Rule #17).
Search across ALL D2R item types: uniques, sets, runewords, bases. Use this when you don't know what type of item you're looking for. Returns up to 20 results tagged by type.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). Tools are marked READ_ONLY, WRITE, or DESTRUCTIVE in metadata but not in schema. Agents cannot infer safety properties from tool definitions alone.
No error handling guidance in descriptions. Tools like d2r_save_scan reference CLAUDE.md rules but do not explain what to do if scanner fails. Descriptions lack recovery hints (e.g., 'If not found, try search_*').
Parameter descriptions are sparse or missing. 'location' in d2r_save_list_items lists valid values but does not explain what each means. Boolean flags like 'force', 'yaml_only', 'no_casc' lack context on consequences.