moodle-mcp
Connects to any Moodle site through the official mobile web service (or browser-session mode where unavailable) to view enrolled courses, sections, activities and files; read course pages, files (PDF, Office, zip, HTML, text) and grades with feedback; list deadlines, assignments, quizzes and forum discussions; review quiz attempts; and upload or submit assignment files and text with explicit confirmation.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
moodle-mcp
MCP server that connects AI assistants to any Moodle site through the official Moodle mobile web service, with a real Chromium browser for sign-in, quiz taking and sites where that service is unavailable. No site-specific setup: give it the site's URL and sign in.
Ask things like "what's due this week?", "summarize the lecture PDF in my history course", "how am I doing in maths?" or "upload essay.docx to the Essay assignment".
Install
Requires Node.js 22 or newer. Install v1.2.1:
npm install -g https://github.com/college-things/moodle-mcp/releases/download/v1.2.1/moodle-mcp-1.2.1.tgz
moodle-mcp browser-installOr install from source:
git clone https://github.com/college-things/moodle-mcp.git
cd moodle-mcp
npm install
npm run build
npm install -g .
moodle-mcp browser-installClaude Desktop
Download moodle-mcp-1.2.1.mcpb from the v1.2.1 release and open it. For browser control, run moodle-mcp browser-install once using the global install above. You can also build a bundle from source with sh scripts/pack-release.sh.
Claude Code
claude mcp add moodle -- moodle-mcpThe repository is also a Claude Code plugin. After cloning it and running npm install, try it with claude --plugin-dir /path/to/moodle-mcp.
Codex
After the install above, register the local server:
codex mcp add moodle -- moodle-mcpIf the desktop app cannot find the command, run moodle-mcp config codex and merge its output into ~/.codex/config.toml (or .codex/config.toml in a trusted project). This generates full paths to Node and this installation, plus timeouts. Restart the client and check codex mcp list or /mcp.
Google Antigravity
Run moodle-mcp config antigravity. In the agent panel, open MCP Servers → Manage MCP Servers → View raw config, and merge the generated moodle entry into mcpServers. Preserve your other server entries, then refresh the server list. Use the config file opened by your installed version; current versions also support workspace .agents/mcp_config.json.
Both clients use the same local sign-ins and expose quiz and browser tools. No client-specific proxy or API key is needed. Configuration references: Codex MCP, Antigravity MCP.
Other MCP clients
After the install above:
{
"mcpServers": {
"moodle": { "command": "moodle-mcp" }
}
}Related MCP server: FCPC-lms-mcp-server
Sign in
Ask the assistant to log in to your site, or run:
moodle-mcp login https://your.moodle.siteEither way, a form opens on 127.0.0.1 in your browser, so your password never passes through the chat. The password goes only to your Moodle site and is not stored.
Sites with single sign-on or a captcha can't use a password here. The form explains how to paste a security key from the site's /user/managetoken.php page instead. This works only if the site shows you that page.
Actual browser control
Install Chromium once for the current computer:
moodle-mcp browser-installAsk your assistant to call moodle_browser_open with your Moodle site URL. It opens a visible Chromium window with its own persistent profile. Sign in directly in that window, including SSO or captcha. The assistant can then inspect the page, click controls, fill answers, navigate quiz pages, show screenshots and submit at your request.
Call moodle_browser_sync_login after sign-in to make the regular read tools use that session too. This replaces the stored login for this site with browser-session mode. Browser control itself does not need a mobile token or a saved cookie. moodle_browser_close saves session cookies privately before closing the window, so reopening can resume the login until Moodle expires it. A session saved by moodle_browser_sync_login can also seed a new browser profile. Closing the browser manually or crashing may lose cookies changed since the last controlled close. Only one running server can open a given site's profile at a time. Profiles live under MOODLE_MCP_HOME/browser (by default ~/.config/moodle-mcp/browser).
Browser control stays on the selected Moodle site. If SSO redirects to an identity provider, finish sign-in manually in the window and return to Moodle. Password fields are excluded from snapshots and masked in screenshots; the action tool refuses to type into them. Opening an activity can mark it as viewed, and browser actions can change Moodle data.
Completing quizzes
With the mobile service enabled:
Use
moodle_quizzesto find the quiz and any active attempt. Resume an existing attempt instead of starting another one.Call
moodle_quiz_start_attemptwithquizidand the exact quiz name inconfirm_namewhen the user requests a new attempt. This can consume an attempt and start a timer.Read
moodle_quiz_attempt_datapage by page. The returned question HTML contains the exact answer field names, option values and:sequencecheckfields. Send these withslotstomoodle_quiz_save_answers. Use fresh data after each save and follownextpageuntil-1.Read
moodle_quiz_attempt_summary, then callmoodle_quiz_submit_attemptwithquizid,attemptidand the quiz's exact name when the user requests submission. It checks that the attempt belongs to that quiz and user. Finished attempts are reported without submitting again.Use
moodle_quiz_attempt_reviewfor results when Moodle permits review.
Without the mobile service, use the browser tools to open the quiz, answer its controls, move through pages, inspect the summary and submit. Moodle enforces access rules, deadlines, attempt limits and review permissions. Password-protected quizzes and custom question types can be handled in the visible browser. There are no automatic retries of quiz writes; after an error, inspect the attempt before continuing. Use these features in accordance with your course's rules.
Sites with the mobile service off
You can use moodle_browser_open and moodle_browser_sync_login as described above. A manual cookie-paste alternative remains available: if the site reports web services or the mobile service as disabled, or refuses them to your account after you sign in, the form switches to browser-session mode and has no password field. You sign in on the site as usual, copy the value of the MoodleSession cookie from your browser's developer tools, and paste it into the form on 127.0.0.1. moodle_check_site shows which mode a site needs (sign_in).
The session ends when you log out on the site or it times out, and then you repeat these steps.
Tools
Tool | What it does |
| Checks whether a URL is a usable Moodle site, without logging in |
| Manage sign-ins; several sites can be signed in at once |
| Enrolled courses, their sections, activities and files |
| Text of Page activities |
| Final grades, grade items and teacher feedback |
| Upcoming and overdue activities across all courses |
| Instructions, due dates, your submission, grade and feedback |
| Start, read, answer and finish quizzes using the mobile service (local only) |
| Control a real browser, sign in and take quizzes (local only) |
| Quiz dates and limits, your attempts and scores, review of finished attempts |
| Announcements and course discussions |
| Text of PDF, |
| Saves a course file to a temporary folder (50 MB limit) |
| Uploads your files or text to an assignment, usually as a draft |
| Hands in a saved draft for grading, after you confirm the assignment's name |
Limits
Quiz taking and browser control run locally. Hosted mode remains read-only and exposes neither browser control nor quiz-taking tools. Starting an attempt may start a timer; finishing it usually cannot be undone. It can show results and, where the teacher allows, review finished attempts.
Homework is your own work, and you stay in control. The assistant should only upload files you name. Replacing files, handing in, and saving on assignments with no drafts each need an explicit confirmation. Moodle's submission statement is shown for you to accept yourself. Hidden folders and key files can't be uploaded.
Homework tools run only on the local server, and need the mobile service. The assignment API tools cannot write in browser-session or hosted mode; local browser actions can interact with assignment pages.
Some files have no readable text. Scanned PDFs and archives other than
.zip, such as.7zand.rar, can only be downloaded.It sees what your account sees. Quiz review works only when the teacher allows it, and quizzes you can't currently access are listed by
moodle_course_contentsbut not bymoodle_quizzes.Regular tools in browser-session mode cover less. The separate browser-control tools can open activities and interact with their pages. In this mode, only these work:
moodle_list_courses,moodle_course_contents,moodle_quizzes,moodle_grades_overview,moodle_course_grades,moodle_deadlines,moodle_assignments,moodle_whoami,moodle_download_fileandmoodle_read_file.moodle_course_contentsgives sections and activity names without file links, and needs Moodle 4.0 or newer.moodle_quizzesgives names, closing dates as the site words them and grades, without attempts.moodle_assignmentsgives names, submission status, grade and the due date as the site words it (Moodle 5.0 and newer also give an exactdue), without instructions, files orassignid.Grades keep the site's own number format, and have no item id or graded date.
moodle_course_pages,moodle_assignment_statusandmoodle_quiz_attempt_reviewreport that they are unavailable. Moodle does not expose them to AJAX on 4.5, and reading their pages would mean opening activities, which can mark them as viewed. The only quiz page the regular read tools open is the course-wide list, which links to quizzes without starting anything.Report pages are ordinary page views, so they appear in the site's logs and update your last access to the course. They don't mark any activity as viewed.
Browser-session mode has been tested on a school site and local installs. On 2 November 2026, a real sign-in to
iekportal.com.uathrough the MCP browser was synced and used for courses, deadlines, course contents, quiz lists and course grades. The regular session read tools also ran against real Moodle 3.11, 4.1, 4.5 and 5.0 installs in Docker with the mobile API off, including Ukrainian, the Classic theme and a custom session cookie name on 4.5. No quiz attempt was created and no activity was marked as viewed. Not checked yet:custom themes from a school or vendor (an unknown layout gives an error, not an empty list)
Moodle 5.1 and newer
session IP tracking or a firewall in front of the site, because every test request came from the same machine as the sign-in
SSO sign-in, and sites that refuse to give out their mobile config at all, which have only run against a mock
Phone apps need a hosted server. Phones can't launch a local stdio server, so they connect to
httpmode, described under Hosting.
Hosting for phone apps
moodle-mcp http serves the read tools over Streamable HTTP, for clients that connect to a remote MCP server. Each person signs in with their own Moodle account and can reach only that account's data.
Before you host this for other people, understand what you would be holding. A Moodle mobile token is not limited to reading. This server only reads with it, but a stolen token allows whatever the Moodle mobile app can do for that student, including submitting work. Passwords also pass through your server's memory during sign-in. You would be responsible for students' credentials and education records, so check your school's policy and the privacy law that applies (FERPA and GDPR are the usual ones) first. Hosting it only for yourself avoids most of this.
How it works
Sign-in. The server is an OAuth 2.1 authorization server with PKCE and dynamic client registration, so clients discover it from the URL alone. During authorization the user enters their site's address, then a password or security key, on a page served by this server. Moodle's answer proves who they are.
Accounts. An account is one Moodle user on one site, identified by a keyed hash of the two. Signing in again reaches the same account and replaces its token. To use a second site or account, disconnect and reconnect.
Isolation. Each
/mcprequest builds a new server bound to the user its bearer token proves. There are no sessions to share, and no tool takes a user as input.Storage. Each user's Moodle token is in its own AES-256-GCM file, with a key derived per record and bound to that user's id, so a file copied to another user does not decrypt. OAuth state is encrypted the same way, and holds refresh tokens only as hashes. Access tokens stay in memory, so a restart sends clients to refresh.
Retention.
moodle_logoutdeletes the stored token and ends every grant for the account. An account with no live grant, which happens 30 days after its last refresh, has its token deleted by an hourly sweep. Neither revokes the token on the Moodle site, because the mobile web service has no call for that. It lasts until the site expires it, or until the user removes it from their Security keys page.Outbound requests. Site addresses come from users, so the server contacts only public addresses over HTTPS, checking DNS answers at connect time. It never follows redirects and caps response size.
Limits of hosted mode
Browser-session sign-in is not offered. Sites with the mobile service off are refused, because collecting students' session cookies on a shared server is too risky.
One Moodle account per connection. A link that adds a site to an existing account would let an attacker send a victim a link and collect the victim's token in the attacker's account, so no such link exists.
moodle_download_filereturns the file in the response, up to 10 MB, and writes nothing to disk.It runs as a single process: sign-ins in progress and access tokens are in memory, and the rest is in local files. Running several instances behind a load balancer does not work.
Deploy
A Dockerfile is included. It stores data in /data, so mount a persistent volume there, and pass the variables below. The steps here run the server directly.
Create a master key and keep it in your platform's secret store, not in the repository or in backups of the data folder:
openssl rand -base64 32Start the server, using a persistent private folder for
MOODLE_MCP_HOME:MOODLE_MCP_MASTER_KEY=... MOODLE_MCP_PUBLIC_URL=https://moodle-mcp.example.org MOODLE_MCP_HOME=/var/lib/moodle-mcp MOODLE_MCP_TRUST_PROXY=1 node dist/index.js httpPut a reverse proxy in front of it to terminate TLS. The server has no TLS of its own and listens on
127.0.0.1:3000by default. Don't log request bodies on the proxy:POST /logincarries passwords.Check
GET /healthz, then addhttps://moodle-mcp.example.org/mcpas a remote connector in your client.
Variable | Purpose |
| Required. 32 random bytes in base64. The server refuses to start without it. |
| Required. Public origin with no path, using HTTPS. Requests with any other |
| Data folder, stored under |
| Listen address. Defaults to |
| Number of proxies in front of the server, so rate limits see real client addresses. Without it, all users share one limit; set too high, clients can spoof their address. |
| Comma-separated Moodle hostnames. Recommended for a single school. |
| Comma-separated HTTPS hostnames of client apps allowed to register. Recommended: see phishing below. |
|
|
| Old key during rotation. |
|
|
To rotate the master key, start once with the new key in MOODLE_MCP_MASTER_KEY and the old one in MOODLE_MCP_PREVIOUS_MASTER_KEY. Startup re-encrypts everything and logs when it's done, and then you can remove the old key. Losing the master key means every user has to sign in again.
What this does not protect against
A compromised running server. Encryption at rest protects a leaked disk or backup. Someone who controls the running process, or has both the data folder and the key, gets every token, and can capture passwords as they are typed.
The operator. Users have to trust whoever runs the server. The sign-in page says so.
Consent phishing. Anyone can register a client and send a victim an authorization link. If the victim signs in, that client gets read access to their Moodle data. The page names the requesting app and where it returns to, and warns about this, but client names are self-declared.
MOODLE_MCP_ALLOWED_REDIRECT_HOSTScloses this by allowing only apps you name.Prompt injection. A malicious course page can still try to instruct the user's assistant. It can only ever reach that user's own data.
What has been tested
Where | Covered |
| Courses, grades, pages, assignments, quiz lists, file download, reading PDF, |
| Inside a signed-in browser, with the parser logic pasted into the page: the course list, deadlines and course contents calls, and the grade, assignment and quiz pages across 9 courses. This found a false error on courses with no assignments, since fixed. One course's grade page answers "invalid user", which the site reports for that account |
Moodle 3.11, 4.1, 4.5 and 5.0 in Docker, mobile service on | Deadlines, quiz attempts and review, forums, and the full homework flow: draft, replace, online text, hand in, no-draft assignments, submission statements, locks |
The same four versions, mobile service off | Browser-session mode, and that it creates no quiz attempt. Course contents need 4.0 or newer |
Moodle 4.5 in Docker, hosted mode | Full OAuth sign-in with a real MCP client over HTTP, reading tools, no write tools, nothing readable on disk. The container image builds and starts |
New quiz API lifecycle, through MCP against a mock | Start, read raw question fields, save, summary, submit, warning handling, identity checks, old/new attempt-list functions and repeated submission |
| CAPTCHA completed by the user, session sync, nine enrolled courses, deadlines, course contents, quiz lists, empty assignment list and course grades in Computer Electronics. Browser course clicks, quiz index, screenshots, saved-session reuse and reopening while signed in. No quiz was started or submitted |
| Sign-in, enrolled courses, course-card clicks after asynchronous rendering, quiz index, PNG screenshot and reopening while signed in. API reads also returned 41 activities and ten Page texts in the health course, assignment status and PDF text. Quiz review was refused by the site's review rules. No quiz was started or submitted |
Real Chromium, through MCP against a local interactive fixture | Browser sign-in, session sync, radio answers, two quiz pages, final submission, PNG screenshots, password redaction, profile persistence and controls rendered after page load |
Mock servers, in | All tools, sign-in forms and hosted mode |
Not tested:
New quiz-taking tools against a real Moodle install, or a full browser-control quiz on a school site. The historical Moodle checks below predate these features.
Launching this version from the Codex or Antigravity application UI; their generated launch configurations are checked locally.
Homework upload on a real school's site, because a test would hand in real work.
Hosted mode on a public deployment, or from a real phone app.
Opening the
.mcpbbundle in Claude Desktop. Its server was unpacked and run directly.
Security
These notes describe the local stdio server. Hosted mode is covered above.
The access token is stored unencrypted in
~/.config/moodle-mcp/sites.json, readable only by your user account. On Windows this relies on the permissions of your profile folder, because the file mode has no effect there. SetMOODLE_MCP_HOMEto use another folder.moodle_logoutforgets the token on this computer but doesn't revoke it on the site.In browser-session mode the same file holds the session cookie, unencrypted. Treat it like a password: until the session ends it allows anything your account can do on the site, not only reading. The regular session read tools only read with it; the browser-control tools can also make changes. Anyone who gets the file could do more. Log out on the site to end the session;
moodle_logoutonly forgets the cookie on this computer.The browser profile and its private
mcp-session.jsonsnapshot also hold sign-in cookies and other browser storage. Treat it like a password. Closing the window or callingmoodle_logoutdoes not clear the profile or log out on Moodle; log out in the browser to end that session.Tokens and session cookies are only sent to the site that issued them, and requests carrying a session cookie never follow redirects.
Site URLs must use HTTPS, except on
localhost.The homework tools read local files, so a malicious course page could try to talk the assistant into uploading something private. Check the file names your client shows before approving these tools, and don't set them to run without asking.
Text from Moodle is written by other people, so a malicious course page could try to instruct the assistant. The server tells assistants to treat it as data. Check the address shown on the login form before typing your password.
Development
npm install
npm run build
node dist/index.js browser-install
npm testscripts/pack-release.sh builds the release files. Tests run the built server over stdio and HTTP against mock Moodle servers and use real headless Chromium against an interactive quiz fixture. They need no Moodle account. On Linux, install browser OS dependencies with npx playwright install --with-deps chromium.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
This server cannot be deployed
Maintenance
Related MCP Connectors
Connect AI assistants to Edusign attendance, courses, learners, documents, and API docs via OAuth.
Run the Geduk LMS from an AI assistant: courses, sessions, enrolments, users and catalogue.
Create, edit, translate, and export SCORM eLearning modules from a connected AI assistant.
Connect AI assistants to your approved computer for files, commands, browser and desktop tasks.
Related MCP Servers
- AlicenseAqualityCmaintenanceEnables AI assistants to interact with Moodle via web services, allowing tasks like listing courses, assignments, events, and downloading files.104MIT
- FlicenseNot gradedqualityBmaintenanceEnables AI assistants to query and manage Moodle LMS data, including assignment deadlines, unread messages, unfinished quizzes, and enrolled courses, using natural language via OpenAI or local LLMs.-
- AlicenseBqualityCmaintenanceConnects Claude to your Moodle account through the same web-service API the mobile app uses. Enables asking about upcoming and overdue deadlines, reading course files and announcements, checking grades, searching course content, and saving assignment submissions from chat.172MIT
- AlicenseAqualityBmaintenanceEnables teachers, through AI assistants, to view courses, assignments, and student submissions, download submission files, and save grades with feedback after explicit confirmation via the Moodle REST API.7137 npmMIT