odoo-mcp-server
Provides read-only tools and resources to query live Odoo 19 data, including partners, sales orders, inventory, revenue summaries, and unpaid invoices, with a defense-in-depth security layer.
Click on "Install 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., "@odoo-mcp-servercheck stock for product 'Office Chair'"
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.
odoo-mcp-server
An MCP server that lets AI assistants safely query live Odoo 19 data — with a defense-in-depth security layer.
✅ Working. The three v1 tools run live against Odoo 19 and are verified end-to-end through Claude Desktop. The security layer is being formalized into dedicated modules and the schema resource is next — see the Roadmap for live status.

Table of Contents
Related MCP server: Odoo MCP Server
Why this exists
Odoo's product direction includes a growing surface of AI/LLM-powered features: AI-computed fields, conversational agents, voice-to-text, OCR, and intelligent document parsing — all leveraging external LLMs through inference APIs. These features need a clean, safe way for AI systems to read live business data without becoming an attack surface.
The Model Context Protocol (MCP) is the open standard that connects AI assistants to external data sources and tools. As of 2026, every major AI client supports it — Claude Desktop, GitHub Copilot, Cursor, Continue, and others.
odoo-mcp-server is what happens when those two worlds meet. It exposes a curated, security-hardened slice of Odoo to any MCP-compatible AI assistant, so users can:
Ask Claude "What were our top customers last quarter?" and get a real answer from live Odoo data.
Ask Copilot "Which products are running low?" while writing code, without switching context.
Build internal AI agents that can read sales, inventory, and finance data without being granted database-level access.
It is built outside Odoo on purpose. The server speaks to Odoo over XML-RPC — meaning it works with any Odoo 19 deployment (community, enterprise, on-premise, or odoo.sh) without modifying the Odoo instance itself.
What v1 delivers
Working now:
✅ 3 read-only tools covering partners, sales, and inventory
✅ XML-RPC Odoo client with authentication and a cached session
✅ FastMCP server, verified end-to-end through Claude Desktop
✅ Field whitelisting and hard result caps enforced on every tool
✅ Typed configuration via Pydantic Settings (fails loudly on bad values)
✅ Docker Compose dev setup (Odoo 19 + Postgres)
In progress:
🔨 Security layer formalized into dedicated modules (RBAC, rate limit, audit)
🔨
odoo://schemaresource for model/field introspection🔨
AI_INTEGRATION_DESIGN.md— LLM-ERP integration trade-offs🔨
LEARNING_JOURNAL.md— the day-by-day build journey
Architecture
The server is structured as 8 layers, each with a single responsibility. Each layer can only talk to the one directly below it — security is enforced at Layer 3, before any tool code runs, so it can never be bypassed by adding a new tool.
See the diagram above for the visual overview. In short:
AI Client Layer — Claude Desktop, Copilot, Cursor, or any MCP client
MCP Server Layer — FastMCP entry point, handshake, transport
Security Gate Layer — Auth, RBAC, field whitelist, rate limit, audit (the wall)
Tool Orchestration — Registry, dispatch, Pydantic schema validation
Domain Logic Layer — Partners, sales, inventory (reporting and finance in v1.1)
Odoo Client Layer — XML-RPC wrapper, cached session
Network Transport — XML-RPC over HTTP(S), service-account auth
Odoo 19 Instance — Any deployment, with native ACLs as defense-in-depth
A full breakdown of each layer's responsibilities and rationale lives in docs/AI_INTEGRATION_DESIGN.md (in progress).
The 3 Tools
All tools in v1 are read-only. Each goes through the security layer before reaching Odoo.
1. search_partners
Find customers, suppliers, or contacts by name.
Input | Type | Description |
| string (optional) | Partial, case-insensitive name match |
| bool (default false) | Return only companies, not individuals |
| int (default 20, capped by server) | Max records to return |
Returns: list of partners with id, name, email, phone, city, country, is_company.
2. list_sale_orders
List sales orders, optionally filtered by customer or status.
Input | Type | Description |
| string (optional) | Partial match on the customer's name |
| enum (optional) |
|
| int (default 20, capped by server) | Max records to return |
Returns: list of orders with id, reference, customer, order date, total, untaxed total, state, currency.
3. check_stock
Physical stock levels per product and location.
Input | Type | Description |
| string (optional) | Partial match on the product's name |
| int (default 20, capped by server) | Max records to return |
Returns: list of stock records with product, location, quantity, and available quantity — internal warehouse locations only.
The Schema Resource
(In progress — targeted for v1.)
odoo://schema
Resources are read-only context endpoints that AI clients can subscribe to. odoo://schema will list the Odoo models the server can read and their accessible fields, after the field whitelist is applied — so an AI client can discover what it is allowed to ask for.
Security Model
This layer is the project's center of gravity. It sits above all tool code and is enforced for every request, before any business logic runs. The field-whitelisting and hard-cap guards are live today; the remaining guards are being formalized into dedicated modules.
Guard 1 — Authentication
Odoo credentials are loaded from environment variables only — never from tool parameters.
API keys (Odoo 14+) are supported and recommended over passwords.
The Odoo user the server authenticates as is intended to be a dedicated service account, never a real human user. This account should have minimum-necessary Odoo ACLs configured in Odoo itself — defense in depth.
Guard 2 — Authorization (RBAC)
Each tool declares its required permission level:
readorwrite.The server boots with a permission profile (default:
read).Write tools refuse to register if write mode is disabled.
The profile is loaded from env var at startup and cannot change at runtime.
Guard 3 — Field Whitelisting
Every tool declares which Odoo model fields it can read.
A per-tool whitelist enforces this before any read hits Odoo — a field outside the list can never leave the system, even by accident.
Some domain filters are enforced invariants the caller cannot override (for example,
check_stockonly ever reads internal warehouse locations).A
FIELD_BLACKLISTof always-rejected fields includespassword,password_crypt,api_key,signature, and binary image fields.
Guard 4 — Rate Limiting & Hard Caps
Per-client request rate: 60 calls/minute (configurable).
Hard cap on result-set size: 100 records per call, enforced in code regardless of what the caller requests, configurable down only.
Query timeout: 10 seconds, to stop long-running queries from hanging the server.
Guard 5 — Audit Logging
Every tool call is logged before execution: timestamp, tool name, parameters (sensitive ones redacted), client identifier.
Every result is logged after execution: success/failure, record count, duration.
Logs are written to rotating files in append-only mode.
Never log full result payloads — only metadata.
Security Defaults (Locked)
Setting | Default | Override |
Permission mode |
|
|
Max records per call | 100 |
|
Query timeout | 10 seconds |
|
Rate limit | 60 calls/min |
|
Audit log path |
|
|
Transport | stdio only | (SSE deferred to v2) |
Master password access | Disabled | (no env override in v1) |
Three Principles
Defense in depth. Five guards plus Odoo's own ACLs on the service account. Compromising one wall does not compromise the system.
Secure by default, opt-in to risk. Read-only at startup; every relaxation requires an explicit, conscious config change.
Fail closed, never open. Auth fails → reject. Rate limit hit → reject. Field not whitelisted → reject. Audit log can't write → halt the server (loud failure, not silent skip).
Tech Stack
Layer | Choice | Why |
Language | Python 3.11+ | Standard for MCP servers and Odoo |
MCP framework | Mature, opinionated, fast | |
Odoo connection |
| Official, no extra dependency |
Validation | Pydantic v2 | Typed schemas for every tool I/O |
Config | Pydantic Settings + | Typed config, fails loudly on bad values |
Testing | pytest | Standard |
Containerization | Docker Compose | Reproducible setup: Odoo + Postgres |
Quick Start
The three tools run against a live Odoo 19 instance today. For development, use
docker-compose.dev.ymlto boot Odoo + Postgres, then run the server on the host and connect it to Claude Desktop.
# Clone
git clone https://github.com/MrKhaled007/odoo-mcp-server.git
cd odoo-mcp-server
# Configure
cp .env.example .env
# Edit .env with your Odoo URL, database, and credentials
# Boot Odoo + Postgres for local development
docker compose -f docker-compose.dev.yml up -d
# Run the MCP server on the host
pip install -e .
python -m odoo_mcp.server
# Connect Claude Desktop
# Add the server to your Claude Desktop MCP config (command, args, cwd, env).
# Full walkthrough coming in docs/CLAUDE_DESKTOP_SETUP.mdConfiguration
All configuration is via environment variables. See .env.example for the full list. Key variables:
# Odoo connection
ODOO_URL=http://localhost:8069
ODOO_DB=odoo_demo
ODOO_USERNAME=service_account
ODOO_API_KEY=<your-api-key>
# Security
MCP_PERMISSION_MODE=read # 'read' or 'write' (write opt-in only)
MCP_MAX_RECORDS=100 # Hard cap, ceiling 500
MCP_QUERY_TIMEOUT=10 # Seconds
MCP_RATE_LIMIT=60 # Calls per minute per client
MCP_AUDIT_PATH=./logs/audit.logRoadmap
v1
Architecture and security model designed
Repo skeleton + README
FastMCP server scaffold
Odoo client wrapper (read-only) — auth + search / read / search_read / search_count
3 tools implemented (search_partners, list_sale_orders, check_stock)
Field whitelisting + hard result caps on every tool
Docker Compose dev setup (Odoo 19 + Postgres)
Verified end-to-end through Claude Desktop
Security gate formalized into modules (RBAC, rate limit, audit)
Resource:
odoo://schemaDemo video
AI_INTEGRATION_DESIGN.mdLEARNING_JOURNAL.md
v1.1 — Mid-July 2026
Tool:
revenue_summary(aggregated sales by period)Tool:
unpaid_invoices(accounts receivable status)Resource:
odoo://company(current company info)Expanded test coverage
v2 — Future
Write tools (create, update, unlink) gated behind explicit opt-in
SSE/HTTP transport for remote deployments
OAuth/API key rotation
Connection pooling beyond a single shared client
Tests with high coverage
PyPI release
Multi-database support
v3 — Long-term
Native Odoo module wrapping the server (so Odoo admins can configure it from the Odoo UI)
AI-computed fields as a separate companion module
Conversational agent flows using the same data layer
Out of Scope (for now)
Explicitly not in v1, by design:
❌ Write tools. Designed, not implemented. Forces the conversation: do you really want an AI writing to your ERP?
❌ SSE / HTTP transport. Stdio only — strongest default security guarantee.
❌ OAuth, API key rotation. Env vars only.
❌ Production packaging. Not on PyPI in v1. Run from source.
❌ High test coverage. Smoke tests only. Real test suite in v2.
These exclusions are not bugs — they are scope discipline. v1 ships a correctly small system, not an incorrectly large one.
About
Built by Mohammed Khaled — final-year BSc Data Science student at Thomas More University Mechelen (Belgium), working on the intersection of AI agents and business systems.
Related open-source work:
OCA/reporting-engine PR #1173 — USAGE documentation for
sql_export_excelgithub.com/MrKhaled007 — other projects
Portfolio: mdkhaledportfolio.netlify.app
License
MIT — do whatever you want, just don't blame me.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/MrKhaled007/odoo-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server