Exposes an MCP (Model Context Protocol) server as part of the Odoo HTTP server.
Claude/Cursor can query and manage your Odoo data using natural language.
Installing the module is enough — no separate process needed.
Setup:
1. Install the module on your Odoo database.
2. Pass the database per request by: ?db=<name>, header X-Odoo-Database, or Bearer demo_ai:YOUR_API_KEY.
3. Claude/Cursor: use mcp-remote with --transport sse-only and --allow-http.
If you get 404: add server_wide_modules = web,rag_odoo_mcp_server to [options] and restart Odoo.
Usage Examples (natural language → MCP tools)
---------------------------------------------
Data retrieval:
• "Show me all customers from Spain"
→ odoo_search_read(model="res.partner", domain=[["country_id.code", "=", "ES"]])
• "Find products with stock below 10 units"
→ use product.product / stock.quant with odoo_search_read or run_readonly_query
• "List today's sales orders over $1000"
→ odoo_search_read(model="sale.order", domain=[["amount_total", ">", 1000], ...])
• "Search for unpaid invoices from last month"
→ odoo_search_read(model="account.move", domain=[["payment_state", "!=", "paid"], ...])
Data management:
• "Create a new customer contact for Acme Corporation"
→ odoo_create(model="res.partner", values={"name": "Acme Corporation", "is_company": true})
• "Add a new product called 'Premium Widget' with price $99.99"
→ odoo_create(model="product.product", values={"name": "Premium Widget", "list_price": 99.99})
• "Update the phone number for customer John Doe"
→ odoo_search_read to find id, then odoo_write(model="res.partner", ids=id, values={"phone": "..."})
• "Change the status of order SO/2024/001 to confirmed"
→ odoo_search_read to find id by name, then odoo_execute(model="sale.order", ids=id, method_name="action_confirm")
• "Delete the test contact we created earlier"
→ odoo_unlink(model="res.partner", ids=[...])
API Endpoints (in-Odoo MCP)
---------------------------
GET /mcp/sse?db=<database> — SSE stream (connect here; receive session endpoint).
POST /mcp/messages/?session_id=<id>&db=<database> — JSON-RPC (tools/list, tools/call).
GET /mcp/health?db=<database> — Health check.
Optional: Authorization: Bearer <key> or X-API-Key: <key> when API key is required in Settings.
MCP tools (in-Odoo): list_tables, describe_table, get_table_row_count, run_readonly_query,
get_odoo_models_info, get_table_schema_pg, odoo_search_read, odoo_create, odoo_write,
odoo_unlink, odoo_execute.
Standalone (read-only SQL, no ORM): pip install -r rag_odoo_mcp_server/requirements-mcp.txt
python -m rag_odoo_mcp_server.mcp_server --host 0.0.0.0 --port 8000
SSE: http://<host>:8000/sse (no odoo_search_read / create / write / unlink / execute).
***How users can specify company (no need we added the selector directly in the configuration menu in the new update) will leave it here for manual config
Three-tier priority: per-tool argument > per-request/session > system default
- Per-tool: odoo_search_read("sale.order", company_id=2)
- Per-request: ?company_id=2 on URL or X-Odoo-Company: 2 header
- Session-level: ?company_id=2 on the SSE connect URL
- System default: Set in Settings > RAG Odoo MCP Server > Company Context
- None: If nothing is set, all companies are visible (backward compatible)****
------------------------------------------
If you're running behind Nginx, calude will be faster if:
location /mcp/ {
proxy_pass http://your_odoo_backend;
proxy_buffering off;
proxy_set_header X-Accel-Buffering no;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
chunked_transfer_encoding on;
}
The key is proxy_buffering off; — without it, Nginx holds SSE events in a buffer and the client may not receive them.
--------------------------------------
update regarding odoo sh, you do not need to specify the database in the config block :
"mcpServers": {
"odoo": {
"command": "npx",
"args": [
"mcp-remote",
"https://link.dev.odoo.com/odoo/mcp/sse",
"--allow-http",
"--transport",
"sse-only",
"--header",
"Authorization:${MCP_CRM_AUTH}"
],
"env": {
"MCP_CRM_AUTH":Bearer tokenkey"
}
}
},