Skip to main content
Glama
ryokumaxell

Odoo MCP Server

by ryokumaxell
README.md
# Odoo MCP Project

Conector MCP remoto seguro para ChatGPT que permite gestionar proyectos, tareas, subtareas, tareas privadas y adjuntos de imagen en Odoo 19.

## Características

- ✅ 23 herramientas MCP para proyectos, tareas y adjuntos
- ✅ Soporte nativo para archivos OpenAI MCP fileParams
- ✅ Fallback Base64 garantizado para ChatGPT
- ✅ Validaciones de seguridad (MIME, tamaño, HTTPS)
- ✅ Logging diagnóstico sin volcar contenido sensible
- ✅ Tests automatizados (30 passing)
- ✅ Despliegue systemd + túnel OpenAI

## Herramientas Principales

### Proyectos y Tareas
- `listar_proyectos`, `buscar_proyectos`, `consultar_proyecto`, `crear_proyecto`, `editar_proyecto`, `archivar_proyecto`
- `listar_tareas_proyecto`, `buscar_tareas`, `consultar_tarea`, `crear_tarea`, `editar_tarea`, `archivar_tarea`
- `cambiar_estado_tarea`, `cambiar_stage_tarea`, `asignar_tarea`
- `listar_subtareas`, `crear_subtarea`, `editar_subtarea`
- `listar_tareas_privadas`, `consultar_tarea_privada`, `crear_tarea_privada`, `editar_tarea_privada`, `archivar_tarea_privada`
- `listar_stages_proyecto`, `listar_stages_tarea`, `listar_stages_tarea_privada`

### Adjuntos de Imagen
- `adjuntar_imagen_tarea` - Polimórfica (download_url, path, data_base64, contents, uri, bytes)
- `adjuntar_imagenes_tarea` - Hasta 5 imágenes
- `adjuntar_imagen_base64_tarea` - Fallback explícito
- `listar_adjuntos_tarea` - Lista con message_id del chatter

## Instalación Rápida

```bash
# Clonar
git clone https://github.com/ryoku-maxell/odoo-mcp-project.git
cd odoo-mcp-project

# Instalar dependencias
uv sync

# Ejecutar tests
uv run pytest -v

# Configurar variables de entorno
cp .env.example .env
# Editar .env con ODOO_URL, ODOO_DB, ODOO_API_KEY

# Ejecutar servidor
uv run python server.py
```

## Configuración de Producción

Ver [AGENTS.md](AGENTS.md) para despliegue completo con systemd y túnel OpenAI.

## Ejemplo para ChatGPT

```python
from pathlib import Path
import base64
import mimetypes

path = Path("/mnt/data/imagen.jpg")
raw = path.read_bytes()

payload = {
    "task_id": 468,
    "filename": path.name,
    "mime_type": mimetypes.guess_type(path.name)[0] or "image/jpeg",
    "data_base64": base64.b64encode(raw).decode("ascii"),
    "comentario": "Descripción de la imagen",
}
# Llamar a adjuntar_imagen_base64_tarea(payload)
```

## Licencia

MIT