campus-unr-mcp
This MCP server lets you read and write data on the FCEIA UNR Moodle campus (cursadas, contenidos, usuarios, foros, calificaciones) via Moodle Web Services.
Site & courses: get site/user info, list enrolled courses, list categories (períodos/carreras).
Course content: fetch sections and activities, list activities grouped by type, list groups (comisiones) and their members.
People: list enrolled users with role filters, list group members with roles.
Assignments & grades: list assignments with submission stats, get assignment submissions, get grades report, get all course grade items, list quiz attempts.
Forums: list course forums with discussion counts, list discussions with content.
Write ops (dry-run by default): create forum discussions, reply to posts, update forums (rename/visibility), update URL activities, save assignment grades (0-10) with feedback, send instant messages, create calendar events.
Provides tools for interacting with the FCEIA UNR Moodle campus virtual environment, including reading course contents, enrollments, groups, activities, assignments, forums, grades, and quizzes, as well as writing operations like creating forum discussions, replying to posts, saving assignment grades, sending messages, and creating calendar events.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@campus-unr-mcp Show me my courses and current grades"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
campus-unr-mcp
Servidor MCP + CLI para el Campus Virtual FCEIA UNR (Moodle).
El cliente no está atado a una sola URL: apunta a la instancia que pongas en CAMPUS_BASE_URL. Confirmado contra el campus de grado https://campusv.fceia.unr.edu.ar/ (Moodle: cookie MoodleSession, login via login/token.php, Web Services REST) y contra el de posgrado https://posgrado.campusvirtual.fceia.unr.edu.ar/ (mismo protocolo; la cantidad de funciones WS puede diferir entre instancias).
Agente Plugins spec 1.0.0 compliant (plugin.json + mcp.json en la raíz).
Estructura
src/campus_unr_mcp/
├── __init__.py
├── client.py # CampusClient: login token + Moodle Web Services (read + write)
├── cli.py # CLI con click + rich (22 subcomandos)
└── mcp_server.py # Servidor MCP stdio (22 tools)
bin/campus-server # Launcher portable para Agent Plugins
plugin.json # Manifest Agent Plugins 1.0.0
mcp.json # Config MCP stdioRelated MCP server: dutic-mcp
Instalación
cd campus-unr-mcp
uv syncConfiguración
Crear .env (ya existe):
CAMPUS_USER=tu_usuario
CAMPUS_PASS=tu_password
CAMPUS_BASE_URL=https://campusv.fceia.unr.edu.ar/CAMPUS_BASE_URL es la raíz de la instancia Moodle (con / final). Credenciales y token son por instancia: el usuario de grado no tiene por qué existir en posgrado.
Requisito de la instancia destino: login/token.php y webservice/rest/server.php habilitados, con el servicio moodle_mobile_app (si el login dummy responde invalidlogin y no servicenotavailable, el servicio está activo).
Uso CLI — Lectura
# Info del sitio y usuario
uv run campus site-info
# Listar cursadas
uv run campus courses
uv run campus courses --json
# Categorías (períodos lectivos / carreras / áreas)
uv run campus categories
# Contenido de un curso (secciones y actividades)
uv run campus contents 442
# Usuarios enrolados (estudiantes)
uv run campus users 442 --role student
# Grupos (comisiones)
uv run campus groups 442
# Miembros de grupos con lista de estudiantes
uv run campus group-members 442
# Actividades agrupadas por tipo
uv run campus activities 442
# Entregas (assignments) con conteo de envíos y calificaciones
uv run campus assignments 442
# Foros de un curso
uv run campus forums 503
# Discusiones (temas) de un foro
uv run campus discussions 7119
# Calificaciones del curso (quizzes + assignments)
uv run campus course-grades 442
# Intentos de quiz (parcial/examen)
uv run campus quiz-attempts 9417
# Iniciar servidor MCP
uv run campus serveUso CLI — Escritura
Todas las operaciones de escritura tienen --dry-run por defecto. Pasar --no-dry-run para ejecutar.
# Renombrar un foro y definir su visibilidad (dry-run por defecto)
uv run campus update-forum 121831 "Avisos 2026 C1" --hidden
uv run campus update-forum 121831 "Avisos 2026 C1" --hidden --no-dry-run
# Cambiar el destino de una actividad URL, conservando nombre y visibilidad
uv run campus update-url 94155 "https://drive.google.com/file/d/ID/view?usp=sharing"
uv run campus update-url 94155 "https://drive.google.com/file/d/ID/view?usp=sharing" --no-dry-run
# Crear tema en foro (dry-run por defecto, valida permisos)
uv run campus post-discussion 7119 "Aviso importante" "<p>Mensaje HTML</p>"
uv run campus post-discussion 7119 "Aviso" "Mensaje" --no-dry-run # ejecutar
# Responder a un post
uv run campus reply-post 113371 "Re: Aviso" "Respuesta" --no-dry-run
# Cargar nota de TP (0-10, con feedback opcional)
uv run campus save-grade 16255 13341 8.5 --feedback "Buen trabajo"
uv run campus save-grade 16255 13341 8.5 --feedback "Buen trabajo" --no-dry-run
# Enviar mensaje a un usuario
uv run campus send-message 13341 "Recordatorio entrega TP"
# Crear evento de calendario (fecha de examen, entrega, etc.)
uv run campus create-event "Parcial" 503 "2026-12-15T10:00:00" --description "Aula 3"Uso como servidor MCP en Hermes
Las credenciales viven en el .env del repo (no en config.yaml). Con
uv --directory <ruta-del-repo>, el cwd del proceso es el repo y se lee ese .env.
En ~/.hermes/config.yaml (ajustá la ruta al clone local):
mcp_servers:
campus_unr:
command: uv
args:
- --directory
- /path/to/campus-unr-mcp
- run
- campus
- serve
connect_timeout: 90.0
enabled: true
timeout: 120O por CLI (sin pasar flags de Hermes como --connect-timeout en --args;
si no, caen como argumentos de campus serve y el server falla):
uv sync
printf 'Y\n' | hermes mcp add campus_unr --command uv \
--args --directory /path/to/campus-unr-mcp run campus serve
hermes config set mcp_servers.campus_unr.timeout 120
hermes config set mcp_servers.campus_unr.connect_timeout 90
hermes config set mcp_servers.campus_unr.enabled true
# Si args quedó como string JSON, dejalo como lista YAML real (como arriba).
hermes mcp test campus_unrReiniciá la sesión CLI / el gateway de Hermes para descubrir las tools (en Telegram hace falta reiniciar el gateway).
Varias instancias Moodle (grado + posgrado)
Un proceso MCP = un CampusClient = un .env. Las credenciales se leen del cwd del proceso (el clone), no de config.yaml. Para usar dos campus a la vez hace falta dos clones (cada uno con su .env) y dos entradas en mcp_servers.
git clone https://github.com/jpmanson/campus-unr-mcp campus-unr-mcp
git clone https://github.com/jpmanson/campus-unr-mcp campus-unr-posgrado-mcp
cd campus-unr-mcp && uv sync
cd ../campus-unr-posgrado-mcp && uv sync.env del clone de grado:
CAMPUS_USER=tu_usuario_grado
CAMPUS_PASS=tu_password_grado
CAMPUS_BASE_URL=https://campusv.fceia.unr.edu.ar/.env del clone de posgrado:
CAMPUS_USER=tu_usuario_posgrado
CAMPUS_PASS=tu_password_posgrado
CAMPUS_BASE_URL=https://posgrado.campusvirtual.fceia.unr.edu.ar/Verificar cada uno antes de registrar el MCP:
cd /path/to/campus-unr-mcp && uv run campus site-info
cd /path/to/campus-unr-posgrado-mcp && uv run campus site-infoEn ~/.hermes/config.yaml:
mcp_servers:
campus_unr:
command: uv
args:
- --directory
- /path/to/campus-unr-mcp
- run
- campus
- serve
connect_timeout: 90.0
enabled: true
timeout: 120
campus_posgrado:
command: uv
args:
- --directory
- /path/to/campus-unr-posgrado-mcp
- run
- campus
- serve
connect_timeout: 90.0
enabled: true
timeout: 120O por CLI (confirmar el prompt de guardar config si la conexión inicial falla; campus serve habla stdio y el probe de hermes mcp add a veces cierra antes):
printf 'Y\n' | hermes mcp add campus_unr --command uv \
--args --directory /path/to/campus-unr-mcp run campus serve
printf 'Y\n' | hermes mcp add campus_posgrado --command uv \
--args --directory /path/to/campus-unr-posgrado-mcp run campus serve
hermes config set mcp_servers.campus_unr.timeout 120
hermes config set mcp_servers.campus_posgrado.timeout 120
hermes mcp test campus_unr
hermes mcp test campus_posgradoLas tools quedan prefijadas por el nombre del server (mcp_campus_unr_* vs mcp_campus_posgrado_*). Después de agregar servers: /reload-mcp en la sesión abierta, o una sesión nueva.
No hace falta un repo GitHub distinto por instancia: el segundo directorio es otro clone del mismo código, solo cambia el .env (que está en .gitignore).
Tools MCP disponibles (22 total)
Lectura (15)
Tool | Descripción |
| Info del sitio y usuario actual |
| Cursos donde el usuario está enrolado |
| Categorías (jerarquía académica) |
| Secciones y actividades de un curso |
| Usuarios enrolados con filtro por rol |
| Grupos (comisiones) de un curso |
| Grupos con lista de miembros y roles |
| Actividades agrupadas por tipo |
| Entregas con stats de envíos/calificaciones |
| Reporte de calificaciones |
| Detalle de entregas de un TP |
| Foros de un curso con conteo de discusiones |
| Temas de un foro con contenido |
| Todos los items de calificación del curso |
| Intentos de un quiz (parcial/examen) |
Escritura (7) — dry_run=True por defecto
Tool | Descripción |
| Renombrar un foro y mostrarlo/ocultarlo |
| Cambiar el destino de una actividad URL |
| Crear tema en foro (valida permisos en dry-run) |
| Responder a un post existente |
| Cargar nota de TP (0-10) con feedback opcional |
| Enviar mensaje instantáneo a un usuario |
| Crear evento (examen, entrega, etc.) |
Cada tool de escritura acepta dry_run: bool = True. En modo dry-run
valida permisos y parámetros sin ejecutar la operación. Pasar
dry_run=False para ejecutar realmente.
Notas
El cliente usa Web Services de Moodle (REST + token), no scraping HTML. Es más rápido y estable.
Autenticación:
login/token.phpcon serviciomoodle_mobile_appobtiene un token de WS automáticamente.SSL auto-firmado:
verify_ssl=Falsepor defecto (común en deployments universitarios).El cliente httpx se cachea y persiste toda la sesión MCP, reutilizando conexiones.
Todos los datos de estudiantes son PII: no commitear exports ni dumps.
Available Tools
20 toolscreate_calendar_eventA
Create a calendar event (fecha de examen, entrega, etc.).
By default runs in dry_run mode. Set dry_run=False to actually create.
Args: name: Event title. course_id: Course ID. timestart: ISO datetime (e.g. "2026-12-15T10:00:00") or unix timestamp. description: Optional event description. eventtype: Event type (course, user, group). Default: course. dry_run: If True (default), validate without creating.
Returns: JSON with validated status and eventid if created.
Inputs: name (required), course_id (required), timestart (required), dry_run, +2 more. Returns: result
create_forum_discussionA
Create a new discussion (tema) in a forum.
By default runs in dry_run mode (validates permissions only). Set dry_run=False to actually post.
Args: forum_id: Forum instance ID (use list_forums to get it). subject: Discussion title. message: Body text (HTML allowed). dry_run: If True (default), validate without posting.
Returns: JSON with validated status, and discussionid if posted.
Inputs: message (required), subject (required), forum_id (required), dry_run. Returns: result
get_assignment_submissionsA
List submissions for a specific assignment.
Args: assignment_id: The assignment instance ID (not course module ID).
Returns: JSON array of submissions with status, dates, and content.
Inputs: assignment_id (required). Returns: result
get_course_contentsA
Get all sections and activities/resources in a course.
Args: course_id: The Moodle course ID.
Returns: JSON array of sections, each with a list of modules (activities and resources) including type, name, and URL.
Inputs: course_id (required). Returns: result
get_course_gradesA
Get all grade items for a course (quizzes, assignments, etc.).
Returns grade data for every enrolled student, organized by grade item.
Args: course_id: The Moodle course ID.
Returns: JSON array of user grade entries with grade items and values.
Inputs: course_id (required). Returns: result
get_grades_reportA
Get grade report for a course (all users or a specific user).
Args: course_id: The Moodle course ID. user_id: Optional user ID to get grades for one student only. 0 or omitted = all enrolled users.
Returns: JSON with grade items and grades per user.
Inputs: course_id (required), user_id. Returns: result
get_site_infoA
Get site information and current user details from the campus.
Returns: JSON with site name, URL, user id, username, full name, and available web service functions count.
Inputs: no named parameters. Returns: result
list_activitiesA
List all activities in a course, grouped by type (quiz, assign, forum, etc.).
Args: course_id: The Moodle course ID.
Returns: JSON object mapping activity type -> list of activities.
Inputs: course_id (required). Returns: result
list_assignmentsB
List assignments (trabajos prácticos/entregas) with submission stats.
Args: course_id: The Moodle course ID.
Returns: JSON array of assignments with submission and grade counts.
Inputs: course_id (required). Returns: result
list_categoriesA
List course categories (períodos lectivos, carreras, áreas).
In Moodle, categories organize courses hierarchically by faculty, degree program, year, or academic period.
Returns: JSON array of categories with id, name, parent, depth, and course count.
Inputs: no named parameters. Returns: result
list_coursesA
List all courses where the current user is enrolled (cursadas).
Returns: JSON array of courses with id, shortname, fullname, category, start/end dates, and the user's roles in each.
Inputs: no named parameters. Returns: result
list_enrolled_usersA
List users enrolled in a course with their roles.
Args: course_id: The Moodle course ID. role: Optional role filter (e.g. 'student', 'editingteacher', 'teacher', 'manager'). Empty = all.
Returns: JSON array of users with id, fullname, email, and roles.
Inputs: course_id (required), role. Returns: result
list_forum_discussionsA
List discussions (temas) in a forum, including message content.
Args: forum_id: The forum instance ID (use list_forums to get it).
Returns: JSON array of discussions with subject, author, message, reply count, and creation/modification dates.
Inputs: forum_id (required). Returns: result
list_forumsA
List forums in a course with discussion counts.
Args: course_id: The Moodle course ID.
Returns: JSON array of forums with id, name, cmid, and discussion count.
Inputs: course_id (required). Returns: result
list_group_membersA
List groups (comisiones) with their member lists.
Args: course_id: The Moodle course ID.
Returns: JSON array of groups, each with name, member count, and a list of members (userid, fullname, email, roles).
Inputs: course_id (required). Returns: result
list_groupsA
List groups (comisiones) in a course.
Args: course_id: The Moodle course ID.
Returns: JSON array of groups with id, name, and description.
Inputs: course_id (required). Returns: result
list_quiz_attemptsA
List attempts for a quiz (parcial/examen).
Args: quiz_id: The quiz instance ID. user_id: Optional user filter (0 = current user only).
Returns: JSON array of attempts with state, score, and timestamps.
Inputs: quiz_id (required), user_id. Returns: result
reply_forum_postA
Reply to an existing forum post.
By default runs in dry_run mode. Set dry_run=False to actually post.
Args: post_id: The ID of the post being replied to (parent). subject: Reply subject. message: Reply body text. dry_run: If True (default), validate without posting.
Returns: JSON with validated status, and postid if posted.
Inputs: message (required), post_id (required), subject (required), dry_run. Returns: result
save_assignment_gradeA
Save a grade for a student's assignment (TP).
By default runs in dry_run mode. Set dry_run=False to actually save.
Args: assignment_id: Assignment instance ID. user_id: Student user ID. grade: Numeric grade (0-10). feedback: Optional feedback comment text. dry_run: If True (default), validate without saving.
Returns: JSON with validated status and confirmation.
Inputs: grade (required), user_id (required), assignment_id (required), dry_run, +1 more. Returns: result
send_message_to_userA
Send an instant message to a user.
By default runs in dry_run mode. Set dry_run=False to actually send.
Args: user_id: Recipient user ID. message: Message text. dry_run: If True (default), validate without sending.
Returns: JSON with validated status and msgid if sent.
Inputs: message (required), user_id (required), dry_run. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 20 tools
Several tools overlap significantly: get_grades_report and get_course_grades both return course grades per user with nearly identical outputs, and list_groups vs list_group_members and list_activities vs get_course_contents provide redundant views. This creates selection ambiguity for an agent.
Most tools follow a verb_noun pattern with snake_case, but the choice of verb is inconsistent (get_ vs list_ for similar read operations). This is a minor deviation from an otherwise predictable scheme.
At 20 tools, the server is on the higher end but each tool covers a distinct Moodle feature (forums, quizzes, grades, activities, users). The count is appropriate for a campus integration.
The read side is comprehensive, covering courses, categories, contents, users, groups, forums, assignments, quizzes, and grades. The write side is more limited but includes the key actions (posting, grading, messaging, calendar events), covering most common workflows.
Maintenance
Related MCP Connectors
MCP server for the Inistate platform: module discovery, entry management, and activity submission.
Read-only MCP server for ClassQuill, a tutoring-business-management platform.
MCP server for Muovi, Argentina's trust-first local services marketplace: find pros, draft tasks.
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceMCP server for Canvas LMS with automatic OAuth authentication. Enables interaction with courses, assignments, grades, modules, discussions, quizzes, files, calendar, messaging, and more without manual API token management.1,589 npm1MIT
- AlicenseAqualityBmaintenanceMCP server for the DUTIC virtual classroom (Moodle) at UNSA. Allows viewing tasks (including hidden ones), courses, resources, and downloading files, from terminal or AI agents.247 npmMIT
- AlicenseAqualityDmaintenanceMCP server and CLI for EVA FING (Moodle of Facultad de Ingeniería, UdelaR) that authenticates headlessly via Shibboleth, enabling AI agents and users to query courses, announcements, activities, calendar, and study material.8MIT
- AlicenseNot gradedqualityBmaintenanceLocal read-only MCP server for e-FICH (Moodle FICH-UNL) enabling course content, announcements, calendar events, and PDF search via MCP clients.3MIT