Skip to main content
Glama
README.md
# D&D Beyond MCP Server

A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that gives Claude direct access to your D&D Beyond account — characters, campaigns, sourcebooks, spells, monsters, rules, encounter planning, treasure generation, and more.

> **What's new** — see the [latest release notes](https://github.com/iamjameslennon/ddb-mcp/releases).

---

## For Players

Use Claude as a session companion that knows your character as well as you do.

<details>
<summary><strong>Example prompts</strong> — character lookups, abilities, rules, spells, sourcebooks</summary>

**Know your character inside out**
```
Give me a full summary of my character Torvin
```
```
What spells do I have prepared right now?
```
```
What concentration spells do I have prepared as Torvin?
```
```
Tell me about Torvin's backstory and personality
```
```
What organisations is Kestrel affiliated with?
```
```
Which of my spells can I cast as rituals without using a slot?
```
```
What's my passive perception and investigation?
```

**Look up your abilities mid-session**
```
How does Uncanny Dodge work on Kestrel?
```
```
What does Hunter's Mark do — can I move it as a bonus action?
```
```
Show me the full text of the Alert feat on my character
```

**Check the rules without leaving the table**
```
What are the rules for grappling?
```
```
What does the Stunned condition do?
```
```
How does concentration work?
```
```
Remind me of the rules for death saving throws
```

**Look up spells and equipment in the compendium**
```
What does Silvery Barbs do?
```
```
Show me the stats for a Flame Tongue longsword
```
```
What's the difference between a Shortbow and a Longbow?
```

**Read your sourcebooks**
```
Show me the table of contents for the Player's Handbook
```
```
Read the Ranger class section from the 2024 Player's Handbook
```

</details>

---

## For Dungeon Masters & Game Masters

Use Claude to plan sessions, build encounters, and run the table faster.

<details>
<summary><strong>Example prompts</strong> — encounters, treasure, monsters, campaign, sourcebooks, rules</summary>

**Get party stats**
```
Show me the full party stats for campaign 6709239
```

**Plan and rate encounters**
```
How hard is this encounter for my party of 4 level 5 players:
2 trolls and a hill giant?
```
```
What CR should I target for a Moderate difficulty encounter
for my party of 3 level 8 characters?
```
```
Give me CR targets for a solo boss fight vs my party of 5 level 10s
```

**Generate treasure**
```
Roll a hoard for a CR 15 encounter for a level 12 party
```
```
Generate individual treasure for 4 bandits and their CR 5 captain
```

**Look up monsters on the fly**
```
Show me the full stat block for a Young Red Dragon
```
```
Find all Large undead with CR 5 or lower
```
```
What monsters have the Legendary Resistance trait?
```

**Manage your campaign**
```
List all the characters in my campaign
```
```
Show me the details for campaign 6709239 — who's playing what?
```

**Read sourcebooks for prep**
```
Read the Lair Actions section from the Monster Manual
```
```
What does the DMG say about setting DCs for ability checks?
```
```
Show me the treasure tables chapter from the Dungeon Master's Guide
```

**Rule lookups mid-session**
```
What are the rules for improvised weapons?
```
```
How does the Exhaustion condition work in 2024 rules?
```
```
Can a character use the Help action to assist with a skill check?
```

</details>

---

## Full Tool Reference

<details>
<summary><strong>All tools</strong> — character, campaign, monster, encounter, spells, reference, library, navigation</summary>

### Character Tools

| Tool | Description |
|------|-------------|
| `ddb_login` | Authenticate with D&D Beyond (Wizards ID). Run once — session is saved to disk and reused. |
| `ddb_logout` | Revoke this server's local access: blocks further authenticated calls immediately, deletes the saved session file, and closes any open browser context. No account input, no remote logout call. See [Logging out](#logging-out) — this is a local-only logout, not a D&D Beyond account logout. |
| `ddb_list_characters` | List all characters in your account with ID, level, race, and class. |
| `ddb_get_character` | Parse a character into a compact, readable sheet. Covers all stats, skills, spells, actions, and inventory. Use `sections` to get just `summary`, `combat`, `spells`, `inventory`, `features`, `concentration`, `notes`, or `full`. Accepts name (fuzzy matched) or numeric ID. |
| `ddb_get_character_raw` | Fetch raw character JSON from the D&D Beyond API. Use `ddb_get_character` for all normal use. |
| `ddb_download_character` | Save a character's full JSON to a local file (must be under ~/Downloads or ~/Documents). |
| `ddb_character_lookup` | Look up the full description of a spell, feat, class feature, racial trait, or item on a character sheet. Supports partial and fuzzy name matching. |

### Campaign Tools

| Tool | Description |
|------|-------------|
| `ddb_list_campaigns` | List all campaigns you're part of (as DM or player). |
| `ddb_get_campaign` | Fetch campaign details — DM, description, and active characters with their levels. |
| `ddb_get_party` | Fetch a compact summary of every character in a campaign — HP, AC, initiative, passive scores, ability scores, and skills for the whole party in one call. |

### Monster & Encounter Tools

| Tool | Description |
|------|-------------|
| `ddb_search_monsters` | Search the D&D Beyond monster compendium by name, CR, type, or size. |
| `ddb_get_monster` | Get the full formatted stat block for a monster by name. |
| `ddb_rate_encounter` | Rate encounter difficulty for a party. Defaults to 2024 XDMG rules (Low/Moderate/High). Set `rules_edition: "2014"` for classic DMG (Easy/Medium/Hard/Deadly). Monsters are looked up automatically. |
| `ddb_encounter_cr` | Given a party and target difficulty, returns recommended CRs broken down by encounter shape: solo boss, duo, squad, horde. |
| `ddb_roll_treasure` | Generate treasure using 2024 XDMG tables. `hoard` rolls once at the highest CR and includes magic items; `individual` rolls per monster. Limits: at most 20 monster entries, at most 100 per entry (applies to hoard too), at most 200 characters per monster name, and — for `individual` only — at most 100 total rolls across all entries. Over-budget requests are rejected with an error, never silently truncated. |

### Spell & Reference Tools

| Tool | Description |
|------|-------------|
| `ddb_search_spells` | Search the full D&D Beyond spell compendium by name, level, school, concentration, or ritual. |
| `ddb_get_spell` | Get the full description of any spell by name. |
| `ddb_search_equipment` | Search the item/equipment compendium by name, rarity, or type. Covers mundane weapons, armour, and magic items. |
| `ddb_get_equipment` | Get the full stats and description of any item — weapon damage, properties, range, STR requirement, etc. |
| `ddb_get_condition` | Look up the rules text for a condition (Poisoned, Stunned, Grappled, etc.). No login required. |
| `ddb_search_rules` | Search all 45 SRD rules sections by keyword. No login required. |
| `ddb_get_rules` | Read the full text of any SRD rules section (Spellcasting, Attacking, Combat, Multiclassing, Rest, Environment, etc.). Supports `query` to jump to a keyword within long sections. No login required. |
| `ddb_search_races` | Search all races and subraces in the D&D Beyond compendium (including homebrew). |
| `ddb_search_classes` | Search all classes with hit die, spellcasting info, and subclasses. |
| `ddb_search_backgrounds` | Search all backgrounds (including homebrew). |
| `ddb_search_feats` | Search feats by name or prerequisite. |
| `ddb_search_class_features` | Search class features by name, class, or level gained. |
| `ddb_search_racial_traits` | Search racial traits by name or race. |

### Library & Navigation Tools

| Tool | Description |
|------|-------------|
| `ddb_list_library` | List all sourcebooks you own, purchased, or have shared with you. |
| `ddb_read_book` | Read content from an owned sourcebook by book slug and optional chapter. |
| `ddb_search_site` | Search D&D Beyond by keyword across spells, monsters, items, races, classes, and feats. |
| `ddb_navigate` | Navigate to any D&D Beyond URL and return its text content. Keeps the browser open for follow-up calls. |
| `ddb_interact` | Click, fill (requires `confirm_fill: true`), or screenshot the currently loaded page. |
| `ddb_get_page` | Return the text content of the currently loaded page. |
| `ddb_close_browser` | Close the background browser window. Call this when done with `ddb_navigate`, `ddb_interact`, or `ddb_get_page`. |

</details>

---

## Prerequisites

- [Node.js](https://nodejs.org) 22 or later
- [Claude Code](https://claude.ai/claude-code) CLI

---

## Installation

> 🆕 **New to all this?** If you're on a Mac starting from scratch (no Homebrew, no Node, no Claude Desktop), follow the [step-by-step beginner tutorial](INSTALL-MACOS.md) instead — it covers everything below plus how to install the prerequisites.

Add this to your MCP client's config — no separate install step needed.

```json
{
  "mcpServers": {
    "dndbeyond": {
      "command": "npx",
      "args": ["-y", "@iamjameslennon/ddb-mcp"]
    }
  }
}
```

> ⚠️ **Merge, don't append.** These config files usually already exist and already have content (Claude Desktop writes its own `"preferences"` there on first launch). A JSON file holds exactly one top-level `{ … }` object, so pasting this block at the end of the file produces a parse error. If the file already has an `"mcpServers"` key, add only the `"dndbeyond": { … }` entry inside it, comma-separated from its neighbours; if it doesn't, add `"mcpServers"` as a new key inside the existing outer braces. Verify before restarting your client:
>
> ```bash
> python3 -m json.tool /path/to/your/config.json > /dev/null && echo "JSON OK"
> ```

On first launch, `npx` fetches the package itself (small — under 200 kB unpacked of JS). For the browser dependency: on first `ddb_login`, the server tries to launch your **already-installed Google Chrome** first — most macOS and Windows users get zero download. If Chrome isn't present, it falls back to downloading Playwright's bundled Chromium (~140 MB), with progress printed to the server log; subsequent logins reuse the cached browser. Set `DDB_USE_BUNDLED_CHROMIUM=1` to skip the system-Chrome attempt and force the bundled path.

Configure the path to your client's config file in the [Connecting to your MCP client](#connecting-to-your-mcp-client) section below.

To pin a version (recommended for production setups), change the args to `["-y", "@iamjameslennon/ddb-mcp@2.10.2"]`.

### Alternative: install globally

If you'd rather have a persistent binary on `PATH` (offline use, air-gapped networks, faster startup):

```bash
npm install -g @iamjameslennon/ddb-mcp
```

Then use `"command": "ddb-mcp"` (no args) in your client config. The browser is still launched on first `ddb_login` (system Chrome if available, bundled Chromium otherwise) rather than during install.

---

## Security & Privacy

- **Credentials stored**: D&D Beyond session cookies are saved to a per-user config directory — `~/.config/ddb-mcp/session.json` on macOS/Linux, `%APPDATA%\ddb-mcp\session.json` on Windows.
- **File permissions**: on macOS/Linux the file is `0600` and the directory `0700` — sessions created by older releases are tightened to these modes automatically on first use. On Windows access is restricted to your user account by default via `%APPDATA%` ACL inheritance — note that on multi-admin/domain-joined machines local administrators may also have read access.
- **Cobalt JWT**: cached in memory only, never written to disk, and cleared on every session transition — a new login, an account swap (a different session file appearing), or `ddb_logout`.
- **Revocable session lifecycle**: the server treats the on-disk session file as the single source of truth for "who am I logged in as." Every character/campaign/monster/reference cache described above is bound to that file's identity and is dropped the moment it changes — including deletion. `ddb_logout` makes this explicit and immediate for the local process; see [Logging out](#logging-out) for exactly what it does and does not guarantee.
- **Network access** (outbound HTTPS only):
  - `*.dndbeyond.com` — character data, auth, campaigns, books
  - `auth-service.dndbeyond.com` — cobalt token exchange
  - `api.open5e.com` — SRD fallback (no auth)
- **Filesystem writes**:
  - Session: `~/.config/ddb-mcp/session.json` (macOS/Linux) or `%APPDATA%\ddb-mcp\session.json` (Windows)
  - Character downloads (opt-in): `~/Downloads` or `~/Documents` only — paths outside these roots are rejected
  - Screenshots (opt-in): `~/Downloads` only
- **Transport**: stdio only — the server opens no HTTP listeners and no ports.
- **`ddb_roll_treasure` work budget**: bounded at both the MCP schema and the runtime level (direct callers of the underlying function bypass the schema, so the runtime check is not optional). Accepted requests: at most 20 monster entries, at most 100 per entry (per-entry limit applies to `hoard` requests too, not just `individual`), at most 200 characters per monster name, and — `individual` only — at most 100 total rolls summed across all entries (`hoard` always makes exactly one roll). Over-budget requests are rejected outright with an error naming the limit and how to reduce the request; counts are never silently clamped. The formatted output is separately capped at 32,000 characters — an oversized upstream monster name can't inflate the response, and aggregate coin totals are always shown in full even if per-roll detail is omitted for space.
- **Browser navigation allowlist**: the browser tools are pinned to `dndbeyond.com`. `ddb_navigate` validates the URL up front, a network-layer guard blocks in-page escapes (link clicks, JS redirects, popups) to any other origin, and `ddb_get_page` refuses to return content from any page outside the allowlist.
- **Untrusted content**: free text authored by D&D Beyond users is wrapped in `<untrusted_dndbeyond_content>` tags — scraped page text (`ddb_navigate`, `ddb_get_page`), book content (`ddb_read_book`), character notes/backstories (`ddb_get_character`, `ddb_get_party`), and homebrew monster stat blocks (`ddb_get_monster`). Embedded delimiter tags in the content are neutralized so it can't break out of the block. Party-member backstories and campaign notes are written by *other people* and may contain prompt-injection attempts — treat everything inside the tags as data, never as instructions. The `confirm_click` / `confirm_fill` gates on `ddb_interact` exist for exactly this reason.
- **Tool annotations & client permissions**: every tool declares MCP behavior hints (`readOnlyHint`, `destructiveHint`, `openWorldHint`) so your MCP client can scope its permission prompts. The read-only tools (searches, lookups, character/campaign reads) are safe to auto-approve. **Never auto-approve `ddb_interact`**: its `confirm_click`/`confirm_fill` gates are set by the calling model, not by you, so your client's per-call permission prompt is the only human-in-the-loop check standing between a prompt-injected page and a click or form submission on your logged-in D&D Beyond session. `ddb_login` (writes credentials) and `ddb_download_character` (writes/overwrites local files) also warrant per-call approval. `ddb_logout` is also `destructiveHint: true` (it deletes the saved session file), though unlike the others it never talks to D&D Beyond and only ever narrows access.
- **Recommendation**: pin the version in your MCP client config — `"@iamjameslennon/ddb-mcp@2.10.2"` — rather than letting `npx` auto-update on every launch.

---

## Connecting to your MCP client

This server was built and tested with Claude — it will work with any MCP-compatible client, but response quality for D&D-specific reasoning will vary depending on the model used.

All clients below use the same JSON config from the [Installation](#installation) section. Merge it into your client's config file (paths below) — see the merge warning there if the file isn't empty — then restart the client.

### Claude Desktop (recommended)

- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
- **Linux**: `~/.config/Claude/claude_desktop_config.json` (community builds only — Claude Desktop has no official Linux release; use [Claude Code](#claude-code) or [Cursor](#cursor) instead)

### Claude Code

One-liner — no manual JSON editing:

```bash
claude mcp add dndbeyond -- npx -y @iamjameslennon/ddb-mcp
```

Or if you installed globally:

```bash
claude mcp add dndbeyond ddb-mcp
```

### Cursor

`~/.cursor/mcp.json`

### Windsurf

`~/.codeium/windsurf/mcp_config.json`

### LM Studio

MCP support was added in LM Studio 0.3.x. Configure through the UI under **Settings → MCP Servers** using the same JSON shape as above. Steps may vary between versions — see [lmstudio.ai/docs](https://lmstudio.ai/docs) for current instructions.

### Open WebUI

MCP servers are configured through the admin panel under **Settings → Tools**. See [docs.openwebui.com](https://docs.openwebui.com) for current instructions — the UI changes frequently between releases.

---

## First-time login

Run `ddb_login` once to authenticate:

```
ddb_login
```

A browser window will open and navigate to the D&D Beyond login page. Complete the login using your Wizards ID account. Once redirected back to D&D Beyond, your session is automatically saved to a per-user config directory (`~/.config/ddb-mcp/session.json` on macOS/Linux, `%APPDATA%\ddb-mcp\session.json` on Windows) and reused on all future calls — no browser needed again until the session expires.

---

## Finding character and campaign IDs

- **Character ID**: the number in the character URL — `dndbeyond.com/characters/140476673`
- **Campaign ID**: the number in the campaign URL — `dndbeyond.com/campaigns/6709239`

You can also use `ddb_list_characters` and `ddb_list_campaigns` to get IDs without leaving Claude.

---

## Book slugs for `ddb_read_book`

Use `ddb_list_library` to get the slug for any book you own. Common examples:

| Book | Slug |
|------|------|
| Player's Handbook (2024) | `dnd/phb-2024` |
| Dungeon Master's Guide (2024) | `dnd/dmg-2024` |
| Monster Manual (2024) | `dnd/mm-2024` |
| Player's Handbook (2014) | `dnd/phb-2014` |

To read a specific chapter, pass the chapter path after the book slug:

```
Read the Ranger class section from the 2024 Player's Handbook
→ book_slug: "dnd/phb-2024", chapter_slug: "character-classes/ranger"
```

---

## Sample `ddb_get_character` output

<details>
<summary><strong>Real character sheet</strong> — Tiefling Wizard 2 with prepared spells, unprepared rituals, and racial/feat spell sources</summary>

```
═══════════════════════════════════════
  Claude Skamos
  Tiefling | Wizard 2 | Level 2
  Background: Sage | XP: 0
  Inspiration: No
═══════════════════════════════════════

HP: 10/10   Temp HP: —   Prof Bonus: +2
Hit Dice: 2d6 (2 remaining)
AC: 10   Initiative: +0   Speed: 30 ft.
Death Saves: Successes 0/3   Failures 0/3

ABILITY SCORES
  STR 8 (-1)  DEX 10 (+0)  CON 10 (+0)  INT 17 (+3)  WIS 15 (+2)  CHA 14 (+2)

SAVING THROWS
  STR -1   DEX +0   CON +0   INT +5*   WIS +4*   CHA +2
  (* proficient)

SKILLS
  Acrobatics (DEX)       +0
  Animal Handling (WIS)  +2
  Arcana (INT)           +5 *
  Athletics (STR)        -1
  Deception (CHA)        +2
  History (INT)          +7 **
  Insight (WIS)          +2
  Investigation (INT)    +5 *
  Perception (WIS)       +4 *
  ... (all 18 skills shown)
  (* proficient, ** expertise)

SENSES
  Passive Perception: 14   Passive Investigation: 15   Passive Insight: 12
  Darkvision 60 ft.

PROFICIENCIES & TRAINING
  Armor: None
  Weapons: Simple Weapons
  Tools: Calligraphers supplies
  Languages: Common, Common sign language, Draconic

DEFENSES
  Resistances: Fire
  Immunities: (none)
  Vulnerabilities: (none)
CONDITIONS: (none)

FEATS (2)
• Magic Initiate (Wizard): Two Cantrips. You learn two cantrips of your choice...
• Sage Ability Score Improvements: ...

CLASS FEATURES
• Core Wizard Traits (Wizard 1)
• Spellcasting (Wizard 1)
• Ritual Adept (Wizard 1)
• Arcane Recovery (Wizard 1)
• Scholar (Wizard 2)

ACTIONS
• Dagger           +2 to hit   1d4 piercing   reach 5 ft.   Finesse, Light, Thrown, Nick
• Quarterstaff     +1 to hit   1d6-1 bludgeoning   reach 5 ft.   Versatile, Topple

BONUS ACTIONS
  (none)

REACTIONS
• Opportunity Attack
• Shield (spell, 1st-level slot)

LIMITED USE
• Arcane Recovery   0 used / 1 max   (Long Rest)

SPELLCASTING
  Wizard: INT  Spell Attack: +5  Save DC: 13

SPELL SLOTS
  Level 1: 3/3

SPELLS
  Cantrips: Mage Hand, Light, Message
  Spells: Comprehend Languages (L1 [ritual]), Detect Magic (L1 [ritual]),
          Find Familiar (L1 [ritual]), Magic Missile (L1), Shield (L1),
          Mage Armor (L1), Chromatic Orb (L1), Grease (L1), ...
  From Racial Trait: Fire Bolt, Thaumaturgy
  From Feat: Dancing Lights, Mending, Tasha's Hideous Laughter (L1)

INVENTORY
  Spellbook, Parchment ×18, Backpack, Calligrapher's Supplies, Robe, ...

ATTUNEMENT: 0/3 slots used
CURRENCY: 34gp, 7sp
```

Key things `ddb_get_character` handles correctly:

- **Wizards**: only shows prepared spells and unprepared rituals (castable from spellbook without a slot) — not the full spellbook
- **Spell sources**: racial traits, class features, feats, and magic items are all labelled separately
- **Ritual spells**: marked with `[ritual]` in the spell list
- **Actions**: weapons include to-hit bonus, damage, range, and mastery properties; magic item bonuses (+1/+2/+3) are applied to both hit and damage
- **Bonus actions / reactions**: spell-based bonus actions and reactions (Healing Word, Shield, Hunter's Mark, Hellish Rebuke, etc.) appear in the correct section with slot cost
- **AC**: correctly calculates Unarmored Defense for Barbarians and Monks; Draconic Resilience base bump; Defense fighting style gated on equipped body armor; selects best armor when multiple items are equipped
- **Skills**: Jack of All Trades applied for Bards; Remarkable Athlete for Champion Fighters (STR/DEX/CON only); expertise marked with `**`
- **Initiative**: Alert feat and Jack of All Trades bonuses applied correctly, with 2014/2024 rule differences handled
- **Global save and ability-check bonuses**: Stone of Good Luck (Luckstone), Ring of Protection, Cloak of Protection, and Paladin Aura of Protection apply across every save and skill / passive score
- **Multiclass**: hit dice shown per class, spell slots computed from combined caster levels, save proficiencies correctly come only from the starting class
- **2014 race ASIs**: Half-Elf and Variant Human chosen +1 ability bonuses are applied alongside the fixed grants; 2024 declined race ASIs (moved to background origin feat) are correctly ignored

</details>

---

## Upgrading

```bash
npm update -g @iamjameslennon/ddb-mcp
```

Then restart your MCP client and run `/mcp` to reconnect the server.

---

## Session storage

Your session is saved to a per-user config directory:

- **macOS/Linux**: `~/.config/ddb-mcp/session.json`
- **Windows**: `%APPDATA%\ddb-mcp\session.json`

This file contains browser cookies from your D&D Beyond login. Keep it private — it grants access to your account.

---

## Logging out

**If your server has `ddb_logout`, use it — it's the preferred way to log out.** Run it as a tool call:

```
ddb_logout
```

`ddb_logout` takes no input and never calls D&D Beyond. It blocks any further authenticated tool call immediately, deletes the local session file, and closes any browser context the server had open. Repeated calls are safe — logging out when you were never logged in, or logging out twice, both report success. If a call fails (e.g. the session file can't be deleted because of a filesystem permission problem, or the browser refuses to close), the tool's error message says exactly which step failed — local access is still revoked for the rest of that failure, it's only the file and/or browser cleanup that didn't finish. It never silently falls back to letting the old session keep working.

**On an older version without `ddb_logout`**, log out manually:

1. Stop the MCP server (close your MCP client, or otherwise terminate the `ddb-mcp` process).
2. Delete the session file:
   ```bash
   # macOS/Linux
   rm ~/.config/ddb-mcp/session.json

   # Windows (PowerShell)
   Remove-Item "$env:APPDATA\ddb-mcp\session.json"
   ```
3. Restart the server.

**Important caveats, on every version:**

- **This is a local logout only — it is NOT a D&D Beyond account logout.** It removes this server's local copy of your session; it does not sign you out of dndbeyond.com in a browser, does not invalidate the session on D&D Beyond's servers, and does not revoke any other device or app using the same account. To sign out of D&D Beyond itself, do that on the website directly.
- **Detection happens at the next protected operation, not instantly.** If the session file is deleted or replaced by something other than `ddb_logout` (manually, by another process, or by an older-version workaround while the server keeps running), the running server only notices the next time it goes to use the old credentials — it re-reads the file at that point and refuses to proceed with the stale session. This means:
  - A request already in flight when the file changes is **not retracted** — it was dispatched under the old credentials before the change was observed.
  - Idle browser activity (an already-open background browser window/context) is **not torn down immediately** just because the file changed on disk; it's closed on the next transition the server observes, not the instant the file disappears.
  - **If you need immediate termination — no in-flight requests, no lingering browser window — stop the MCP server process itself.** That's the only action that's instantaneous; deleting the file (with the server still running) is not.

---

## Configuration

| Variable | Default | Description |
|----------|---------|-------------|
| `DDB_CHARACTER_CACHE_TTL` | `60` | Character sheet cache lifetime in seconds. Lower values give fresher HP/spell slot data during live play at the cost of more API calls. Set to `10` for active sessions, leave at default for prep work. |
| `DDB_NO_SANDBOX` | — | Set to `1` to disable Chromium sandboxing. Required in some container/CI environments. |

---

## Troubleshooting

**"Not logged in" or 403 errors**
Your session has expired. Run `ddb_login` to re-authenticate.

**Browser won't launch on `ddb_login`**
The server prefers your installed Google Chrome and falls back to Playwright's bundled Chromium if Chrome isn't present. If the bundled-Chromium fallback is in use and its download failed (network or sandbox issue), run `ddb_login` again — the server retries on each call. To fetch the bundled browser manually:
```bash
npx playwright install chromium
```
The same global Playwright cache is shared by every install path (npx, global, local clone) — one successful install is reused everywhere. If your system Chrome is broken or outdated and you want to force the bundled path, set `DDB_USE_BUNDLED_CHROMIUM=1`.

**Character returns 403 or "private"**
The character is set to private on D&D Beyond. You must be logged in as the owner, or the owner must make it public.

**MCP server not appearing in Claude Code**
Run `/mcp` in Claude Code to reconnect. If it still doesn't appear, run `claude mcp list` to confirm the `dndbeyond` entry exists.

**Server crashes on startup**
Make sure you're running Node.js 20 or later: `node --version`.

---

## Development

<details>
<summary><strong>Local commands</strong> — install, dev, build, watch, test</summary>

```bash
# Install dependencies — prefer npm ci to respect the lockfile
npm ci

# Run in development mode (no build step needed). Chromium is fetched lazily
# on first `ddb_login`; if you want to pre-warm the cache:
#   npx playwright install chromium
npm run dev

# Build
npm run build

# Watch mode
npm run build:watch

# Run tests (browser-free — they mock the Playwright surface)
npm test
```

</details>

---

## Credits

Forked from [ddb-mcp/ddb-mcp](https://github.com/ddb-mcp/ddb-mcp). The monster, reference, and session-workflow tooling was inspired by [dndbeyond-mcp](https://www.npmjs.com/package/dndbeyond-mcp). This fork significantly expands character parsing, adds session-based API fetching, and introduces compendium, reference, encounter, and treasure tools.

<details>
<summary><strong>Full list of improvements over the upstream fork</strong></summary>

**Character parsing improvements:**

- **Complete stat block**: saving throws, all 18 skills with proficiency/expertise markers, senses (passive scores + darkvision/tremorsense), proficiencies & training (armor, weapons, tools, languages), damage resistances/immunities/vulnerabilities, conditions, inspiration, death saves, hit dice per class
- **Accurate AC**: Unarmored Defense calculated correctly for Barbarians (10 + DEX + CON) and Monks (10 + DEX + WIS); when multiple armors are equipped, picks the best-AC combination; shield stacks additively
- **Correct spell display for Wizards**: shows only prepared spells and unprepared rituals — not the full spellbook
- **All spell sources**: racial traits, class features, feats, and magic items each labelled separately
- **Ritual spells**: marked with `[ritual]`
- **Full action classification**: bonus actions and reactions list both class features and spell-based entries with slot cost
- **Magic weapon bonuses**: enhancement bonuses (+1/+2/+3) applied to both to-hit and damage
- **Weapon properties and mastery**: all properties and mastery tags shown per weapon
- **Skill and initiative accuracy**: Jack of All Trades and Alert feat handled correctly for both 2014 and 2024 rules
- **Multiclass support**: hit dice per class, spell slots from combined caster levels

**Other improvements:**

- Session-based API fetching (no browser required after login for most tools)
- Encounter difficulty rating for both 2024 XDMG and 2014 DMG rules
- Treasure generation using 2024 XDMG tables
- SRD rules search and retrieval (no login required)
- Security: path constraints on file writes, slug validation, session file permissions (0600), prompt injection gate on browser form fills

</details>

---

## License

MIT

TDQS

A3.7/5.0

Scored across 35 tools

Disambiguation4/5

Most tools have clearly distinct purposes: search_* vs get_* vs list_*, plus unique tools like ddb_login and ddb_rate_encounter. Minor overlap exists between ddb_search_site and the specific compendium searches, and between ddb_get_rules and ddb_get_condition, but descriptions help clarify.

Naming Consistency4/5

The ddb_ prefix and common verbs (search_*, get_*, list_*) create a predictable pattern. Deviations like ddb_character_lookup (instead of ddb_lookup_character) and single-word verbs (ddb_login, ddb_navigate, ddb_interact) break the convention slightly, but the overall scheme remains readable.

Tool Count2/5

With 35 tools, this is well beyond the 25+ threshold and feels heavy for an agent to navigate. While the domain is broad, many tools could be consolidated (e.g., a single compendium search with type filters) or the server could be split into focused servers.

Completeness3/5

The tool surface is extensive, covering characters, campaigns, compendium searches, rules, books, browser automation, and encounter tools. However, there are notable gaps: you can search for feats, races, classes, backgrounds, and class features, but there are no corresponding ddb_get_* tools for these categories (only ddb_character_lookup which requires a character). This makes it impossible to directly retrieve full details for those compendium items.

Maintenance

ActivityActive
ResponsivenessNo issues