moodle-mcp
Integrates with Moodle using a personal Moodle mobile web service token to read course data. Provides tools for listing courses, getting course outlines, deadlines, announcements and forum discussions, checking and marking content updates as seen, reading files as text, downloading selected files, and mirroring a course's Moodle file structure locally. The integration is read-only and does not submit, post, or modify anything in Moodle.
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-mcp What do I have to hand in 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-mcp
Let your AI assistant read your Moodle courses. Ask things like:
What do I have to hand in this week? Anything new on Moodle since last time? Summarize the latest slides of INFO-F403. Download the new exercise sheets of the crypto course into my OneDrive course folder.
moodle-mcp is an MCP server: a small program that AI apps (Claude Code,
Claude Desktop, Codex, Cursor, Gemini CLI, Windsurf…) launch in the background to get extra tools. It talks to
Moodle with your own token, through the same API as the official Moodle mobile app, and only reads.
Made for the ULB (uv.ulb.ac.be, the default), but it works with any Moodle site that allows the mobile app.
Install (5 minutes)
1. Install uv (a Python tool installer). Skip this step if you already have it.
macOS / Linux:
curl -LsSf https://astral.sh/uv/install.sh | shWindows (PowerShell):
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
Then open a new terminal.
2. Install moodle-mcp
uv tool install git+https://github.com/Nicolas-Prn/moodle-mcp3. Run the setup
moodle-mcp setupIt asks for your Moodle token (see below), checks it, then offers to register the server in every AI app it finds on your computer. Restart Claude Desktop (or other open apps) afterwards. That's it.
Getting your Moodle token
The token gives read access to your courses, as the Moodle app has. Keep it private.
Option A: Security keys page (easiest)
Log in to Moodle in your browser.
Open https://uv.ulb.ac.be/user/managetoken.php (profile picture → Preferences → Security keys).
Copy the key in the Moodle mobile web service row and paste it into
moodle-mcp setup.
Option B: if there is no such page or row
Log in to Moodle in Chrome, Edge or Firefox.
Open the developer tools (F12, or Cmd+Option+I on a Mac) and select the Network tab.
In the same tab, go to
https://uv.ulb.ac.be/admin/tool/mobile/launch.php?service=moodle_mobile_app&passport=1&urlscheme=moodlemobileClick the
launch.phprequest (it shows as failed, that's expected). Under Response Headers, copy the wholelocationvalue (moodlemobile://token=…) and paste it intomoodle-mcp setup, which decodes it.
For another university, replace uv.ulb.ac.be with your Moodle address and run moodle-mcp setup --url <address>.
Related MCP server: Moodle Student MCP
Using it
Just ask your assistant in plain language, in any conversation and any folder. It picks the right tools:
Tool | What it does |
| Your courses (current ones, or past ones too) |
| Sections, activities, links and files of a course, with file references |
| Upcoming and overdue things to do (assignments, quizzes…) |
| Recent announcements and forum posts, across all courses or one |
| A full forum thread |
| What is new / changed / removed since you last marked a course as seen |
| Marks the current content as seen (the assistant does it once you've dealt with the changes) |
| Reads a file as text so the assistant can explain or summarize it (PDF, Word, PowerPoint, HTML, code…) |
| Saves chosen files into a folder you name, optionally renamed or sorted into sub-folders |
| Saves a whole course, mirroring its Moodle structure ( |
A course can be named by its code (F403, info-h417), part of its name, or its id.
Downloads never overwrite a file that already exists, so annotating or editing downloaded files is safe.
When Moodle has a newer version of a file you already have, the assistant can save it next to yours as
name (2).pdf. check_updates compares Moodle with what it saw last time, not with your local files.
Supported apps
moodle-mcp setup (or moodle-mcp install later) registers the server automatically in:
Claude Code (all projects), Claude Desktop, Codex, Cursor, Gemini CLI and Windsurf.
For any other app that supports local (stdio) MCP servers, add a server with the command that
moodle-mcp status prints, for example:
{ "mcpServers": { "moodle": { "command": "/Users/you/.local/bin/moodle-mcp", "args": ["serve"] } } }Use the full path: desktop apps do not see your terminal's PATH.
Not supported yet: ChatGPT and the claude.ai website or mobile app. They can only reach MCP servers hosted on the internet, while this one runs on your computer (which is also why your token never leaves it).
Commands
moodle-mcp setup # save or replace your token, then register in your AI apps
moodle-mcp status # check the token and see which apps were detected
moodle-mcp install [apps...] # register again (e.g. after installing a new app): claude-code, claude-desktop, codex, cursor, gemini, windsurf
moodle-mcp uninstall # unregister from the apps
uv tool upgrade moodle-mcp # update to the latest versionTo remove everything: moodle-mcp uninstall, uv tool uninstall moodle-mcp, then delete ~/.config/moodle-mcp.
Privacy and security
The token is stored only on your computer, in
~/.config/moodle-mcp/config.json(readable by you only). App configurations contain just the command, never the token. You can also provide it through theMOODLE_TOKEN(andMOODLE_URL) environment variables instead.The server never changes anything on Moodle: no submissions, no posts, no messages.
The token is only ever sent to your Moodle site, and is removed from error messages.
Forum posts, descriptions and files are written by other people. The server tells the assistant to treat them as information, not as instructions.
To revoke access, use Reset on the Security keys page, then run
moodle-mcp setup --new-token.
Troubleshooting
The assistant doesn't see the Moodle tools: restart the app, then run
moodle-mcp status. In Claude Code,/mcplists connected servers."invalidtoken" or "No Moodle token configured": run
moodle-mcp setup --new-token.A big
mirror_coursetimes out: some apps stop waiting after a minute or two. Downloads already finished are kept, so asking again resumes where it stopped.
Development
git clone https://github.com/Nicolas-Prn/moodle-mcp && cd moodle-mcp
uv sync
uv run pytest
uv run moodle-mcp status
npx @modelcontextprotocol/inspector uv run moodle-mcp serve # try the tools in a web UICode layout (src/moodle_mcp/): server.py defines the MCP tools, courses.py the course and file model
(including file references), client.py the Moodle Web Service client, updates.py change detection,
downloads.py saving files, text.py text extraction, config.py settings and cli.py the commands.
License: MIT.
Available Tools
10 toolscheck_updatesARead-only
What is new, changed or removed on Moodle since the courses were last marked as seen.
The first call for a course records a baseline (everything currently there counts as seen).
Inputs: course.
download_filesAIdempotent
Download course files into a local folder. Existing files are never overwritten.
- files: refs from get_course_outline / get_announcements / check_updates (or Moodle pluginfile URLs).
- dest_dir: absolute local folder (or ~/...), created if needed.
- save_as: optional {ref: "relative/path/name.pdf"} to choose where each file goes inside dest_dir;
by default a file keeps its Moodle name (and its sub-folder, for files inside folder modules).
- on_conflict: "skip" (default) leaves an existing file alone; "rename" saves the new one as "name (2).ext".
Inputs: files (required), course (required), dest_dir (required), save_as, +1 more.
get_announcementsARead-only
Recent forum discussions (announcements and other course forums), newest first, with attachment refs.
Messages are shortened; use read_discussion for a full thread.
Inputs: days, limit, course.
get_course_outlineARead-only
Sections, activities, links and files of a course, with the file refs used by read_file/download_files.
Modules with many files are truncated; pass module_id to list every file of one module.
Inputs: course (required), module_id.
get_deadlinesCRead-only
Upcoming deadlines and actions to do (assignments, quizzes...), including overdue ones from the last 2 weeks.
Inputs: days, course.
list_coursesARead-only
List the courses the user is enrolled in (id, code, name). Past courses are hidden unless include_past.
Inputs: include_past.
mark_updates_seenAIdempotent
Record the current Moodle content as seen, so check_updates stops reporting it. Only touches local state.
Inputs: course.
mirror_courseAIdempotent
Download every file of a course into dest_dir, mirroring Moodle's structure. Never overwrites.
Layout: `<NN section>/<file>` for single-file resources, `<NN section>/<activity>/<file>` otherwise
(folders, multi-file resources, assignment statements), `Forum: <name>/<discussion>/` for attachments.
Use dry_run=True first on large courses to see what would be downloaded and how much.
Inputs: course (required), dest_dir (required), dry_run, include_forums.
read_discussionBRead-only
Every post of a forum discussion (ids come from get_announcements).
Inputs: discussion_id (required).
read_fileARead-only
Text content of a course file (PDF, Word, PowerPoint, HTML, code, plain text).
`file` is a ref from get_course_outline/get_announcements (or a Moodle pluginfile URL).
`pages` selects PDF pages or PowerPoint slides, e.g. "1-5" or "2,7-9".
Inputs: file (required), course (required), pages, max_chars.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 10 tools
Tools are mostly distinct, but get_announcements and check_updates both surface new course content, and download_files and mirror_course both download files; descriptions clarify boundaries, but an agent could occasionally misselect.
All tool names use a consistent snake_case verb_noun pattern (get_, list_, read_, check_, mark_, download_, mirror_), making the set predictable and easy to scan.
10 tools is well-scoped for a Moodle course-access client, with no redundant or trivial tools; each covers a distinct capability.
The surface covers core read workflows (courses, outline, deadlines, announcements, discussions, files, updates, mirroring), but lacks search, grades, or assignment interaction, which are minor gaps for a read-only client.
Maintenance
Related MCP Connectors
Read-only access to Epivo's live course catalogue for AI agents.
Connect AI assistants to Edusign attendance, courses, learners, documents, and API docs via OAuth.
Secure AI access to OpenOak tasks, notes, and Kanban boards.
Search university course materials, your flashcards, quizzes, streak and quota. All tools read-only.
Related MCP Servers
- AlicenseAqualityCmaintenanceEnables AI assistants to interact with Moodle via web services, allowing tasks like listing courses, assignments, events, and downloading files.1052 PyPI4MIT
- AlicenseAqualityCmaintenanceEnables read-only querying of Moodle as a student, including courses, assignments, grades, forums, and files, using a personal web services token.1137 npmMIT
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to read your Moodle courses, list materials, quizzes, and search content to plan exam preparation through natural language.1-
- AlicenseAqualityBmaintenanceEnables AI apps to read a student's Moodle courses, upcoming and overdue due dates, assignment submission statuses, course grades, gradebook items and announcements. It is strictly read only, so it can never submit, edit or delete anything.17186 npmMIT