Skip to main content
Glama

isu-moodle-mcp

Conecta Moodle a Claude mediante un servidor MCP. Se divide en dos capas:

  • Capa API (18 herramientas, la principal): API REST oficial de Web Service. No rastrea HTML, no necesita abrir un navegador.

  • Capa CDP (6 herramientas, para rellenar huecos) + capa de sistema antiguo (4 herramientas): solo se usa Chrome en modo debug cuando la API realmente no puede obtener algo. La más importante es probe_course_access() — es la única forma de detectar que "hay un curso que ya no puedes ver".

Para uso normal, la capa API es suficiente. La capa CDP está pensada para preguntas como "¿están todos los cursos que he impartido en la lista?".

Pensado para el taller "Diseño de cursos con IA: aplicaciones prácticas" (2026-08-21) de la Universidad I-Shou. Haz clic en "Usar plantilla" para crear tu propio repositorio, no necesitas una cuenta de GitHub.


Qué es esto

El flipclass-mcp que se demostró en clase es un servidor MCP para FlipClass de la Universidad del Sur de Taiwán. Ese sistema no tiene API, así que obtiene los datos de dos maneras: rastreo de HTML (32 expresiones xpath) + Chrome en modo debug (matriz de calificaciones, listas de miembros y otras páginas que no se pueden leer por HTTP puro). Eso es la demostración de "por muy cerrado que esté el sistema, con una cuenta y contraseña se puede hacer ingeniería inversa completa".

Esta es la otra mitad de la misma historia: cuando el sistema tiene API, se puede cambiar todo el backend manteniendo el mismo contrato de herramientas MCP.

flipclass-mcp

moodle-mcp

Obtención de datos

Rastreo de HTML + lxml xpath

API REST oficial

Autenticación

Cuenta/contraseña + token anticsrf + caché de cookies

Un token, sin estado

Expulsión por inicio de sesión múltiple

Ocurre (problema conocido)

No ocurre

Lista de miembros / matriz de calificaciones

Requiere abrir Chrome en modo debug con CDP

Disponible directamente en la API

Email de estudiantes

Se deduce concatenando el número de matrícula

Viene directamente en la lista

Código relacionado con autenticación

Aprox. 247 líneas

Aprox. 15 líneas

Chrome en modo debug

Hay que abrirlo cada vez (sin él no hay matriz de calificaciones)

Solo se necesita al consultar relaciones de matrícula

Los nombres de las herramientas y sus docstrings se mantienen idénticos a propósito, para que puedas comparar directamente cómo se ve la misma necesidad cuando "hay API" y cuando "no hay API".


Related MCP server: Moodle MCP Server

Inicio rápido

1. Obtener el código

git clone https://github.com/scatjay/isu-moodle-mcp.git

Si no tienes git, también puedes pulsar Code → Download ZIP en la página de GitHub.

2. Instalar las dependencias

pip install -r requirements.txt

Solo hay dos: requests y mcp.

3. Obtener un token nuevo

python get_token.py https://moodle.你的學校.edu.tw

Te pedirá tu usuario y contraseña de Moodle; si es correcto, escribirá el token en .env.

Ejecuta este paso en tu propia terminal, no dentro de una conversación con IA. Las transcripciones de conversaciones pueden guardarse o hacerse copias de seguridad; si la contraseña y el token aparecen ahí, es como si se hubieran filtrado.

¿Por qué un token y no usuario/contraseña? Un token se puede revocar, solo tiene los permisos tuyos y, si se filtra, no pierdes todo como con una contraseña. El token de Moodle caduca por defecto a las 12 semanas — si a mitad del semestre la herramienta falla de repente y dice invalidtoken, solo tienes que volver a ejecutar este paso.

4. Conectar con Claude

En el archivo de configuración de Claude Desktop (claude_desktop_config.json), añade:

{
  "mcpServers": {
    "moodle": {
      "command": "python",
      "args": ["C:/你的路徑/isu-moodle-mcp/server.py"],
      "env": {
        "MOODLE_URL": "https://moodle.你的學校.edu.tw",
        "MOODLE_TOKEN": "貼上 .env 裡那一串",
        "MOODLE_LEGACY_URL": "https://舊站網址(沒有舊站就整行刪掉)"
      }
    }
  }
}

5. Ejecutar primero el diagnóstico

Después de conectarlo, lo primero que debes pedir a Claude es que ejecute diagnose(). Te dirá si el token es válido, qué funciones puedes llamar realmente y qué falta. Si no conecta, esta es la primera herramienta que debes ejecutar.


Qué herramientas hay

Tool

Qué hace

diagnose()

Diagnóstico de conexión. Si no conecta, ejecuta esto primero.

list_current_courses()

Cursos en curso

list_history_courses()

Todos los cursos que aún puedes ver (consulta las limitaciones conocidas más abajo)

search_courses(keyword)

Busca tus cursos por palabra clave

get_course_overview(course_id)

Cuántas secciones, materiales y tareas tiene el curso

list_materials(course_id)

Lista de materiales (incluye URL de descarga)

list_homework(course_id)

Lista de tareas

list_submissions(assignment_id)

Estado de entregas de toda la clase

read_members(course_id)

Lista de matriculados (nombre / email / rol)

read_score_matrix(course_id)

Matriz de calificaciones: cada estudiante × cada elemento evaluable

get_completion_status(course_id)

Estado de finalización de actividades

download_file(fileurl, dest_path)

Descarga archivos de materiales

raw_call(wsfunction, params_json)

Llama directamente a cualquier función de Moodle (para explorar)

get_submission_report(assignment_id)

Informe de entregas: incluye fecha, retrasos y reenvíos

get_student_grade_record(course_id, uid)

Calificaciones detalladas de un estudiante

get_student_email(course_id, uid)

Consulta el email de un estudiante

fetch_course_bundle(course_id, dest)

Descarga todo el paquete de un curso: materiales + tareas + lista + calificaciones

fetch_all_courses_bundle(dest)

Descarga el paquete de todos los cursos, de una vez

Capa CDP (primero ejecuta python start_debug_chrome_moodle.py e inicia sesión en esa ventana)

Tool

Qué hace

cdp_status()

Comprueba si el Chrome en modo debug responde y si has iniciado sesión

probe_course_access(course_id)

Comprueba si todavía puedes entrar en este curso — la pregunta que la API no puede responder

enrolment_details(course_id)

Estado de cada matrícula, método, fecha de alta y de baja

find_hidden_courses()

Escanea y busca cursos que "existen pero ya no puedes ver"

webservice_overview()

Qué servicios tienen qué funciones y quién puede generar tokens

role_capabilities(role_id)

Matriz de capacidades de un rol (más de 300 entradas, la API no las da)

Capa de sistema antiguo (cuando la escuela ha cambiado de plataforma)

Hay que añadir una línea en .env: MOODLE_LEGACY_URL=https://url-del-sitio-antiguo.

Tool

Qué hace

legacy_status()

Comprueba si el sitio antiguo sigue vivo y si usa API o CDP. Ejecuta esto primero antes de extraer datos.

legacy_list_courses()

Cursos visibles en el panel del sitio antiguo

legacy_probe_course(course_id)

Versión para sitio antiguo de "¿puedo seguir entrando en este curso?"

legacy_course_contents(course_id)

Secciones y materiales de un curso en el sitio antiguo

Esta versión no incluye deliberadamente ninguna herramienta de escritura (por ejemplo, mod_assign_save_grade para modificar calificaciones). Si algo de solo lectura falla, como mucho los datos serán incorrectos; si algo de escritura falla, estarás modificando las calificaciones reales de los estudiantes. Si de verdad lo necesitas, añádelo tú mismo, pero primero practica en un sitio de pruebas.


Limitaciones conocidas (por favor, lee esta sección completa)

🔴 Los cursos antiguos desaparecen silenciosamente — pero la condición es más restrictiva de lo que crees

core_enrol_get_users_courses solo devuelve los cursos en los que todavía tienes una relación de matrícula activa.

Probado el 2026-08-20 en dos instancias locales de Moodle 4.1.18, verificando punto por punto:

Qué hace la escuela

¿El curso sigue en tu lista?

Oculta el curso (visible=0)

Sí, se sigue viendo

La fecha de fin del curso ya ha pasado

Sí, se sigue viendo

La matrícula del profesor se ha puesto como "desactivada"

Desaparece. Y no da ningún error.

Esta tabla desmiente una creencia muy extendida (incluida la versión anterior de este mismo README): "ocultar o archivar un curso antiguo hace que desaparezca". La prueba demuestra que no es cierto. Lo que realmente hace desaparecer un curso es solo la última fila. Lo escribo aquí porque: una afirmación desmentida por pruebas que se queda en la documentación es peor que no escribir nada — la seguirías para pedirle a tu administrador algo que no es.

El curso, los estudiantes y las tareas siguen en la base de datos; simplemente no los ves. Y la API no te dice "hay un curso que ya no puedes ver", simplemente no lo menciona.

Por eso, antes de hacer análisis de períodos largos, ejecuta find_hidden_courses() o probe_course_access(course_id) para comprobar curso por curso, y no te fíes solo de la lista de list_history_courses(). Esa herramienta siempre devuelve un campo caveat para recordártelo; por favor, no lo ignores.

Los errores de Moodle llegan con HTTP 200

Cuando Moodle devuelve un error, el código de estado HTTP sigue siendo 200; el error está oculto en el campo exception del cuerpo. raise_for_status() no lo detecta en absoluto. Este servidor ya lo gestiona, pero si escribes tu propio código contra Moodle, recuérdalo.

accessexception es difícil de diagnosticar

La lista oficial de causas tiene siete u ocho, y a menos que el administrador active el modo debug en NORMAL o superior, el mensaje de error no te dice cuál es. Este servidor lo traduce a lenguaje claro y te da las tres causas más probables, pero para saber con certeza cuál es, tendrás que ejecutar diagnose() y ver qué funciones incluye realmente tu token.

Solo ves tus propios cursos

Esto es una garantía interna de Moodle, no una limitación de esta herramienta. El token hereda exactamente tus permisos, y cada llamada hace una comprobación de permisos a nivel de contexto. Esto es a la vez una garantía de seguridad y una limitación.

Los parámetros de tipo array no se pueden pasar como JSON

El REST de Moodle usa el $_POST de PHP para analizar los datos; los arrays deben escribirse como courseids[0]=5&courseids[1]=7. Si envías una cadena JSON, se interpretará como una sola cadena y dará invalidparameter. Este servidor ya aplana los arrays automáticamente.

El nombre del parámetro para descargar archivos es diferente

El endpoint REST usa wstoken, pero webservice/pluginfile.php usa token. Es el detalle que más fácil se pasa por alto al移植. Además, el servicio debe tener activada la opción downloadfiles.


Si get_token.py falla

Error

Significado

Qué hacer

invalidlogin

Usuario o contraseña incorrectos

El usuario de Moodle no tiene por qué ser tu email

servicenotavailable

El sitio no tiene activado el servicio para móviles

Pide al administrador que active enablemobilewebservice

cannotcreatetoken

Tu cuenta no tiene permiso para crear tokens

La escuela ha cambiado los permisos por defecto; pide al administrador que te dé un token

sitemaintenance

El sitio está en mantenimiento

Espera un poco y vuelve a intentarlo

Por defecto, Moodle otorga moodle/webservice:createmobiletoken a todos los usuarios con sesión iniciada, así que normalmente un profesor puede renovar su token sin necesidad del administrador. Pero la escuela puede cambiar este valor por defecto — si lo ha cambiado, solo te darás cuenta cuando intentes renovarlo, no se puede detectar desde fuera.


Notas de desarrollo

Esta herramienta es un移植 de flipclass-mcp. Al移植, se eliminó la mitad más dolorosa y se conservó la mitad más valiosa:

  • Eliminado (aprox. 247 líneas): _login, gestión de anticsrf, caché de cookies, checkMultiLogin para inicios de sesión múltiples, análisis con 32 expresiones lxml xpath, conexión CDP (Chrome en modo debug)

  • Conservado: el esqueleto de FastMCP, la firma y el docstring de cada @mcp.tool() ——esto es el verdadero activo, porque es el contrato que ve el LLM

La razón es que ningún paquete Python de Moodle existente servía: moodlepy lleva casi dos años sin actualizarse y fija las dependencias en attrs<23 (una versión de 2022); moodle_api.py lleva tres años sin actualizarse y no está en PyPI; python-moodle se mantiene, pero en realidad rastrea HTML, no es un cliente REST. El REST de Moodle es tan simple que se escribe en una docena de líneas;引入 un paquete sin mantenimiento solo añade deuda técnica.


Licencia

MIT. Úsalo para crear la versión de tu propia escuela, sin necesidad de pedir permiso.

A
license - permissive license
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
  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides Claude with full access to Moodle learning management systems, enabling interaction with courses, files, assignments, grades, and calendar events. It also supports building Obsidian study vaults from course materials through automated knowledge graph creation.
    14
    16
    MIT

View all related MCP servers

Related MCP Connectors

  • Read-only MCP server for ClassQuill, a tutoring-business-management platform.

  • WHOOP recovery, strain, sleep and workouts in Claude via official WHOOP OAuth. Free, open source.

  • Read-only tools over the Safer Agentic AI framework: 238 patterns + 14 heuristics.

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/scatjay/isu-moodle-mcp'

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