moodle-um
Provides tools for interacting with the University of Montpellier Moodle through its ENT/CAS login flow, including browsing courses and activities, reading and submitting assignments, downloading course files, checking grades and deadlines, managing quiz attempts, and fetching or driving Moodle pages.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@moodle-um what assignments are due this week?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Moodle UM — CLI + MCP server
A CLI and MCP server for the University of Montpellier Moodle (https://moodle.umontpellier.fr). It signs in through the real ENT/CAS flow, then lets you or an AI agent browse courses, read and submit assignments, download course files, check grades and deadlines, and drive pages that have no dedicated tool.
Independent project. Not affiliated with or endorsed by Université de Montpellier. Use it responsibly — see Responsible use.
First run — sign in once
Requirements: Python ≥ 3.12, uv, and Chromium or Google Chrome.
The only manual step is the first ENT login. Clone, install, and sign in once:
git clone https://github.com/do-2k25-28/moodle-um.git
cd moodle-um
uv sync
uv run moodle-um login
uv run moodle-um statusA Chromium window opens on the ENT/CAS page. Sign in with your identifiant and
MFA; the window closes automatically when the Moodle session is detected. The
session is saved in ~/.config/moodle-um/ (mode 0600) and reused by every CLI
command and MCP tool.
No password is stored — only the resulting session cookies.
MCP: if
moodle_statusreturnsauthenticated: false, callmoodle_loginonce before any other tool. The server does not open a browser by itself.Expired session: run
moodle-um loginagain, or keep it alive with the keepalive timer.You do not sign in per command, per course, or per tool call.
Optional: uv tool install . puts moodle-um and moodle-um-mcp on your
PATH.
Related MCP server: moodle-mcp
What it can do
Area | Capabilities |
Courses | List enrolled courses, sections, activities, resources, descriptions, completion info |
Assignments | List devoirs, due dates, submission status, instructions, attachments |
Submission | Upload files and/or online text, accept the originality statement, final submit, remove a submission |
Files | Download |
Grades | Read the per-course grade report |
Calendar | Upcoming deadlines and action events |
Quizzes | List quizzes, read settings/attempts/grades, start/resume an attempt, read questions + choices, save answers and submit with confirmation; finished attempts are parsed from the review page |
Any page | Fetch any Moodle page as Markdown, or drive it with a headless browser ( |
Interfaces | Typer CLI + stdio MCP server (Claude Desktop, Claude Code, Cursor, DeepSeek Harness, any MCP client) |
Session | One interactive ENT login, saved cookies, optional keepalive timer |
What it cannot do (yet)
Limitation | Detail |
No SEB / proctoring bypass | Safe Exam Browser, lockdown browsers and proctoring are not bypassed. If an exam requires SEB, use SEB. |
No built-in LLM solver | The MCP exposes the questions and a save/submit API; the calling AI proposes the answers. You review them before submission. |
No SEB / proctoring bypass | Safe Exam Browser, lockdown browsers and proctoring are not bypassed. If an exam requires SEB, use SEB. |
No teacher/admin actions | The tool acts as the logged-in student. |
Not every activity type | BigBlueButton, H5P, attendance, etc. are reachable through the generic page/browser tools, not first-class tools. |
MFA is interactive | No password is stored, so the first login needs a browser and MFA. |
Session lifetime | Moodle expires idle sessions after ~2 h. The keepalive timer prevents this while the machine is awake; a long suspend can still require a new login. |
CLI
uv run moodle-um courses # all enrolled courses
uv run moodle-um courses -q ansible # filter
uv run moodle-um course <course-id> # sections + activities
uv run moodle-um assignments <course-id> # devoirs, due dates, status
uv run moodle-um assignment <cmid> # one devoir in detail
uv run moodle-um upcoming -n 20 # deadlines / calendar
uv run moodle-um grades <course-id> # grade report
uv run moodle-um quizzes <course-id>
uv run moodle-um quiz <cmid>
uv run moodle-um quiz-start <cmid> # start/resume, get questions + choices
uv run moodle-um quiz-attempt <attempt-id> # read a page of an attempt
uv run moodle-um quiz-solve <attempt-id> --answers '{"1":"b","2":"Paris"}'
uv run moodle-um quiz-submit <attempt-id> --yesRead any page as Markdown:
uv run moodle-um page '/mod/forum/view.php?id=<id>'
uv run moodle-um page '/course/view.php?id=<course-id>'Download a file:
uv run moodle-um download 'https://moodle.umontpellier.fr/pluginfile.php/...'
# -> ~/Downloads/moodle-um/<filename>Submit a devoir
uv run moodle-um submit <cmid> \
--file ~/Documents/rapport.pdf \
--text "Quelques remarques…" \
--yes
# Undo an accidental submission:
uv run moodle-um unsubmit <cmid> --yes--filecan be repeated.--no-submitstops after saving. Careful: some assignments do not use drafts, so saving is already a final submission. The command reportssubmitted_for_gradingand adds a warning in that case.--yesis mandatory: the action may be graded and cannot be undone.If the assignment shows an originality statement ("Ce document est le fruit de mon propre travail…"), the tool accepts it when submitting.
The MCP equivalent is moodle_submit_assignment and also requires
confirm=true.
Drive a page with the headless browser
For quizzes or any JS-heavy page:
uv run moodle-um browse '/mod/quiz/view.php?id=<cmid>' \
--actions '[{"type":"click","selector":"a[href*=\"startattempt.php\"]"}]'It returns the page text, URL, and every visible form element (name, label, options). Use a second call with the returned attempt URL to fill answers and click Next page / Finish attempt.
Supported actions: click, fill, type, select, check, uncheck,
press, set_file, goto, wait, wait_for, scroll.
MCP server
The server uses stdio. Point your MCP client at the installed binary, or
run it through uv:
{
"mcpServers": {
"moodle-um": {
"command": "/absolute/path/to/moodle-um/.venv/bin/moodle-um-mcp"
}
}
}{
"mcpServers": {
"moodle-um": {
"command": "uv",
"args": ["--directory", "/absolute/path/to/moodle-um", "run", "moodle-um-mcp"]
}
}
}Claude.ai / cloud clients (multi-user HTTP)
claude.ai connectors need a public HTTPS MCP URL; they cannot spawn a local stdio process. The server can host one Moodle session per person, with a personal bearer token per user.
Run it in Streamable HTTP mode:
# 32-byte onboarding secret; do not commit or share it
SECRET=$(python3 -c 'import secrets; print(secrets.token_urlsafe(32))')
export MOODLE_UM_MULTIUSER=1
export MOODLE_UM_MCP_PATH="/$SECRET/mcp"
export MOODLE_UM_PUBLIC_URL="https://<machine>.<tailnet>.ts.net/$SECRET"
uv run moodle-um mcp --http --host 127.0.0.1 --port 8765 --path "$MOODLE_UM_MCP_PATH"With Tailscale:
tailscale funnel --bg 8765If Funnel is configured on a non-default HTTPS port (for example :8443),
include that port in the connector URL and in MOODLE_UM_PUBLIC_URL.
Each user:
signs in once on their own machine:
uv run moodle-um loginopens the onboarding page and uploads
~/.config/moodle-um/storage_state.json:https://<machine>.<tailnet>.ts.net/<secret>/connectreceives a personal token, then in Claude adds the connector with:
Authentication: No sign-in
Request headers:
Authorization: Bearer <token>MCP server URL:
https://<machine>.<tailnet>.ts.net/<secret>/mcp
The server validates the uploaded session against Moodle, stores it under
~/.config/moodle-um/users/<hash>/ (mode 0600), and routes every MCP request
to the user selected by the token. Run the keepalive for everyone with:
uv run moodle-um keepalive --allA systemd user service is provided in
systemd/moodle-um-mcp-http.service; put
deployment values in ~/.config/moodle-um/mcp.env:
MOODLE_UM_MCP_PATH=/<secret>/mcp
MOODLE_UM_PUBLIC_URL=https://<machine>.<tailnet>.ts.net/<secret>Why not Claude OAuth? Claude's "Sign in" authenticates the connector, but
Moodle's session cookie is scoped to moodle.umontpellier.fr; an OAuth login
does not give the server that cookie. The upload/token flow is the bridge that
actually links each user's Moodle account. No ENT password is stored.
Security: a token is a bearer credential for one Moodle session. Use HTTPS, do not paste it into issues or screenshots, and rotate it by uploading a new session (which creates a new token) if it leaks.
Claude Desktop
Merge the JSON above into
~/.config/Claude/claude_desktop_config.json (Linux) or
~/Library/Application Support/Claude/claude_desktop_config.json (macOS), then
restart Claude Desktop.
Claude Code
claude mcp add moodle-um -- /absolute/path/to/moodle-um/.venv/bin/moodle-um-mcpCursor
Put the same mcpServers object in .cursor/mcp.json (project) or
~/.cursor/mcp.json (global). See examples/.
DeepSeek Harness
A config-only bundle is included in dsh-bundle/. Edit its
cordis.patch.yml to replace /path/to/moodle-um, then:
# from a terminal:
dsh plugin --profile web add file:$PWD/dsh-bundle
# or from the DSH plugin-manager tool:
plugin_manager install_bundle target=file:$PWD/dsh-bundleTools appear as mcp__um__moodle_* (the server name is um). Remove with
plugin_manager remove_bundle target=@local/dsh-moodle-um.
Tools exposed
Tool | What it does |
| Check the saved session and who is logged in |
| Open the ENT login window (interactive, once) |
| Enrolled courses, with ids |
| Sections, activities, descriptions, file links |
| Devoirs + due dates + submission status |
| Instructions, attachments, status, edit/remove URLs |
| Upload files / online text; final submit ( |
| Undo an accidental submission ( |
| Quizzes in a course |
| Quiz settings, attempts, |
| Start/resume an attempt; return questions, choices, input names |
| Read one page of an in-progress or finished attempt |
| Save answers from question numbers/labels (does not submit) |
| Final submit, |
| Grade report for a course |
| Upcoming deadlines/calendar |
| Any Moodle page as Markdown |
| Headless browser + click/fill actions |
| Download a file to |
Typical agent flow:
moodle_list_courses→ pick a course id.moodle_get_course/moodle_list_assignments→ see what is due.moodle_get_assignment→ read instructions and attachments.Ask the user to confirm, then
moodle_submit_assignment(confirm=true, …).For a quiz:
moodle_quiz_start→ solve/read questions →moodle_quiz_solve→ user confirms →moodle_quiz_submit.
The server instructions tell the model to never submit without explicit user confirmation and never invent answers for an exam.
Keep the session alive
Moodle expires an idle session after 2 hours. A lightweight ping slides the expiry forward:
uv run moodle-um keepalive --onceA systemd user timer can run it every 10 minutes:
mkdir -p ~/.config/systemd/user
cp systemd/moodle-um-keepalive.service systemd/moodle-um-keepalive.timer \
~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now moodle-um-keepalive.timerCheck it:
systemctl --user list-timers --all | grep moodle
journalctl --user -u moodle-um-keepalive.service -n 20
tail -f ~/.config/moodle-um/keepalive.logThe units use %h/moodle-um; adjust them if you cloned elsewhere. This keeps
the session alive while the machine is running and the timer fires. A suspend
longer than two hours can still expire it — run moodle-um login after waking.
Fully unattended re-login would require storing ENT credentials and an MFA
secret, which this tool deliberately does not do.
How it works
flowchart LR
A[ENT / CAS<br/>MFA] -->|Playwright, once| B[MoodleSession cookies]
B -->|httpx| C[moodle.umontpellier.fr]
C --> D[Moodle AJAX API]
C --> E[HTML pages / forms]
C --> F[repository_ajax.php<br/>draft uploads]
B --> G[headless Chromium<br/>quizzes, JS pages]
B --> H[keepalive timer]Login is done once in a real browser; session state is stored in
~/.config/moodle-um/storage_state.json.Course/assignment data comes from the same HTML and AJAX endpoints the web interface uses, so it reflects what you see.
File submission uploads to Moodle's draft area, then posts the normal submission form (including the originality statement when present).
The generic browser layer handles JS-heavy pages without pretending every Moodle activity has a stable API.
Process model — no server to host
moodle-um-mcp is a stdio MCP server, not an HTTP service:
AI client (Claude / Cursor / DSH)
│ JSON-RPC over stdin/stdout
▼
moodle-um-mcp ──HTTPS──► moodle.umontpellier.frThe AI client spawns
moodle-um-mcpas a child process and talks to it over stdin/stdout. There is no port to expose, no daemon to deploy, and nothing to host.The process lives only while the client keeps it open. In this DeepSeek Harness it is a child of the Web process; the only listening socket is the DSH Web UI itself on
127.0.0.1:3080.The optional keepalive is a systemd user timer running
moodle-um keepalive --onceevery 10 minutes. It is a one-shot local job, not a network server.Network egress is limited to the university Moodle (and CAS during login).
Where credentials live
No ENT password and no MFA secret are stored. The only credential material is the browser session created by the one-time login:
Path | Contents | Mode |
| Session cookies ( |
|
| Site URL, user id/name, user agent |
|
| Chromium profile used for login (cookies, cache, history) |
|
| Timestamps and user id of keepalive pings |
|
The repository contains none of these. The DSH bundle only passes the
MOODLE_UM_HOME path — no secret.
To revoke access:
systemctl --user disable --now moodle-um-keepalive.timer
rm -rf ~/.config/moodle-umThen log out of Moodle/ENT in your browser. Deleting the directory logs the tool out; it does not end a separately open browser session.
Configuration
Variable | Default | Meaning |
|
| Session/config directory |
|
| Default download directory |
| auto-detected | Chromium/Chrome executable |
|
| Seconds to wait for ENT login |
|
| Moodle base URL |
|
|
|
|
| HTTP bind address |
|
| Streamable HTTP path; use a random secret for remote mode |
Quiz attempts
v0.3 adds the full read → solve → submit loop:
moodle_quiz_start(cmid)starts or resumes an attempt (it does not submit) and returns the attempt id, page, timer, question text, choices, select options, text fields and the exact input names. Starting can consume one of your allowed attempts, so only use it when you explicitly want to take the quiz.moodle_quiz_attempt(attemptid, page=0)reads an in-progress page; if the attempt is finished, it parses the review page and returns the questions with their correct-answer markers.moodle_quiz_solve(attemptid, answers, page=None)maps answers such as{"1": "b", "2": "Paris", "3": ["A", "C"]}to the real Moodle inputs and saves the page. It does not submit.moodle_quiz_submit(attemptid, confirm=true)finishes the attempt. It is irreversible and requires explicit confirmation.The same actions are available from the CLI with
quiz-start,quiz-attempt,quiz-solveandquiz-submit.
Example shape:
{
"attemptid": 42,
"page": 0,
"timeleft": "00:14:32",
"questions": [
{
"number": 1,
"type": "multichoice",
"text": "What is 2 + 2?",
"choices": [
{"name": "q42:1_answer", "value": "0", "label": "a. 3", "selected": false},
{"name": "q42:1_answer", "value": "1", "label": "b. 4", "selected": true}
]
}
]
}Solving workflow
moodle_quiz_start(cmid)(ormoodle_quiz_attemptfor an in-progress attempt) returns the questions and choices.The AI proposes answers. Show the questions and answers to the user.
moodle_quiz_solve(attemptid, {"1": "b", "2": "Paris"})saves the page. Repeat for each page.After the user confirms,
moodle_quiz_submit(attemptid, confirm=true).Review the result page.
The save/submit flow is tested offline against Moodle-shaped forms with a
mocked processattempt.php, and the parser is validated against a real finished
UM attempt. A Docker-based local Moodle lab for full end-to-end attempts is in
docs/quiz-test-lab.md.
The model does the reasoning; the MCP does not embed an LLM or auto-submit a graded exam. Do not use this on SEB/proctored exams or without the user's explicit approval.
Responsible use
This is a client for your own Moodle account. Do not use it to:
bypass Safe Exam Browser, proctoring, or exam access rules;
submit work that is not yours;
access another student's data or impersonate someone else.
Submitting an assignment or an exam is final. The CLI and MCP tools require an explicit confirmation flag; you remain responsible for what you submit. Check your institution's rules before using automation for graded work.
Development
uv sync
uv run pytest -q
uv run ruff check src testsLayout:
src/moodle_um/
auth.py # Playwright ENT/CAS login + session persistence
client.py # cookie-authenticated httpx client, AJAX, downloads
services.py # courses, assignments, quizzes, grades, calendar, submit
parsers.py # HTML → text / links
browser.py # generic headless-browser actions
keepalive.py # periodic session ping
cli.py # Typer CLI
mcp_server.py # FastMCP server
tests/ # offline unit tests + local Moodle lab
systemd/ # optional keepalive timer
dsh-bundle/ # DeepSeek Harness registrationDebug a page's raw HTML:
uv run moodle-um raw '/mod/assign/view.php?id=<cmid>' -o /tmp/page.htmlSee CONTRIBUTING.md and SECURITY.md.
License
MIT — see LICENSE.
Available Tools
19 toolsmoodle_browserA
Browse any Moodle page in a real headless browser, optionally clicking/filling.
This is the universal fallback for anything without a dedicated tool: taking a quiz, filling a form, uploading a file, reading a forum. Each call is stateless but the server-side Moodle state persists.
Action objects (executed in order): {"type":"click","selector":"text=Attempt quiz now"} {"type":"fill","selector":"#id_answer","value":"42"} {"type":"select","selector":"select[name=x]","value":"1"} {"type":"check","selector":"input[value=1]"} {"type":"set_file","selector":"input[type=file]","value":"/path/file.pdf"} {"type":"press","value":"Enter"} {"type":"goto","url":"/mod/quiz/attempt.php?attempt=..."} {"type":"wait","value":1000} {"type":"wait_for","selector":".que"} {"type":"scroll","value":800}
Returns the page title, URL, readable text, and all visible form elements (with names/labels/options) plus optional screenshot path. JavaScript confirm/alert dialogs are accepted automatically.
Args: url: page to open (path or full university URL). actions: optional list of actions to perform before reading the page. screenshot: save a PNG screenshot and return its path.
Inputs: url (required), actions, screenshot.
moodle_download_fileA
Download a course file (pluginfile.php / resource) to the local disk.
Args: url: file URL from a course or assignment page. dest: optional destination path; defaults to ~/Downloads/moodle-um/.
Inputs: url (required), dest.
moodle_get_assignmentA
Get one assignment: instructions, attachments, due date and submission state.
Args:
cmid: course-module id (the id= value in /mod/assign/view.php?id=...).
Inputs: cmid (required).
moodle_get_courseA
Get a course's sections, activities, descriptions, dates and file links.
Args: courseid: Moodle course id (from moodle_list_courses).
Inputs: courseid (required).
moodle_get_gradesC
Get the user's grade report for a course.
Args: courseid: Moodle course id.
Inputs: courseid (required).
moodle_get_pageA
Fetch any Moodle page and return it as readable Markdown.
Use this for forums, resources, pages, sections, or anything without a
dedicated tool. The URL may be a path like /mod/forum/view.php?id=123 or a
full https://moodle.umontpellier.fr URL.
Args: url: path or full URL on moodle.umontpellier.fr.
Inputs: url (required).
moodle_get_quizA
Get a quiz's settings, attempts and available actions.
Args:
cmid: course-module id (the id= value in /mod/quiz/view.php?id=...).
Inputs: cmid (required).
moodle_list_assignmentsB
List the assignments ("devoirs") of a course, with due dates and status.
Args: courseid: Moodle course id.
Inputs: courseid (required).
moodle_list_coursesB
List the courses the user is enrolled in.
Args: query: optional case-insensitive filter on course name or shortname.
Inputs: query.
moodle_list_quizzesC
List the quizzes/tests ("tests") of a course.
Args: courseid: Moodle course id.
Inputs: courseid (required).
moodle_loginA
Open a Chromium window so the user can sign in through ENT/CAS.
The window stays open until the user completes the ENT login (identifiant, password, MFA). It then closes automatically and the session is saved. Only needed once, or when the session has fully expired.
Inputs: no named parameters.
moodle_quiz_attemptA
Read one page of an in-progress quiz attempt.
Returns the same question/choice structure as moodle_quiz_start, without creating or submitting anything.
Args: attemptid: attempt id from moodle_quiz_start or the attempt URL. page: zero-based page number (default 0).
Inputs: attemptid (required), page.
moodle_quiz_solveA
Save answers for one quiz page, using question numbers or choice labels.
answers maps a question number (for example "1") to a choice label/value
("b", "4", "True") or a list for multiple-response questions, and/or
a raw Moodle input name to its value. It saves the page; it does not submit
the attempt. Show the questions and proposed answers to the user first.
Args: attemptid: quiz attempt id. answers: question-number/label map, or raw input-name map. page: optional zero-based page number.
Inputs: answers (required), attemptid (required), page.
moodle_quiz_startA
Start or resume a quiz attempt and return its questions and choices.
Creates a real attempt on Moodle (it does not submit it). Starting a quiz can consume one of your allowed attempts, so only call this when the user explicitly asks to start or take the quiz. The result contains the attempt id, page, timer, question text, choices and the exact input names to answer with. If Moodle requires a password, an honour statement or Safe Exam Browser, the result says so instead of starting.
Args: cmid: course-module id of the quiz.
Inputs: cmid (required).
moodle_quiz_submitA
Finish and submit a quiz attempt. IRREVERSIBLE.
Only call with confirm=true after showing the user the answers and getting an explicit "yes".
Args: attemptid: quiz attempt id. page: optional zero-based page number. confirm: must be true.
Inputs: attemptid (required), page, confirm.
moodle_remove_submissionA
Remove your submission for an assignment. IRREVERSIBLE.
Use this to undo an accidental submission. Requires explicit user confirmation (confirm=true).
Args: cmid: course-module id of the assignment. confirm: must be true.
Inputs: cmid (required), confirm.
moodle_statusA
Check whether a saved Moodle session is valid, and who is logged in.
Returns user_id, user_name and site URL. Call this first at the start of a session; if authenticated is false, call moodle_login once.
Inputs: no named parameters.
moodle_submit_assignmentA
Submit an assignment (online text and/or files). IRREVERSIBLE once submitted.
Before calling with confirm=true, show the user exactly what will be submitted and get an explicit "yes". If the assignment has an originality statement checkbox, this tool accepts it on the user's behalf.
Args: cmid: course-module id of the assignment. text: online text to submit (optional). files: local file paths to upload (optional). submit_for_grading: if true, also post the final "Submit assignment" step. If false, stop after saving — but note that assignments without drafts submit as soon as they are saved. confirm: must be true; safety switch against accidental submissions.
Inputs: cmid (required), text, files, confirm, +1 more.
moodle_upcomingB
List upcoming calendar events and deadlines.
Args: limit: maximum number of events (default 30).
Inputs: limit.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 19 tools
Most tools target clearly distinct resource+action pairs (list vs get assignment, quiz start/attempt/solve/submit). The only real overlap is moodle_get_page versus moodle_browser, both generic fallbacks, though the descriptions differentiate static Markdown reading from interactive headless browser actions. Quiz tools are separated by lifecycle stage in a way that is understandable but requires careful reading.
All tools share a consistent moodle_ prefix, but the verb pattern is mixed: mostly verb_noun (list_courses, get_course, submit_assignment) with a noun_verb quiz cluster (quiz_start, quiz_attempt, quiz_solve, quiz_submit) plus verbless names (status, login, upcoming, browser). It remains readable but is not a single predictable convention.
19 tools is slightly on the heavy side but each maps to a distinct part of the Moodle lifecycle: auth, courses, assignments, quizzes, grades, calendar, file download, and fallbacks. The multi-step quiz flow legitimately requires several tools rather than one generic blob. Nothing appears obviously redundant.
The surface covers login/session, courses, assignments (submit and remove submission), quizzes end-to-end, grades, upcoming deadlines, file download, plus a raw page fetcher and headless browser as escape hatches for forums and forms. Minor gaps remain in dedicated forum/messaging or notifications tools, but the generic fallbacks mitigate them.
Maintenance
Related MCP Connectors
A real browser for your agent: screenshots, page checks, Markdown and PDFs.
Control a real browser from AI agents: navigate, click, type, screenshot, read the page.
Web data for agents. Extract web pages, crawl websites, discover URLs, and search the web.
Let your AI agent operate any website through a real, logged-in browser session.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to interact with Moodle LMS via the Moodle REST API, supporting management of courses, users, enrollments, grades, and content.1GPL 3.0
- AlicenseAqualityCmaintenanceEnables AI agents to access a student's EPFL Moodle data—deadlines, course files, assignments, forums, and grades—through read-only tools.12MIT
- AlicenseNot gradedqualityBmaintenanceConnects AI agents to Argentine universities' Moodle virtual classrooms and SIU Guaraní self-service portals, enabling them to read course materials, announcements, grades, and enrollment data. With user confirmation it can also post to forums, submit assignments, answer choices, and send private messages.311 npm1MIT
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to sign into a real Moodle LMS and handle the student workflow end to end: browsing courses, schedules, forums and grades, converting assignments and attachments into markdown, and uploading and submitting work as drafts or finalized submissions. Ships as a single static binary with write actions confirmed by the user and quiz-taking deliberately excluded.29MIT