Self-hostable agentic-AI LMS: catalog, RAG tutor, FSRS reviews, AI authoring, ingest.
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent β or use 1-click editor setup below.
π‘ Paste the JSON block into your client's configuration file under mcpServers, then restart the application.
Type a one-sentence learning goal β an AI orchestrator builds you a private course in ~50 seconds, a RAG tutor with citations teaches it, and you can audit every agent decision it made.
Custom multi-agent system, no LangChain Β· public evals with the weak scores kept in Β· live in production
Live demo Β· Eval results Β· Architecture Β· MCP server
Real production recording (Groq Llama 3.3 70B). Intake trimmed 6Γ, the ~50 s build 16Γ β the brief and the finished course are real-time.
Try it yourself: the one-click demo pre-fills demo@lumen.test / Demo!2026 and drops you into the tutor (free-tier box β give a cold page a few seconds).
A learner-owned, two-role e-learning platform β every signed-in user runs the whole loop themselves; admin only moderates and configures. The product is the loop; the point of the repo is the agentic system underneath it.
| Step | What happens |
|---|---|
| Define | A guided AI intake (capped at six turns) turns a fuzzy goal into a structured learning brief β the source goal is field-encrypted at rest |
| Build | The authoring orchestrator builds a private course from the brief β honest status, no half-finished partials, re-runnable, cancellable (build.py, the durability/idempotency/quota shell) |
| Learn | A course-scoped RAG tutor answers with lesson citations and a visible tool-call trace |
| Share | Publishing stays private; public listing is an explicit share + admin moderation state machine with an immutable audit trail |
| Clone | Any listed course can be remixed into your own draft, with server-written "Based on β¦" provenance and a sanitized export (no enrollments, traces, or soft-deleted content) |
| BYOK | Bring your own model key (OpenAI / Anthropic / Groq / Mistral) β allowlisted providers, server-owned base URLs, envelope-encrypted write-only keys |
Shipped to production as 2.0.0-two-role (CHANGELOG) β built as a gated waterfall: requirements β design β 6 ADRs β seven build streams, each cleared a Codex challenge, an independent Claude review, and a live in-browser walk before merge.
Every item below is on production today, with the code one click away.
The tutor picks per-turn among five sub-agents in tutor_subagents/ β retriever, web_searcher, code_runner, quiz_generator, concept_explainer β under a hard cap on tool-call rounds (streaming variant). The authoring side runs a six-stage pipeline β researcher β outliner β critic β reviser β lesson-drafter β final-critic β in authoring_orchestrator.py, capped at six revise/critic calls.
Production recording at 2Γ β the retriever fires (latency on-screen), then the answer streams.
Retrieval is scoped per course and routed through a single ACL clause (visibility.py, ADR-0029) so private and cloned courses never leak chunks. Embeddings via Cloudflare Workers AI (bge-small-en-v1.5, 384-dim) into pgvector; answers cite specific lesson chunks.
Each LLM call logs prompt/completion tokens, USD cost, latency, and outcome to the llm_calls table (llm_call_log.py); each agent step lands in agent_tracer.py. Learners get a per-turn "show me how you got this" drill-down β planner steps, tool calls, retrieval audits with similarity scores; authors get a step-by-step build replay.
| Tutor-turn trace | Authoring build replay |
|---|---|
![]() | ![]() |
Three golden suites (30-item tutor, 10 authoring, 10 ingest) under evals/, judged 0β5 per axis, plus adversarial probes. A 3-item smoke gates every PR (workflow); results are public at /eval.
The point isn't the scores β it's the harness: LLM-as-judge applied honestly to one strong subsystem and two early ones, every number reproducible with make eval suite=β¦ and smoke-gated in CI.
| Suite | Judged | LLM-judge score | Reading |
|---|---|---|---|
| Authoring | 10 / 10 | 3.85 / 5 | Strong β the headline number, backed by the raw JSONL |
| Tutor | 10 / 30 | 2.33 / 5 | Early β citation-format mismatch between the judge's expected citations and what the retriever pulls; 20 items skipped, cause documented |
| Ingest | 4 / 10 | 0.83 / 5 | Early β v1 chunker emits one module per video; 6 items failed upstream transcript fetch before judging |
The weak scores are published whole, on purpose. Methodology Β· raw reports.
app/mcp/ exposes nine tools (catalog, RAG tutor, FSRS reviews, AI authoring, ingest) over stdio + HTTP with OAuth client-credentials, published as io.github.ahmedEid1/lumen. Write tools gate on the can_author capability; URL ingest stays admin-only + flag-gated (ADR-0025).
Wiring it into an MCP client takes one JSON block:
Or for Claude Code: LUMEN_MCP_AUTH_TOKEN=<secret> claude mcp add lumen -- python -m app.mcp --transport stdio, then ask "list my Lumen courses" and watch list_courses, ask_tutor, create_course_draft, β¦ fire. Full operator guide: docs/mcp.md.
Per-credential 256-bit DEKs wrapped by a versioned server KEK (secrets_crypto.py); decryption only inside the dispatch path β never in logs, traces, exports, or admin views. A prod boot guard refuses to start with stored credentials but no real KEK (ADR-0027). Request-count quotas close the $0-BYOK bypass of the dollar budget guard.
The two-role rebuild migrated student/instructor β user live: widen accepted roles β backfill β drop old values only after access tokens drained their 15-min TTL. The Alembic chain enforces one phase per run, and migration-level evidence gates refuse to tighten constraints over un-backfilled rows β one of them caught a real prod data condition (85 legacy chunks with NULL embedding model) at deploy time.
The short version: one FastAPI service owns all invariants, the agents are plain service-layer code, and every LLM call crosses one provider seam and one cost meter.
Factual signals from GitHub, npm, and our automated checks β not a rating.
No reviews yet β be the first to share how this listing worked for you.
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/lumen-2)<a href="https://allmcps.com/mcp/lumen-2"><img src="https://allmcps.com/api/badge/lumen-2?style=directory" alt="Lumen on AllMCPs" /></a>