Skip to main content
Glama
Mnehmos
by Mnehmos
README.md
# mnehmos.open5e.mcp

> MCP server for [Open5e](https://open5e.com) - Query D&D 5e game data and contribute to the open-source database

[![Tests](https://img.shields.io/badge/tests-178%20passing-brightgreen)](./tests)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
[![Node](https://img.shields.io/badge/node-%3E%3D18.0.0-blue)](https://nodejs.org)

A dual-mode MCP server that provides:
- **Consumer Mode**: Query spells, monsters, items, conditions, and more from 22+ source books
- **Contributor Mode**: Validate entries, check for collisions, diff against live API, and generate PR-ready JSON
- **RAG Developer Chatbot**: Search and chat with Open5e repository documentation

## Features

| Category | Tools | What It Does |
|----------|-------|--------------|
| **Consumer** | 6 tools | Search, get, list, batch fetch D&D 5e content |
| **Contributor** | 5 tools | Validate schemas, check slugs, diff entries, generate PRs |
| **RAG** | 5 tools | Search repo docs, chat with AI about contributing |
| **Meta** | 3 tools | Health checks, list documents/endpoints |

## Installation

### npm

```bash
npm install -g mnehmos.open5e.mcp
```

### From Source

```bash
git clone https://github.com/Mnehmos/mnehmos.open5e.mcp.git
cd mnehmos.open5e.mcp
npm install
npm run build
```

### Claude Desktop Configuration

Add to your `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "mnehmos.open5e.mcp": {
      "command": "node",
      "args": ["path/to/mnehmos.open5e.mcp/dist/index.js"]
    }
  }
}
```

Or if installed globally:

```json
{
  "mcpServers": {
    "mnehmos.open5e.mcp": {
      "command": "mnehmos-open5e-mcp"
    }
  }
}
```

## Quick Start

### Search for Spells

```
Search: "fireball"
→ Returns Fireball, Delayed Blast Fireball from multiple sources
```

### Get a Monster

```
Get: monsters/goblin
→ Full stat block with AC, HP, abilities, actions, environments
```

### Validate a Contribution

```
Validate: { name: "Custom Spell", level: 3, school: "Evocation", ... }
→ Errors for missing required fields
→ Suggestions for slug format
→ Warnings for unusual values
```

## Tool Reference

### Consumer Tools

#### `search`
Search across all Open5e resources with optional filters.

```typescript
search({
  query: "fireball",
  resource_type: "spells",      // optional: spells, monsters, items, etc.
  document_slug: "srd-2014",    // optional: filter by source book
  limit: 10                     // optional: max results (default 20)
})
```

Returns results with `slug`, `key` (for v2 resources), `name`, `excerpt`, and `web_url`.

#### `get`
Fetch a single resource by slug. Auto-tries common document prefixes for v2 resources.

```typescript
// Simple slug - auto-discovers the full key
get({ resource_type: "spells", slug: "fireball" })
// → Finds srd-2024_fireball or srd-2014_fireball

// Full key - direct lookup
get({ resource_type: "spells", slug: "srd-2014_fireball" })
```

#### `list`
List resources with filters (pagination supported).

```typescript
list({
  resource_type: "monsters",
  cr: 3,                        // Challenge Rating
  document_slug: "wotc-srd",    // Source book
  type: "Dragon",               // Creature type
  limit: 20,
  offset: 0
})

list({
  resource_type: "spells",
  level: 3,                     // Spell level (0-9)
  school: "Evocation",          // Spell school
  document_slug: "srd-2014"
})
```

#### `batch_get`
Fetch multiple resources in parallel (max 50).

```typescript
batch_get({
  requests: [
    { resource_type: "monsters", slug: "goblin" },
    { resource_type: "monsters", slug: "kobold" },
    { resource_type: "conditions", slug: "blinded" }
  ]
})
```

#### `list_documents`
List all available source books.

```typescript
list_documents()
// → srd-2014, srd-2024, tob, tob2, tob3, a5e-ag, bfrd, etc.
```

#### `list_endpoints`
List all API endpoints with version info.

```typescript
list_endpoints()
// → spells (v2), monsters (v1), conditions (v2), etc.
```

### Contributor Tools

#### `validate_entry`
Validate a draft entry against Open5e schema.

```typescript
validate_entry({
  resource_type: "spells",
  data: {
    name: "Test Spell",
    slug: "test-spell",
    level: 3,
    school: "Evocation",
    // ... other fields
  },
  strict: false  // optional: fail on warnings
})
```

Returns:
- `valid`: boolean
- `errors`: Array of schema violations
- `warnings`: Unusual but valid values
- `suggestions`: Helpful hints (slug format, valid enums)

#### `check_slug`
Check if a slug exists or would collide.

```typescript
check_slug({
  resource_type: "monsters",
  slug: "goblin",
  document_slug: "wotc-srd",     // optional
  original_slug: "goblin-old"    // optional: detect mutations
})
```

Returns:
- `exists`: boolean
- `is_mutation`: boolean (slug changed from original)
- `collision_risk`: "none" | "same_document" | "different_document"
- `existing_entry`: Details if exists

#### `diff`
Compare a draft entry against the live API version.

```typescript
diff({
  resource_type: "monsters",
  slug: "goblin",
  draft: {
    name: "Goblin",
    hit_points: 10,  // Changed from 7
    // ... partial or full entry
  },
  ignore_fields: ["page_no"]  // optional
})
```

Returns field-by-field diff with `type`: "added" | "removed" | "modified".

#### `normalize`
Clean up and standardize entry data.

```typescript
normalize({
  resource_type: "spells",
  data: {
    name: "test   spell",
    desc: "A   spell   with   bad   spacing.\n\nAnd extra   newlines."
  },
  options: {
    fix_whitespace: true,
    fix_markdown: true,
    standardize_names: true,
    generate_slug: true
  }
})
```

#### `generate_pr_json`
Generate PR-ready JSON with file path and checklist.

```typescript
generate_pr_json({
  resource_type: "spells",
  document_slug: "srd-2014",
  operation: "add",  // or "modify"
  data: { /* validated entry */ }
})
```

Returns:
- `json_output`: Formatted JSON string
- `file_path`: Where to place the file (e.g., `data/srd-2014/spells/test-spell.json`)
- `validation`: Pre-flight validation results
- `checklist`: PR submission checklist

### RAG Tools

The RAG tools connect to the Open5e Developer Chatbot, which indexes the entire open5e-api and open5e (frontend) repositories.

#### `rag_health`
Check RAG service status.

```typescript
rag_health()
// → { healthy: true, chunks: 484, vectors: 484, sources: 214 }
```

#### `rag_stats`
Get index statistics.

```typescript
rag_stats()
// → Project info, chunk/vector counts, embedding status
```

#### `rag_sources`
List all indexed sources with GitHub URLs.

```typescript
rag_sources()
// → README.md, CONTRIBUTING.md, AGENTS.md, models/*.py, views/*.py, etc.
```

#### `rag_search`
Search repository documentation.

```typescript
rag_search({
  query: "how to add a new monster",
  mode: "hybrid",    // semantic, keyword, or hybrid
  top_k: 5
})
```

Returns chunks with scores, source URLs, and positions.

#### `rag_chat`
Chat with AI about Open5e development.

```typescript
rag_chat({
  message: "How do I add a new monster to the Open5e database?",
  history: [],  // optional: conversation history
  top_k: 5      // optional: context chunks
})
```

Returns detailed answer with source citations.

### Meta Tools

#### `health_check`
Check API connectivity and cache status.

```typescript
health_check()
// → { api_reachable: true, api_latency_ms: 628, cache_status: {...}, version: "0.1.0" }
```

## Available Source Books

| Slug | Name | Publisher |
|------|------|-----------|
| `srd-2014` | System Reference Document 5.1 | Wizards of the Coast |
| `srd-2024` | System Reference Document 5.2 | Wizards of the Coast |
| `tob` | Tome of Beasts | Kobold Press |
| `tob-2023` | Tome of Beasts (2023) | Kobold Press |
| `tob2` | Tome of Beasts 2 | Kobold Press |
| `tob3` | Tome of Beasts 3 | Kobold Press |
| `a5e-ag` | Adventurer's Guide (A5E) | EN Publishing |
| `a5e-mm` | Monstrous Menagerie (A5E) | EN Publishing |
| `bfrd` | Black Flag Reference Document | Kobold Press |
| `deepm` | Deep Magic | Kobold Press |
| ... | *22 total sources* | |

Use `list_documents()` for the complete list.

## Resource Types

| Type | API Version | Filters Available |
|------|-------------|-------------------|
| `spells` | v2 | level, school, document_slug |
| `monsters` | v1 | cr, type, document_slug |
| `conditions` | v2 | document_slug |
| `items` | v1 | document_slug |
| `magicitems` | v1 | document_slug |
| `weapons` | v2 | document_slug |
| `armor` | v2 | document_slug |
| `feats` | v2 | document_slug |
| `backgrounds` | v2 | document_slug |
| `races` | v2 | document_slug |
| `classes` | v1 | document_slug |

## Usage Patterns

### Game Master: Building an Encounter

```typescript
// Find CR 3 monsters from the SRD
const monsters = await list({
  resource_type: "monsters",
  cr: 3,
  document_slug: "wotc-srd"
});

// Get full details for selected monsters
const details = await batch_get({
  requests: monsters.results.slice(0, 5).map(m => ({
    resource_type: "monsters",
    slug: m.slug
  }))
});
```

### Contributor: Adding a New Spell

```typescript
// 1. Draft the spell
const draft = {
  name: "Arcane Bolt",
  slug: "arcane-bolt",
  level: 0,
  school: "Evocation",
  casting_time: "1 action",
  range: "120 feet",
  verbal: true,
  somatic: true,
  material: false,
  concentration: false,
  ritual: false,
  duration: "Instantaneous",
  desc: "You hurl a bolt of arcane energy at a creature...",
  document__slug: "homebrew"
};

// 2. Validate
const validation = await validate_entry({
  resource_type: "spells",
  data: draft
});

// 3. Check for collisions
const slugCheck = await check_slug({
  resource_type: "spells",
  slug: "arcane-bolt"
});

// 4. Generate PR JSON
const prData = await generate_pr_json({
  resource_type: "spells",
  document_slug: "homebrew",
  operation: "add",
  data: draft
});
```

### Learning: Understanding the Codebase

```typescript
// Search for how monsters are modeled
const results = await rag_search({
  query: "Monster model fields actions abilities",
  top_k: 5
});

// Ask the chatbot
const answer = await rag_chat({
  message: "What fields are required for a monster entry in v1?"
});
```

## Integration

### rpg-mcp

This server is designed to integrate with [rpg-mcp](https://github.com/Mnehmos/rpg-mcp) for live creature lookups during gameplay:

```typescript
// Replace hardcoded creature presets with Open5e lookups
const creature = await open5e.get({
  resource_type: "monsters",
  slug: "adult-red-dragon"
});
```

### Quest Keeper AI

Surface contributor workflows in the Quest Keeper AI frontend for community content creation.

## Development

### Setup

```bash
npm install
npm run build
```

### Testing

```bash
npm test              # Run all tests
npm run test:watch    # Watch mode
npm run test:coverage # Coverage report
```

### Scripts

| Command | Description |
|---------|-------------|
| `npm run build` | Compile TypeScript |
| `npm run dev` | Watch mode compilation |
| `npm start` | Run the server |
| `npm test` | Run tests |
| `npm run lint` | Lint source files |
| `npm run typecheck` | Type check without emit |

### Project Structure

```
src/
├── index.ts          # MCP server entry point, tool registration
├── types.ts          # Shared TypeScript types
├── api/              # Open5e API client
├── cache/            # Response caching
├── contributor/      # Validation, diff, PR generation
├── schema/           # Zod schemas for all resource types
└── utils/            # Helpers, slug handling
```

## API Reference

- **Open5e API**: https://api.open5e.com
- **API Documentation**: https://open5e.com/api-docs
- **GitHub Repository**: https://github.com/open5e/open5e-api
- **Discord**: https://discord.gg/9RNE2rY

## Contributing

1. Fork the repository
2. Create a feature branch
3. Run tests: `npm test`
4. Submit a pull request

## License

MIT © [Mnehmos](https://github.com/Mnehmos)

---

**Part of the Mnehmos MCP ecosystem**

- [mnehmos.ooda.mcp](https://github.com/Mnehmos/mnehmos.ooda.mcp) - File system and shell operations
- [mnehmos.synch.mcp](https://github.com/Mnehmos/mnehmos.synch.mcp) - Agent memory and handoffs
- [rpg-mcp](https://github.com/Mnehmos/rpg-mcp) - RPG game engine

TDQS

B3.2/5.0

Scored across 18 tools

Disambiguation4/5

The generic retrieval tools get, list, and search have some conceptual overlap, but descriptions clarify slug-based lookup vs. type listing vs. cross-resource search. The rag_* group, contribution workflow tools, and metadata tools are clearly distinct from the core API tools.

Naming Consistency3/5

The set mixes bare verbs (get, search, list, diff, normalize), verb_noun tools (health_check, list_documents, validate_entry, generate_pr_json), and a rag_ prefixed subgroup. The rag_* cluster is consistent, but the overall surface does not follow a single predictable convention.

Tool Count4/5

At 18 tools, the server is slightly above the ideal range, but the tools are divided into three coherent clusters: core Open5e API access, contribution preparation, and RAG chatbot access. No cluster appears bloated for its purpose.

Completeness4/5

The surface covers read/search/list/batch access, document and endpoint discovery, contribution validation and normalization, PR JSON generation, and comprehensive RAG operations. Minor gaps include no direct document-content fetch and no actual PR submission tool, though generate_pr_json prepares the output.

Maintenance

ActivityInactive
ResponsivenessUnresponsive