Moodle-MCP
Zero-dependency MCP server for the Moodle Web Service API — read-only course, assignment, quiz, deadline and file tools for Claude, Cursor and any MCP client. Actively maintained · v1.4.0 · 10 tools · docs in 10 languages.
Install / Use
claude mcp add Faixiang -- npx -y github:Faixiang/Moodle-MCPIf the server publishes to npm under a different name, use that package instead — check the repo README.
MCP Server
Model Context Protocol server
Quality Score
Category
AI & Machine LearningSupported Platforms
Our assessment of Moodle-MCP
Moodle-MCP scores 84/100 on our quality scale, 606th of 939 AI & Machine Learning skills we index.
Its MCP Server is 14 KB long, well organised into 27 sections with 6 code examples: a thorough specification that gives an agent plenty to work with.
It has 10 GitHub stars, so there is little community track record yet; judge it on its content.
Maintenance, license and trust
- The repository was last updated today, so Moodle-MCP is actively maintained.
- It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
- Its trust signals score 97/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.
Safety scan
No issues foundOur scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands.
Automated pattern scan on 2026-11-02. It catches known dangerous patterns, not every risk — read a skill before letting an agent act on it.
Moodle-MCP compared with similar skills
All 4 of these similar skills score higher than Moodle-MCP; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| Moodle-MCP (this skill)by Faixiang | 84 | 10 | today | MCP Server |
| claude-memby thedotmack | 100 | 109.6k | today | CLAUDE.md |
| Agent-Reachby Panniantong | 100 | 107.7k | 1d ago | CLAUDE.md |
| Understand-Anythingby Egonex-AI | 100 | 89.7k | 7d ago | CLAUDE.md |
| headroomby headroomlabs-ai | 100 | 78.6k | 1d ago | CLAUDE.md |
Frequently asked questions
- How do I install Moodle-MCP?
- Run
claude mcp add Faixiang -- npx -y github:Faixiang/Moodle-MCP. The install tabs above show the steps for each supported agent. - Which AI agents does Moodle-MCP work with?
- It is written for Claude Code, Claude Desktop and Cursor, as a MCP Server file. Other agents that read the same format can often use it too.
- Is Moodle-MCP safe to use?
- Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. It is MIT-licensed and scores 97/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
- Is Moodle-MCP still maintained?
- The repository was last updated today, so Moodle-MCP is actively maintained.
Skill content
View source on GitHubMoodle-MCP
Your Moodle, as tools an AI agent can actually use
Read assignments, deadlines and course files straight out of the Moodle Web Service API — no browser, no scraping, no clicking.
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-yellow.svg" alt="MIT License"></a> <img src="https://img.shields.io/badge/python-3.8%2B-3772FF?logo=python&logoColor=white" alt="Python 3.8+"> <img src="https://img.shields.io/badge/MCP-2024--11--05-8A2BE2" alt="MCP 2024-11-05"> <img src="https://img.shields.io/badge/Moodle-3.x%20%7C%204.x-F98012?logo=moodle&logoColor=white" alt="Moodle 3.x / 4.x"> <img src="https://img.shields.io/badge/dependencies-0-success" alt="Zero dependencies"> <a href="https://github.com/Faixiang/Moodle-MCP/stargazers"><img src="https://img.shields.io/github/stars/Faixiang/Moodle-MCP?style=social" alt="GitHub stars"></a> <img src="https://img.shields.io/badge/version-1.4.0-1f6feb" alt="Version 1.4.0"> <img src="https://img.shields.io/badge/status-actively%20maintained-brightgreen" alt="Actively maintained">
<p> <b>English</b> · <a href="README.zh-CN.md">简体中文</a> · <a href="README.zh-TW.md">繁體中文</a> · <a href="README.ja.md">日本語</a> · <a href="README.ko.md">한국어</a> · <a href="README.es.md">Español</a> · <a href="README.fr.md">Français</a> · <a href="README.de.md">Deutsch</a> · <a href="README.pt-BR.md">Português</a> · <a href="README.ru.md">Русский</a> </p> </div>Companion skill — moodle-course-watch This server is the plumbing; the skill is the workflow on top of it. It diffs new coursework, mirrors missing week folders, lists what is still unsubmitted, and walks through the downloaded files with graded key points. It is mounted as a git submodule in this repository at
skill/moodle-course-watch/(clone with--recurse-submodules), and is also a standalone repo for anyone who wants only the skill.
Actively maintained. Latest release v1.3.0 (2026-10-27): quizzes are no longer a blind spot —
moodle_quiz_statusreads real attempt state and scores. Full changelog at the end of this file.
Preview 🖥️
<img src="docs/preview.svg" alt="Example MCP session" width="100%">Why this exists 🎯
Moodle powers a large share of universities and colleges worldwide, yet it had no general-purpose MCP server. Scraping it with a headless browser is slow, brittle and tends to trip WAFs — while Moodle itself already ships a stable, documented REST API.
This project is the missing wrapper: one zero-dependency Python file, ten read-only tools, working against any Moodle 3.x/4.x site with Web Services enabled.
No pip install. No node. No browser. Just python server.py.
Features ✨
Data retrieval
- Deadline-aware — assignments split into due soon, overdue and no pressure, with days remaining computed for you
- Weekly digest — recent additions + deadlines + overdue in a single call, formatted for direct reading
- Course files — section structure and file lists with direct download URLs and modified times, metadata only, nothing downloaded
- Diagnostics built in —
moodle_site_inforeports site version, account identity and which functions your token may actually call
Engineering
- Zero dependencies — Python standard library only (
urllib,json,ssl), so nothing pollutes your runtime - Single file — copy
server.pyanywhere; no package layout, no build step - stdio JSON-RPC 2.0 — drops into Claude Desktop, Cursor, Marvis or any MCP-compatible client
- WAF-friendly — serialised calls with a 150 ms gap, because hammering Moodle gets you
502 - Read-only by design — no submit, enrol, edit or delete endpoint exists in the code
Tools 🧰
| Tool | What it does | Arguments |
|---|---|---|
| moodle_setup_guide | Step-by-step guide for getting a Moodle web-service token and wiring it into this server (browser UI path, SSO caveat, config.json and environment-variable options). Needs no token, so it always works. Call it on first setup or after a TOKEN_MISSING error. | — |
| moodle_config_status | Self-check of the local configuration: config.json path, existence and parse result, MOODLE_URL / MOODLE_TOKEN environment variables, effective URL, where the token came from and its length. The token itself is masked to the first 4 characters. Needs no token. | — |
| moodle_site_info | Validate the token, return site name, Moodle version, current user and the list of web-service functions the account may call (diagnostics). | — |
| moodle_list_courses | List every enrolled course with id, shortname and fullname. | — |
| moodle_recent_updates | Content added or updated in the last N days (assignments, files, announcements), newest first. | days (default 7), course_ids |
| moodle_pending_assignments | Unsubmitted assignments, split into due soon / overdue / no pressure, with deadline and days remaining. | ahead_days (default 14), course_ids |
| moodle_quiz_status | Per-quiz attempt state straight from mod_quiz_get_user_attempts: submitted / in progress / never started, with best score, open–close window, time limit and a window closed flag. | course_ids, only_pending |
| moodle_course_files | Section structure and file list for one course, including direct download URLs and modified times. Metadata only — nothing is downloaded. | course_id |
| moodle_download_week | Download one week's files (slides + assignment attachments) into a local folder named after the section — Week N when the section title carries a week number, otherwise the section's own title (Online Judge Questions, Project Submission). Creates folders, verifies sizes, skips files already present. Omit dest_root to get the list only. | course_id, week (e.g. 6 or "Week 6", or all), dest_root |
| moodle_weekly_digest | The one-shot summary: recent additions + due-soon + overdue + counts. Best starting point. | days (default 7), ahead_days (default 14) |
moodle_download_weekonly writes to your local disk — it never submits anything to Moodle. File URLs returned by the read tools already carry your token, so they download as-is: treat them as secrets and keep them out of logs, screenshots and public repos.
Requirements 📦
| Component | Notes |
|---|---|
| Python | 3.8+ (standard library only) |
| MCP protocol | 2024-11-05 |
| Moodle | 3.x / 4.x with Web Services + REST protocol enabled |
| Account | Holds the webservice/rest:use capability |
| Verified against | Moodle 4.3.6, full 435-function grant |
Quick start 🚀
① Get a token
Moodle needs a personal access token. Pick whichever works for your site:
A. Web UI (recommended, works with SSO accounts)
- Log in to your Moodle site
- Avatar → Preferences → Account → Security → Manage access keys
- Create, name it
Moodle-MCP, service = Moodle mobile web service - Copy the token
B. Mobile-app service via script (only if your site has local passwords)
python get_token.py
Walks through /login/token.php with the moodle_mobile_app service and validates the result. Password input is hidden and never logged. If your account is SSO-only this returns invalidlogin — use method A instead.
C. Environment variables
MOODLE_URL=https://moodle.your-school.edu
MOODLE_TOKEN=your_token_here
② Configure
Create config.json next to server.py (or copy config.example.json):
{
"url": "https://moodle.your-school.edu",
"token": "your_token_here"
}
Environment variables take precedence over the file.
③ Register the server
Claude Desktop / Cursor (mcp.json):
{
"mcpServers": {
"moodle": {
"command": "python",
"args": ["/absolute/path/to/Moodle-MCP/server.py"]
}
}
}
Use an absolute path to server.py. If you have several Python installs, point command at the full interpreter path.
④ Verify
Ask your client to call moodle_site_info. A working setup returns the site name, Moodle version and your user record. If it fails, jump to Troubleshooting.
Configuration reference ⚙️
| Key | Type | Required | Description |
|---|---|---|---|
| url / MOODLE_URL | string | yes | Base URL of your Moodle site, no trailing path |
| token / MOODLE_TOKEN | string | yes | Personal access token from Manage access keys |
| config.json | file | optional | Read from the directory containing server.py |
Precedence: environment variables → config.json → error.
Usage examples 💬
"What do I still owe this week?"
The agent calls moodle_weekly_digest and gets back a ready-to-read brief:
## Due in the next 7 days, not submitted
| CIS225 Data Structures | A10021 Crosswords | 2026-10-29 23:59 | 3 days |
| CIS225 Data Structures | A10022 Cow Jogging | 2026-10-29 23:59 | 3 days |
## Overdue
| CIS225 Data Structures | A10009 Dancing | 2026-10-11 23:59 | 15 days late |
## Totals
Submitted/graded: 51 | Outstanding: 25 (due soon 4, overdue 14, other 7)
Other prompts that work well:
| Prompt | Tool it lands on |
|---|---|
| "What new material appeared in CIS225 this week?" | moodle_recent_updates |
| "List the files in GER405, don't download anything" | moodle_course_files |
| "Which of my courses have nothing overdue?" | moodle_pending_assignments |
| "Is my token still valid?" | moodle_site_info |
Troubleshooting 🤔
<details> <summary><b><code>invalidlogin</code> when running get_token.py</b></summary>Your account authenticates through SSO/OIDC only, so /login/token.php has no local password to check. Use method A — create the token in Manage access keys instead.
The site's WAF is rate-limiting you. This server already serialises calls and pauses 150 ms between them; if you still hit it, wait a few minutes and retry, and avoid firing several tools in parallel.
</details> <details> <summary><b>Tools return empty lists</b></summary>Check three things: Web Services and the REST protocol are enabled site-wide; the account has webservice/rest:use; and any course_ids filter you passed is correct. Run moodle_site_info first — if the function list is short, the admin restricted your grant to the mobile subset.
Expected. turnitintooltwo is its own module without mod_assign semantics and exposes no usable deadline field, so it is the one remaining blind spot. Check those in the web UI.
By design. Quizzes live in mod_quiz, not mod_assign, so they have their own tool: moodle_quiz_status returns attempt state, best score and the open–close window for every quiz.
The teacher never configured a due date for that assignment. There is nothing to compute; the item still appears so you don't forget it exists.
</details> <details> <summary><b>Garbled characters in Windows terminals</b></summary>Output is UTF-8. In legacy consoles run chcp 65001 first, or use Windows Terminal.
Security notes 🔒
- The token is a credential. Store it in
config.jsonor an environment variable, never in a repo..gitignorealready excludesconfig.jsonandget_token.log. get_token.pynever logs the password — only its length — and reads it withgetpass.- Every tool is read-only by design, so a leaked token cannot modify or delete coursework through this server. Revoke it from *Manage access ke
Truncated for display — read the full file on GitHub.
Related Skills
claude-mem
109.6kPersistent Context Across Sessions for Every Agent – Captures everything your agent does during sessions, compresses it with AI, and injects relevant context back into future sessions. Works with Claude Code, OpenClaw, Codex, Gemini, Hermes, Copilot, OpenCode + More
Agent-Reach
107.7kGive your AI agent eyes to see the entire internet. Read & search Twitter, Reddit, YouTube, GitHub, Bilibili, XiaoHongShu — one CLI, zero API fees.
Understand-Anything
89.7kGraphs that teach > graphs that impress. Turn any code into an interactive knowledge graph you can explore, search, and ask questions about. Works with Claude Code, Codex, Cursor, Copilot, Gemini CLI, and more.
headroom
78.6kCompress tool outputs, logs, files, and RAG chunks before they reach the LLM. 20% fewer tokens for coding agents, 60-95% fewer tokens for JSON, same answers. Library, proxy, MCP server.
Languages
Trust signals
From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.
