Install
$ agentstack add mcp-arnaudguiovanna-tutor-mcp Open-source listing, not yet scanned by AgentStack. Follow the source repository for install instructions.
Security review
⚠ Flagged1 finding(s); flagged for manual review. · v0.1.0 How review works →
- • Prompt-injection patterns
- • Secret / credential exfiltration
- • Dangerous shell & filesystem operations
- • Untrusted network calls
- • Known-malicious package signatures
- high Pipes remote content directly into a shell (remote code execution).
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Tutor MCP — Adaptive learning runtime for LLMs
> Turn any LLM into an intelligent tutor. Tutor MCP is an open-source MCP server that gives an AI assistant durable learner state, cognitive-science scheduling, session memory, misconceptions, metacognition, and auditable pedagogical decisions. No item bank — the LLM generates content, Tutor MCP remembers and decides.
Tell the LLM what you want to learn — Spanish for travel, Go for backend, medieval history — and the runtime orchestrates the journey: what to study next, when to review, when you've mastered a concept, when you need a nudge. The next conversation starts from what the learner has mastered, forgotten, misunderstood, felt, and explicitly committed to do next.
Status — alpha v0.4.0. The full regulation pipeline (phase FSM + concept/action selectors + gate + threshold resolver) ships default-on; the fade controller is opt-in. Suitable for individual use, small groups, and classroom-scale (≤200 active learners). Single-tenant; runs single-node on SQLite + in-process scheduler by default, and now scales horizontally on an opt-in PostgreSQL backend (DB_DRIVER=postgres) with a distributed scheduler and shared rate-limit store for stateless multi-node deployments.
Compatible clients
Claude (web + Desktop + Code), ChatGPT (Developer Mode), Le Chat, Gemini Enterprise / CLI. See the [client setup guide](#setup) below.
Continuity model
The missing layer is not content. It is continuity.
LLMs can explain. Tutor MCP remembers and decides. The runtime owns the durable learner state and the pedagogical decisions; the LLM stays free to explain, reframe, question, generate exercises, and consolidate narrative memory from the traces it receives.
| Layer | Stored as | What it gives the tutor | |---|---|---| | Algorithmic state | SQLite domains, concept states, interactions, affect, calibration, transfer, intentions | Domains, prerequisites, phase, mastery, retention, ability, review timing, transfer readiness, active misconceptions | | Episodic memory | Markdown sessions/*.md with YAML frontmatter | Affect, concepts touched, salient exchanges, mental-model observations, implementation intentions | | Narrative state | Markdown MEMORY.md, MEMORY_pending.md, concepts/*.md, archives/*.md | Stable learner facts, pending observations, concept notes, medium-term trajectory, contradictions to verify | | Operator view | Pedagogical snapshots + decision replay | Why an activity was selected, why a concept was held back, whether evidence was missing or noisy |
get_next_activity merges the algorithmic signals with episodic_context: stable memory, pending observations, recent sessions, archives, concept notes, and detected OLM inconsistencies. The LLM receives enough context to form a brief hypothesis about the learner's current cognitive state, but it does not own the schedule.
How it works
The server sits between a learner and an LLM. It splits the job cleanly:
| Component | Owns | Does not own | |---|---|---| | Deterministic engine — Tutor MCP | Cognitive signals, phase control, evidence gates, session history, Markdown learner memory, audit trail | Learner-facing prose, examples, Socratic phrasing | | Generative coach — your LLM | Content generation, natural language coaching, interpretation briefs, session summaries, memory consolidation | Durable mastery state, review timing, prerequisite gates |
Four loops run from the first session:
- Learning loop — Before and after every exchange, the LLM calls
get_next_activityandrecord_interaction. The runtime updates BKT mastery, FSRS recall, IRT ability, Rasch/Elo exercise calibration, transfer evidence and misconception status — in real time, on every interaction. The LLM never picks scheduling itself. - Narrative memory loop —
record_session_closeasks the LLM for a factual session trace;update_learner_memorystores stable memory, pending observations, concept notes, sessions and archives. The nextget_next_activitycall can use those traces to avoid a generic exercise. - Metacognitive loop — Affect check-ins (
record_affect), calibration tracking (calibration_check/record_calibration_result) and an autonomy score observe the learner's relationship to the system. A factual mirror surfaces consolidated dependency patterns — the system aims to make itself progressively unnecessary. - Motivation loop — A brief engine selects one motivational angle per exercise (milestone, competence value, growth mindset, affect reframe, plateau recontext, utility value) and emits signals + instruction — never canned text. The LLM phrases it.
The pillars of an Intelligent Tutoring System map cleanly:
| ITS pillar | Owner | |---|---| | Domain model (concept graph, prerequisites) | Tutor MCP runtime — KST-validated | | Learner model (mastery, ability, recall, transfer) | Tutor MCP runtime — BKT, IRT, Rasch/Elo, PFA | | Pedagogical model (scheduling, regulation, alerts) | Tutor MCP runtime — FSRS, evidence gates, orchestrator | | Interface + content | The LLM — Claude / ChatGPT / Le Chat / Gemini |
The cognitive science is rigid and measurable; the LLM is infinitely flexible. Together they ship an ITS that works on day one for any topic, without an editorial team.
Quick start
1. Install or build
# Latest Linux release (no sudo: set TUTOR_MCP_INSTALL_DIR)
curl -fsSL https://tutor-mcp.dev/install.sh | sh
# Or build from source
go build -o tutor-mcp
2. Run
export JWT_SECRET="$(openssl rand -base64 32)" # required — must be base64
export BASE_URL=https://your.domain # public origin, no trailing slash
./tutor-mcp # listens on :3000 by default
Verify: curl $BASE_URL/health → {"status":"ok"}.
For real use, put the runtime behind a public reverse proxy with TLS — see [OPERATIONS.md](./OPERATIONS.md). Web clients (Claude.ai, ChatGPT, Le Chat) require a public HTTPS endpoint; http://localhost is rejected by their cloud connectors.
3. Connect a client
Add https://your.domain/mcp as a custom MCP connector. OAuth 2.1 + PKCE with dynamic client registration: no client ID or secret to copy by hand. On the first connection the client opens /authorize — register (email + password) or log in. Subsequent launches reuse refresh tokens silently.
| Client | Path | Notes | |---|---|---| | Claude.ai | Settings → Connectors → + → URL https://your.domain/mcp | Pro, Max, Team, Enterprise | | ChatGPT | Settings → Connectors → Advanced → Developer Mode → Create | Plus, Pro, Team, Enterprise, Edu | | Le Chat | Connectors → + Add Connector → Custom MCP | Auto-detects OAuth | | Gemini Enterprise | GCP Console → Custom MCP server data store | StreamableHTTP transport | | Gemini CLI | geminicli.com/docs/tools/mcp-server/ | Local CLI | | Claude Code (CLI, local) | .mcp.json with "url": "http://localhost:3000/mcp" | No HTTPS needed |
MCP tools (35)
All tools accept an optional domain_id for multi-domain learners; without it, the most recently active non-archived domain is used.
Core learning loop (7)
| Tool | Purpose | |---|---| | get_learner_context | Session-start context: active domain, concept states, recent history, active misconceptions | | get_pending_alerts | Learning + metacognitive alerts requiring action | | get_next_activity | Next optimal activity + episodic context + reasoning request + tutor mode + motivation brief + mastery uncertainty + transfer profile + Rasch/Elo calibration | | record_interaction | Persist outcome, update BKT/FSRS/IRT/Rasch-Elo; tracks hints, initiative, error type, misconception, rubric evidence, interpretation brief | | check_mastery | Mastery-challenge readiness: BKT + evidence diversity + uncertainty + transfer status | | get_olm_snapshot | Open Learner Model: per-concept mastery, retention, fringe membership | | get_dashboard_state | Full dashboard: progress, retention, autonomy, calibration bias, affect history |
Domain management (9)
| Tool | Purpose | |---|---| | init_domain | Create domain with concept graph, prerequisites, personal goal | | add_concepts | Append concepts without resetting progress | | validate_domain_graph | Audit graph: cycles, orphans, depth, disconnections | | archive_domain / unarchive_domain / delete_domain | Lifecycle | | set_domain_priority | Re-rank domains for scheduling weight | | set_goal_relevance / get_goal_relevance | LLM-decomposed relevance vector over the concept graph (biases the concept selector) — gated by REGULATION_GOAL |
Metacognition (5)
| Tool | Purpose | |---|---| | record_affect | Energy + confidence (start), satisfaction + difficulty + intent (end) | | calibration_check / record_calibration_result | Self-prediction (1–5) + bias update | | get_autonomy_metrics | Autonomy score 0–1 with 4 components (initiative, calibration, hint independence, proactive review) | | get_metacognitive_mirror | Factual mirror message when a dependency pattern is consolidated over 3+ sessions | | update_learner_profile | Persist learner metadata (objective, language, calibration bias, …) |
Audit & replay (3)
| Tool | Purpose | |---|---| | get_pedagogical_snapshots | Before / observation / after / decision trace | | get_decision_replay_summary | Offline audit: replay coverage, missing rubrics, transfer gaps, JSON issues | | get_misconceptions | Per-concept misconceptions with status (active / resolved) and frequency |
Transfer & negotiation (4)
| Tool | Purpose | |---|---| | feynman_challenge | Learner explains a mastered concept; LLM detects gaps for BKT injection | | transfer_challenge / record_transfer_result | Structured probe in near/far/debugging/teaching/creative | | learning_negotiation | Expose system plan + tradeoffs; learner can propose alternatives |
Memory & session (5)
| Tool | Purpose | |---|---| | update_learner_memory / read_raw_session / get_memory_state | Markdown memory: sessions, concepts, stable memory, archives | | record_session_close | Recap brief + optional Gollwitzer if-then implementation intention | | queue_webhook_message | Queue a structured Discord nudge (why_now, learning_gain, open_loop, next_action) |
Availability (1)
| Tool | Purpose | |---|---| | get_availability_model | Learner's time windows and session frequency |
Alert engine
The scheduler detects nine alert types — learning (FORGETTING, PLATEAU, ZPD_DRIFT, OVERLOAD, MASTERY_READY) and metacognitive (DEPENDENCY_INCREASING, CALIBRATION_DIVERGING, AFFECT_NEGATIVE, TRANSFER_BLOCKED). Daily dedup, per-day frequency cap; archived/deleted domains are filtered out of reads and webhooks.
Cognitive science engine
Pure-function algorithms running on every interaction, composed by the regulation orchestrator (engine/orchestrator.go; design notes in [docs/regulation-design/](./docs/regulation-design/)).
| Algorithm | Role | |---|---| | BKT + individualized BKT | Estimates mastery confidence per concept, not just whether the learner answered right today; recent-history profile individualizes P(Learn), P(Slip), P(Guess) — never tuned by the LLM | | FSRS | Decides when to bring a concept back, using stability and difficulty curves | | IRT | Tracks learner ability θ from response patterns so activity difficulty is calibrated to the current learner | | Rasch / Elo | Keeps a deterministic learner-ability vs exercise-difficulty signal, exposed to the LLM and stored in snapshots | | PFA | Weighs wins and losses on each concept to predict how the next attempt is likely to go | | KST | Validates prerequisite graph; gates new concepts on mastery of ancestors | | Structured transfer | Checks whether knowledge moves beyond the training pattern across near/far/debugging/teaching/creative probes |
The regulation pipeline runs as a 7-stage chain inside get_next_activity: threshold resolver → goal decomposer → phase FSM (DIAGNOSTIC ↔ INSTRUCTION ↔ MAINTENANCE) → concept selector → gate (anti-repeat / session-budget / no-fringe escape) → action selector → fade controller. Pure functions are unit-tested (~90 tests); the orchestrator integration is covered by SQLite in-memory + migration tests. Full design rationale in [docs/regulation-design/](./docs/regulation-design/).
Configuration
Environment variables read at boot:
| Variable | Default | Effect | |---|---|---| | JWT_SECRET | — (required) | HS256 secret. Must be valid base64 (plain strings rejected at boot). Use openssl rand -base64 32 — 32+ decoded bytes recommended for HS256. Must be identical on every instance in a multi-node deployment. | | PORT | 3000 | HTTP listen port | | DB_DRIVER | sqlite | sqlite (default, embedded, no external service) or postgres (horizontal multi-node). | | DB_PATH | ./data/runtime.db | SQLite path (ignored when DB_DRIVER=postgres) | | DATABASE_URL | — | Postgres DSN, required when DB_DRIVER=postgres (e.g. postgres://user:pass@host:5432/db?sslmode=require). | | DB_MAX_CONNS | 10 | Postgres connection-pool size per instance (ignored on SQLite). Keep DB_MAX_CONNS × instances < Postgres max_connections. | | SCHEDULER_MODE | inprocess | inprocess (single-node cron) or distributed (per-run DB lease for exactly-once across a fleet). | | RATELIMIT_BACKEND | memory | memory (per-instance, default) or postgres/db (shared, fleet-wide rate-limit + login-failure stores — required for coherent throttling across multiple instances). | | BASE_URL | http://localhost:$PORT | Public origin (no trailing slash). Triggers HSTS when https://. | | LOG_LEVEL | info | debug, info, warn, error | | TRUSTED_PROXY_CIDRS | — | Comma-separated CIDRs of trusted reverse-proxies. Required behind a public proxy — without it every IP-rate-limit collapses under the proxy's loopback bucket. | | MCP_RATE_LIMIT_PER_MIN | 60 | Per-IP and per-learner cap on /mcp | | MCP_RATE_LIMIT_BURST | 60 | Burst allowance | | TUTOR_MCP_MEMORY_ENABLED | on | Markdown learner memory; set off for pre-memory contract | | TUTOR_MCP_MEMORY_ROOT | ~/.tutor-mcp/ | Memory FS root | | REGULATION_THRESHOLD | on | off reverts to legacy split thresholds (BKT 0.85 / KST 0.70 / Mid 0.80) | | REGULATION_GOAL | on | off hides set_goal_relevance / get_goal_relevance and drops the goal-aware prompt section | | REGULATION_ACTION / _CONCEPT / _GATE | on | off drops the system-prompt appendix only — the selector / gate logic always runs | | REGULATION_FADE | off (opt-in) | Strict literal on enables the fade controller (verbosity reduction + webhook frequency + ZPD aggressiveness + proactive review). Any other value keeps it off. |
Auth endpoints are rate-limited at 10/min (/authorize, /token), 5/min (/register); the MCP endpoint applies the per-IP and per-learner caps configured above.
Architecture
main.go HTTP + MCP handler + OAuth + scheduler
auth/ OAuth 2.1 + JWT + PKCE + rate limiter
algorithms/ BKT / FSRS / IRT / Rasch-Elo / PFA / KST + thresholds
engine/ Orchestrator + phase FSM + selectors + gate + fade
+ alert / motivation / mirror / replay / OLM
models/ Typed structs (learner, domain, interactions, regulation, …)
db/ Store (SQLite default + Postgres) + dialect-aware schema + checksummed migrations
memory/ Markdown learner memory (stable / pending / sessions / concepts / archives)
tools/ MCP tool handler
…
## Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [ArnaudGuiovanna](https://github.com/ArnaudGuiovanna)
- **Source:** [ArnaudGuiovanna/tutor-mcp](https://github.com/ArnaudGuiovanna/tutor-mcp)
- **License:** MIT
- **Homepage:** https://tutor-mcp.dev/
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.