MoirAI Story Engine is the backend for MoirAI, an AI-powered text adventure platform. It exposes a REST API and WebSocket interface consumed by the MoirAI Web UI, handling worlds, adventures, player characters, RPG mechanics, AI narration, moderation, notifications and user authentication via Discord OAuth2.
- Java 25
- Maven
- Spring Boot
- Spring Web
- Spring WebSocket (STOMP)
- Spring Data JPA
- Spring Security
- PostgreSQL
- Liquibase
- Qdrant
- S3 (MinIO locally)
- JTokkit
MoirAI Story Engine powers AI-driven text adventures. Users create worlds, adventures and player characters, configure a Narrator with a custom personality, and play through the web UI, alone or with other players. The engine evaluates each player action, rolls dice when the RPG mechanics call for it, assembles the narrator's context with lorebook and memory retrieval via vector search, generates and moderates the AI's text, keeps long-term memory as chronicle summaries, and pushes every update to the players in real time over WebSockets.
Yes and no. The code is free to use. However, MoirAI relies on OpenAI's API for text generation, embeddings, moderation and images, so you will need an OpenAI account and will be billed according to your usage and chosen model.
MoirAI Story Engine currently supports OpenAI's GPT-5 model family.
To run MoirAI Story Engine locally, you will need JDK 25, Maven, a PostgreSQL database, a Qdrant instance and S3-compatible storage for images. docker-compose-infrastructure.yaml spins up PostgreSQL, Qdrant, MinIO and a mock of Discord for local development. A Discord application is only needed outside local development.
MoirAI uses Discord exclusively for user authentication. Users sign up and sign in from the web UI: the engine sends the browser to an authorize page, which sends it back to the engine's callbacks, /auth/signup/code and /auth/signin/code. The callbacks only accept logins that started at the engine, so they are never opened by hand.
Local development. No Discord application is needed. The mock started by docker-compose-infrastructure.yaml on port 8081 stands in for both Discord's authorize page and its API:
AUTHORIZE_URL:http://localhost:8081/oauth2/authorizeDISCORD_API_BASE_URL:http://localhost:8081DISCORD_BOT_SIGNIN_REDIRECT_URLandDISCORD_BOT_SIGNUP_REDIRECT_URL:http://localhost:8080/auth/signin/codeandhttp://localhost:8080/auth/signup/code- The Discord client ID, client secret and bot token can be any value
Then sign up or sign in from the web UI. The mock's page suggests a random account name; type an existing one to log back in as that account. Use a private window or a separate browser profile for each account you want signed in at the same time.
With Discord. Create an application in the Discord Developer dashboard and register two OAuth2 redirect URIs, one for signing up and one for signing in, pointing at the engine's callbacks through the same host that serves the web UI. Use the same two URIs for the redirect URL variables, set AUTHORIZE_URL to https://discord.com/oauth2/authorize, leave DISCORD_API_BASE_URL unset, and use the application's client ID, client secret and bot token.
You will need your OpenAI API key and, outside local development, your Discord OAuth2 client ID and secret and your Discord bot token.
- Clone the repo
- Set up the required environment variables:
DISCORD_BOT_CLIENT_ID— your Discord OAuth2 client IDDISCORD_BOT_CLIENT_SECRET— your Discord OAuth2 client secretDISCORD_BOT_TOKEN— your Discord bot tokenDISCORD_BOT_SIGNIN_REDIRECT_URL— your Discord OAuth2 redirect URI for signing inDISCORD_BOT_SIGNUP_REDIRECT_URL— your Discord OAuth2 redirect URI for signing upAUTHORIZE_URL— the authorize page users are sent to when they sign in or sign up (https://discord.com/oauth2/authorize)AUTH_SUCCESS_REDIRECT_URL,AUTH_FAIL_REDIRECT_URL,AUTH_LOGOUT_REDIRECT_URL,AUTH_SIGNUP_REDIRECT_URL,AUTH_NOT_REGISTERED_REDIRECT_URL— the web UI pages users land on after each authentication stepALLOWED_ORIGINS— the web UI's origin (e.g.http://localhost:5173); only pages from it may send changesALLOWED_HEADERS— headers allowed in CORS requests (e.g.Content-Type)OPENAI_API_TOKEN— your OpenAI API keyPOSTGRES_HOST,POSTGRES_DB,POSTGRES_USER,POSTGRES_PASSWORD— your PostgreSQL connection detailsQDRANT_HOST,QDRANT_PORT— your Qdrant instance detailsS3_ENDPOINT,S3_ACCESS_KEY,S3_SECRET_KEY,S3_BUCKET,S3_REGION— your S3 storage details
- Start the infrastructure with
docker compose -f docker-compose-infrastructure.yaml up -d, or bring your own - Compile with
mvn clean install - Run the application:
- Through the IDE of your choice
- Through Maven with
mvn spring-boot:run - By running the JAR directly with
java -jar storyengine-X.X.X.jar
- Clone the repo
- Open
docker-compose.yaml.sampleand fill in your keys and tokens in theenvironmentsection, replacing allCHANGE_THIS_VALUEentries - Save the modified file as
docker-compose.yaml - Run
docker-compose upfrom the project root
- AI-powered text adventure engine with context-aware generation
- World and adventure management with full CRUD support, images and sharing
- Narrator configuration with custom personality per adventure
- Player characters with a character sheet, skills, XP and level-ups
- RPG mechanics: AI evaluation of player actions and dice checks
- Lorebook with vector search (RAG) for context enrichment
- Long-term memory through chronicle summaries
- Multiplayer adventures with invitations
- AI moderation powered by OpenAI's API
- REST API consumed by the MoirAI web UI
- Real-time adventure gameplay