FCEFyN MCP
Allows querying FCEFyN's Moodle virtual classroom, including listing enrolled courses, retrieving course sections and activities, reading pages and PDFs, and searching course indexes.
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., "@FCEFyN MCPListá mis cursos del aula virtual"
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.
FCEFyN MCP
Servidor Model Context Protocol para consultar tus cursos del aula virtual de FCEFyN, Universidad Nacional de Córdoba desde un asistente compatible con MCP. Implementado con el SDK oficial de Python.
Inicia sesión con Login UNC (SAML/CAS), incluyendo el formulario de usuario y el de contraseña. También admite el formulario local de Moodle si no hay un acceso SAML. No necesita un token ni permisos de administrador.
Instalación
Requisitos: Python 3.11 o superior y uv.
git clone https://github.com/bernoulli2005/fcefyn-mcp.git
cd fcefyn-mcp
uv sync --locked
cp .env.example .env
chmod 600 .envCompletá .env localmente:
MOODLE_URL=https://fcefyn.aulavirtual.unc.edu.ar
MOODLE_USERNAME=tu_usuario@mi.unc.edu.ar
MOODLE_PASSWORD=tu_contraseñaEn la copia local preparada durante el desarrollo, .env ya está configurado. Las variables de entorno del proceso tienen prioridad sobre el archivo.
Related MCP server: moodle-utn-mcp
Conectar un cliente MCP
Agregá esta entrada a la configuración de un cliente que admita servidores locales por stdio (por ejemplo, Claude Desktop). Sustituí la ruta por la ubicación de tu clon y uv por su ruta absoluta si el cliente no lo encuentra:
{
"mcpServers": {
"fcefyn": {
"command": "uv",
"args": [
"--directory", "/ruta/absoluta/fcefyn-mcp",
"run", "--frozen", "fcefyn-mcp"
]
}
}
}No hace falta copiar la contraseña a la configuración del cliente. Reiniciá el cliente después de agregar el servidor.
Para ejecutarlo manualmente:
uv run fcefyn-mcpEl proceso espera mensajes MCP por stdin. No es un chat ni un servidor web; stdout está reservado al protocolo.
Herramientas
Herramienta | Uso |
| Lista todos tus cursos matriculados, con sus IDs y enlaces. |
| Recorre las secciones visibles, pestañas y subsecciones del curso; devuelve actividades, textos en línea y descripciones, sin duplicados. |
| Lee páginas, actividades y PDFs con texto. Devuelve enlaces a archivos y capítulos; usá |
| Busca en nombres y descripciones del índice del curso; no busca dentro de los archivos. |
Ejemplos de pedidos al asistente:
“Listá mis cursos del aula virtual”.
“Mostrame todas las unidades y los materiales de este curso”.
“Buscá las guías de prácticos y resumí el PDF de la primera unidad”.
“Abrí esta carpeta y mostrame sus archivos”.
El flujo habitual es listar cursos → obtener el índice de uno → leer los enlaces de las actividades. El índice puede ser grande; el asistente debe recorrer los materiales que necesite para responder. No se descargan todos los archivos automáticamente.
Alcance y privacidad
Solo consulta información disponible para tu cuenta. No entrega tareas, inicia intentos de examen ni publica mensajes. Moodle puede registrar las visitas como cualquier navegación normal.
Los PDFs escaneados necesitan OCR, que este proyecto no incluye. Archivos como ZIP, videos y documentos de Office se identifican por su formato y se devuelven con un enlace para abrir desde el aula.
Los enlaces a servicios externos permanecen en el índice, pero el servidor no los descarga ni les envía credenciales. Puede ser necesario abrirlos en el navegador.
Límite de 30 MB por respuesta descargada y de 100.000 caracteres por fragmento. No guarda cookies ni contenidos del aula en disco.
.env, cookies, descargas, cachés y entornos virtuales están excluidos de Git. El repositorio público no debe contener credenciales ni material privado de cursos.Si UNC cambia el formulario, exige MFA o Moodle cambia su HTML, puede ser necesario adaptar el cliente. Una sesión vencida se señala para volver a iniciar sesión en la siguiente llamada.
Proyecto independiente, sin afiliación oficial con la UNC. Usa tus propios permisos de acceso.
Desarrollo y verificación
uv sync --locked
uv run ruff check src tests scripts
uv run ruff format --check src tests scripts
uv run pytest -qLas pruebas automatizadas usan respuestas simuladas para verificar acceso SAML, paginación de cursos, pestañas, subsecciones, textos en línea, URLs permitidas y redirecciones. También inician un proceso MCP real para verificar el protocolo stdio y las herramientas.
Con credenciales locales, ejecutá la comprobación real de lectura de cursos y una muestra de materiales, a través del protocolo MCP:
uv run python scripts/verify_live.pyEste comando requiere acceso a internet y solo imprime conteos y formatos. No se ejecuta en CI, donde no se necesitan credenciales del aula.
Available Tools
4 toolsget_course_contentsBRead-only
Devuelve todas las secciones visibles, descripciones y actividades de un curso.
| Name | Required | Description | Default |
|---|---|---|---|
| course_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=true, so the safety profile is covered. The description adds meaningful context with "visibles", indicating only sections visible to the caller are returned, but says nothing about pagination, ordering, or response shape.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with the scope ("todas", "visibles") stated first and no wasted words. It is perhaps slightly too terse to carry usage guidance, but structurally efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read-only listing tool backed by annotations, the description covers the essential scope. It stops short of the completeness an agent needs for large courses, omitting any note on result volume, ordering, or what happens when sections are hidden.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is a single parameter (course_id) with 0% schema description coverage, so the description carries the burden. It implies a course scope but never clarifies that course_id is a numeric identifier or where to obtain it; the mapping is only inferable from the tool's subject matter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: returns all visible sections, descriptions and activities of a course. An agent can distinguish it as a full-contents fetch, but the description never names or contrasts it with siblings like search_course_contents or read_content.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The word "todas" implies this is the exhaustive-retrieval option versus a targeted search, so the choice is inferable. However, there is no explicit when-to-use, no exclusions, and no mention of alternatives such as search_course_contents when the agent only needs a subset.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_coursesARead-only
Lista todos los cursos matriculados del usuario, con ID, nombre y enlace.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=true, so the safety profile is covered externally. The description adds only the shape of the results (ID, name, link), with no mention of volume, pagination, or whether all enrollments are included.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence that states the scope and the returned fields with no filler. Appropriate sizing for a zero-argument listing tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no inputs, an output schema present, and annotations covering the safety profile, almost nothing else is required. Minor residual gaps: it restates return fields the output schema already provides, and says nothing about result volume or pagination.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is no parameter semantics to explain; the baseline of 4 applies. Nothing in the description conflicts with the empty schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb and resource ('Lista todos los cursos matriculados del usuario') and even enumerates the fields returned (ID, nombre, enlace). It is clearly distinguishable from the content-oriented siblings (get_course_contents, read_content, search_course_contents) by implication, though it never explicitly says so.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The scope phrase 'cursos matriculados del usuario' implies when the tool applies (discovering the user's courses before drilling into contents), but there is no explicit when-to-use, when-not-to-use, or named alternative such as get_course_contents.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_contentBRead-only
Lee actividad, carpeta, página, capítulo de libro o PDF del aula. Pagina con next_offset.
En carpetas y libros devuelve enlaces que se pueden leer con esta misma herramienta. Para formatos sin extracción devuelve el enlace. No envía tareas ni publica mensajes.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | ||
| offset | No | ||
| max_chars | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/openWorld/non-destructive, and the description adds real context beyond them: pagination via next_offset, links returned for formats without text extraction, and an explicit non-scope statement ('doesn't send tasks or publish messages'). It stops short of saying what a page/truncation boundary looks like in practice.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Very short and front-loaded: the core capability is in the first clause, followed by pagination and return-format notes. Minor waste in the trailing scope sentence, but nothing bloated.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only tool with no output schema, it covers return behavior (extracted text vs. links) and pagination reasonably. The gaps are the undocumented offset/max_chars inputs and the absence of any indication of what the response looks like beyond 'next_offset'.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden. It references pagination ('next_offset') and thus hints at the offset param, but the name doesn't match the actual 'offset' parameter and max_chars (the 30000-char truncation knob) is never explained anywhere.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb (read) and enumerates the resource types it handles: activity, folder, page, book chapter, PDF from the classroom. That scope implicitly separates it from list_courses/get_course_contents/search_course_contents, but no sibling is ever named, so an agent must infer the boundary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a genuine usage hint for recursion: folders and books return links that can be read with this same tool. However, it never states when to pick this over search_course_contents or get_course_contents, nor what input (URL) is expected to come from those tools. Usage is implied rather than prescribed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_course_contentsARead-only
Busca por nombre y descripción en el índice de un curso (no dentro de archivos).
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| course_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, openWorldHint=true and destructiveHint=false, so the safety profile is covered. The description adds the useful behavioral detail that search operates on the index, not file contents, but nothing about match semantics or limits; with annotations carrying the burden, a 3 fits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with the scope boundary in parentheses; nothing is wasted. It is terse but does not read as under-specified for its length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema available and annotations covering the safety profile, the description needs only purpose and scope, which it delivers. The main residual gap is match semantics for the query parameter, which is minor given the small two-parameter surface.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the schema gives no parameter meaning. The description partially compensates: 'por nombre y descripción' indicates what the query string matches, and 'de un curso' implies course_id scopes the search. It still omits matching behavior (exact vs partial) and query format.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Busca) and resource (el índice de un curso) and adds a scope boundary (no dentro de archivos) that separates it from read_content. It does not name the sibling tools explicitly, but the boundary is clear enough to distinguish intent.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The parenthetical '(no dentro de archivos)' implies an exclusion, steering the agent away for file-content search, but it never names the alternative tool or states the condition for switching. Usage must be largely inferred.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
v0.1.0- First observed
get_course_contents - First observed
list_courses - First observed
read_content - First observed
search_course_contents
TDQS
Scored across 4 tools
Each tool targets a distinct step in a browsing workflow: listing courses, dumping a course's structure, searching that structure, and reading a specific item. The main risk is get_course_contents vs search_course_contents, but descriptions clarify that one returns the full visible outline and the other searches name/description fields only. read_content is clearly the terminal action for a specific activity or resource.
All four names follow a consistent snake_case verb_noun pattern: list_courses, get_course_contents, read_content, search_course_contents. The verbs are conventional and predictable for the actions they represent, with no mixed conventions or vague names.
Four tools is on the lean side but well-scoped for a read-only LMS browsing server; each tool (list, outline, search, read) earns its place without redundancy. It is slightly thin compared with richer LMS surfaces, but not a mismatch for the stated browsing purpose.
The surface covers the full read-only discovery lifecycle: list enrolled courses, inspect course structure, search the index, and read individual activities/resources with pagination. Minor gaps remain (no user/profile or grade overview, and write actions are explicitly excluded), but core browsing workflows have no dead ends.
Maintenance
Related MCP Connectors
Read-only MCP server exposing a user ORANO library to their own AI agent.
Run the Geduk LMS from an AI assistant: courses, sessions, enrolments, users and catalogue.
Hosted MCP for LearnOS: search courses, lesson citations, flashcards and notes from any MCP client.
Read-only MCP server: let AI agents read your ORANO saved-video library, tasks, and memory.
Related MCP Servers
- FlicenseAqualityCmaintenanceEnables AI assistants to query the UTN distance learning Moodle campus, providing tools to list courses, view content, check deadlines, see grades, and more.7-
- FlicenseNot gradedqualityBmaintenanceEnables browser-based login to approved UTN Moodle sites and read-only access to the user's profile, course list, and course activities via local Chromium automation.2-
- FlicenseAqualityBmaintenanceMCP server for the Moodle-based Campus Virtual FCEIA UNR, providing tools to read courses, assignments, forums, and grades, plus write operations (posting, grading, messaging, events) with dry-run safety.201-
- AlicenseNot gradedqualityCmaintenanceLocal read-only MCP server for e-FICH (Moodle FICH-UNL) enabling course content, announcements, calendar events, and PDF search via MCP clients.3MIT