Catálogo / PNS AI Engine
Módulo de Odoo · pns_ai_mcp

PNS AI Engine

IA dentro de tu Odoo, para consultores. El Motor de IA corre en el Odoo de tu cliente. Proveedores, agentes, conocimiento y aprobaciones son registros de Odoo, y los agentes viven en módulos normales de Odoo. Código abierto, nada que licenciar. Odoo 14.0 y 19.0.

Versión 3.1.931Odoo 14.0 · 19.0Apache-2.028 contextos ↓10 proveedores de ejemplo ↓

El dolor

IA para tus clientes como un módulo más. Código abierto, sin licencias. No un servicio al lado que conectas cliente a cliente. Una IA que se instala, se actualiza y se desinstala como cualquier otro módulo, en el Odoo que el cliente ya tiene. Aquí los agentes viven en módulos normales de Odoo.

01 — ¿Atado a un proveedor? Pon varios, cada uno para lo suyo: conversación, audio, imagen, vídeo. Si uno cae, responde el siguiente.
02 — ¿Y si la IA escribe en producción? Su código corre en una caja de arena de solo lectura. Para cambiar algo propone un plan, y lo aprueba una persona.
03 — ¿Un prompt cerrado que no conoce a tu cliente? Los contextos se editan y se amplían en el propio Odoo: su vocabulario, sus reglas, sus costumbres.

Qué te llevas

Agentes que son Odoo

  • Un agente es un registro que trae un módulo. Instalas el módulo y el agente está; lo desinstalas y se va.
  • Cada agente tiene su propia lista de proveedores, en el orden que tú pongas.
  • Todo está en la base de datos del cliente: no hay una segunda copia en otro sitio.

Proveedores para cada tarea

  • OpenAI y cualquier servicio compatible con OpenAI, Anthropic, OpenRouter. También un modelo local (Ollama, LM Studio) en el propio servidor del cliente.
  • Roles por proveedor: conversación, audio, imagen, vídeo, maquetar una página, pasar una frase a los campos de un skill, decisiones de sí o no.
  • Si un proveedor falla, responde el siguiente de la lista.
  • La clave se queda en la base de datos del cliente, nunca en el módulo.

Una caja de arena y una persona

  • El código que escribe la IA lee en una transacción de solo lectura, con los permisos de quien preguntó.
  • Un cambio en Odoo es un plan que espera a que una persona lo apruebe en Odoo.
  • Cada llamada queda registrada: cada usuario ve su actividad, el administrador la de todos.
  • Direcciones de fuera, solo las de una lista blanca que tú mantienes.

Conocimiento tuyo

  • Contextos: las palabras, reglas y costumbres del cliente, editadas en Odoo.
  • Skills: procedimientos que se escriben una vez y se lanzan por su nombre. Sus tablas y gráficos salen del código, no de la IA.
  • Exportas toda la configuración de IA de un cliente a un fichero y la importas en el siguiente.

Un servidor MCP en el Odoo del cliente

  • Cursor y otros clientes MCP se conectan a /mcp con una clave personal.
  • Ninguna contraseña de administrador sale de Odoo. Cada clave lee con los permisos de su usuario.
  • Piensa el modelo del propio cliente MCP; Odoo responde a sus llamadas. Para eso no hace falta proveedor.

Nada que licenciar

  • Apache 2.0. Sin cuota por usuario, por base de datos ni por año.
  • Un módulo de Odoo normal: sin servidor externo que mantener.
  • El mismo módulo en todos los clientes de una versión soportada.

Agentes, roles y cadenas

Qué es un agente. Cualquier cosa de Odoo que use IA: un chat, un asistente de voz, un punto MCP, un trabajo que corre por detrás. En el motor es un registro (Motor de IA → Agentes) con un código, sus contextos, sus skills y su lista de proveedores.

Lo natural es que un agente venga con el módulo de Odoo que lo necesita: instalas el módulo y el agente está; lo desinstalas y se va. Un módulo puede traer más de uno. Este motor trae dos:

  • MCP Server (pns_ai_mcp) da contextos y herramientas a un cliente de fuera, como Cursor. El modelo corre en ese cliente; Odoo contesta a sus llamadas.
  • AI Admin (pns_ai_admin) hace los trabajos del propio motor: escribir un skill, leer la documentación de una API.

Chatboo trae el agente del chat. También se puede crear un agente a mano en Odoo.

Dos tipos. Inferencia: Odoo llama al modelo, con los proveedores del agente (un chat, un asistente de voz). Endpoint: el modelo está fuera y Odoo solo le sirve (MCP).

Roles. Un rol dice para qué sirve un proveedor. Un proveedor puede tener varios.

Rol Para qué
Conversación El turno de texto normal. Un proveedor sin rol hace lo mismo.
Audio Un audio de voz a texto.
Visión Una foto o una página escaneada.
Vídeo Un vídeo.
Decisión Un sí o un no cerrado, con su confianza. Si nadie lo tiene, es no.
Diseño Maqueta una página con los datos de un turno. Si nadie lo tiene, contesta Conversación.
Parser Una frase corta a campos, como los argumentos de un skill. Basta un modelo pequeño. Si nadie lo tiene, contesta Conversación.

La cadena. Cada agente tiene sus proveedores, en el orden que pongas. Cuando un turno necesita un rol, el motor toma los proveedores de ese agente que lo tienen, en ese orden. Si uno falla o se queda colgado, contesta el siguiente.

  • Cada enlace tiene sus tiempos de espera: segundos sin datos y segundos para una ronda entera.
  • Un proveedor que solo tiene ese rol va antes que los que hacen de todo: se eligió para eso.
  • Si la cadena no tiene a nadie para un rol que no sea Conversación, el motor busca entre todos los proveedores activos.
  • Sin failover externo corta la cadena en ese proveedor. Sirve para un modelo local cuyos datos no deben salir.
  • Una clave que llegó a su tope de gasto del mes se salta.
  • Un agente sin cadena usa todos los proveedores activos.

Por ejemplo: un modelo grande para la conversación, uno pequeño solo con Parser, y un modelo local al final de la cadena como respaldo.

Qué trae el módulo

Leído de los propios ficheros del módulo, versión 3.1.931. Las descripciones van en inglés, como en el módulo.

Contextos

Código Tipo Descripción
system_prompt core Odoo Autonomous Agent - Strict Tool Execution Protocol
account domain Odoo Accounting module knowledge - invoices, refunds, payments
business_documents domain Read, create and modify business documents (quotations, orders, invoices, pickings)
cost_accounting domain Analytic accounting: correct ORM fields and group-by patterns
dates domain ORM date/period composition: calendar Date/Datetime vs identifier text
email domain Email in Odoo — mail.mail (mailbox) vs mail.notification (delivery)
fetch_url_recipe domain How to fetch external data: use the fetch_url safe operation, never import urllib/requests in relaxaicode
filters domain ir.filters knowledge - creating and managing filters
geography domain Geographic knowledge - country/province/city model, administrative levels (region is NOT a state), resolution funnel, and HONEST handling of missing geo data (report, never invent)
hr_contracts domain [RECOMMENDED] Employment contracts: employee master first, hr.contract only if installed, never contract.contract
hr_payroll domain [RECOMMENDED] Payroll: accounting first, payslip fallback, honest empty state
hr_payroll_accounting_present domain Payroll accounting: partner totals → hr.employee match + structured rows (all locales)
hr_payroll_de_DE domain Payroll Germany - account 4100 SKR first, payslip fallback
hr_payroll_en_US domain Payroll US - accounts 5100-5300 first, payslip fallback
hr_payroll_es_AR domain Payroll Argentina - account 411 first, payslip fallback
hr_payroll_es_ES domain Payroll Spain - accounting 640/4751/476 first, payslip fallback [RECOMMENDED]
hr_payroll_es_MX domain Payroll Mexico - account 5100 first, payslip fallback
hr_payroll_fr_FR domain Payroll France - account 421 first, payslip fallback
hr_payroll_it_IT domain Payroll Italy - account 2120 first, payslip fallback
hr_payroll_pt_BR domain Payroll Brazil - accounts 311/3.1.1 first, payslip fallback
invoice_concepts domain Invoice field mappings, calculations and coding conventions
partners domain res.partner knowledge - customers, suppliers, location search
sale_order_duplicate_workflow domain How to duplicate a sale order and change its lines in two separate steps. Includes how to get the URL of the new order.
self_mcp domain MCP endpoint identity — knowledge layer for an external LLM
trial_balance domain Trial balance - accounts with debits, credits and balance by date range (generic fallback)
trial_balance_es_ES domain Trial balance - accounts with debits, credits and balance by date range (Spain)
corporate_terms locale English corporate terminology mapping - Odoo field and model translations (factory fallback)
corporate_terms_es_ES locale Spanish corporate terminology mapping - Odoo field and model translations

Proveedores de ejemplo

En static/examples/providers/, sin clave.

Nombre Protocolo Modelo Roles
Anthropic anthropic claude-opus-4-8
Lemonade openai gpt-oss-20b-NPU
OpenAI openai gpt-4-turbo
OpenRouter - Conversation openrouter anthropic/claude-opus-5.5 conversation, vision, design
OpenRouter - Vision openrouter ~anthropic/claude-sonnet-latest vision
OpenRouter - Design openrouter ~anthropic/claude-opus-latest design
OpenRouter - Audio openrouter google/gemini-3.5-transcribe audio
OpenRouter - Parser openrouter anthropic/claude-haiku-5.5 parser
OpenRouter - Decision systemone typesafe/jev-1.13 decision
OVH - Backup openai Qwen3.8-27B conversation, vision

Qué no hace

  • Sin pantalla de chat. El motor no trae ventana de conversación para los usuarios. Eso es Chatboo.
  • No escribe por su cuenta. La IA nunca cambia Odoo sola. Cada cambio es un plan que aprueba una persona en Odoo.
  • Cuatro protocolos de proveedor. Compatible con OpenAI, OpenRouter, Anthropic y SystemOne (decisiones de sí o no). Una API que no hable ninguno no se conecta.
  • Dos versiones probadas. 14.0 y 19.0. De la 15.0 a la 18.0 construyes tú el módulo y lo pruebas antes; la 13.0 y anteriores no funcionan (ver Versiones de Odoo).

Preguntas

¿Es un servidor MCP? Lo incluye, en el mismo módulo. POST /mcp habla Streamable HTTP. /mcp/sse con /mcp/message es para clientes que solo hablan SSE. /mcp/<agente> ata la llamada a un agente. Tres herramientas: relaxaicode (Python de solo lectura contra Odoo), safe_plan_request (proponer un cambio) y safe_plan_status (ver si se aprobó).

¿Adónde van los datos del cliente? A los proveedores que configures, y a las direcciones de fuera y servidores de API que permitas. Cuando se conecta Cursor u otro cliente MCP, su propio modelo ve lo que devuelven las herramientas.

¿Necesito Chatboo? No. El motor solo ya sirve a clientes MCP. Chatboo añade el chat dentro de Odoo y trae el motor con él.

¿Qué es pns_base? La capa común de los módulos PNS: las mismas pantallas cargan en Odoo 14 y 19, y trae utilidades pequeñas (avisos, importar y exportar, PDF). Se instala como dependencia.

Puesta en marcha

  1. Instala. ¿Quieres también el chat? Instala Chatboo; trae este módulo. Solo el motor: clona la rama 14.0 o 19.0 de pns_base y de pns_ai_mcp, añade cada clon al addons_path e instala PNS AI Engine desde Aplicaciones. En Odoo 14, antes, pip install "openpyxl>=3.1.2".
  2. Hazte administrador de IA. Ajustes → Usuarios: date IA Administrador. Sal y vuelve a entrar.
  3. Saca tu clave API. Motor de IA → Seguridad → Usuarios: tu fila, marca IA Conversacional y pulsa Generar Clave API.
  4. Pon un proveedor. Motor de IA → Conexiones → Proveedores: protocolo, dirección, clave API y modelo, con el rol Conversación. O parte de uno hecho: en static/examples/providers/ están OpenRouter, OVH, OpenAI, Anthropic y Lemonade, sin clave. Ajustes → Motor de IA → Importar configuración, eliges el fichero y escribes tu clave en cada proveedor.

Listo. Apunta Cursor (o cualquier cliente MCP) a https://<tu-odoo>/mcp con la clave en la cabecera X-MCP-API-Key. Ejemplo más abajo, en Conectar un cliente MCP.

Para el equipo de IT

Conectar un cliente MCP

En Cursor, añade el servidor a ~/.cursor/mcp.json (todos los proyectos) o a .cursor/mcp.json (un proyecto). Los demás clientes MCP piden lo mismo: la dirección y la cabecera.

{
  "mcpServers": {
    "odoo-de-mi-cliente": {
      "url": "https://odoo.example.com/mcp",
      "headers": {
        "X-MCP-API-Key": "<tu-clave-api>"
      }
    }
  }
}

La clave es la del paso 3 y lee con los permisos de ese usuario. Una clave por persona; no subas a git el fichero con la clave dentro.

Estructura del repositorio

main es un solo árbol para todas las versiones. Una rama plana (14.0, 19.0) es ese árbol construido para una versión, listo para el addons path.

Ruta Contenido
common/ Código común a todas las versiones, skills, contextos, datos, ficha de Apps
stacks/owl1/pns_ai_mcp/ Odoo 14
stacks/owl2/pns_ai_mcp/ Odoo 15 y siguientes

El instalador copia common/ y encima la pila; si un fichero está en los dos, gana el de la pila. Lo común se edita solo en common/. El módulo plano de una versión se construye con ./install_flat.sh 19.0 /ruta/a/addons. Utilidades de interfaz del dominio: utils/mcp_ui.py.

Python: no añadas requests ni reportlab (ya vienen con Odoo). pns_base no necesita nada de pip. En la 14, usa un openpyxl reciente (los antiguos fallan con NumPy moderno).

Versiones de Odoo

Versión Estado
14.0, 19.0 Probadas. Rama plana publicada.
15.0 – 18.0 Sin probar, ni por personas ni por el CI. Sin rama publicada.
13.0 y anteriores No soportadas.

De la 15.0 a la 18.0. No hay rama que clonar. Construye tú el módulo plano desde main, que tiene el código de todas las versiones (owl2 para la 15.0 y siguientes). Lo mismo con pns_base:

git clone https://github.com/patanegra-soft/pns_base.git
git clone https://github.com/patanegra-soft/pns_ai_mcp.git
cd pns_base   && ./install_flat.sh 17.0 /ruta/a/addons && cd ..
cd pns_ai_mcp && ./install_flat.sh 17.0 /ruta/a/addons

El script avisa de que esa versión no está probada. Nadie ha usado el motor en estas versiones: pruébalo antes en una base de pruebas y pasa ahí los tests de Odoo (ver Tests). Si funciona, o si no, cuéntanoslo (CONTRIBUTING.md).

Odoo 13 no tiene OWL, sobre el que está hecho el chat. De Odoo 8 a 12 usan un Python anterior al 3.7, que es el que necesita el motor. La suite mantiene dos pilas (owl1 para la 14.0 y owl2 para la 15.0 y siguientes).

Tests

Dónde estás Qué se ejecuta
main python -m pytest unit_tests, sin Odoo. Después los tests de Odoo, tras ./install_flat.sh 19.0 <dir>.
Una rama plana (14.0, 19.0) Los tests de Odoo en tests/. Los unitarios viven en main.
odoo-bin -d <db> -i pns_ai_mcp --test-enable --stop-after-init --test-tags /pns_ai_mcp

Licencia, marcas, entrenamiento

Apache-2.0: ver LICENSE y NOTICE. PATANEGRA Soft™ y PAAP™ (Patanegra Application Agent Protocol, que implementa este motor) son marcas de PATANEGRA Soft SL; la licencia no las concede. Se permite la minería de textos y el entrenamiento de IA (TDMRep tdm-reservation = 0).

Seguridad: SECURITY.md. Errores, ideas y preguntas: CONTRIBUTING.md.