Skip to main content
Glama
README.md
# eva-mcp

Servidor **MCP** y **CLI** para el **EVA FING** (Moodle de la Facultad de
Ingeniería, UdelaR), con acceso *headless*: autentica contra el SSO de UdelaR
(Shibboleth) sin navegador y deja que **agentes de IA** (Claude Desktop, Cursor,
Hermes, etc.) y **humanos** consulten cursos, avisos, actividades, calendario y
material de estudio.

> Hecho por y para estudiantes de la FING. Sin API de Moodle (está cerrada para
> estudiantes): todo funciona vía sesión autenticada por Shibboleth.

---

## Casos de uso

### "¿Hay algún aviso nuevo en Métodos Numéricos?"

Le preguntás a tu agente y te responde con los últimos avisos (título, autor,
fecha):

```
Vos: ¿Cuáles son los últimos avisos de MetNum?
Agente: llama eva_avisos("MetNum-2S") → te lista los avisos del foro.
```

Sin agente, desde la terminal: `eva avisos metnum`.

### "Bajame el material de una materia"

Enunciados de prácticos, notas de teórico, exámenes viejos — todo en una carpeta:

```
Vos: Bajame todo el material de BD NoSQL a ~/Documents/BDNR
Agente: llama eva_descargar_material("BDNR", destino) → descarga los PDFs.
```

Sin agente: `eva material bdnr -d ~/Documents/BDNR`.

### "¿Cuándo es el parcial / qué entregas tengo?"

El calendario del EVA tiene los vencimientos de entregas y cuestionarios:

```
Vos: ¿Qué tengo en el calendario del EVA este mes?
Agente: llama eva_calendario() → te lista los eventos con fecha.
```

Sin agente: `eva cal`.

### "¿Qué actividades tiene tal curso?"

Cuestionarios, foros, tareas y recursos por sección:

```
Vos: ¿Qué actividades tiene Sistemas Operativos en la sección de prácticos?
Agente: llama eva_actividades("Sistemas Operativos", seccion="prácticos").
```

Sin agente: `eva actividades so --seccion "Práctico"`.

### Automatizar / cron

Como es headless, podés correrlo desde un cron para recibir alertas sin abrir el
EVA:

```bash
# avisar si hay un aviso nuevo en MetNum (ej. vía un script que te notifique)
eva avisos metnum -n 3
```

### Armar notas / vault

Bajás todo el material de una materia y lo organizás en tu vault de notas
(Obsidian, etc.) con un solo comando — ideal para arrancar el semestre.

---

## Requisitos

- **Python 3.11+**
- [`uv`](https://docs.astral.sh/uv/) (o `pipx`) — para instalar desde GitHub.

---

## Instalación (desde GitHub)

> El proyecto **no está en PyPI**; se instala directo desde el repo.

### Para usarlo con un agente (MCP)

**Claude Desktop** — `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "eva": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/FranciszekaMateu/eva-mcp", "eva-mcp"]
    }
  }
}
```

**Cursor** — `.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "eva": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/FranciszekaMateu/eva-mcp", "eva-mcp"]
    }
  }
}
```

**Hermes**:

```bash
hermes mcp add eva --command uvx --args --from git+https://github.com/FranciszekaMateu/eva-mcp eva-mcp
```

### Para usarlo desde la terminal (CLI)

Instalá los dos comandos (`eva` y `eva-mcp`) de una:

```bash
uv tool install "git+https://github.com/FranciszekaMateu/eva-mcp"
```

O correr sin instalar (one-shot):

```bash
uvx --from "git+https://github.com/FranciszekaMateu/eva-mcp" eva cursos
```

### Para desarrollo / contribuir

```bash
git clone https://github.com/FranciszekaMateu/eva-mcp
cd eva-mcp
uv venv .venv
uv pip install --python .venv/Scripts/python -e ".[dev]"
```

> ⚠️ El venv se crea con `uv` (sin `pip` propio). Instalá con `uv pip install
> --python .venv/Scripts/python`, no con `.venv/Scripts/python -m pip`.

---

## Configuración (credenciales)

La forma recomendada es usar el **llavero del sistema** (Windows Credential
Manager, macOS Keychain, Linux Secret Service). La contraseña queda **cifrada por
el sistema operativo**, nunca en texto plano:

```bash
eva login
```

Te pide el CI y la contraseña una sola vez (sin mostrarla) y las guarda cifradas.
La sesión también se cachea **cifrada** en `~/.eva-cli/cookies.enc` y se renueva
sola al expirar. Para borrar todo: `eva logout`.

Alternativa (fallback, texto plano): variables de entorno `EVA_USER`/`EVA_PASS`
o un archivo `.env`. El orden de resolución es: **entorno → llavero → `.env`**.

---

## Tools MCP

| Tool | Qué hace |
|---|---|
| `eva_cursos` | Lista los cursos matriculados (id, nombre) |
| `eva_avisos` | Últimos avisos del foro de un curso |
| `eva_aviso` | Texto completo de un aviso |
| `eva_actividades` | Actividades de un curso (filtrable por sección) |
| `eva_calendario` | Eventos del calendario (mes actual por defecto) |
| `eva_material` | Lista los archivos/páginas de un curso |
| `eva_descargar_material` | Descarga el material a una carpeta |
| `eva_login` | Fuerza un login fresco |

> En Hermes las tools aparecen como `mcp__eva__*` recién en una sesión nueva
> (no hay hot-reload de MCP).

---

## Comandos CLI

```bash
eva login            # guarda credenciales en el llavero del sistema (seguro)
eva logout           # borra credenciales y sesión
eva cursos           # lista tus cursos (id, nombre)
eva avisos metnum    # últimos avisos de un curso (nombre o id)
eva aviso 11740      # texto completo de un aviso
eva actividades metnum --seccion "Material teórico"
eva cal              # eventos del calendario
eva material metnum -d ./material   # descarga el material a una carpeta
```

`-d` acepta rutas Windows nativas, `~/...` y rutas MSYS (`/c/Users/...`, `/tmp/...`).

---

## Arquitectura

```
src/eva_cli/
├── auth.py       # login SAML Shibboleth (3 pasos, sin navegador)
├── client.py     # scraping: cursos, avisos, actividades, calendario, material
├── session.py    # credenciales (.env) + cache de sesión (compartido CLI/MCP)
├── paths.py      # normalización de rutas MSYS → Windows
├── cli.py        # comandos typer (eva)
└── mcp_server.py # servidor fastmcp (eva-mcp) → tools mcp__eva__*
```

Núcleo (`EvaClient`) + dos fachadas: `eva` (CLI) y `eva-mcp` (MCP).

---

## Desarrollo

```bash
uv run --python .venv/Scripts/python pytest   # 20 tests con httpx.MockTransport
uv run --python .venv/Scripts/python ruff check src tests scripts
```

> Nota para el desarrollo en Windows: el `PYTHONPATH` del entorno de Hermes puede
> contaminar el venv (apunta al site-packages del agente). Correr con
> `PYTHONPATH=` limpio, y el server MCP ya se blinda solo (`sys.path` limpio
> antes de importar fastmcp).

---

## Licencia

[MIT](LICENSE) © 2026 Francisco Escobar

TDQS

A3.5/5.0

Scored across 8 tools

Disambiguation4/5

Tools are mostly distinct by resource type: courses, notices, activities, calendar, materials, login. The main potential confusion is between eva_avisos and eva_aviso, but the plural/list versus singular/detail distinction is clear enough.

Naming Consistency4/5

All tools share the eva_ prefix and use Spanish names, which creates a recognizable pattern. Minor inconsistency exists because most are noun-based (eva_material, eva_cursos) while two are verb-inclusive (eva_descargar_material, eva_login).

Tool Count5/5

Eight tools is well-scoped for a learning-environment server covering courses, announcements, activities, calendar, and materials. Each tool serves a distinct purpose without unnecessary bloat.

Completeness4/5

The set provides good read-only coverage of the main EVA student workflows: list courses, browse announcements, view activities, check calendar, and access materials with download support. Minor gaps exist such as no activity detail view or course-level overview beyond listings.

Maintenance

ActivitySlowing
ResponsivenessNo issues