You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
mnehmos.rpg.mcp is a rules-enforced RPG backend MCP server that transforms any LLM into a game master with mechanical integrity. It provides a complete D&D 5e-compatible simulation kernel where LLMs propose narrative intentions but the engine validates and executes all game mechanics, preventing AI hallucination of dice rolls, spell slots, or hit points. Players interact through natural language with an AI dungeon master while the server handles all combat, spellcasting, inventory, quests, and world state with full SQLite persistence.
Architecture
System Design
The project implements an Event-Driven Agentic AI Architecture based on the OODA loop pattern (Observe-Orient-Decide-Act). LLMs act as the "brain" proposing intentions, while the engine serves as the "nervous system" validating constraints and executing actions. The system uses the Model Context Protocol (MCP) to expose 32 tools that LLMs can call to interact with the game world. All world state is persisted in SQLite with WAL mode, supporting multi-tenant projects, parallel worlds, and deterministic replay. The server can run via stdio, TCP, Unix sockets, or WebSockets for integration with various MCP clients.
The architecture enforces a key invariant: LLMs never directly mutate world state. All changes flow through validated tool calls, creating an anti-hallucination design where the AI cannot invent game outcomes.
Consolidated Tool Pattern
The server uses an action-routed consolidated tool architecture. Instead of exposing 145+ individual tools (one per operation), all operations are grouped into 28 domain tools that accept an action parameter with fuzzy matching:
Player: "I attack the goblin"
|
LLM -> combat_action({ action: "attack", targetId: "goblin-1" })
|
Action Router: Match "attack" -> handleExecuteCombatAction()
|
Combat Engine: Roll initiative, check AC, calculate damage
|
Update HP in database -> Emit combat_state_changed event
|
Return combat result with embedded JSON (hit/miss, damage, new HP)
|
LLM narrates outcome based on mechanical result
API Surface
Tool Architecture
All 32 tools are registered via MCP protocol. The 28 consolidated tools use action routing; 4 are standalone meta/event tools. All consolidated tools accept a sessionId parameter for multi-session support.
Meta & Event Tools (4 standalone)
Tool
Purpose
search_tools
Search tools by keyword or category
load_tool_schema
Load full Zod schema for a tool on-demand
subscribe_to_events
Subscribe to PubSub event topics (combat, quest, etc.)
unsubscribe_from_events
Unsubscribe from event topics
Consolidated Tools (28 action-routed)
Each tool accepts { action: string, ...params }. The action parameter is fuzzy-matched.
No environment variables required for basic operation. The server uses sensible defaults.
Variable
Type
Default
Description
RPG_MCP_DB_PATH
string
./rpg-mcp.db
SQLite database file path
RPG_MCP_TRANSPORT
string
stdio
Transport mode (stdio, tcp, unix, websocket)
RPG_MCP_PORT
number
3000
Port for TCP/WebSocket transport
Usage Examples
Basic Usage
// Example: Starting a new game with character creation// (These are the MCP tool calls an LLM would make)// 1. Create a worldconstworld=awaitworld_map({action: "generate",projectId: "my-game",worldId: "world-1",width: 100,height: 100,seed: "adventure-42"});// 2. Create a character using presetconstcharacter=awaitspawn_manage({action: "equipped_character",projectId: "my-game",worldId: "world-1",preset: "fighter",name: "Thorgrim Ironheart"});// 3. Start combat encounterconstencounter=awaitcombat_manage({action: "create",projectId: "my-game",worldId: "world-1",participants: [{id: "thorgrim",name: "Thorgrim",hp: 45,maxHp: 45,initiativeBonus: 2},{id: "goblin-1",name: "Goblin",hp: 7,maxHp: 7,initiativeBonus: 2}]});// 4. Execute attackconstattackResult=awaitcombat_action({action: "attack",actorId: "thorgrim",targetId: "goblin-1"});// Returns: hit/miss, damage rolled, new HP, embedded JSON with full state
// Example: Batch operations for efficient world building// Spawn multiple NPCs in one callconstnpcs=awaitbatch_manage({action: "create_npcs",projectId: "my-game",worldId: "world-1",npcs: [{name: "Barkeep",role: "merchant",location: "tavern"},{name: "Guard Captain",role: "guard",location: "gate"},{name: "Mysterious Stranger",role: "quest_giver",location: "corner"}]});// Create a preset encounter scaled to party levelconstencounter=awaitspawn_manage({action: "preset_encounter",projectId: "my-game",worldId: "world-1",preset: "goblin_ambush",partyLevel: 5});
Dependencies
Runtime Dependencies
Package
Version
Purpose
@modelcontextprotocol/sdk
^1.23.0
MCP server implementation and transport layers
better-sqlite3
^12.4.6
SQLite database with WAL mode and sync API
zod
^3.25.76
Schema validation for all tool inputs and data
uuid
^13.0.0
Unique identifier generation for entities
seedrandom
^3.0.5
Seeded random number generation for deterministic worlds
simplex-noise
^4.0.3
Perlin/simplex noise for procedural terrain generation
mathjs
^15.1.0
Algebra solver and mathematical operations
nerdamer
^1.1.13
Symbolic algebra solver for physics calculations
ws
^8.16.0
WebSocket transport support
Development Dependencies
Package
Version
Purpose
typescript
^5.9.3
TypeScript compiler with strict mode enabled
vitest
^1.6.1
Test framework (1889 passing tests, 6 skipped)
@types/node
^24.10.1
Node.js type definitions
@types/better-sqlite3
^7.6.13
SQLite type definitions
@types/ws
^8.5.10
WebSocket type definitions
ts-node
^10.9.2
TypeScript execution for development
esbuild
^0.27.0
Fast bundler for binary compilation
@yao-pkg/pkg
^6.10.1
Standalone binary packager
Integration Points
Works With
Project
Integration Type
Description
Claude Desktop
MCP Client
Primary integration target for AI-driven gameplay
Any MCP-compatible client
MCP Client
Works with any client supporting MCP protocol
mnehmos.quest-keeper.game
Peer
Desktop AI dungeon master app using this engine
This is a standalone MCP server with no direct dependencies on other Mnehmos projects. However, it is designed to be the backend engine for AI-driven RPG experiences.
External Services
No external services required. The server is fully self-contained with local SQLite persistence.
Development Guide
Prerequisites
Node.js 20 or higher
npm or pnpm package manager
SQLite3 (bundled with better-sqlite3)
Setup
# Clone the repository
git clone https://github.com/Mnehmos/mnehmos.rpg.mcp
cd mnehmos.rpg.mcp
# Install dependencies
npm install
# Build TypeScript
npm run build
# Run tests (1889 tests should pass)
npm test
Running Locally
# Development mode with TypeScript
npm run dev
# Production build and run
npm run build
npm start
# Run with specific transport
node dist/server/index.js --tcp --port 3000
node dist/server/index.js --websocket --port 3001
node dist/server/index.js --unix /tmp/rpg-mcp.sock
Testing
# Run all tests
npm test# Run tests in watch mode
npm run test:watch
# Run tests with coverage
npm run test:coverage
# Run tests with UI
npm run test:ui
# Run specific test file
npx vitest tests/engine/combat/engine.test.ts
Note: Vitest is configured with globals: true. Do NOT add import { describe, it, expect } from 'vitest' to test files - this causes silent test collection failure on Windows with vitest 1.6.1.
Building
# Build TypeScript to JavaScript
npm run build
# Output: dist/# Build standalone binaries for all platforms
npm run build:binaries
# Output: dist-bundle/rpg-mcp-win.exe, rpg-mcp-macos, rpg-mcp-macos-arm64, rpg-mcp-linux
MCP Client Integration
Add to Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):