Skip to main content
Glama

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 | sh

  • Windows (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-mcp

3. Run the setup

moodle-mcp setup

It 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)

  1. Log in to Moodle in your browser.

  2. Open https://uv.ulb.ac.be/user/managetoken.php (profile picture → Preferences → Security keys).

  3. 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

  1. Log in to Moodle in Chrome, Edge or Firefox.

  2. Open the developer tools (F12, or Cmd+Option+I on a Mac) and select the Network tab.

  3. In the same tab, go to https://uv.ulb.ac.be/admin/tool/mobile/launch.php?service=moodle_mobile_app&passport=1&urlscheme=moodlemobile

  4. Click the launch.php request (it shows as failed, that's expected). Under Response Headers, copy the whole location value (moodlemobile://token=…) and paste it into moodle-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

list_courses

Your courses (current ones, or past ones too)

get_course_outline

Sections, activities, links and files of a course, with file references

get_deadlines

Upcoming and overdue things to do (assignments, quizzes…)

get_announcements

Recent announcements and forum posts, across all courses or one

read_discussion

A full forum thread

check_updates

What is new / changed / removed since you last marked a course as seen

mark_updates_seen

Marks the current content as seen (the assistant does it once you've dealt with the changes)

read_file

Reads a file as text so the assistant can explain or summarize it (PDF, Word, PowerPoint, HTML, code…)

download_files

Saves chosen files into a folder you name, optionally renamed or sorted into sub-folders

mirror_course

Saves a whole course, mirroring its Moodle structure (dry_run shows the size first)

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 version

To 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 the MOODLE_TOKEN (and MOODLE_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, /mcp lists connected servers.

  • "invalidtoken" or "No Moodle token configured": run moodle-mcp setup --new-token.

  • A big mirror_course times 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 UI

Code 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 tools
check_updatesA
Read-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_filesA
Idempotent

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_announcementsA
Read-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_outlineA
Read-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_deadlinesC
Read-only

Upcoming deadlines and actions to do (assignments, quizzes...), including overdue ones from the last 2 weeks.

Inputs: days, course.

list_coursesA
Read-only

List the courses the user is enrolled in (id, code, name). Past courses are hidden unless include_past.

Inputs: include_past.

mark_updates_seenA
Idempotent

Record the current Moodle content as seen, so check_updates stops reporting it. Only touches local state.

Inputs: course.

mirror_courseA
Idempotent

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_discussionB
Read-only

Every post of a forum discussion (ids come from get_announcements).

Inputs: discussion_id (required).

read_fileA
Read-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

    A3.7/5.0

    Scored across 10 tools

    Disambiguation4/5

    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.

    Naming Consistency5/5

    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.

    Tool Count5/5

    10 tools is well-scoped for a Moodle course-access client, with no redundant or trivial tools; each covers a distinct capability.

    Completeness4/5

    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

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers