Skip to main content
Glama
Anggelie

UVG Local MCP Server

by Anggelie
README.md
# UVG Local MCP Server

**Autor:** Anggelie Velásquez — Carné 221181
**Universidad del Valle de Guatemala** — Curso CC3067

## 1. Descripción

Servidor MCP (Model Context Protocol) **local**, implementado desde cero en Python 3 estándar, sin usar FastMCP ni ningún SDK oficial de MCP. El servidor se comunica con un cliente a través de **stdio**, usando **JSON-RPC 2.0** implementado manualmente.

## 2. Objetivo

Demostrar la comprensión del ciclo de vida de un servidor MCP (`initialize` → `notifications/initialized` → `tools/list` → `tools/call`) construyendo el protocolo manualmente, sin depender de librerías que oculten esa lógica.

## 3. Arquitectura

```
Cliente MCP  <-- stdio (stdin/stdout) -->  server.py
                                              │
                                    ┌─────────┴─────────┐
                                    │                    │
                                jsonrpc.py           tools.py
                          (formato JSON-RPC 2.0)  (herramientas)
```

- `server.py`: punto de entrada, bucle de lectura de stdin y enrutamiento de métodos.
- `jsonrpc.py`: construcción de respuestas/errores JSON-RPC 2.0 y validación básica.
- `tools.py`: registro centralizado de herramientas (metadata + schema + función ejecutora).

## 4. Protocolo utilizado

- **Transporte:** stdio (entrada estándar / salida estándar).
- **Framing:** un mensaje JSON-RPC 2.0 por línea (**JSON Lines / NDJSON**). No se usa framing tipo `Content-Length`.
- **Formato de mensajes:** JSON-RPC 2.0, implementado manualmente (sin librerías de JSON-RPC ni de MCP).
- **Versión de protocolo MCP reportada:** `2024-11-05` (campo `protocolVersion` en la respuesta de `initialize`).
- `stdout` se reserva **exclusivamente** para respuestas JSON-RPC. Todos los logs se envían a `stderr`.

## 5. Métodos MCP implementados

| Método | Tipo | Descripción |
|---|---|---|
| `initialize` | Solicitud | Devuelve `protocolVersion`, `capabilities` e `serverInfo`. |
| `notifications/initialized` | Notificación | Confirmación del cliente; no genera respuesta. |
| `tools/list` | Solicitud | Devuelve la lista de herramientas disponibles con su `inputSchema`. |
| `tools/call` | Solicitud | Ejecuta una herramienta con los argumentos recibidos. |

Cualquier otro método devuelve el error JSON-RPC `-32601 Method not found`.

## 6. Herramientas disponibles

### `analizar_texto`
Entrada: `{ "texto": "Hola mundo" }`
Devuelve: cantidad de caracteres, cantidad de palabras, cantidad de líneas, texto en mayúsculas y en minúsculas.

### `calcular_estadisticas`
Entrada: `{ "numeros": [10, 20, 30, 40] }`
Devuelve: cantidad, suma, promedio, mínimo y máximo.
Valida que `numeros` sea una lista, no vacía, y con solo valores numéricos.

### `informacion_sistema`
Sin argumentos. Devuelve: sistema operativo, versión de Python, plataforma y directorio de trabajo actual.
**No** expone contraseñas, tokens, variables de entorno ni contenido de archivos.

## 7. Requisitos

- Python 3.8 o superior.
- No se requieren dependencias externas (ver [requirements.txt](requirements.txt)).

## 8. Instalación

```powershell
git clone https://github.com/Anggelie/mcp-local-server-uvg.git
cd mcp-local-server-uvg
```

## 9. Cómo ejecutar el servidor manualmente

Desde PowerShell, el servidor queda esperando mensajes por stdin:

```powershell
python src/server.py
```

Puedes escribir una línea JSON y presionar Enter, por ejemplo:

```
{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {}}
```

El servidor responderá con una línea JSON en stdout. Para terminar, presiona `Ctrl+Z` y luego Enter (fin de stdin en Windows).

También puedes enviar todo el archivo de ejemplo de una sola vez:

```powershell
Get-Content examples/requests.jsonl | python src/server.py
```

## 10. Cómo probarlo

### Pruebas automáticas (unittest)

```powershell
python -m unittest discover tests -v
```

### Cliente de demostración (subproceso)

```powershell
python examples/test_client.py
```

Este script levanta `src/server.py` como subproceso y ejecuta automáticamente el ciclo `initialize -> initialized -> tools/list -> tools/call` para las 3 herramientas, además de un caso de método inexistente.

## 11. Cómo configurarlo en un cliente MCP

Se incluye una configuración de ejemplo en [client-config/claude_desktop_config.example.json](client-config/claude_desktop_config.example.json):

```json
{
  "mcpServers": {
    "uvg-local-server": {
      "command": "python",
      "args": [
        "C:\\RUTA\\AL\\PROYECTO\\src\\server.py"
      ]
    }
  }
}
```

**Importante:** reemplaza `C:\RUTA\AL\PROYECTO` por la ruta real donde clonaste este repositorio en tu máquina.

## 12. Ejemplos

Ver [examples/requests.jsonl](examples/requests.jsonl), que contiene un mensaje JSON-RPC por línea cubriendo `initialize`, `notifications/initialized`, `tools/list` y `tools/call` para las tres herramientas, además de casos de error.

## 13. Estructura del proyecto

```
mcp-local-server-uvg/
│
├── src/
│   ├── server.py      # Punto de entrada del servidor
│   ├── jsonrpc.py      # Utilidades JSON-RPC 2.0
│   └── tools.py        # Registro de herramientas
│
├── tests/
│   ├── test_jsonrpc.py
│   └── test_tools.py
│
├── examples/
│   ├── requests.jsonl
│   └── test_client.py
│
├── client-config/
│   └── claude_desktop_config.example.json
│
├── .gitignore
├── requirements.txt
├── README.md
└── README_ES.md
```

## 14. Manejo de errores

Se implementan los códigos estándar de JSON-RPC 2.0:

| Código | Significado | Cuándo ocurre |
|---|---|---|
| `-32700` | Parse error | La línea recibida no es JSON válido. |
| `-32600` | Invalid Request | Falta `jsonrpc: "2.0"` o `method`. |
| `-32601` | Method not found | El método solicitado no está implementado. |
| `-32602` | Invalid params | Argumentos faltantes o de tipo incorrecto en `tools/call`. |
| `-32603` | Internal error | Error inesperado durante la ejecución (no debe tumbar el servidor). |