Skip to main content
Glama

FCPC LMS MCP server

An MCP server that lets an AI assistant answer questions about a student's own Moodle account — assignments due, unread messages, pending quizzes and enrolled courses.

Students connect from Claude on the web, on a phone, or on a desktop by registering one URL. No software to install, no tokens to copy by hand.

Built for First City Providential College, but it works against any Moodle site with web services enabled.

What it can answer

  • Everything with a deadline in the coming days, in one list

  • Unread messages from teachers and classmates

  • Notifications: reminders, grading notices and alerts

  • The overall grade in each course

  • Assignments due, and quizzes not yet completed

  • Announcements posted by teachers

  • What is inside a course: sections, activities and links

  • Which courses you are enrolled in

"Do I have any new messages?"
"What is due this week?"
"How am I doing in my courses?"
"Did I miss anything?"
"What are we covering in week 3 of History?"

Related MCP server: Moodle MCP Server

Two ways to run it

Remote server

Local server

Who it is for

A class or a whole institution

One person, on their own machine

Client

Claude (web, iOS, Android, desktop)

Any MCP client on that machine

Student sets up

One URL

Nothing, but needs the repo installed

Sign-in

OAuth, handled by Claude

A token in .env

Entry point

remote_server.py

server.py

Most deployments want the remote server.


Requirements

  • Python 3.11 or newer

  • cloudflared (brew install cloudflared) or any other way to expose an HTTPS address

  • A Moodle account on the site, used once during setup to record the site address

For the administrator

  1. Run setup.command (macOS) or setup.bat (Windows) once and sign in. This writes your Moodle site address to .env.

  2. Run start-server.command. It prints the URL to hand out:

https://xxxx.trycloudflare.com/mcp

Closing that window stops the server, so leave it open while the service is in use. Free trycloudflare.com addresses change every restart; use a named tunnel for a fixed address.

For students

  1. Open claude.ai in any browser, including a phone.

  2. Go to Settings → Connectors → Add custom connector.

  3. Give it any name and paste the URL you were given.

  4. Claude opens the Moodle sign-in page. Sign in with your usual Moodle username and password.

That is the whole setup. Afterwards it works in the Claude mobile apps too.

The same page has a second box that takes a web service token instead. Use it when the account has no Moodle password — a Google or other SSO account — or to demonstrate the connector with a token you already hold. It accepts the plain token, or the whole moodlemobile://token=... value from admin/tool/mobile/launch.php.

Connectors can only be added from the Claude website, but a phone browser works fine. Once added, they sync to the apps.

How sign-in works

Student's Claude ──HTTPS──▶ MCP server ──▶ Moodle
                 (OAuth)

Each user is identified by an OAuth sign-in. When a student signs in, their Moodle token is encrypted into the access token itself and handed back to Claude.

  • The server stores no Moodle tokens and no passwords

  • A password is used once to obtain a token, then discarded

  • One user can never see another user's data

.oauth_key (the encryption key) and .oauth_clients.json are secrets. Both are excluded from git. Deleting .oauth_key signs everyone out.


Local server

For running the MCP server on your own machine, over stdio.

  1. Run setup.command / setup.bat, or:

python -m venv venv
source venv/bin/activate          # macOS/Linux
.\venv\Scripts\activate           # Windows PowerShell
pip install -r requirements.txt
python setup_gui.py
  1. Point your MCP client at server.py. For example, in Claude Desktop's claude_desktop_config.json:

{
  "mcpServers": {
    "moodle": {
      "command": "/path/to/venv/bin/python",
      "args": ["/path/to/server.py"]
    }
  }
}

To see exactly what the AI receives:

python list_tools.py

There are also two standalone chat clients, client.py (OpenAI) and client_localLLM.py (ollama). Both take the server script as an argument:

python client.py server.py

Testing

selftest.py checks everything that can be checked without a browser: the Moodle connection, both servers, the OAuth flow through to a real tool call, and that users cannot see each other's data.

python selftest.py             # all checks
python selftest.py --offline   # skip anything needing the network

It exits 0 when everything passes and prints the remaining manual steps: registering the connector in Claude, signing in, asking a question, and repeating it on a phone.

Run it after installing, after changing the code, and on the machine that will host the server.

It cannot tell "no assignments are due" apart from "the tool is broken", because both look the same against an empty account. TEST_DATA.md specifies the courses, activities and accounts to create in Moodle so that every answer has something to be right about.


Limitations

Known and deliberate, as of the current version.

Students cannot get a token on an SSO site

Where Moodle authenticates through Google or another identity provider, students have no Moodle password and no way to issue themselves a web service token. An administrator has to issue them. See the SSO section below and ADMIN_REQUEST.md. On such a site this is a hard prerequisite, not a detail - without tokens nobody can connect.

One Moodle site per server

MOODLE_URL in .env holds a single address, so one running server serves one institution. Serving several would mean either one server each, or a change to let the sign-in page ask which site the user belongs to.

There is no audit log

Nothing records who asked what. For a pilot among consenting users that is usually acceptable; for an institutional rollout, and certainly before any teacher-facing tool that reads other people's data, it will not be.

Times are shown in JST

moodle_client.py formats timestamps as UTC+9. For an institution in another timezone they are wrong by the difference - one hour for the Philippines.

It affects message and announcement timestamps. Deadlines are mostly unaffected, because get_upcoming_deadlines prefers the time Moodle itself formatted in the user's own timezone and only falls back to JST when Moodle omits it. The fix is to read the timezone from the site rather than hard-coding it.

Read-only by design

Nothing submits work, posts to forums or sends messages, although the Moodle API would allow it with these tokens. An AI acting on a misunderstanding cannot un-submit an assignment, so writing is left out until it can be done behind an explicit confirmation step.

Teacher-facing tools do not exist

All ten tools answer about the signed-in user's own data. A teacher gets their own courses and grades, not their students'. The Moodle functions needed for "who has not submitted?" are reachable, but building them needs a teacher account to verify against - Moodle answers some permission failures with an empty list rather than an error, so a broken tool and an empty class look identical. check_token.py --teacher-probe exists to tell them apart.

Free tunnels are not a deployment

start-server.command uses a trycloudflare.com address, which changes on every restart and disappears when the window closes. Every student would have to re-register the connector. A pilot can live with it; a service needs a fixed address and a host that stays up.

Site-specific

Global search is disabled on lms.fcpc.edu.ph, so nothing can search Moodle by keyword; content is reached by walking from the course list. Other sites may allow it.

Notes on Moodle

Some Moodle sites sit behind Cloudflare and reject ordinary HTTPS clients with HTTP 403. Requests therefore go through curl_cffi with a browser TLS fingerprint. This is why the server cannot be reimplemented in, say, Apps Script, and why it should run somewhere with a normal-looking network path.

Sites that use SSO

If students sign in to Moodle through Google or another identity provider, they have no Moodle password, so login/token.php cannot issue them a token. The mobile route admin/tool/mobile/launch.php does issue one, but Moodle returns it only as moodlemobile://token=... and validates the scheme against ^[a-zA-Z][a-zA-Z0-9-+.]*$, so a web application cannot receive it. Only a native app can. decode_token.py decodes that value if you can capture it by hand.

On such a site the administrator has to issue tokens. ADMIN_REQUEST.md is a document you can hand to them; it sets out the two workable arrangements and their security trade-offs.

Files

File

Purpose

remote_server.py

Remote MCP server with OAuth, for Claude connectors

oauth_provider.py

OAuth authorization server; stores no tokens

login_page.py

The Moodle sign-in page Claude opens

server.py

Local MCP server over stdio

moodle_client.py

Moodle API client, one token per instance

moodle_auth.py

Token retrieval and .env handling

setup_gui.py

Setup wizard

setup.command / setup.bat

Double-click setup (macOS / Windows)

start-server.command

Publish the remote server (macOS)

selftest.py

Check the installation end to end

list_tools.py

Print the tools the AI sees

get_token.py

Fetch a token from the command line

decode_token.py

Token extraction for SSO users

ADMIN_REQUEST.md

What to ask a Moodle administrator for on an SSO site

TEST_DATA.md

The Moodle courses and accounts needed to test against live data

TEST_PLAN.md

Two-pass test procedure: as a student, then as a teacher

check_token.py

Show which account a token belongs to and what it can see

TEST_DATA.md

The Moodle courses and accounts needed to test against live data

client.py, client_localLLM.py

Standalone chat clients

Credits

The MCP server itself (server.py, client.py, client_localLLM.py) was written by Jiseong JEONG (@jeongjisung690). Original repository: https://github.com/jeongjisung690/Moodle---MCP-server

This repository adds:

  • Support for Moodle sites behind Cloudflare

  • Automatic token retrieval from a username and password

  • Token extraction for SSO users

  • A setup wizard for non-technical users

  • A remote MCP server with OAuth, so students connect with a single URL

License

No license has been set. Please contact the authors before using or redistributing this code.

F
license - not found
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables 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.
    14
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables interaction with Moodle learning management systems through the REST API. Supports course management, user enrollment, assignment handling, and forum operations through natural language.
    14
    MIT

View all related MCP servers

Related MCP Connectors

  • Connect AI assistants to your GitHub-hosted Obsidian vault to seamlessly access, search, and analy…

  • Let ChatGPT, Claude & Cursor use your Mac: email, calendar, iMessage, Teams, files. Local, free.

  • Connect AI assistants to ITM Platform projects, tasks, budgets, risks, and team workload.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Ogaaawa/FCPC-lms-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server