scheherazade
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@scheherazadeWhat threads are active and which characters are currently in the castle?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Scheherazade's Hoard
Who's alive? Who's where? What have you promised them?
A world-state and continuity keeper for interactive fiction and tabletop play — it remembers everything a language model forgets, and hands the narrator exactly the slice it needs for the next scene.
Español · Quick start · Connect to Faustus · MCP reference · Portfolio
The real application with synthetic demo data ("El Archipiélago de Sal", an original setting seeded by --demo).
Why
Language models are good narrators and terrible continuity editors. After an hour of interactive fiction or a tabletop session they forget who knows what, resurrect dead characters, move towns, lose the plot threads and fudge dice. Scheherazade keeps the world state outside the model — entities, relationships, secrets, places, a chronology, open threads, clocks, tables and an audited dice log — and builds the narrator a compact, ranked, budget-bound brief for the next scene, then records what that scene actually changed. It can narrate on its own with a shared local model, or hand its tools to another AI (Faustus) so that AI narrates while this app remembers everything.
Related MCP server: Timelines MCP Server
What is implemented
Area | Available now | Boundary |
World state | Entities (character/location/faction/item/lore/creature) with aliases, stats and GM secrets, relations, facts with provenance and a canon flag, timeline, threads, clocks, random tables; SQLite + FTS5 with accent-insensitive search | One local writer; no multi-user editing |
Dice |
| Bounded on purpose (200 dice per roll, 100 characters per expression) |
Context builder |
| Ranking is lexical and rule-based, not embedding search |
Delta engine | Validation per item, then the delta and its turn in one SQLite transaction; the scene carries over between turns; undo walks back turn by turn within the current session | No redo; turns of an earlier session cannot be undone |
Narrator (standalone) | Builds the prompt, calls the shared model through Hoard Link, separates narration from the delta (fenced or bare JSON; repairs typographic quotes, comments, trailing commas, a delta nested under | Not streamed: one reply, with a spinner |
Consistency check | Rules for a dead character acting, a character placed away from where they were last seen and a contradicted relation (whole-word, alias-aware), plus an LLM judge over matching facts that must cite fact ids; the result says whether the judge ran | Heuristics: it misses contradictions that no rule covers and no fact states |
Export | Session as a manuscript-clean Markdown chapter (no ids, dice or out-of-character lines; actions in italics; Spanish raya dialogue), optionally polished by the shared model (falls back to the plain chapter and says why), world bible in Markdown, full JSON export and import | Polish is instructed not to add facts but is not checked against the source; chapters over 6000 characters are not polished; an imported world keeps its sessions and turns but not their undo history |
Illustrations | "Illustrate" calls Prospero's Hoard's agent API when it answers on 127.0.0.1:8815; the button is hidden otherwise | Needs that separate app; the image is shown, not stored on the turn |
Shared model backend | Hoard Link vendored unmodified ( | Only the language-model capability is used; the app never loads a model itself |
UI | Play (Narration/Action/Dialogue/Out-of-character modes and a scene editor for place, cast and mood), Bible (create and edit: status, summary, aliases, tags, secrets), Map of relations (SVG), Timeline, Threads & clocks (kanban and segmented clocks), Tables, Sessions (start, rename, export), Dice log, Backends, Assistant activity, Settings; a continuity check box in Play; accent-insensitive Bible search; Spanish and English, light and dark | The map uses a fixed circular layout, not a physics simulation |
Use cases
Eight scenarios for a solo player who also writes, each walked in the browser and over MCP before and after the usability review (docs/USE_CASES.md; findings and a verdict per use case in docs/USABILITY_REPORT.md). Among them:
First evening without a model: create a world, its people and places, set the scene and play it by hand, dice included.
A long night narrated by a local model through Faustus: 44 beats in Spanish where the dead stay dead, people stay where they were last seen and a bad turn can be taken back.
A clean chapter for the manuscript: the session exported as prose and raya dialogue, without ids, dice or out-of-character lines.
The app narrates on its own: a 27B model's sloppy JSON is repaired and every proposed change is reviewed before it touches the world.
Continuity questions while writing: "who has died?", "what does Iria know?", "is it consistent that Mateo opens the door?", answered in one or two tool calls, asked in Spanish.
The next evening, fixing by hand: correct a summary, mark someone missing, tick a clock, undo a turn — no model needed.
Connect it to Faustus
The app declares itself with faustus-plugin.json. Start the app, then in
Faustus: Connectors → Nearby apps → Add. Faustus finds it by scanning
loopback ports and reading that manifest, which also tells it how to start
the app (python -m scheherazades_hoard --no-browser, ready when
/api/health answers) and how to launch the MCP server
(python scheherazades_hoard/mcp_server.py over stdio, with
SCHEHERAZADE_URL pointing at the running app).
Two ways to play, same world: connected, Faustus is the narrator and uses
the tools below (the narrator-loop skill tells it in which order); on
its own, the app narrates with the model Faustus already has loaded,
found through Hoard Link, so nothing is loaded twice.
Tool | Read-only | What it does |
| yes | List every world with counts and current session |
| no | Create a new world |
| yes | The narrator's brief for the next scene |
| yes | Search entities/facts |
| yes | One entity with relations and facts |
| no | Create or update an entity |
| no | Record a turn and apply a delta, atomically |
| no | Roll dice with an audited log |
| no | Roll on a random table |
| no | Advance/resolve/abandon a thread |
| no | Advance a clock |
| yes | Check a statement against established facts |
| no | Start a new, optionally named session |
| no | Rename a session |
| yes | Export a chapter / the bible / full JSON, a page at a time |
| no | Revert the last turn and everything its delta changed |
Full argument lists, return shapes and limits: docs/MCP.md.
It also works with any other MCP client over stdio (on Linux/macOS the
interpreter is .venv/bin/python):
{
"mcpServers": {
"scheherazade": {
"command": "/absolute/path/to/scheherazades-hoard/.venv/Scripts/python.exe",
"args": ["/absolute/path/to/scheherazades-hoard/scheherazades_hoard/mcp_server.py"],
"env": { "SCHEHERAZADE_URL": "http://127.0.0.1:8816" }
}
}
}Quick start
Windows
Double-click Iniciar Scheherazade's Hoard.cmd. It runs
scripts/start.ps1, which finds Python 3.11 or newer, creates .venv
and installs requirements-lock.txt (again whenever the lock changes),
builds the interface if frontend/dist is missing (Node 22 is needed
only then), starts the app with the repo root as working directory, waits
for /api/health and opens the browser. If the app is already running it
only opens the browser. Stop it with Detener Scheherazade's Hoard.cmd
(scripts/stop.ps1), which also stops an instance Faustus started.
Manual steps, from a fresh clone, in PowerShell:
git clone https://github.com/Luissalet/ScheherazadesHoard.git
cd ScheherazadesHoard
python -m venv .venv
.venv\Scripts\python.exe -m pip install -r requirements-lock.txt
cd frontend; npm ci; npm run build; cd ..
.venv\Scripts\python.exe -m scheherazades_hoard --demoLinux / macOS
The app itself is plain Python + a static frontend build, so it runs the
same way outside Windows (only the .cmd launchers and scripts/*.ps1
are Windows-only):
git clone https://github.com/Luissalet/ScheherazadesHoard.git
cd ScheherazadesHoard
python3 -m venv .venv
.venv/bin/python -m pip install -r requirements-lock.txt
cd frontend && npm ci && npm run build && cd ..
.venv/bin/python -m scheherazades_hoard --demo--demo uses a synthetic seeded world in data-demo/ instead of your
real data/, so you can try everything without touching (or needing) any
real data. Drop --demo for your own worlds; add --no-browser to skip
the automatic tab.
Shared models (Hoard Link)
The app never starts or loads a model of its own. It uses
Hoard Link, vendored
byte-identical in scheherazades_hoard/hoard_link/ (version in
VENDORED.txt), to find the language model that is already running:
explicit settings from the Settings screen or HOARD_* environment
variables first, then the model Faustus already uses, then resident
models on loopback (llama.cpp, Ollama, any OpenAI-compatible server).
When nothing answers, Settings says why and everything except
"Narrate", "Polish" and the continuity judge keeps working.
Architecture
flowchart LR
UI["React UI<br/>(frontend/dist)"] -->|REST| API["FastAPI app<br/>127.0.0.1:8816"]
AI["Faustus or any<br/>MCP client"] -->|stdio| MCP["mcp_server.py"]
MCP -->|loopback HTTP<br/>/api/agent/*| API
API --> Core["context · delta · consistency<br/>dice · export"]
Core --> DB[("SQLite + FTS5<br/>data/")]
API -->|Hoard Link| LLM["Local model server"]
API -.->|optional| P["Prospero's Hoard<br/>(illustrations)"]Modules, data model, the atomic delta engine, and the decisions behind
them: docs/ARCHITECTURE.md.
Development
.venv\Scripts\python.exe -m pip install -r requirements-lock.txt
.venv\Scripts\python.exe -m pytest tests/ -q
cd frontend; npm ci; npm run build.venv/bin/python -m pip install -r requirements-lock.txt
.venv/bin/python -m pytest tests/ -q
cd frontend && npm ci && npm run buildThe same commands run in CI (.github/workflows/ci.yml: Ubuntu,
Python 3.12, Node 22).
294 tests, offline (no real model: Hoard Link, the narrator and the
Prospero adapter run against httpx.MockTransport), in well under a
minute.
They cover the dice grammar and its bounds, ruleset readings, the context
builder's budget, ranking and secret exclusion, delta validation, the
single-transaction turn and undo (including repeated updates in one
delta), scene carry-over, JSON extraction including the sloppy shapes a
small model sends, first-name entity lookup, the consistency rules,
accent-insensitive and status search, the manuscript-clean chapter,
exports and import, the static file server
against path traversal, the Host/Origin guard, the CLI start with its pid
file and log, and an MCP protocol test that spawns the real adapter over
stdio against a live instance (list_tools, annotations, Keywords lines,
and a create, roll, append, context and undo round trip), plus a check
that a picker reading only line one of each tool description finds the
right tool for Spanish requests.
npm run build (inside frontend/) runs tsc -b && vite build with
TypeScript strict mode, noUnusedLocals and noUnusedParameters on.
Privacy and security
Binds
127.0.0.1only, rejects other Host headers and cross-site writes, and refuses to be framed by web pages. No telemetry. The only network calls are to model servers on your machine (or the Faustus you configured) and to Prospero's Hoard, both on loopback.Your worlds live in
data/(gitignored) as one SQLite file; the log isdata/logs/app.logand records tool names and timings, never story text, secrets or tokens.Agent tools never return GM secrets unless asked with
include_secrets=true; every agent call is written to an audit table (agent_calls: tool, ok/error, duration) that "Assistant activity" shows, and your own clicks in the interface are kept out of it.The narrator's structured output is parsed from free text; a reply that cannot be parsed is kept as narration marked
unparsed, never guessed at.
Roadmap / known limits
Open items from the project's own design notes (docs/USABILITY_REPORT.md), roughly in order of value:
world_contextreturns about 1.5 times its character budget, because thescene,lore,threadsandrecent_turnsfields repeat what the brief already says.An agent cannot create a clock or add a standalone relation/fact outside of a turn; both need the HTTP route today.
"Where was X last seen" has no direct tool answer outside
world_check.story_appendover MCP has norollsargument, so a roll the model makes is logged but not linked to its turn.thread_updateneeds a thread's id or full title; part of a title does not match.The proposal card in Play shows facts, updates and clock ticks but not a proposed scene move, cast or mood change.
The relations map uses a fixed circular layout that overlaps labels once a world has 30+ entities, and does not visually distinguish dead or missing entities.
Below 760px there is no way to open the navigation sidebar.
Play always opens at the top of the transcript, so a long session needs a scroll to reach the latest turn.
A JSON world backup over MCP pages a large string through the model's context; importing through the UI does not have this limit.
Some messages are still English-only in an otherwise Spanish session: delta rejections ("… is dead and cannot act"), raw roll bands (
weak_hit), status badges and some Backends reasons.world_check's dead-acting rule has a false positive when a dead character is only mentioned, not acting.The polished-chapter route does not check the model's reply for length or truncation before it can replace the original chapter, and refuses to polish chapters over 6000 characters.
None of these block using the app today — see the verdict per use case in docs/USABILITY_REPORT.md.
License
MIT — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
- OrbismoOAuthcom.orbismo
A persistent world-building memory your AI can read and write in any chat.
Campaign manager for D&D and TTRPG GMs: your AI reads and writes a live typed campaign database.
Persistent AI entity framework with causal memory, emotional state, and identity.
Persistent AI memory with semantic search, conflict detection, and ticketing.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables creation and management of structured game worlds for text adventures and RPGs with character creation, world generation, and natural language interaction through AI integration.1MIT
- AlicenseNot gradedqualityDmaintenanceHelps LLMs maintain coherent timelines, track events, and manage characters across long-form narratives for fiction writing or historical accounts.1MIT
- AlicenseNot gradedqualityDmaintenanceA narrative graph engine that enables LLMs to generate, track, and mutate complex fictional worlds while maintaining consistency between factions, characters, and locations. It acts as a specialized RAG framework for storytelling, allowing models to manage thousands of entities without exceeding context limits.MIT
- FlicenseAqualityCmaintenanceGives an AI game master a persistent memory for tabletop roleplaying games by storing worlds, characters, plots, and scenes. It enables saving, searching, and loading game state (via MCP tools) so the GM doesn't have to recall plot and details only from the context window.2131-