Skip to main content
Glama
Migbolivar

agent-mcp-oauth

by Migbolivar
README.md
# 🤖 Agent + MCP + OAuth 2.0 — Demo Técnica

> Landing con un **agente de IA** que usa herramientas de un **servidor MCP propio**,
> protegida con **OAuth 2.0 real** ("Sign in with GitHub", Authorization Code + PKCE).
> Construido por **BMOPS Consulting** — todo funciona de verdad, nada es mockup.

**🔗 Demo en vivo:** https://agentdemo.bmops.tech (o http://localhost:8780 en local)

---

## ✨ Qué demuestra

| Capa | Qué hace | Cómo está implementado |
|---|---|---|
| **OAuth 2.0** | Login con GitHub | Flujo **Authorization Code + PKCE** contra `github.com/login/oauth/authorize`. Sesión en cookie firmada **HMAC-SHA256**. El chat exige sesión (401 sin ella). |
| **MCP** | Servidor de herramientas estándar | `mcp_server.py` — servidor **MCP real** (JSON-RPC 2.0 sobre stdio) escrito con el SDK oficial `fastmcp`. Expone 5 tools: `hora_actual`, `fetch_url`, `consultar_docs`, `indexar_documento`, `listar_documentos`. |
| **Agente = cliente MCP** | El LLM decide qué tool usar | `server.py` se conecta al servidor MCP con `ClientSession` + `stdio_client` (cliente oficial del SDK) y ejecuta la tool por protocolo. Nada de hardcode: la decisión la toma el LLM en 2 pasadas JSON. |
| **RAG con tus archivos** | Sube PDF/DOCX/TXT y pregúntale sobre ellos | Botón 📎 → el backend extrae el texto y lo indexa en **Qdrant vía la tool MCP `indexar_documento`**. Las preguntas se responden con `consultar_docs` (RAG) citando tu documento como fuente. Todo el pipeline de datos pasa por MCP. |
| **LLM self-hosted** | Razonamiento | Gateway local de modelos (gratis) — sin depender de APIs de pago. |

## 🏗️ Arquitectura

```
navegador ──► FastAPI (server.py) ── OAuth 2.0 ──► github.com (consentimiento)
                 │                        │
                 │  ┌─────────────────────┘
                 ▼  ▼
            sesión cookie HMAC
                 │
                 ▼
         /api/chat (agente)
           │ 1. LLM decide: ¿tool MCP?
           │ 2. ClientSession.call_tool(nombre, args)     ← protocolo MCP
           ▼                        │
   gateway LLM :3010        mcp_server.py (stdio)
   (razonamiento)             ├─ hora_actual()
                              ├─ fetch_url(url)
                              ├─ consultar_docs(q) ──► Qdrant (vectores)
                              ├─ indexar_documento(nombre, texto) ──► Qdrant
                              └─ listar_documentos()
   ```

## 🚀 Correr en local

```bash
# 1. Requisitos: Python 3.11+, Qdrant y servidor de embeddings opcionales
#    (sin Qdrant, consultar_docs responde "no encontré" — hora_actual y fetch_url siguen vivos)
pip install -r requirements.txt

# 2. Crea una OAuth App en GitHub: Settings → Developer settings → OAuth Apps
#    Homepage URL: http://localhost:8780
#    Callback URL: http://localhost:8780/callback

# 3. Configura (o exporta como env vars)
cp .env.example .env   # rellena GITHUB_CLIENT_ID y GITHUB_CLIENT_SECRET

# 4. Lanza
uvicorn server:app --port 8780   # o: python3 server.py
```

Abre http://localhost:8780 → **Continuar con GitHub** → prueba:
- 🕐 *"¿Qué hora es?"* → usará `hora_actual`
- 📚 *"¿Qué documentos tienes indexados?"* → usará `listar_documentos`
- 📎 **Sube un PDF/DOCX/TXT** → se indexa vía `indexar_documento` → *"resume mi documento"* → usará `consultar_docs` (RAG con tu archivo)
- 🌐 *"Lee https://bmops.tech"* → usará `fetch_url`

## 🧪 Probar el servidor MCP solo (sin web)

```bash
python3 test_mcp2.py   # lista tools y ejecuta hora_actual + consultar_docs
```

## 📁 Estructura

```
├── server.py          # FastAPI: OAuth 2.0 + sesión + agente cliente MCP + chat
├── mcp_server.py      # Servidor MCP propio (tools: hora_actual, fetch_url, consultar_docs, indexar_documento, listar_documentos)
├── static/index.html  # Landing premium (login GitHub + chat con indicador de tools)
├── seed_qdrant.py     # Siembra la colección mcp_demo en Qdrant
├── test_mcp2.py       # Test del servidor MCP vía cliente oficial
├── requirements.txt
└── .env.example
```

## 🔒 Notas de seguridad (patrones BMOPS)

- **Anti-inyección deny-first**: el chat filtra intentos de prompt injection antes de llegar al LLM (patrón probado en producción).
- **Sesión firmada**: cookie `HttpOnly` + HMAC-SHA256 (el `SESSION_SECRET` va en `.env`, nunca en el repo).
- **PKCE**: el `code_verifier` viaja en cookie `HttpOnly`; el `state` se valida con comparación en tiempo constante.

## ⚖️ Stack

Python · FastAPI · MCP SDK (`fastmcp` + cliente oficial `mcp`) · OAuth 2.0 (PKCE) · Qdrant · Embeddings MiniLM · Docker/VPS self-hosted

---
*BMOPS Consulting — agentes de IA en producción con usuarios reales. 17+ webs, 3 agentes RAG, pipeline lead→CRM→Stripe, infraestructura self-hosted con 7 MCP servers operativos.*