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 more limited browser-session mode for 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.
Claude Desktop
Download moodle-mcp-1.1.1.mcpb from the latest release and open it.
Claude Code
npm install -g https://github.com/college-things/moodle-mcp/releases/download/v1.1.1/moodle-mcp-1.1.1.tgzclaude 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.
Other MCP clients
After the global install above:
{
"mcpServers": {
"moodle": { "command": "moodle-mcp" }
}
}Related MCP server: mcp-moodle
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.
Sites with the mobile service off
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 |
| 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
No quiz taking, on purpose. It can't start, answer or submit quizzes, and it never reads the questions of an attempt in progress. Having an AI answer graded tests would be cheating, so this won't be added. 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. Browser-session mode and hosted mode can't change assignments.
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.Browser-session mode covers less. 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 this mode opens 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 is tested on local installs, not yet on a school's site. The tools above 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 same 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 |
Mock servers, in | All tools, sign-in forms and hosted mode |
Not tested:
Homework upload on a real school's site, because a test would hand in real work.
A full browser-session sign-in on
iekportal.com.ua, which needs a user to paste their own cookie. The parts it relies on were checked inside a signed-in browser instead.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. This server only reads with it, but 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.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 testscripts/pack-release.sh builds the release files. Tests run the built server over stdio and HTTP against mock Moodle servers, so they need no account.
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
- AlicenseNot gradedqualityDmaintenanceEnables interaction with Moodle learning management systems through the Moodle REST API. Supports course management, user enrollment, assignments, forums, quizzes, and file operations through natural language.23 npmMIT
- AlicenseAqualityCmaintenanceEnables AI assistants to interact with Moodle via web services, allowing tasks like listing courses, assignments, events, and downloading files.1037 PyPI4MIT
- 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