Skip to main content

Table of contents


What it does

Moodle is the learning platform used by thousands of universities and schools. MCP-Moodle connects it to any Model Context Protocol client — Claude Desktop, Gemini CLI, ChatGPT desktop, Cursor, VS Code, and more — so an AI can:

  • Read: list courses, inspect course contents, see enrolled students, quizzes, grades, quiz results, activity completion, notifications, and competencies.
  • Build: create courses, users, categories, groups, enrolments, and actual content: pages, books, labels, URLs, forums, assignments, quizzes, and six quiz question types — or a whole course from one JSON outline with build_course.
  • Protect: back any course up to a real .mbz file on your disk and restore it later.
  • Safely: every write operation is off by default and only enabled with an explicit flag.

How it works (two pieces)

Moodle's built-in Web Services API can create courses and users, but it has no core function to create an activity (a Page, Book, Quiz…). So this project ships two parts that work together:

┌────────────────┐     MCP tools      ┌──────────────────┐    REST + token    ┌─────────────────┐
│  AI client     │ ◄────────────────► │   moodle-mcp     │ ◄────────────────► │   Moodle site   │
│ (Claude, etc.) │                    │  (Python server) │                    │  + local plugin │
└────────────────┘                    └──────────────────┘                    └─────────────────┘
Piece Path Role
Moodle plugin local/mcpbridge/ Adds the activity-creation web service functions Moodle core is missing, using Moodle's official add_moduleinfo() helper, so it's upgrade-safe (no raw DB writes).
MCP server moodle-mcp/ Wraps Moodle's read/write API, core and the plugin's new functions, as typed MCP tools for an AI client.

Compatibility & authentication

Works with any Moodle 4.2 or newer: self-hosted or institutional. There is nothing site-specific in the code.

Authentication uses a web service token, not a password. The MCP server never sends a username or password, it sends a token (a long random string) that an admin generates in Moodle. The token is tied to one user account and one service (a fixed list of allowed functions), and it can only do what that user's capabilities permit.

Because the token is a separate auth channel, it works regardless of how your users log in: Manual, LDAP, SAML/SSO (Shibboleth, ADFS), Google/Microsoft OAuth, CAS, etc. all make no difference. A university Moodle behind SSO works exactly the same: an admin just creates a token.

What you need

Requirement Why
Admin access (yours or an admin's) To install the plugin, enable web services, and create the token
Web services + REST enabled The authentication mechanism
A user account for the token The token inherits that user's capabilities

Caveats (be honest with yourself here)

  • You must be able to install a plugin: full control on self-hosted/institutional Moodle; a locked-down managed host may require the admin to do it.
  • Some managed clouds (e.g. MoodleCloud free tier) block custom plugins and full web services, activity creation won't work there.
  • Without the plugin, the MCP server's core tools (list/create courses, users, enrolment, grades) still work with a token; you only lose the plugin's activity-creation tools.

Features

  • 88 tools: reads, a student-assistant layer (deadlines, dashboards, task analysis), core writes, activity creation, quiz results, completion tracking, backup/restore, and a one-call course builder
  • Six quiz question types: multiple choice, true/false, short answer, essay, numerical (with tolerances), matching
  • Read/write split: read tools always on; write tools gated behind MOODLE_ALLOW_WRITE=true
  • Upgrade-safe plugin: uses Moodle's own add_moduleinfo(), never touches module tables directly
  • Clean error handling: detects Moodle's JSON-error-on-HTTP-200 quirk and surfaces readable messages
  • Token never logged: config from environment variables only
  • One token for everything: read, core writes, and the plugin functions in a single service

Quick start

1. Install the plugin (local_mcpbridge)

Copy the local/mcpbridge/ folder into your Moodle so it lives at {moodle}/local/mcpbridge/, then visit Site administration as an admin, Moodle will detect it and prompt you to upgrade. Confirm, and you're done.

2. Enable web services & generate a token

In Moodle as an admin:

  1. Enable web services: Site administration → Advanced features → tick Enable web services.
  2. Enable REST: Server → Web services → Manage protocols → enable REST protocol.
  3. Build the service: Server → Web services → External services. Use the ready-made MCP Bridge Service the plugin created, then click Functions and add the core read/write functions you want (list in Tool reference).
  4. Authorise a user for the service and make sure they have the needed capabilities (notably moodle/course:manageactivities in the target courses).
  5. Create a token: Server → Web services → Manage tokens → pick the user and the MCP Bridge Service. Copy it.

Verify before you wire up the AI: run the test script to confirm the plugin and token work end to end.

3. Run the MCP server

Easiest — from PyPI:

pip install moodle-mcp-bridge
MOODLE_URL=https://moodle.example.edu MOODLE_TOKEN=your_token moodle-mcp-bridge

Or from a checkout:

cd moodle-mcp
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env        # then edit .env with your URL + token
python server.py
Env var Meaning
MOODLE_URL Base URL, no trailing slash
MOODLE_TOKEN The token from step 2 (never logged)
MOODLE_ALLOW_WRITE true to enable write tools; anything else = read-only

4. Connect Claude Desktop

Add to claude_desktop_config.json (pip install):

{
  "mcpServers": {
    "moodle": {
      "command": "moodle-mcp-bridge",
      "env": {
        "MOODLE_URL": "https://moodle.example.edu",
        "MOODLE_TOKEN": "your_token_here",
        "MOODLE_ALLOW_WRITE": "true"
      }
    }
  }
}

Running from a checkout instead? Use "command": "/absolute/path/to/moodle-mcp/.venv/bin/python" with "args": ["/absolute/path/to/moodle-mcp/server.py"].

Not just Claude: any MCP client works

MCP is an open protocol, so the same server works with Gemini CLI, ChatGPT desktop (developer mode), Cursor, Windsurf, VS Code Copilot agent mode, Cline, LM Studio, and anything else that speaks MCP. The config is nearly identical everywhere — the moodle-mcp-bridge command plus the three env vars. Example for Gemini CLI (~/.gemini/settings.json):

{
  "mcpServers": {
    "moodle": {
      "command": "moodle-mcp-bridge",
      "env": {
        "MOODLE_URL": "https://moodle.example.edu",
        "MOODLE_TOKEN": "your_token_here",
        "MOODLE_ALLOW_WRITE": "true"
      }
    }
  }
}

Tool-use quality depends on the model: with 88 tools, stronger models chain calls (create course → add section → add quiz) more reliably than small local ones.

Restart Claude Desktop and the Moodle tools appear.


Tool reference

88 tools, grouped by what they touch. Access shows whether a tool is always available (read) or needs MOODLE_ALLOW_WRITE=true (write). Tools backed by the plugin are marked plugin; everything else uses Moodle core functions.

Courses & structure

Tool What it does Access
list_courses / search_courses List all courses / search by field read
get_course_content Everything inside a course (sections, activities, files) read
get_my_courses Courses the current user is enrolled in read
create_course / update_course Create or update a course write
create_category / delete_category Manage course categories write
create_section / delete_section plugin Manage course sections write
delete_courses Delete courses (irreversible) write
import_course Copy content from one course into another write

Course builder & backup

Tool What it does Access
build_course Build a whole course — sections, activities, quizzes with questions — from one JSON outline, with a per-item build log write
backup_course plugin Full course backup, saved as a real .mbz on your local disk write
restore_course plugin Restore a .mbz file into a brand-new course write

Content & activities

Tool What it does Access
create_page / update_page plugin HTML page activities write
create_book plugin Book with its first chapter write
create_label plugin Inline text/label on the course page write
create_url plugin External link resource write
create_forum / create_choice plugin Forum / poll activities write
create_assignment plugin Assignment with due date and grade write
update_activity / move_activity / delete_activity plugin Rename, hide, move or delete any activity write
upload_file / download_file Transfer files to/from Moodle write

Quizzes & questions

Tool What it does Access
list_quizzes Quizzes in given courses read
get_quiz_results A user's attempts + best grade for a quiz read
get_quiz_attempt_review Finished attempt, question by question read
get_quiz_report Whole-class analytics: grade distribution, average, pass rate, non-attempters, per-question facility index read
create_quiz plugin Quiz container with timing/grade settings write
add_quiz_question plugin Multiple-choice question write
add_truefalse_question plugin True/false question write
add_shortanswer_question plugin Short-answer question write
add_essay_question plugin Essay (manually graded) question write
add_numerical_question plugin Numerical question with tolerances write
add_matching_question plugin Matching-pairs question write

Users, enrolment & groups

Tool What it does Access
get_enrolled_users Who is enrolled in a course read
create_user / update_user / delete_users Manage user accounts write
enrol_user / enrol_users / unenrol_user Manual enrolment (single or bulk) write
assign_role / unassign_role Role assignments write
create_group / add_group_members Course groups write
create_cohort / add_cohort_members Site-wide cohorts write

Communication

Tool What it does Access
get_course_announcements News-forum announcements read
get_notifications Unread count + recent notifications read
send_message Direct message to a user write
start_forum_discussion / reply_forum_post Post in forums write

Assignments & grading

Tool What it does Access
get_assignments / get_assignment_status Assignments and submission/grading state read
get_upcoming_deadlines / get_overdue_assignments Deadline tracking read
analyze_assignment / extract_assignment_requirements Requirements + context for one assignment read
find_relevant_materials / decompose_task / create_implementation_plan Scaffolds for working on an assignment read
grade_assignment Save a grade with feedback text to the gradebook write

Grades, progress & completion

Tool What it does Access
get_grades / get_user_grades Grade overview or per-course detail read
get_course_progress / get_course_health Progress and at-a-glance course health read
get_activity_completion Which activities a user completed read
get_course_completion_status Whole-course completion criteria read
list_course_competencies / get_learning_plans Competency framework data read
mark_activity_complete Tick your own manual completion box write
override_activity_completion Teacher: set a student's completion state write

Planning & insights

Tool What it does Access
get_upcoming_events Calendar events read
get_recent_activity Updates across courses since a time read
get_study_load Assignment distribution by week read
get_actionable_tasks Prioritized to-do list by urgency read
semester_dashboard / daily_briefing / weekly_review Combined snapshots read

Search & assist

Tool What it does Access
server_info Health check: server version, write-mode, whether the plugin is installed (start here) read
verify_connection Site info + available functions read
search_course_materials Search across course materials read
ask_moodle Route a natural-language question to the right data read

Quizzes: the six add_*_question tools use Moodle's Question Bank API (multiple choice, true/false, short answer, essay, numerical, matching). That API is version-sensitive — tested on Moodle 5.0; test on your version first.

Missing function? A tool whose web service function isn't in the token's service returns a clean "access control exception" — add the function to MCP Bridge Service and retry. Installing plugin 1.6.0+ registers the complete list automatically.


Testing from the shell

Confirm the plugin + token work before wiring up the AI:

cd moodle-mcp

# Read-only checks (site info + course list):
MOODLE_URL=https://moodle.example.edu MOODLE_TOKEN=xxxx ./test_rest.sh

# Full write test, creates a page, label, url, book, quiz + question in COURSEID:
MOODLE_URL=https://moodle.example.edu MOODLE_TOKEN=xxxx COURSEID=2 ./test_rest.sh --write

A successful create returns e.g. {"cmid": 47, "instanceid": 12}. A Moodle error (still HTTP 200) returns a JSON object with an exception field, which the server surfaces as a clean message.


Safety & write mode

For a full hardening checklist (dedicated service account, scoped role, HTTPS, token expiry), see SECURITY.md.

  • Writes hit live data. Every write tool creates or changes real records. There is no dry-run.
  • Writes are gated. If MOODLE_ALLOW_WRITE is not exactly true, the server registers read tools only: writes cannot be exposed by accident.
  • The token is the blast radius. Bind it to a dedicated service account with only the capabilities and courses you need. A site-admin token lets the AI do anything an admin can.
  • The token is never logged: read from the environment, sent only to Moodle over HTTPS.
  • Start read-only. Turn on write mode deliberately, on a test course, and confirm the shell test passes first.

Extending it

Adding a new capability (e.g. create_assignment, create_forum) is copy-paste-modify. Each plugin function follows the same three-method shape, see create_page.php as the template, and CONTRIBUTING.md for the full recipe.


Contributing

Contributions are very welcome, this is built to be extended!

  1. Fork the repo (top-right Fork button).
  2. Create a branch: git checkout -b feature/my-thing.
  3. Make your change and test it (php -l, py_compile, ideally against a real Moodle).
  4. Push and open a Pull Request to main.

See CONTRIBUTING.md for the full workflow, coding standards, and the pattern for adding a new function. Please also read our Code of Conduct. Found a bug or want a feature? Open an issue.


License

MIT, free to use, modify, and distribute.

Built for educators, admins, and anyone who wants to talk to Moodle instead of clicking through it.

Metadata

Release files for moodle-mcp-bridge 1.7.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for moodle-mcp-bridge 1.7.0
File Size Uploaded
moodle_mcp_bridge-1.7.0.tar.gz 31.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for moodle-mcp-bridge 1.7.0
File Interpreter ABI Platform
moodle_mcp_bridge-1.7.0-py3-none-any.whl Python 3 none any Details

Total release size: 63.5 kB

Release files / moodle_mcp_bridge-1.7.0.tar.gz

Download URL moodle_mcp_bridge-1.7.0.tar.gz
Size 31.0 kB
Tags Source
SHA-256 checksum
How to use checksums
1a5f897538214bfd9260fab42dfa82727a60e570774a4d56056452b4eb5717e3
BLAKE2b-256 checksum
How to use checksums
f3502a4059f95e04d42cbfedd5fe37a29ba2a32cab32f379fac5f76e7c0ba5dc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 24, 2026.

Transparency log

Release files / moodle_mcp_bridge-1.7.0-py3-none-any.whl

Download URL moodle_mcp_bridge-1.7.0-py3-none-any.whl
Size 32.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4b3abb22772a1664b20b374b897c2cf2887aa514ff0e39d1cb71f782581ed751
BLAKE2b-256 checksum
How to use checksums
b470f31e30b6cc91c589d29487228085bc860331085f53e8ff7c7a86f28c5110
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 24, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.7.0 This release

2 release files

1.6.2

2 release files

1.6.1

2 release files

1.6.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page