Narrarium Framework
Narrarium Framework is a local-first book writing framework built around three pieces:
- a strict but extensible repository convention where the repository is the book
- a local MCP server that teaches OpenCode or Claude how to create, search, validate, and enrich that repository
- an Astro-based reader package that turns the repository into a browsable website
Packages
packages/core: schemas, templates, repo scaffolding, search, validation, and EPUB export helperspackages/mcp-server: local stdio MCP server for OpenCode, Claude Desktop, and compatible clientspackages/create-narrarium-book: starter CLI to scaffold a new book repository from the terminalpackages/astro-reader: Astro reader that renders the repository chapter by chapter
Local MCP workflow
The intended workflow is local-first:
- OpenCode runs with the local Narrarium MCP server enabled.
- You ask for book tasks in natural language.
- OpenCode calls Narrarium MCP tools to scaffold the repository, create entities, create chapters, search canon, validate metadata, and optionally fetch Wikipedia research.
- The same repository can then be rendered as a website or exported to EPUB.
This keeps the actual writing artifacts in your filesystem instead of hiding them inside a hosted app.
Quick start from npm
If you just want to use Narrarium, start from the published packages:
npx create-narrarium-book my-book --title "My Book" --language en
cd my-book
npm run dev
This scaffolds a book repo, creates reader/ by default, installs the reader dependencies, prepares OpenCode config, and gives you a live reading site plus EPUB export while you write.
If you want sample content from the start:
npx create-narrarium-book my-book --title "My Book" --language en --sample
If you want a book repo without the reader scaffold:
npx create-narrarium-book my-book --title "My Book" --language en --no-reader
The starter also has an interactive mode:
npx create-narrarium-book
Run the MCP server from npm
npx narrarium-mcp-server
If the package is already installed in the project or globally, the binary is:
narrarium-mcp
Scaffold a standalone reader from npm
Create a standalone Astro reader app inside or beside a book repo:
npx narrarium-astro-reader reader --book-root .. --package-name my-book-reader
cd reader
npm install
npm run dev
The reader includes dedicated indexes for chapters, characters, locations, factions, items, secrets, and timeline events, and npm run dev watches the linked book repo for live reload plus EPUB refresh.
Develop this monorepo
These commands are for working on the Narrarium framework repository itself:
npm install
npm run build
Run the automated test suite with:
npm run test
For a publish-ready workspace check:
npm run release:check
Build the GitHub Pages documentation site locally with:
npm run docs:build
Repo-only helper commands:
npm run create:book -- my-book --title "My Book" --language en --sample
npm run dev:mcp
npm run reader:init -- reader --book-root .. --package-name my-book-reader
If you want the public HTTP version locally, for Vercel-style setup and research flows:
npm run dev:http -w narrarium-mcp-server
This serves:
http://localhost:3000/mcphttp://localhost:3000/health
OpenCode config
An example project config lives in opencode.jsonc and points OpenCode to the local MCP server build output.
Agent rules
Project-level OpenCode and agent rules live in AGENTS.md.
Main MCP tools
init_book_repo: scaffold a book repository in a target foldersetup_framework: return the exactnpxcommands to bootstrap a new Narrarium projectrepository_spec: return the repo model and canon rulescharacter_wizard: return the checklist of fields needed for a full charactercreate_character: create a rich character file with voice, role, backstory, and function in booklocation_wizard,faction_wizard,item_wizard,secret_wizard: return the checklist for each canon typetimeline_event_wizard,chapter_wizard,paragraph_wizard: return the checklist for those creation flowscreate_location,create_faction,create_item,create_secret,create_timeline_event: create rich canonical files for those typesstart_wizard,wizard_answer,wizard_status,wizard_finalize,wizard_cancel: run a true multi-step guided creation sessioncreate_entity: create faster stubs for other canon filesupdate_chapter,update_paragraph: update existing chapter and scene files without structural migrationupdate_entity: patch frontmatter and body on existing canon filescreate_asset_prompt,register_asset,generate_asset_image: manage canonical art prompts and image filesrename_entity,rename_chapter,rename_paragraph: rename canon safely and move matching asset folders toosearch_book: search the repository before inventing canonlist_related_canon: find files that reference an id or conceptsync_resume: refresh chapter or total summaries from current filessync_all_resumes: refresh all chapter resumes plus the total summary in one passevaluate_chapter: refresh a deterministic evaluation scaffoldevaluate_book: refresh the full-book evaluation scaffold and optionally all chapter evaluationswikipedia_searchandwikipedia_page: research factual or historical materialexport_epub: turn the repository into an EPUB
Practical image examples
With the local MCP server and OPENAI_API_KEY configured, a typical image workflow looks like this.
| Use case | Subject | Asset path | Typical tool flow |
|---|---|---|---|
| Book cover | book |
assets/book/cover.* |
register_asset or generate_asset_image |
| Character portrait | character:lyra-vale |
assets/characters/lyra-vale/primary.* |
create_asset_prompt -> generate_asset_image |
| Chapter art | chapter:001-the-arrival |
assets/chapters/001-the-arrival/primary.* |
create_asset_prompt -> generate_asset_image |
| Scene art | paragraph:001-the-arrival:001-at-the-gate |
assets/chapters/001-the-arrival/paragraphs/001-at-the-gate/primary.* |
generate_asset_image directly or after create_asset_prompt |
Create a reusable character portrait prompt:
{
"tool": "create_asset_prompt",
"arguments": {
"rootPath": "C:/books/my-book",
"subject": "character:lyra-vale",
"body": "# Intent\n\nPrimary portrait for Lyra.\n\n# Prompt\n\nPortrait of Lyra Vale, guarded expression, harbor fog, muted cinematic palette, portrait composition, 2:3 ratio.\n\n# Notes\n\nKeep facial features consistent across future chapter and scene art.",
"orientation": "portrait",
"aspectRatio": "2:3"
}
}
Generate the actual image into assets/characters/lyra-vale/primary.png:
{
"tool": "generate_asset_image",
"arguments": {
"rootPath": "C:/books/my-book",
"subject": "character:lyra-vale",
"provider": "openai",
"model": "gpt-image-1"
}
}
Generate a scene image directly for a paragraph:
{
"tool": "generate_asset_image",
"arguments": {
"rootPath": "C:/books/my-book",
"subject": "paragraph:001-the-arrival:001-at-the-gate",
"prompt": "Lyra arriving at Gray Harbor's gate in cold fog, suspicious guards, cinematic portrait framing, book-cover quality illustration, 2:3 ratio.",
"provider": "openai",
"model": "gpt-image-1"
}
}
Import an image you created elsewhere into the canonical assets tree:
{
"tool": "register_asset",
"arguments": {
"rootPath": "C:/books/my-book",
"subject": "book",
"assetKind": "cover",
"sourceFilePath": "C:/renders/my-book-cover.png",
"body": "# Intent\n\nMain book cover.\n\n# Prompt\n\nFinal cover prompt used for the external render."
}
}
Generate chapter art into assets/chapters/001-the-arrival/primary.png:
{
"tool": "generate_asset_image",
"arguments": {
"rootPath": "C:/books/my-book",
"subject": "chapter:001-the-arrival",
"prompt": "Lyra approaching Gray Harbor through cold fog, chapter-opening illustration, portrait orientation, dramatic negative space, consistent with the book's visual language.",
"provider": "openai",
"model": "gpt-image-1"
}
}
The recommended place for reusable style rules and prompt templates is guidelines/images.md.
The Astro reader now auto-renders these canonical assets when present for:
bookcover on the home page- entity detail pages such as characters, locations, factions, items, secrets, and timeline events
- chapter pages and paragraph or scene sections
If you later rename canon with rename_entity, rename_chapter, or rename_paragraph, Narrarium also moves the matching asset folders.
Repository spec
The current repository convention is documented in docs/repository-spec.md.
Publishing
The final public package set is:
narrariumnarrarium-mcp-servercreate-narrarium-booknarrarium-astro-reader
The initial public version is 0.1.0.
Publishing notes and release order live in docs/publishing.md.
GitHub Actions
Two workflows are included:
.github/workflows/ci.yml: runs build, validation, and tests on pushes and pull requests.github/workflows/publish-npm.yml: auto-publishes bumped package versions onmain, with manual dispatch and GitHub Release as fallbacks.github/workflows/deploy-vercel-mcp.yml: deploys the public HTTP MCP endpoint to Vercel.github/workflows/deploy-docs-pages.yml: builds and publishes the documentation site to GitHub Pages
Current production domains:
- docs site:
https://narrarium.net - public MCP endpoint:
https://narrarium.space/mcp - public MCP health:
https://narrarium.space/health
To enable npm publishing from GitHub:
- Add the repository secret
NPM_TOKENusing an npm Automation token - Ensure the npm account behind the token can publish the chosen unscoped package names
- Bump the package versions and merge that change to
main
On main, the publish workflow compares local package versions against npm and only publishes versions that are not already online.
When it finds unpublished versions, it runs npm run release:check first, then publishes in dependency order.
If GitHub Actions fails with EOTP, the token is not suitable for CI publish with 2FA enabled. Replace it with an npm Automation token or move this repo to npm Trusted Publishing.
If GitHub Actions fails with E404 while publishing narrarium or the other public packages, double-check the package names, registry, and authenticated npm account.
For the Vercel deploy workflow, add this repository secret:
VERCEL_TOKEN
The workflow is already pinned to:
VERCEL_ORG_ID=team_Jut3umUxSp1D1Z1sqmv4iUjcVERCEL_PROJECT_ID=prj_b9bxn0P4ilMmG40DiZoZ057qA1Zj
For local or CI image generation with generate_asset_image, also set:
OPENAI_API_KEY
Vercel MCP
This repository now includes a Vercel-ready public MCP endpoint:
api/mcp.tsapi/health.tsvercel.json
After deploying the repo to Vercel, the public endpoints are:
/mcp/health
Important: the Vercel deployment is intended for setup guidance, repository spec guidance, and Wikipedia research. Actual local filesystem writing still belongs to the local stdio MCP server.