Manage business accounting via Odoo ERP using XML-RPC API. Use when creating invoices, recording expenses, querying financial data, or managing customers and products. NOT when using QuickBooks or Xero (different systems).
FastMCP server for Odoo ERP integration via XML-RPC API.
# Start MCP server
python src/mcp_servers/odoo_server.py
# Check connection
python -c "from src.mcp_servers.odoo_server import check_connection; print(check_connection())"
| Tool | Description |
|---|---|
create_customer_invoice | Create customer invoice with line items |
record_expense | Record vendor bill (expense) |
get_financial_summary | Revenue, expenses, profit for date range |
list_recent_invoices | List recent customer invoices |
list_recent_bills | List recent vendor bills |
list_products | Search/list products |
get_partner_details | Get customer/vendor details |
check_connection | Verify Odoo connectivity |
Invoice lines require Odoo's special tuple format (0, 0, {...}):
# ✓ CORRECT - Tuple format for new lines
invoice_line_values.append((0, 0, {
'product_id': product_id,
'name': description,
'quantity': quantity,
'price_unit': unit_price
}))
# ✗ WRONG - Plain dictionary
invoice_line_values.append({
'product_id': product_id,
...
})
The (0, 0, {...}) means: "Create new record with these values".
Odoo uses move_type to distinguish invoice types:
| Type | Move Type |
|---|---|
| Customer Invoice | out_invoice |
| Customer Refund | out_refund |
| Vendor Bill | in_invoice |
| Vendor Refund | in_refund |
When customer/vendor doesn't exist, system auto-creates:
customer_rank: 1supplier_rank: 1Missing products are auto-created as type: 'service'. For physical products, create manually in Odoo.
Partner fields return [id, name] tuple, not just ID:
# partner_id = [42, "Acme Corp"]
customer_name = invoice['partner_id'][1] # "Acme Corp"
customer_id = invoice['partner_id'][0] # 42
Only invoices/bills with state: 'posted' are included in financial summaries. Draft invoices are excluded.
All dates must be ISO format YYYY-MM-DD:
# ✓ CORRECT
create_customer_invoice(..., invoice_date="2026-01-30")
# ✗ WRONG
create_customer_invoice(..., invoice_date="01/30/2026")
API calls use circuit breaker for resilience. After 3 failures, circuit opens for 30 seconds.
Required in .env:
ODOO_URL=http://localhost:8069 # Odoo server URL
ODOO_DB=digital_fte # Database name
ODOO_USERNAME=admin # Odoo username
ODOO_PASSWORD=your_password # Odoo password (KEEP SECRET)
See docs/setup/ODOO_SETUP.md for full setup guide.
Quick local setup:
docker run -d -e POSTGRES_USER=odoo -e POSTGRES_PASSWORD=odoo -e POSTGRES_DB=postgres --name db postgres:13
docker run -d -p 8069:8069 --link db:db -e HOST=db -e USER=odoo -e PASSWORD=odoo --name odoo odoo
Odoo 14+ has XML-RPC enabled by default. Verify at:
http://localhost:8069/xmlrpc/2/common
For production, create a dedicated API user with appropriate permissions.
AuditDomain.BUSINESSODOO_PASSWORD in .env, never commitConnection is cached globally to avoid repeated authentication:
_odoo_connection = None # Module-level cache
def get_odoo() -> OdooConnection:
global _odoo_connection
if _odoo_connection is None:
_odoo_connection = OdooConnection(...)
return _odoo_connection
Run: python scripts/verify.py
generating-ceo-briefing - Uses financial data for reportswatching-gmail - Detect invoice requests from emailsdigital-fte-orchestrator - Process accounting tasks