Odoo MCP Server
A modular, type-safe, and secure MCP (Model Context Protocol) server for interacting with Odoo 18 ORM.
mcp-name: io.github.nicolasramos/odoo-mcp
Overview
Odoo MCP Server provides a comprehensive interface to Odoo 18 through the MCP protocol, enabling LLMs (Large Language Models) to interact with Odoo in a secure, controlled manner. The server replaces monolithic CRUD access with granular tools for specific business operations while respecting Odoo's native security model.
Architecture
The server is built with a 6-layer architecture:
- Core Layer: RPC client, session management, exceptions, domain validation, and serialization
- Security Layer: Allowlists, denylists, guards, audit logging, and data redaction
- Observability Layer: Structured logging, performance metrics, and audit trails
- Schemas Layer: Pydantic validation for all requests
- Tools Layer: 38+ MCP tools for specific operations (CRUD, business logic)
- Services Layer: 14 domain services orchestrating complex operations
Key Features
- 🔒 Security-First: Native Odoo ACL delegation, allowlists, denylists, and field-level protection
- 🏢 Multi-Company: Full support for Odoo's multi-company architecture
- 📊 Observability: Built-in logging, metrics, and audit trails
- ✅ Type-Safe: Full Pydantic validation on all inputs/outputs
- 🧪 Well-Tested: Comprehensive test suite with E2E validation
- 🔧 Modular: Easy to extend with new tools and services
- 📝 Odoo 18 Compatible: Updated for latest Odoo 18 field changes (customer_rank, supplier_rank, payment_state)
Installation
From Source
git clone https://github.com/nicolasramos/odoo-mcp.git
cd odoo-mcp
pip install -e .
Development Installation
pip install -r requirements-dev.txt
pre-commit install
Configuration
Create a .env file from the example:
cp .env.example .env
Edit .env with your Odoo credentials:
ODOO_URL=https://yourcompany.odoo.com
ODOO_DB=database_name
ODOO_USERNAME=admin
ODOO_PASSWORD=your_password
ODOO_MCP_DEFAULT_LIMIT=50
ODOO_MCP_MAX_LIMIT=80
Usage
Running the Server
# As a Python module
python -m odoo_mcp
# Or using the installed command
odoo-mcp
Available MCP Tools
The server provides 38 tools organized by domain:
Core CRUD
odoo_search- Search records with domain filtersodoo_read- Read specific record IDsodoo_create- Create new recordsodoo_write- Update existing recordsodoo_invoke_action- Execute workflow actions
Partners & Customers
odoo_find_partner- Find or create partnersodoo_get_partner_summary- Get partner overview with related documents
Sales & CRM
odoo_find_sale_order- Search sale ordersodoo_get_sale_order_summary- Get detailed order informationodoo_create_sale_order- Create new sale ordersodoo_confirm_sale_order- Confirm draft ordersodoo_create_lead- Create CRM leads/opportunities
Projects & Tasks
odoo_find_task- Search project tasksodoo_create_task- Create new tasksodoo_update_task- Update task status/assignmentodoo_log_timesheet- Log work time
Activities & Chatter
odoo_create_activity- Schedule activitiesodoo_list_pending_activities- List pending activitiesodoo_mark_activity_done- Complete activitiesodoo_post_chatter_message- Post messages to records
Accounting & Finance
odoo_find_pending_invoices- Find unpaid invoicesodoo_get_invoice_summary- Get invoice detailsodoo_register_payment- Record paymentsodoo_create_vendor_invoice- Create vendor bills
Purchasing
odoo_create_purchase_order- Create purchase orders
Calendar
odoo_create_calendar_event- Create meetings/appointments
Inventory
odoo_get_product_stock- Check product quantities
Helpdesk
odoo_create_helpdesk_ticket- Create support ticketsodoo_create_helpdesk_ticket_from_partner- Create tickets from partners
Contracts
odoo_create_contract_line- Add contract linesodoo_replace_contract_line- Replace contract linesodoo_close_contract_line- Close contract lines
Introspection
odoo_get_model_schema- Get model field definitionsodoo_get_capabilities- List available operationsodoo_get_record_summary- Get record overview
MCP Resources
The server exposes 5 dynamic resources:
odoo://context/odoo18-fields-reference- Critical Odoo 18 field changesodoo://models- List of available modelsodoo://model/{model}/schema- Model field definitionsodoo://record/{model}/{id}/summary- Record summariesodoo://record/{model}/{id}/chatter_summary- Chatter history
Security
Native Odoo Security
The server authenticates with Odoo using standard JSON-RPC endpoints and executes all operations as the configured user. This ensures:
- ✅ Record Rules are respected
- ✅ Access Rights (ACL) are enforced
- ✅ Company segregation is maintained
- ✅ User permissions are honored
Important: For production use, create a dedicated Odoo user with minimal required permissions for the specific models and operations you need.
MCP Security Layers
- Model Allowlist: Only 28 approved models can be accessed
- Field Denylist: Protected fields (company_id, state, etc.) cannot be written directly
- Unlink Blocking: All delete operations are blocked
- Action Guards: Only workflow actions (action_, button_) are permitted
- Data Redaction: Sensitive values (passwords, tokens) are redacted from responses
Development
Running Tests
# Unit tests
pytest tests/ -v
# With coverage
pytest tests/ --cov=src/odoo_mcp --cov-report=html
# E2E tests (requires real Odoo instance)
python tests/qa_e2e_runner.py
Code Quality
# Format code
black src/ tests/
# Lint
ruff check src/ tests/
# Type check
mypy src/
Documentation
- Architecture - Detailed system architecture
- Deployment Guide - Production deployment instructions
- QA Runbook - Comprehensive testing guide
Examples
See the examples/ directory for usage examples:
basic_usage.py- Basic MCP interactionsmcp_config.json- MCP client configuration
Odoo 18 Compatibility
This server is designed for Odoo 18 and includes critical updates for field changes:
res.partner Changes
- ❌
customer=True→ ✅customer_rank > 0 - ❌
supplier=True→ ✅supplier_rank > 0 - ❌
is_customer=True→ Field does not exist
account.move Changes
- ❌
state=open→ ✅state=postedANDpayment_state=not_paid - ❌
state=paid→ ✅state=postedANDpayment_state=paid
Always use odoo_find_pending_invoices - it handles Odoo 18 domains correctly.
Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Development Guidelines
- Follow PEP 8 style guidelines
- Add tests for new features
- Update documentation for API changes
- Use type hints where appropriate
- Keep security in mind - allowlist models, validate inputs
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
Author
Nicolás Ramos - GitHub
Acknowledgments
Built with:
Metadata
Release files for odoo-18-mcp-server 2.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| odoo_18_mcp_server-2.0.0.tar.gz | 9.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| odoo_18_mcp_server-2.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 16.3 kB
Release files / odoo_18_mcp_server-2.0.0.tar.gz
| Download URL | odoo_18_mcp_server-2.0.0.tar.gz |
|---|---|
| Size | 9.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
64d924e2db60d88f6a45192043e20e30e66d61ba61718764d8eb380a4c52298c
|
|
BLAKE2b-256 checksum How to use checksums |
5c93704d70f8b3cc18693013445621ce3bd16ed0593c3162ab0595c7485f3efc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|
Release files / odoo_18_mcp_server-2.0.0-py3-none-any.whl
| Download URL | odoo_18_mcp_server-2.0.0-py3-none-any.whl |
|---|---|
| Size | 6.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1c1826c3387da7ca81b437969405d6fb2a3ec05e3cc39f69d8bb87f53092c107
|
|
BLAKE2b-256 checksum How to use checksums |
b511819866b5ae4a2f3b9b7e0125947bd81ad2fb80c2c645ed653a763135ff2c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|