mcp_odoo_fresh
Provides tools for interacting with the Odoo ERP system, enabling AI agents to search for customers/products, create and confirm sales quotations, and manage other sales-related operations through a standardized MCP interface.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp_odoo_freshCreate a quotation for product Laptop for customer TechCorp"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Agente Inteligente QuindíColor: Odoo + MCP + OpenAI
Proyecto Hackathon 🚀
Este proyecto, desarrollado para una hackathon, demuestra la creación de un agente conversacional inteligente capaz de interactuar con un sistema ERP Odoo (específicamente una instancia alojada en Odoo.sh) para realizar tareas clave del flujo de ventas de la empresa ficticia "QuindíColor".
El agente utiliza el SDK de OpenAI Agents para su lógica y razonamiento, se comunica mediante voz o texto a través de interfaces web interactivas creadas con Gradio, y, de manera crucial, accede a las funcionalidades de Odoo de forma estandarizada y desacoplada gracias al Model Context Protocol (MCP).
Objetivo Principal: Simplificar y agilizar operaciones comunes de ventas en Odoo (buscar clientes/productos, crear y confirmar cotizaciones) mediante una interfaz conversacional avanzada (texto y voz), resaltando la flexibilidad que aporta MCP.
Related MCP server: Odoo MCP Server
Tecnologías Utilizadas 🛠️
Python: Lenguaje principal de programación (v3.10+ recomendado).
Odoo (Odoo.sh): Sistema ERP de destino donde residen los datos y se ejecutan las acciones comerciales.
Model Context Protocol (MCP): Protocolo estándar utilizado para la comunicación entre el agente inteligente y el servidor que expone las capacidades de Odoo. Se implementa un servidor MCP personalizado.
Se usa el SDK
mcppara Python (pip install mcp).
OpenAI Agents SDK: Framework para construir la lógica del agente, manejar el flujo conversacional y la integración con herramientas MCP (
pip install openai-agents).OpenAI API:
LLM (GPT-4o): Para el razonamiento del agente, comprensión del lenguaje natural y selección de herramientas.
Whisper: Para la transcripción de Voz a Texto (STT).
TTS API: Para la síntesis de Texto a Voz (TTS).
Se requiere la librería
openai(pip install openai).
Gradio: Framework para crear rápidamente las interfaces web interactivas de chat y voz (
pip install gradio).Odoo API (XML-RPC): Método de comunicación específico utilizado por nuestro servidor MCP para interactuar con la API externa de Odoo.
uv: Gestor de paquetes y entornos virtuales Python (
pip install uv).python-dotenv: Para gestionar credenciales y configuraciones de entorno de forma segura.
Arquitectura del Sistema 🏛️
El sistema conecta al usuario con Odoo a través de varias capas, donde MCP juega un papel central como puente estandarizado.
Flujo Típico:
El Usuario interactúa (voz/texto) con la Interfaz Gradio.
La App Backend (Gradio + Python) recibe el input. Si es voz, llama a la API Whisper (STT) de OpenAI para transcribir.
El texto (transcrito o escrito) se pasa a la Lógica del Agente (OpenAI Agents SDK) junto con el historial.
El Agente llama al LLM (GPT-4o) de OpenAI con el prompt, historial y la lista de herramientas disponibles (descubiertas vía MCP).
El LLM decide si responder directamente o usar una herramienta.
Si decide usar una herramienta Odoo (ej.
buscar_cliente):La Lógica del Agente instruye al Conector MCP (
MCPServerStdio).El Conector MCP envía una petición
tools/callusando el Protocolo MCP a nuestro Servidor MCP Odoo (mcp_odoo_server.py), que corre como proceso hijo.Nuestro Servidor MCP traduce la petición MCP a una llamada XML-RPC a la API de Odoo.sh.
Odoo.sh procesa la solicitud y devuelve el resultado vía XML-RPC.
Nuestro Servidor MCP recibe la respuesta de Odoo y la formatea como un Resultado MCP.
El Conector MCP recibe el resultado y lo devuelve a la Lógica del Agente.
El Agente envía el resultado de la herramienta de nuevo al LLM para generar la respuesta final al usuario.
La Lógica del Agente recibe la respuesta final en texto del LLM.
La App Backend llama a la API TTS de OpenAI para convertir el texto en audio (si es la interfaz de voz).
La App Backend actualiza la Interfaz Gradio mostrando el texto en el chat y/o reproduciendo el audio.
El Usuario ve/escucha la respuesta.
Importancia del Model Context Protocol (MCP):
MCP es la clave para la integración flexible y modular en este proyecto:
Estandarización: Define un contrato claro (
list_tools,call_tool) entre el agente y las capacidades de Odoo. El agente no necesita saber cómo hablar XML-RPC con Odoo, solo cómo usar las herramientas MCP.Desacoplamiento: La inteligencia del agente (OpenAI SDK) está separada de la implementación específica de Odoo (nuestro servidor MCP). Podemos cambiar el agente o el servidor Odoo (ej. a otra versión de Odoo o API) modificando solo una parte, siempre que se respete el contrato MCP.
Reusabilidad: Nuestro
mcp_odoo_server.pypodría ser utilizado por cualquier otro sistema o agente que entienda MCP, no solo por el SDK de OpenAI Agents.Modularidad: Permite exponer funcionalidades de sistemas complejos (como Odoo) de forma granular y controlada (herramienta por herramienta).
MCP actúa como una capa de abstracción esencial, permitiendo que sistemas inteligentes interactúen con herramientas y datos de forma estandarizada y segura.
Estructura del Proyecto 📂
mcp_odoo_fresh/
├── .venv/ # Entorno virtual Python (creado por uv)
├── agente_quindicolor_openai.py # Lógica del Agente OpenAI, configuración MCP
├── app_gradio_texto.py # Interfaz Gradio para chat de texto
├── app_gradio_voz.py # Interfaz Gradio para chat de voz (STT/TTS)
├── mcp_odoo_server.py # Servidor MCP -> Odoo (FastMCP, XML-RPC)
├── mcp_odoo_debug.log # Archivo de log del servidor MCP Odoo
├── .env # Archivo para credenciales (¡IGNORADO POR GIT!)
├── .env.example # Archivo de ejemplo para .env
├── pyproject.toml # Configuración del proyecto (usado por uv)
├── README.md # Este archivo
└── uv.lock # Dependencias bloqueadas por uvInstrucciones de Configuración 🛠️
Clonar/Descargar: Obtén los archivos del proyecto.
Prerrequisitos:
Python 3.10 o superior.
uvinstalado (ver guía oficial).Acceso a una instancia de Odoo (preferiblemente Odoo.sh) con un usuario y Clave API.
Una Clave API de OpenAI con crédito/cuota suficiente.
Crear y Activar Entorno Virtual:
cd ruta/a/mcp_odoo_fresh uv venv source .venv/bin/activate # Linux/macOS # .venv\Scripts\activate # WindowsInstalar Dependencias:
uv pip install openai-agents openai python-dotenv gradio mcp(Puedes también crear un
requirements.txtconuv pip freeze > requirements.txty luego usaruv pip install -r requirements.txt).Configurar Credenciales:
Renombra o copia
.env.examplea.env.Edita el archivo
.envy rellena TODAS las variables con tus valores reales:# === Credenciales Odoo.sh === ODOO_URL=https://tu-instancia.odoo.com ODOO_DB=nombre_tu_base_de_datos ODOO_USER=tu_login_odoo ODOO_PASSWORD=TU_CLAVE_API_DE_ODOO_SH # ¡Generada en Odoo.sh! # === Credenciales OpenAI === OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxxxxxx
Ejecución de la Demo ▶️
Puedes ejecutar la interfaz de texto o la de voz de forma independiente. Ambas iniciarán el servidor MCP Odoo necesario en segundo plano.
Opción 1: Interfaz de Texto
python app_gradio_texto.pyAbre la URL que indica la consola (normalmente http://127.0.0.1:7861).
Opción 2: Interfaz de Voz
python app_gradio_voz.pyAbre la URL que indica la consola (normalmente http://127.0.0.1:7860). Recuerda dar permiso al navegador para usar el micrófono.
Guiones de Prueba
Puedes usar los guiones proporcionados anteriormente (adaptados a tus productos/clientes) para probar el flujo completo en cualquiera de las interfaces.
Troubleshooting Básico 🐛
Error Odoo: Revisa URL, DB, User, Password (API Key!) en .env. Mira mcp_odoo_debug.log.
Error OpenAI: Verifica tu API Key y cuota en platform.openai.com.
Error Gradio (Micrófono): Revisa permisos del navegador/OS. Usa URL local. Prueba otro navegador.
Otros: Revisa los logs en la terminal donde ejecutas la app Gradio.
Ideas Futuras 💡
Implementar la herramienta crear_factura_desde_pedido (requiere investigar método Odoo no privado).
Añadir más herramientas (ej. consultar stock, estado pedido).
Mejorar el manejo de errores y la robustez.
Implementar streaming de texto en la interfaz de voz.
Optimizar el arranque/conexión del servidor MCP.
Usar un gr.Chatbot visible en la app de voz para mostrar historial
este proyecto nos hizo ganadores jeje
Available Tools
5 toolsbuscar_clienteA
Busca clientes en Odoo cuyos nombres coincidan (parcialmente, sin importar mayúsculas/minúsculas) con el nombre proporcionado. Devuelve ID, Nombre, Email, Teléfono (máx 5).
| Name | Required | Description | Default |
|---|---|---|---|
| nombre_cliente | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses the partial match, case-insensitivity, return fields, and the 5-result limit. It does not mention error handling or no-match behavior, but for a read-only search this is sufficient.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence that front-loads the action and includes key details (matching behavior, return fields, limit) without any unnecessary wording.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a low-complexity tool with one parameter and no output schema, the description covers the essential information: what it searches, how it matches, and what it returns. It lacks explicit error or empty-result behavior, but that is not critical for a simple search.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has only one parameter (nombre_cliente) with 0% description coverage. The description adds that the provided name is used for partial, case-insensitive matching, which clarifies the parameter's semantics beyond the raw name. However, it does not provide format or length constraints.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb (busca), the resource (clientes en Odoo), the matching behavior (parcial, case-insensitive), and the return fields with a max limit. This distinguishes it from sibling tools like buscar_producto which search a different entity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies its usage for searching customers by name, but it does not explicitly mention when to use it over alternatives or any exclusion criteria. For a simple search tool, this is adequate but not explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
buscar_productoA
Busca productos en Odoo cuyos nombres coincidan (parcialmente, sin importar mayúsculas/minúsculas) con el nombre proporcionado. Devuelve ID, Nombre, Código, Precio, Cant. Disponible (máx 5).
| Name | Required | Description | Default |
|---|---|---|---|
| nombre_producto | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden. It discloses partial matching, case-insensitivity, and a maximum of 5 results, which is useful. However, it does not mention read-only nature or error handling, though these are typical for search tools.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no fluff: the first states the purpose and matching rules, the second lists return fields and the result cap. Information is front-loaded and efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter search with no output schema, the description covers the essential aspects: what it searches, how it matches, and what it returns. It does not specify empty-result behavior, but that is a minor gap for a search tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has no description for 'nombre_producto', so the description compensates by explaining the parameter's role as the name to match and how matching works (partial, case-insensitive). This adds meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Busca' (searches), the resource 'productos en Odoo', and the matching criteria (partial, case-insensitive). It distinguishes from siblings like listar_productos by focusing on name-based search and explicitly lists returned fields.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage when a product name is known, but does not explicitly mention when not to use it or compare it to alternatives like listar_productos. The context is clear but lacks explicit routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
confirmar_cotizacionA
Confirma una cotización (Orden de Venta) en Odoo usando su ID. Verifica el estado antes y después. La cotización debe estar en 'draft' o 'sent'.
| Name | Required | Description | Default |
|---|---|---|---|
| cotizacion_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses that the tool verifies state before and after and requires 'draft' or 'sent' status, which is useful. However, it doesn't disclose what happens on failure, whether the operation is reversible, or what the response contains. The state verification detail adds value but the mutation's side effects are not fully described.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences with no filler. The core action is front-loaded, followed by the state precondition and verification behavior. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter tool with no output schema, the description covers the essential action and precondition. However, it lacks information about error handling, what the confirmation result looks like, and any side effects (e.g., sending the order, locking it). Given no annotations and no output schema, a bit more behavioral context would make it complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It explains that cotizacion_id is the ID of the quote to confirm, which adds meaning beyond the bare schema. However, it doesn't specify the ID format beyond being an integer, which the schema already provides, so the added value is modest.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Confirma una cotización (Orden de Venta) en Odoo usando su ID') and identifies the resource (cotización/Orden de Venta). It distinguishes itself from siblings like crear_cotizacion by focusing on confirmation, though it doesn't explicitly name a sibling alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context: the cotización must be in 'draft' or 'sent' state, and it verifies state before and after. This implies when to use the tool (when confirming a quote) and gives a precondition, though it doesn't explicitly state when not to use it or name alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
crear_cotizacionA
Crea una nueva cotización (Orden de Venta) en Odoo para un cliente específico con las líneas de producto dadas.
Args: cliente_id (ID del cliente), lineas (Lista de dicts {'product_id': ID_PROD, 'product_uom_qty': CANTIDAD}).
Returns: ID de la cotización creada o mensaje de error.
Ejemplo lineas: [{'product_id': 40, 'product_uom_qty': 2}, {'product_id': 35, 'product_uom_qty': 1}]
| Name | Required | Description | Default |
|---|---|---|---|
| lineas | Yes | ||
| cliente_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden. It does disclose that this is a creation operation and that it returns either the new quote ID or an error message. However, it omits details about authorization requirements, side effects, idempotency, or failure modes beyond the generic 'mensaje de error', leaving meaningful gaps for a mutation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, well-organized, and front-loaded with the core purpose. The Args, Returns, and example sections each earn their place, adding concrete usage detail without unnecessary verbosity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter creation tool with no annotations and no output schema, the description covers the essential context: what the tool does, the exact parameter shapes, and the return value. It falls slightly short of a 5 only because it does not mention preconditions such as the client and products needing to exist, or what error conditions can be expected.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it does thoroughly. It explains cliente_id as the client ID and lineas as a list of dicts with product_id and product_uom_qty keys, and it provides a concrete example. This tightens the loose schema, where lineas items have additionalProperties: true.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Crea una nueva cotización (Orden de Venta) en Odoo para un cliente específico con las líneas de producto dadas.' This clearly states what is created, in which system, and for whom. It is also easy to distinguish from the sibling tools, which are search/listing/confirmation operations rather than creation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes the invocation context obvious: an agent should call this tool when it needs to create a new sales quotation with specified product lines for a client. It does not explicitly name alternatives or list when not to use it, but the creation-oriented wording is unambiguous enough to avoid confusion with the search/confirm siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
listar_productosA
Lista los primeros 20 productos vendibles disponibles en Odoo.
Args:
None
Returns:
Una cadena de texto formateada con la lista de productos (ID, Nombre, Código, Precio)
o un mensaje de error.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does disclose the return shape: a formatted string with ID, name, code, and price, or an error message. However, it does not mention ordering, pagination, read-only status, or side effects, leaving moderate gaps.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and well-structured, with the main action front-loaded and an Args/Returns section. Every sentence adds meaningful information, aside from the minor redundancy of 'Args: None' with the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple 0-parameter listing tool with no output schema, the description is nearly complete: it identifies the resource and specifies the returned fields and error fallback. It omits details about pagination beyond the first 20, but that is a minor gap for this complexity level.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the 0-parameter baseline of 4 applies. The description reinforces this with 'Args: None', and the input schema already fully covers the empty parameter set.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: listing the first 20 sellable products in Odoo, with a clear scope. This distinguishes it from the sibling buscar_producto, which searches for a specific product rather than listing a range.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is given about when to use this tool versus buscar_producto or the other siblings. The only signal is implicit, and the description never states exclusions or the selection rule that would route an agent to this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.1.0- First observed
buscar_cliente - First observed
buscar_producto - First observed
confirmar_cotizacion - First observed
crear_cotizacion - First observed
listar_productos
TDQS
Scored across 5 tools
buscar_cliente and buscar_producto are clearly separated by entity, and crear_cotizacion/confirmar_cotizacion distinguish creation from state transition. There is minor overlap between buscar_producto and listar_productos, but the descriptions make the search-vs-list distinction explicit.
All tool names follow a consistent Spanish verb_noun pattern: buscar_cliente, buscar_producto, crear_cotizacion, confirmar_cotizacion, listar_productos. No mixed casings or inconsistent verb styles are present.
Five tools tightly cover the core quotation workflow: find customer, find product, list products, create quote, and confirm quote. The count is appropriate and nothing feels redundant or out of scope.
The create-and-confirm quotation lifecycle is covered, and customer/product search avoids dead ends. Missing operations like updating, canceling, or viewing quotation details are minor gaps for this focused server, though they would matter for broader sales-order management.
Maintenance
Related MCP Connectors
- odooOAuthcom.odooconsole
Odoo ERP for AI agents: hosted OAuth endpoint, gated writes, one endpoint for every instance.
Let AI agents query data and act across all your business apps via MCP.
Hosted MCP for e-commerce: live product catalog, stock, and pricing for AI agents.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables LLMs to interact with Odoo ERP systems through MCP protocol. Supports multi-server architecture with secure authentication, allowing natural language access to Odoo data, resources, and business operations.-
- AlicenseNot gradedqualityDmaintenanceBridges AI agents to Odoo ERP via MCP, enabling CRUD operations, model introspection, and report generation with secure API key and connection management through a web admin UI.4GPL 3.0
- AlicenseNot gradedqualityCmaintenanceEnables interaction with Odoo ERP systems for product, customer, order, invoice, and payment management using MCP tools.6MIT
- FlicenseNot gradedqualityDmaintenanceFull-featured MCP connector for Odoo ERP via XML-RPC, enabling natural language interaction with CRM, sales, inventory, and other Odoo modules.-