Skip to main content
Glama
README.md
# FCEFyN MCP

Servidor [Model Context Protocol](https://modelcontextprotocol.io/docs/develop/build-server) 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](https://github.com/modelcontextprotocol/python-sdk/tree/v1.x).

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](https://docs.astral.sh/uv/getting-started/installation/).

```bash
git clone https://github.com/bernoulli2005/fcefyn-mcp.git
cd fcefyn-mcp
uv sync --locked
cp .env.example .env
chmod 600 .env
```

Completá `.env` localmente:

```dotenv
MOODLE_URL=https://fcefyn.aulavirtual.unc.edu.ar
MOODLE_USERNAME=tu_usuario@mi.unc.edu.ar
MOODLE_PASSWORD=tu_contraseña
```

En la copia local preparada durante el desarrollo, `.env` ya está configurado. Las variables de entorno del proceso tienen prioridad sobre el archivo.

## 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:

```json
{
  "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:

```bash
uv run fcefyn-mcp
```

El proceso espera mensajes MCP por stdin. No es un chat ni un servidor web; stdout está reservado al protocolo.

## Herramientas

| Herramienta | Uso |
| --- | --- |
| `list_courses()` | Lista todos tus cursos matriculados, con sus IDs y enlaces. |
| `get_course_contents(course_id)` | Recorre las secciones visibles, pestañas y subsecciones del curso; devuelve actividades, textos en línea y descripciones, sin duplicados. |
| `read_content(url, max_chars=30000, offset=0)` | Lee páginas, actividades y PDFs con texto. Devuelve enlaces a archivos y capítulos; usá `next_offset` para continuar un texto largo. |
| `search_course_contents(course_id, query)` | 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

```bash
uv sync --locked
uv run ruff check src tests scripts
uv run ruff format --check src tests scripts
uv run pytest -q
```

Las 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:

```bash
uv run python scripts/verify_live.py
```

Este comando requiere acceso a internet y solo imprime conteos y formatos. No se ejecuta en CI, donde no se necesitan credenciales del aula.

TDQS

A3.7/5.0

Scored across 4 tools

Disambiguation4/5

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.

Naming Consistency5/5

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.

Tool Count4/5

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.

Completeness4/5

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

ActivityMaintained
ResponsivenessNo issues