Saltar al contenido
NUEVOGuía práctica con 5 agentes Python para Odoo, verificada contra Odoo 20 →
Focuz/academy

agentes ia

Odoo 20 trae su propio servidor MCP: conecta un agente en Python

Conectamos un agente en Python al servidor MCP nativo de Odoo 20 y lo probamos de verdad: endpoint, API key, las 5 herramientas por defecto, el requisito de pgvector y la transcripción real del agente consultando el CRM.

Focuz Academy · 7 de octubre de 2026 · 10 min

Las notas de versión de Odoo 20 lo resumen en una línea: "Connect to your database via MCP". Para un desarrollador eso cambia mucho: cualquier agente compatible con MCP puede consultar Odoo sin que escribas una sola herramienta a mano. No nos quedamos con la teoría: lo instalamos en nuestra instancia Odoo 20 de demostración y conectamos un agente real.

Qué verificamos y cómo

Afirmación Cómo lo verificamos
Módulo, endpoint y autenticación Código fuente del módulo ai_mcp de Odoo 20 Enterprise
Herramientas por defecto tools/list contra nuestro Odoo 20 y el archivo ai_mcp/data/ir_actions_server_data.xml
Requisito de pgvector Error real al instalar ai_mcp y lectura de ai/__init__.py
Agente → Odoo funcionando Script Python con claude-agent-sdk 0.2.164 ejecutado contra Odoo 20
Respuesta del agente correcta Comparada con una consulta SQL directa a la base de datos

1. El módulo: ai_mcp

  • Se llama "AI MCP Server", es de licencia Enterprise (OEEL-1) y depende del módulo ai.
  • El servidor queda en <url de tu Odoo>/mcp. Por ejemplo, https://erp.tuempresa.com/mcp.
  • La autenticación es con un API key de alcance "MCP", enviado como Authorization: Bearer <API_KEY>. Se genera en Mi perfil → Seguridad de la cuenta → Nueva clave API, eligiendo el alcance MCP.
  • El módulo trae además un servidor OAuth propio, para clientes que prefieren iniciar sesión en lugar de usar una clave.
  • Funciona por HTTP directo (MCP streamable HTTP): lo probamos sin necesidad del puente mcp-remote que muestra la documentación.

La descripción del propio módulo insiste en dos reglas: nunca compartas el token y guárdalo siempre en campos de tipo credencial o contraseña.

2. El requisito que casi nadie menciona: pgvector

Nuestro primer intento de instalar ai_mcp se detuvo con este error:

PostgreSQL extension 'vector' is required to enable RAG for AI agents.

El módulo ai comprueba que exista la extensión vector (pgvector) en PostgreSQL e intenta crearla. Si tu servidor no la tiene, ni ai ni el servidor MCP se instalan.

Cómo lo resolvimos sin riesgo: construimos una imagen propia basada en la misma imagen postgres:16-alpine que ya usábamos, con pgvector compilado. Misma versión de PostgreSQL y misma librería del sistema, así que los datos quedan intactos:

FROM postgres:16-alpine
RUN apk add --no-cache --virtual .build-deps git build-base \
 && git clone --depth 1 --branch v0.8.7 https://github.com/pgvector/pgvector.git /tmp/pgvector \
 && cd /tmp/pgvector && make with_llvm=no && make with_llvm=no install \
 && cd / && rm -rf /tmp/pgvector && apk del .build-deps

Evita cambiar de una imagen Alpine a una Debian (o viceversa) sobre los mismos datos: la librería de C cambia el orden de los textos y puede dañar índices. Y haz siempre un respaldo antes.

Otro aprendizaje: al instalar los módulos de IA, Odoo intentó instalar automáticamente ai_website, que falló porque nuestros addons Enterprise eran más nuevos que la imagen Community de Docker. El servidor MCP no lo necesita: mantén ambas partes en versiones alineadas para evitar sorpresas.

3. Las 5 herramientas que Odoo expone por defecto

Esto devolvió tools/list en nuestro Odoo 20. Todas vienen marcadas como solo lectura (readOnlyHint: true):

Herramienta MCP Para qué sirve
ai_tool_mcp_retrieve_initial_context Usuario actual, zona horaria y empresa
ai_tool_get_models Listar los modelos accesibles
ai_tool_get_fields Ver los campos de un modelo
ai_tool_search Buscar registros y sus valores
ai_tool_read_group Agrupar y totalizar

¿Quieres exponer más? Toda acción de servidor tiene ahora la casilla "Available in MCP" (campo use_in_mcp). Según la documentación oficial, la opción "Readonly Tool" solo le indica al cliente que la herramienta es segura de invocar sin aprobación: no reemplaza a los permisos del usuario dueño del API key.

4. El agente en Python

Con claude-agent-sdk 0.2.164, el agente se conecta a Odoo como un servidor MCP remoto. Dentro del agente, las herramientas se llaman mcp__<servidor>__<herramienta>:

import asyncio, os
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

ODOO_MCP = {
    "type": "http",
    "url": f"{os.environ['ODOO_URL']}/mcp",
    "headers": {"Authorization": f"Bearer {os.environ['ODOO_MCP_API_KEY']}"},
}

SOLO_LECTURA = [
    "mcp__odoo__ai_tool_mcp_retrieve_initial_context",
    "mcp__odoo__ai_tool_get_models",
    "mcp__odoo__ai_tool_get_fields",
    "mcp__odoo__ai_tool_search",
    "mcp__odoo__ai_tool_read_group",
]

async def main():
    opts = ClaudeAgentOptions(
        model="claude-sonnet-5-5",
        mcp_servers={"odoo": ODOO_MCP},
        tools=[],                    # sin herramientas integradas: solo Odoo
        allowed_tools=SOLO_LECTURA,
        permission_mode="dontAsk",   # todo lo no permitido se rechaza
        verbatim_prompts=True,       # el texto del usuario no dispara @archivos ni /comandos
        max_turns=10,
        max_budget_usd=1.50,
        system_prompt=("Eres analista de datos de Odoo 20. Las oportunidades del CRM están en "
                       "crm.lead (campos stage_id y expected_revenue). Usa pocas llamadas."),
    )
    prompt = ("¿Cuántas oportunidades del CRM hay por etapa y cuál etapa suma más ingreso esperado? "
              "Responde con una tabla breve.")
    async for msg in query(prompt=prompt, options=opts):
        if isinstance(msg, ResultMessage) and msg.subtype == "success":
            print(msg.result)

asyncio.run(main())

5. La prueba real: qué hizo el agente

Ejecutamos el script contra nuestro Odoo 20 de demostración (datos de ejemplo de Odoo). Esta es la transcripción resumida:

HERRAMIENTAS: mcp__odoo__ai_tool_get_fields, mcp__odoo__ai_tool_get_models,
              mcp__odoo__ai_tool_mcp_retrieve_initial_context,
              mcp__odoo__ai_tool_read_group, mcp__odoo__ai_tool_search
LLAMADA: ai_tool_mcp_retrieve_initial_context {}
LLAMADA: ai_tool_read_group {"model_name": "crm.lead", "domain": "[]",
         "groupby": ["stage_id"], "aggregates": ["__count", "expected_revenue:sum"],
         "order": "expected_revenue:sum DESC"}
LLAMADA: ai_tool_search {"model_name": "crm.stage", "domain": "[[\"id\",\"in\",[1,2,3,4]]]"}
RESULTADO: success | turnos: 4 | costo USD: 0.23

Y su respuesta:

Etapa Oportunidades Ingreso esperado
New 25 514 844
Proposition 6 105 100
Qualified 5 87 300
Won 3 23 800
Total 39 731 044

¿Es correcto? Lo comparamos con una consulta SQL directa a la base de datos: las cuatro etapas, los conteos y los montos coinciden exactamente. El agente no inventó nada: leyó Odoo.

Tres cosas para notar en la transcripción:

  1. Eligió la herramienta correcta: usó read_group (una sola llamada agregada) en lugar de traer los 39 registros.
  2. Respetó los límites: 4 turnos y USD 0,23, muy por debajo de max_turns y max_budget_usd. En una primera prueba con un presupuesto de USD 0,50 y sin contexto, el agente exploró más y el SDK lo detuvo al llegar al límite: exactamente el control que queremos en producción.
  3. El contexto ayuda: decirle en el system_prompt en qué modelo están los datos ahorra llamadas y costo.

6. Buenas prácticas antes de llevarlo a producción

  1. Usuario dedicado para el API key, con los permisos mínimos: el agente puede todo lo que puede ese usuario. En nuestra prueba usamos un usuario de solo lectura del CRM.
  2. allowed_tools explícito y permission_mode="dontAsk". Evita comodines como mcp__odoo__* si expones acciones de escritura.
  3. Límites siempre: max_turns y max_budget_usd.
  4. Presupuesta los créditos: las notas de Odoo 20 indican que todas las funciones de IA de Odoo requieren créditos IAP.
  5. Prueba primero en una base neutralizada, nunca directo en producción.

¿Quieres entender el ciclo completo antes de conectar Odoo? Empieza por qué es el agent loop o descarga nuestra guía práctica con 5 agentes para Odoo.

Guía gratuita: 5 agentes Python para Odoo

Casos de Junior a Senior, con código verificado contra Odoo 20.

Descargar →

¿Empiezas desde cero? Lee qué es el agent loop y sigue las lecciones gratuitas.

Sigue leyendo