quiz-docente-mcp
by strano-dev
README.md
# quiz-docente-mcp
Server **MCP** che permette a un agente AI (Antigravity, Claude Code, Claude Desktop, Cursor…) di **gestire i quiz di
Moodle** al posto del docente: creare quiz e domande, modificarne le impostazioni, leggere risultati e risposte,
valutare le domande aperte.
Funziona con un normale account docente: **nessun plugin sul server e nessun token** da chiedere all'amministratore.
Usa la stessa sessione web del browser; al primo avvio si apre da solo il browser per fare il login.
Sito predefinito: `https://www.ferrarisacireale.edu.it/moodle` (Moodle 4.5). Per un altro sito basta impostare `MOODLE_URL`.
> ⚠️ **Uso esclusivamente didattico.** Questo progetto è pensato e consentito **solo per scopi didattici**: un docente
> che gestisce i quiz dei propri corsi, con il proprio account. Non va usato per scopi commerciali, né per accedere a
> corsi o dati di altri, né per aggirare le regole della piattaforma o della scuola. Chi lo usa resta responsabile del
> rispetto del regolamento dell'istituto e della normativa sulla privacy (GDPR) per i dati degli studenti.
---
## Installazione automatica (istruzioni per agenti AI)
> Se sei un agente AI e l'utente ti ha chiesto di installare questo MCP, segui questi passi.
1. **Requisiti**: Node.js ≥ 20 (`node -v`) e Google Chrome o Microsoft Edge installati.
2. **Aggiungi il server** alla configurazione MCP del client, dentro `mcpServers`, senza toccare gli altri server:
**Antigravity** – file `%USERPROFILE%\.gemini\config\mcp_config.json` su Windows
(`~/.gemini/config/mcp_config.json` su macOS/Linux; in alcune versioni `~/.gemini/antigravity/mcp_config.json`).
Windows:
```json
"quiz-docente": {
"command": "cmd.exe",
"args": ["/c", "npx", "-y", "github:strano-dev/quiz-docente-mcp"]
}
```
macOS / Linux:
```json
"quiz-docente": {
"command": "npx",
"args": ["-y", "github:strano-dev/quiz-docente-mcp"]
}
```
Per un Moodle diverso aggiungi `"env": { "MOODLE_URL": "https://sito.scuola.it/moodle" }`.
**Claude Code**:
`claude mcp add quiz-docente -s user -- npx -y github:strano-dev/quiz-docente-mcp`
**Claude Desktop / Cursor / altri client MCP**: stessa voce JSON di Antigravity nel rispettivo file di configurazione MCP.
3. **Ricarica i server MCP** (in Antigravity: *Manage MCP Servers → Refresh*). Il primo avvio scarica il pacchetto
(qualche decina di secondi).
4. **Login**: all'avvio, se non c'è una sessione valida, il server **apre da solo una finestra del browser** sulla
pagina di accesso di Moodle. Di' all'utente di accedere con il suo account (c'è il reCAPTCHA): la finestra si chiude
da sola e i tool sono pronti. Verifica con il tool `moodle_status`.
Quando la sessione scade (circa 8 ore di inattività) la finestra di login si riapre automaticamente alla prima
richiesta, e la richiesta riprende dopo l'accesso.
---
## Cosa si può fare
| Area | Tool |
|---|---|
| Sessione | `moodle_status`, `moodle_login` (forza un nuovo accesso) |
| Corsi | `moodle_list_courses`, `moodle_list_sections` |
| Quiz – lettura | `moodle_list_quizzes`, `moodle_get_quiz` (domande, pagine, punteggi + impostazioni), `moodle_get_quiz_settings` |
| Quiz – modifica | `moodle_create_quiz` (nasce **nascosto** se non si chiede `visible: true`), `moodle_update_quiz_settings` (date, durata, tentativi, valutazione, navigazione, comportamento, password, opzioni di revisione, visibilità), `moodle_add_questions_to_quiz`, `moodle_add_random_questions`, `moodle_remove_quiz_slots`, `moodle_set_slot_mark`, `moodle_move_quiz_slot`, `moodle_set_quiz_max_grade`, `moodle_repaginate_quiz` |
| Banca domande | `moodle_list_question_categories`, `moodle_create_question_category`, `moodle_list_questions`, `moodle_get_question` (Moodle XML completo), `moodle_export_questions` (GIFT/XML), `moodle_create_questions` (da JSON: scelta multipla, vero/falso, risposta breve, numerica, aperta, corrispondenza, descrizione), `moodle_import_questions` (GIFT, Moodle XML, Aiken, Cloze: qualsiasi tipo), `moodle_update_question` |
| Risultati | `moodle_get_quiz_grades`, `moodle_get_quiz_responses`, `moodle_get_attempt_review`, `moodle_grade_attempt_question` (voto e commento manuale, es. domande aperte), `moodle_get_quiz_statistics` |
### Scelta di progetto: niente eliminazioni
Non esistono tool per **eliminare quiz o domande**: le eliminazioni le fa sempre il docente, a mano, da Moodle.
`moodle_remove_quiz_slots` toglie una domanda da un quiz ma la lascia nella banca domande.
Un quiz che ha già tentativi degli studenti non permette di aggiungere o togliere domande (vincolo di Moodle).
### Identificativi
- `courseid`: id del corso (`course/view.php?id=…`)
- `cmid`: id del quiz come modulo del corso (`mod/quiz/view.php?id=…`)
- `slot_id`: posizione di una domanda nel quiz, da `moodle_get_quiz`
- `category_id`, `question_id`: dai tool della banca domande, che accettano `courseid` (banca del corso) oppure
`cmid` (banca propria del quiz)
---
## Configurazione
| Variabile | Default | Significato |
|---|---|---|
| `MOODLE_URL` | `https://www.ferrarisacireale.edu.it/moodle` | URL del sito Moodle |
| `MOODLE_AUTO_LOGIN` | `1` | `1` = apre il login all'avvio e quando la sessione scade; `ondemand` = solo quando serve a un tool; `0` = mai |
| `MOODLE_READ_ONLY` | – | `1` = espone solo i tool di lettura |
| `MOODLE_MCP_DIR` | `~/.moodle-mcp` | dove vengono salvati sessione e profilo del browser di login |
| `MOODLE_BROWSER_PATH` | – | percorso di chrome.exe / msedge.exe se non vengono trovati |
| `MOODLE_LOGIN_TIMEOUT_MS` | `300000` | attesa massima per l'accesso |
La sessione è salvata in `~/.moodle-mcp/session.json` e contiene il cookie di accesso: **non condividerla**.
Login manuale da terminale: `npx -y -p github:strano-dev/quiz-docente-mcp quiz-docente-mcp-login`.
## Sviluppo
```bash
git clone https://github.com/strano-dev/quiz-docente-mcp
cd quiz-docente-mcp
npm install
npm test # test unitari (Vitest)
npm run check # typecheck + test con copertura + build: da eseguire prima di ogni commit
npm run build # compila src/ in dist/ (dist/ è versionata: serve a npx per avviare senza build)
npm run login # login manuale
npm start # avvia il server MCP su stdio
```
### Regola: si procede sempre in TDD
Ogni modifica al codice segue il ciclo **Test-Driven Development**, senza eccezioni:
1. **Red** – scrivi prima un test in `test/` che descrive il comportamento voluto e verifica che **fallisca**.
2. **Green** – scrivi in `src/` il codice minimo che lo fa passare.
3. **Refactor** – migliora il codice tenendo tutti i test verdi.
Regole pratiche:
- ogni bug si corregge partendo da un test che lo riproduce;
- nessuna nuova funzione o nuovo tool MCP senza i relativi test;
- i test unitari **non chiamano mai il Moodle reale**: `test/helpers/fake-moodle.ts` simula il sito intercettando
`fetch`, `test/helpers/moodle-html.ts` genera pagine sintetiche con la stessa struttura di Moodle 4.5 (nessun dato reale),
Playwright viene sostituito con un mock;
- prima di ogni commit `npm run check` deve passare; le soglie minime di copertura (righe 90%, rami 80%) sono
configurate in `vitest.config.ts` e fanno fallire la suite se non rispettate;
- dopo aver modificato `src/` ricompila (`npm run build`) e versiona anche `dist/`.
| File di test | Cosa copre |
|---|---|
| `test/client.test.ts` | cookie, redirect, sessione scaduta, `sesskey`, chiamate AJAX, file di sessione, `parseNum` |
| `test/forms.test.ts` | lettura e invio dei form Moodle (checkbox avanzate, select, editor, date, durate, errori) |
| `test/courses.test.ts` | corsi e sezioni |
| `test/quizzes.test.ts` | struttura del quiz, impostazioni, creazione, slot, domande casuali, voto massimo, pagine |
| `test/questions.test.ts` | categorie, elenco/export, conversione JSON → Moodle XML, import con upload, modifica domande |
| `test/reports.test.ts` | voti, risposte, revisione tentativi, valutazione manuale, statistiche |
| `test/auth.test.ts` | finestra di login (Chrome/Edge), timeout, lock contro finestre multiple |
| `test/server.test.ts` | elenco tool, modalità sola lettura, errori, login automatico con nuovo tentativo, mappatura argomenti |
| `test/login-runner.test.ts`, `test/config.test.ts` | comando di login e variabili d'ambiente |
## Come funziona
Moodle non espone ai docenti API per creare quiz e domande, quindi il server usa gli stessi endpoint dell'interfaccia web,
ricavati analizzando il traffico del browser:
| Funzione | Endpoint Moodle |
|---|---|
| corsi, sezioni, quiz di un corso | AJAX `core_course_get_enrolled_courses_by_timeline_classification`, `core_courseformat_get_state` |
| struttura del quiz | `mod/quiz/edit.php` |
| punteggio, rimozione, spostamento delle domande nel quiz | `mod/quiz/edit_rest.php` |
| aggiunta domande, voto massimo, ripaginazione | POST `mod/quiz/edit.php` |
| domande casuali | AJAX `mod_quiz_add_random_questions` |
| impostazioni e creazione quiz | form `course/modedit.php` (letto, modificato, reinviato) |
| categorie | `question/bank/managecategories/category.php`, AJAX `core_form_dynamic_form` |
| elenco e lettura domande | `question/edit.php`, `question/bank/exporttoxml/exportone.php`, `pluginfile.php/…/question/export/…` |
| creazione / import domande | upload `repository/repository_ajax.php` + form `question/bank/importquestions/import.php` |
| modifica domanda | form `question/bank/editquestion/question.php` (Moodle salva una nuova versione) |
| voti e risposte | `mod/quiz/report.php?mode=overview|responses&download=json` |
| revisione e valutazione manuale | `mod/quiz/review.php`, `mod/quiz/comment.php` |
Testato su Moodle 4.5.11. I report voti/risposte sono stati verificati solo su quiz senza tentativi di studenti
(le anteprime del docente non compaiono nei report).
## Licenza
MIT (vedi `LICENSE`). Resta valida l'indicazione d'uso esclusivamente didattico riportata all'inizio.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues