| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
Discuss (mail)
|
| Lines of code | 7980 |
| Technical Name |
lm_mcp_server |
| License | OPL-1 |
| Website | https://lemacore.com |
| Versions | 16.0 17.0 18.0 |
| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
Discuss (mail)
|
| Lines of code | 7980 |
| Technical Name |
lm_mcp_server |
| License | OPL-1 |
| Website | https://lemacore.com |
| Versions | 16.0 17.0 18.0 |
Lema Core Technologies
MCP Server — Connect AI Agents to Live Odoo Data
Turn Odoo into an AI-ready tool server. Securely expose your ERP to Claude, ChatGPT, Gemini, Cursor, n8n, LangChain, and any MCP-capable client through a single endpoint — with OAuth 2.0, scoped tokens, audit logs, BI tools, portal pages, async jobs, and AI-driven module generation.
Odoo 18 OPL-1 34+ MCP Tools
Lema Core Technologies is a provider of business software solutions specializing in custom Odoo development. We help businesses unlock the full potential of their Odoo instances through reliable, well-tested modules.
Demo Preview
See MCP Server in Action
Admin Guide
How Do You Perform Maintenance in Odoo?
MCP Server ships with built-in admin controls — manage tokens, audit sessions, clear cache, set retention policies, and test Redis connectivity — all from within Odoo Settings.
Use Cases
What You Can Build with MCP + Odoo
Turn Odoo into an AI-ready tool server. Connect Claude, ChatGPT, Gemini, Cursor/Claude Code, n8n, LangChain, crewAI (and more) to live Odoo data — with governance and audit logs.
Prompt-to-Dashboard
Dashboards inside Odoo
Generate KPI tiles, tables, and interactive ECharts visuals — with filters and drill-down to Odoo records.
Example: "Create a sales executive dashboard for YTD revenue by month and top customers."
Prompt-to-Portal
Public pages from live Odoo data
Create shareable portal pages that render server-side and stay always up-to-date (KPIs, charts, tables).
Example: "Create a shipping schedule page at /mcp-page/shipping with today's outgoing pickings."
Reporting / BI-Ready
Pivot, time-series, funnel, cohort
Opinionated helpers for analytics queries: pivot, timeseries, top-N, cohort, funnel, and export in one call.
Example: "Top 10 customers by revenue this quarter, grouped by salesperson."
Prompt-to-Workflow
Automations that respect ACLs
Create/update records via scoped keys, run batch operations, and offload heavy work to async background jobs.
Example: "Create leads from this CSV and assign by territory (batch + background job)."
Prompt-to-Module
Generate installable Odoo modules
Build a validated module spec, generate a ZIP, and install (or download) — including models, security, menus, and views.
Example: "Create a theme park management module with a kanban view and access groups."
External Apps
Standalone dashboards & portals
Build shipping schedules, executive dashboards, or customer portals outside Odoo — backed by live ERP data through one MCP endpoint.
Example: "Build a sales portal that shows real-time order status by customer."
Screenshots
Visual Walkthrough
OAuth 2.0 Authorize Access
Standards-compliant OAuth 2.0 Authorization Code flow with PKCE S256. Users authorize MCP clients through a branded login screen — credentials never leave Odoo.
Personal Access Tokens
Each user can mint their own scoped Personal Access Tokens for command-line tools, CI pipelines, and headless integrations. SHA-256 hashed at rest, shown only once.
Token Governance
Configure per-token scope (read-only, read-write, admin), model allowlist, field allowlist, IP allowlist/denylist, and audit payload capture — least-privilege access by default.
Session Audit Trail
Every MCP session is recorded with transport type, IP address, tool call count, duration, and (optionally) full request/response payloads with PII redaction.
Async Job Queue
Offload heavy work — bulk updates, mass exports, multi-step automations — to a background queue. Poll progress, inspect payloads, retry failures, and surface results back to the AI client without hitting HTTP timeout limits.
AI-Generated Portal Pages
Ask Claude to "create a shipping dashboard at /mcp-page/shipping" and get a public, mobile-responsive page rendered server-side from live Odoo data — KPI tiles, ECharts visuals, and interactive tables, no front-end work required.
Prompt-to-Module Generator
Describe the module you need in plain English. Claude produces a validated spec, the generator builds a fully-formed Odoo module (models, security, views, menus), and you can install it directly or download the ZIP for review.
One Settings Panel for Everything MCP
Manage retention policies, rate limits, Redis caching, schema cache TTL, and the module-generator feature flag — all from a single screen inside Odoo Settings. No external admin UI required.
AI Agent Conversations
Real conversations with Claude querying live Odoo data — search records, create sale orders, post chatter messages, generate reports, all through natural language.
Mobile Access
Ask Claude on Your Phone.
Get Live Odoo Data in Seconds.
No VPN. No Odoo login screen. No reports to run. Just open Claude on your phone, ask a question in plain English,
and get live ERP data back instantly — from anywhere, on any device.
Click to open full size
📱
Any Device, Anywhere
Phone, tablet, or desktop. The Claude connection follows the user — not the device or the office network.
💬
Plain English Queries
"What are my open invoices?" — Claude queries Odoo and returns a clear, structured answer in seconds.
🔒
Fully Governed
Per-key scopes, Odoo ACLs, and audit logs — every mobile query is controlled, traceable, and least-privilege.
Features
What You Get
Connectivity & Authentication
🔐 OAuth 2.0 + PKCE
Standards-compliant Authorization Code flow with PKCE S256, dynamic client registration (RFC 7591), refresh token rotation, and auto-discovery via /.well-known endpoints.
🔑 Personal Access Tokens
Self-service token management. Each user mints PATs for headless integrations. SHA-256 hashed at rest, displayed only once at creation.
⚡ Dual Transport
Streamable HTTP transport (MCP spec 2025-03-26) plus legacy SSE — works with Claude Desktop, ChatGPT, Cursor, Gemini, n8n, LangChain, and any MCP-capable client.
Governance & Audit
🛡️ Per-Token Scope
Read-only, read+write, or admin. Restrict the blast radius of each token. Combine with model allowlist and field allowlist for precise least-privilege access.
🌐 IP Allow/Deny Lists
CIDR-based IP restrictions per token. Lock tokens to your office network, your VPN range, or a specific automation server.
🔎 Audit Trail + Redaction
Every tool call logged with duration, record count, and result. Optional payload capture with automatic PII redaction (passwords, tokens, SSN, credit cards).
Advanced Capabilities
📊 BI Reporting Tools
Seven analytics tools in one call: pivot tables, time-series with gap-filling, top-N ranking, cohort retention, funnel conversion, CSV and XLSX exports.
🌍 Portal Pages
Public shareable dashboards with KPI tiles, ECharts visualizations, and tables. Server-side rendered, always live, mobile-responsive, embeddable via signed URL.
⚙️ Async Job Queue
Submit bulk updates, exports of 100k+ records, or heavy method calls and poll for status. Background cron processes jobs respecting token scope and restrictions.
Infrastructure
Deployment & Performance
Designed from the ground up for production use with horizontal scalability and observability.
🚀 Horizontal scalability
- Works with 1 worker, 10 workers, or 100+ workers
- Redis-backed distributed rate limiting (no coordination needed)
- Shared cache for model schemas across all workers
- No session affinity or sticky sessions required
- Automatic fallback if Redis unavailable
⚡ Performance benchmarks
- Cached requests: ~2ms (96% faster)
- Uncached requests: ~50-100ms (standard)
- Throughput: 4x improvement with caching
- Cache hit ratio: 80-90% typical
- Latency percentiles: p50: 3ms, p95: 25ms, p99: 80ms
What You Get
Capabilities
Built for secure AI connectivity with governance, least privilege, and predictable tooling.
🔧 Core capabilities
- MCP-style JSON-RPC endpoint for tool discovery and execution
- CRUD tools for controlled read/write operations
- Model discovery & description for agent planning
- Reporting/BI helpers (pivot, timeseries, top-N, cohort, funnel, export)
- Portal pages at /mcp-page/<slug> (KPIs, charts, tables)
- Module Builder for validated specs + installable ZIP modules
- Batch & async tools for efficient multi-call flows and long-running jobs
🛡️ Valuable safeguards
- Per-key scopes and standard Odoo ACLs/record rules
- Field allowlists and domain filters for least privilege
- Distributed rate limits with Redis backing (or in-memory fallback)
- Token rotation with zero-downtime grace periods
- Schema caching with automatic invalidation
- Audit logs with optional payload capture and retention policy
Connect multiple LLMs and agent frameworks: Claude, ChatGPT, Gemini, custom LLMs, LangChain, and crewAI.
System Architecture
End-to-End Integration
AI client → OAuth or Bearer token → /mcp endpoint → governance gate → tool dispatcher → live Odoo data
Transport Modes
Technical Specifications
Built on Odoo 18 Standards
📦 Dependencies
- base, web, mail
- Optional: redis-py (for distributed rate limit)
- Optional: xlsxwriter (for XLSX export)
🖥️ Deployment
- Odoo Community & Enterprise
- Odoo.sh (PaaS)
- On-Premise multi-worker
⚡ Performance
- Schema cache for fields_get / get_models / get_views (configurable TTL)
- Redis-backed distributed rate limit with in-memory fallback
- Auto-invalidation on schema change, LRU eviction at 1000 entries
🔒 Security
- Bearer tokens SHA-256 hashed, 30-day access / 90-day refresh expiry
- Per-token scope, model allowlist, field allowlist, IP allow/deny lists
- HTTPS enforcement option, CORS preflight, RFC 7009 token revocation
Integration Guides
How to Connect
Connect your favorite AI client to live Odoo data in minutes. No code required.
Step-by-step
Connect with Claude Web
Use Claude.ai with MCP to query Odoo data, create records, run reports, and build dashboards — directly from your browser.
- Install MCP Server for Odoo from the Apps menu.
- Go to MCP Server → Settings and copy your MCP endpoint URL.
- In Claude.ai, open your Project settings and add a new MCP integration.
- Paste your Odoo MCP endpoint and authorize via OAuth 2.0.
- Start chatting — ask Claude to search records, create invoices, or build a dashboard.
Step-by-step
Connect with Grok
Grok supports MCP connections for tool use. Link it to your Odoo instance and query your business data with natural language from the Grok interface.
- Generate a Personal Access Token from your Odoo user profile.
- In Grok's tool settings, add a new MCP server with your Odoo endpoint URL.
- Enter your Bearer token for authentication.
- Grok will auto-discover all available Odoo tools via tools/list.
- Ask Grok to pull CRM data, run analytics, or generate a report.
Step-by-step
Connect with ChatGPT
ChatGPT supports MCP servers through its connector framework. Point it at your Odoo MCP endpoint and give ChatGPT full access to your live ERP data.
- Go to MCP Server → Tokens and create a token with the required scope.
- In ChatGPT settings, navigate to Connectors and add a new MCP connection.
- Enter your Odoo MCP URL and paste your Bearer token.
- ChatGPT will auto-discover all tools from the tools/list endpoint.
- Start a chat: "What are my top 5 customers by revenue this month?"
Version History
What's New
Frequently Asked Questions
Got Questions?
Which AI clients can connect to this MCP Server?
How is authentication handled? Are credentials stored?
Can I limit what a token can read or write?
What tools does the AI client get out of the box?
What are Portal Pages and how do they work?
What is the Async Job Queue for?
How does the Module Generator work? Is it safe?
What about rate limiting and performance at scale?
Is this available for Odoo Community and Enterprise?
Do purchases include future version upgrades?
Related Products
MCP Server for Odoo — Technical Guide
Table of Contents
Overview
MCP Server for Odoo exposes your Odoo 18 instance as a Model Context Protocol (MCP) server. AI clients — Claude, ChatGPT, Gemini, Cursor, n8n, LangChain, crewAI — connect to live Odoo data through a single HTTP endpoint with OAuth 2.0 or Bearer token authentication.
- Protocol: MCP 2025-03-26 (Streamable HTTP) + legacy SSE
- Auth: OAuth 2.0 Authorization Code + PKCE S256, PAT Bearer tokens
- Tools: 34+ MCP tools (CRUD, analytics, BI, portal pages, async jobs, module generator)
- Odoo version: 18.0 (Community and Enterprise)
- License: OPL-1
Requirements
System Requirements
- Odoo 18.0 (Community or Enterprise)
- Python 3.11+
- PostgreSQL 15+
- Odoo must be reachable over HTTPS in production (required for OAuth 2.0 redirects)
Optional Python Packages
These are installed separately if you want the optional features:
# For distributed Redis rate limiting pip install redis # For XLSX export (odoo_export_xlsx tool) pip install xlsxwriter
Both packages fall back gracefully if not installed: redis → in-memory rate limiter, xlsxwriter → error response for XLSX only.
Installation
Install via Odoo Apps Store
- Log in to your Odoo instance as Administrator.
- Go to Apps → search for MCP Server.
- Click Install.
- The module installs with all dependencies automatically.
Install from Source
# Clone or copy the module into your addons path cp -r lm_mcp_server /path/to/your/addons/ # Restart Odoo ./odoo-bin -c odoo.conf --stop-after-init # Install the module ./odoo-bin -c odoo.conf -d your_db -i lm_mcp_server --stop-after-init
Upgrade
./odoo-bin -c odoo.conf -d your_db -u lm_mcp_server --stop-after-init
Configuration
Access the MCP Server settings at Settings → MCP Server (Technical section).
General Settings
| Parameter | Default | Description |
|---|---|---|
| Session retention (days) | 90 | Auto-purge sessions older than N days |
| Log retention (days) | 30 | Auto-purge audit log entries older than N |
| Rate limit per minute | 60 | Max requests per token per sliding window |
| Rate limit window (seconds) | 60 | Sliding window duration |
Redis Rate Limiting (Optional)
For multi-worker or multi-instance deployments, enable Redis so the rate limit is shared across all workers:
- Check Enable Redis rate limiting.
- Enter your Redis URL, e.g. redis://localhost:6379/0 or redis://:password@redis-host:6379/0.
- Click Test Redis Connection to verify.
If Redis is unreachable at runtime, the server falls back to in-memory rate limiting automatically — no downtime.
Schema Cache
The schema cache stores fields_get, get_models, and get_views results in memory (LRU, 1000 entries).
- Check Enable schema cache.
- Set Cache TTL (seconds) (default: 3600).
- Click Clear Schema Cache after installing new modules or changing field definitions.
The cache is automatically invalidated when ir.model or ir.model.fields records change.
Module Generator (Feature Flag)
The AI module generator is disabled by default. To enable:
- Check Enable module generator.
- Set Generated modules path — an absolute path to a writable addons folder (e.g. /opt/odoo/custom_addons). The generator refuses to write into community/ or enterprise/ directories.
- Restart Odoo after changing the addons path so the new folder is in scope.
Endpoints
MCP Endpoints
| Endpoint | Description |
|---|---|
| POST /mcp | Streamable HTTP transport (MCP 2025-03-26) |
| POST /mcp/sse | Streamable HTTP alias (backward compatible) |
| GET /mcp/sse | SSE transport — event stream |
| POST /mcp/messages | SSE transport — message endpoint |
Portal Endpoints
| Endpoint | Description |
|---|---|
| GET /mcp-page/<slug> | Public portal page (HTML) |
| GET /mcp-page/<slug>/data | Portal page data (JSON) |
| GET /mcp-page/<slug>/embed | Embeddable page (signed token required) |
Authentication
Personal Access Token (PAT)
PATs are the simplest authentication method for CLI tools, scripts, and server-to-server integrations.
Generate a PAT:
- Go to MCP Server → Tokens.
- Click Generate PAT.
- Copy the token from the dialog — it is shown only once.
- Store it securely (password manager, CI/CD secrets).
Token properties:
- SHA-256 hashed at rest; the plain token is never stored
- Valid 30 days by default
- No refresh token; generate a new one when it expires
- Can be revoked at any time from the Tokens list
Using a PAT in requests:
POST /mcp HTTP/1.1 Host: your-odoo.com Authorization: Bearer <your-PAT> Content-Type: application/json
OAuth 2.0 Authorization Code + PKCE
OAuth 2.0 is used by GUI clients (Claude Web, Claude Desktop, Cursor) that display a browser login window. It does not require users to generate tokens manually.
Flow:
1. Client → GET /.well-known/oauth-authorization-server → discover endpoints 2. Client → POST /oauth/register → get client_id (dynamic registration) 3. User → browser → GET /oauth/authorize?code_challenge=S256&... 4. Odoo → user logs in → redirect with authorization_code 5. Client → POST /oauth/token (code + PKCE verifier) → access_token + refresh_token 6. Client → POST /mcp with Bearer access_token
Token lifetimes:
- Access token: 30 days
- Refresh token: 90 days (auto-renews the access token transparently)
Token Governance
Each token supports fine-grained restrictions, configurable in MCP Server → Tokens → [token]:
Connecting AI Clients
Claude CLI / Claude Code
claude mcp add odoo --transport http https://your-odoo.com/mcp \ --header "Authorization: Bearer <your-PAT>"
Or via ~/.claude.json:
{ "mcpServers": { "odoo": { "type": "http", "url": "https://your-odoo.com/mcp", "headers": { "Authorization": "Bearer <your-PAT>" } } } }
Claude Desktop
Edit claude_desktop_config.json (~/Library/Application Support/Claude/ on macOS, %APPDATA%\Claude\ on Windows):
{ "mcpServers": { "odoo": { "type": "http", "url": "https://your-odoo.com/mcp", "headers": { "Authorization": "Bearer <your-PAT>" } } } }
Claude Web (OAuth 2.0)
- Open claude.ai → Settings → Integrations → Add MCP Server.
- Enter: https://your-odoo.com/mcp
- Click Connect — Claude Web opens a browser window for Odoo login.
- Authorize the connection. Claude Web handles token storage and renewal.
VSCode Extension
Add to settings.json:
{ "claude.mcpServers": { "odoo": { "type": "http", "url": "https://your-odoo.com/mcp", "headers": { "Authorization": "Bearer <your-PAT>" } } } }
Cursor
Go to Cursor Settings → MCP → Add Server:
{ "mcpServers": { "odoo": { "type": "http", "url": "https://your-odoo.com/mcp", "headers": { "Authorization": "Bearer <your-PAT>" } } } }
ChatGPT (Connector)
- Go to ChatGPT Settings → Connectors → Add MCP Server.
- Enter your Odoo MCP URL: https://your-odoo.com/mcp.
- Enter your Bearer token (PAT or OAuth access token).
- ChatGPT auto-discovers all tools via tools/list.
Grok
- Go to Grok Settings → Tools → Add MCP Server.
- Enter URL: https://your-odoo.com/mcp.
- Enter your Bearer token.
- Confirm connection — Grok lists all available Odoo tools.
Continue.dev
Edit ~/.continue/config.json:
{ "experimental": { "modelContextProtocolServers": [ { "transport": { "type": "sse", "url": "https://your-odoo.com/mcp/sse", "requestOptions": { "headers": { "Authorization": "Bearer <your-PAT>" } } } } ] } }
Windsurf / Void
{ "mcpServers": { "odoo": { "serverUrl": "https://your-odoo.com/mcp/sse", "headers": { "Authorization": "Bearer <your-PAT>" } } } }
n8n
In n8n, add an MCP Client Tool node:
- Transport: Streamable HTTP
- URL: https://your-odoo.com/mcp
- Authentication → Header Auth: Authorization: Bearer <your-PAT>
LangChain (Python)
from langchain_mcp_adapters.client import MultiServerMCPClient async with MultiServerMCPClient({ "odoo": { "url": "https://your-odoo.com/mcp", "transport": "streamable_http", "headers": {"Authorization": "Bearer <your-PAT>"} } }) as client: tools = client.get_tools()
Vercel AI SDK (TypeScript)
import { experimental_createMCPClient as createMCPClient } from 'ai'; const mcpClient = await createMCPClient({ transport: { type: 'http', url: 'https://your-odoo.com/mcp', headers: { Authorization: 'Bearer <your-PAT>' }, }, }); const tools = await mcpClient.tools();
Stdio-Only Clients (Jan, Msty) via mcp-remote
Clients that only support stdio need the mcp-remote bridge:
npm install -g mcp-remote
Then configure:
{ "mcpServers": { "odoo": { "command": "npx", "args": [ "mcp-remote", "https://your-odoo.com/mcp/sse", "--header", "Authorization: Bearer <your-PAT>" ] } } }
Production Deployment
Nginx Reverse Proxy
MCP Server uses HTTP streaming (SSE / chunked transfer) and requires CORS headers so browser-based AI clients (Claude Web, ChatGPT, etc.) can connect. The config below is the production-tested reference.
# Upstream — adjust host/port to match your Odoo instance upstream odoo_mcp { server 127.0.0.1:8069; keepalive 32; } # Restrict CORS to known AI client origins. # Add more origins with additional map entries as needed. map $http_origin $cors_origin { default ""; "https://claude.ai" $http_origin; "https://chatgpt.com" $http_origin; "https://app.grok.com" $http_origin; } server { listen 443 ssl http2; server_name your-odoo.com; ssl_certificate /etc/ssl/your-odoo.com/fullchain.pem; ssl_certificate_key /etc/ssl/your-odoo.com/privkey.pem; # ── MCP endpoints (SSE + Streamable HTTP) ──────────────────────────── location ~ ^/mcp { # OPTIONS preflight — answer directly from nginx if ($request_method = OPTIONS) { add_header Access-Control-Allow-Origin $cors_origin always; add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always; add_header Access-Control-Allow-Headers "Content-Type, Authorization, Mcp-Session-Id, Last-Event-ID" always; add_header Access-Control-Max-Age 86400 always; return 204; } proxy_pass http://odoo_mcp; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # SSE — must disable buffering for streaming to work proxy_buffering off; proxy_cache off; proxy_read_timeout 3600s; proxy_send_timeout 3600s; add_header X-Accel-Buffering no always; # CORS response headers add_header Access-Control-Allow-Origin $cors_origin always; add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always; add_header Access-Control-Allow-Headers "Content-Type, Authorization, Mcp-Session-Id, Last-Event-ID" always; } # ── OAuth 2.0 + Well-Known discovery endpoints ──────────────────────── location ~ ^/(oauth|\.well-known)/ { # OPTIONS preflight — required for POST /oauth/register from browser clients if ($request_method = OPTIONS) { add_header Access-Control-Allow-Origin $cors_origin always; add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always; add_header Access-Control-Allow-Headers "Content-Type, Authorization" always; add_header Access-Control-Max-Age 86400 always; return 204; } proxy_pass http://odoo_mcp; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # CORS — required so browser-based AI clients can read the response add_header Access-Control-Allow-Origin $cors_origin always; add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always; add_header Access-Control-Allow-Headers "Content-Type, Authorization" always; } # ── Main Odoo application ───────────────────────────────────────────── location / { proxy_pass http://odoo_mcp; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_redirect off; } gzip on; gzip_vary on; gzip_types text/css text/javascript application/json application/javascript text/plain text/xml; error_page 404 /404.html; error_page 500 502 503 504 /50x.html; }
Note
Why ``proxy_read_timeout 3600s``? SSE connections are long-lived. Claude Desktop and other MCP clients keep a persistent event stream open for the duration of a session. A short timeout (e.g. 300s) causes the client to disconnect and reconnect repeatedly.
Note
Why separate ``/mcp`` and ``/(oauth|.well-known)/`` locations? The /mcp location needs Mcp-Session-Id and Last-Event-ID in Access-Control-Allow-Headers. Keeping OAuth/discovery in its own block keeps the CORS header set minimal and avoids leaking internal headers.
Multi-Worker Configuration
MCP Server is stateless by design — no sticky sessions required.
Odoo config (``odoo.conf``):
[options] workers = 4 limit_time_real = 120 limit_time_cpu = 60 # For distributed rate limiting and schema cache # (add redis-py to requirements first)
Redis for distributed rate limiting:
# No odoo.conf change needed — configure via Settings → MCP Server # Redis URL example: # redis://localhost:6379/0 # redis://:password@redis-cluster:6379/0
Cloudflare / CDN Considerations
If Cloudflare (or another CDN) sits in front of Odoo:
- Disable response buffering on the /mcp and /mcp/sse paths. In Cloudflare, set a Cache Rule with Bypass Cache for /mcp*.
- Increase the read timeout to at least 300s on the path (Cloudflare Pro+: add a Page Rule with SSL = Full (Strict) and Origin Response Timeout = 300).
- For SSE specifically, ensure Cloudflare does not strip Transfer-Encoding: chunked headers — use HTTP/2 between Cloudflare and your origin.
Scheduled Jobs
Two cron jobs are installed automatically:
| Job | Default interval | Action |
|---|---|---|
| MCP Server: Purge expired sessions | Daily | Deletes sessions older than retention setting |
| MCP Server: Process async job queue | Every 5 minutes | Runs pending mcp.job records |
Configure cron intervals at Settings → Technical → Scheduled Actions.
Maintenance
Revoking tokens
Go to MCP Server → Tokens, open the token, and click Revoke. The token is rejected on the next request. Active sessions using that token are not terminated immediately but all subsequent requests fail.
Clearing audit logs
Session and log retention is enforced nightly by the purge cron. For an immediate purge, run from an Odoo shell:
env['mcp.session'].sudo()._purge_expired()
Clearing the schema cache
After installing or upgrading modules:
- Go to Settings → MCP Server.
- Click Clear Schema Cache.
Or from an Odoo shell:
from odoo.addons.lm_mcp_server.services import schema_cache schema_cache.invalidate("")
Troubleshooting
Import error on install: models.Constraint
Cause: models.Constraint was introduced in Odoo 17 but may not be available in all patch versions. The module uses _sql_constraints (the universal fallback) from version 18.0.2.0.0 onward.
Fix: upgrade to module version 18.0.2.0.0 or later.
OAuth redirect fails (localhost or HTTP URL)
Odoo's OAuth redirect validation requires HTTPS in production. For local development, add to odoo.conf:
[options] proxy_mode = True
And access Odoo through a reverse proxy that sets X-Forwarded-Proto: https, or use ngrok / localtunnel for a temporary HTTPS tunnel.
Rate limit exceeded (HTTP 429)
The default limit is 60 requests per 60 seconds per token. Increase it at Settings → MCP Server → Rate limit per minute, or configure Redis for shared state across workers.
SSE connection drops after 60 seconds
Nginx proxy_read_timeout is too short. Set it to 300s on the /mcp/sse location (see Nginx config above).
MCP client reports "transport error"
- Verify the endpoint URL: https://your-odoo.com/mcp (no trailing slash).
- Check the Authorization header is present and the token is not expired.
- For SSE clients, use /mcp/sse (not /mcp).
- Check Nginx is not buffering the response (proxy_buffering off).
Extension & Development
Adding Custom Tools
Extend the tool registry by inheriting mcp.tool.registry:
from odoo import api, models class MyCustomTools(models.AbstractModel): _inherit = "mcp.tool.registry" @api.model def get_tools(self) -> list: base_tools = super().get_tools() return base_tools + [ { "name": "odoo_my_custom_tool", "description": "My custom tool description", "inputSchema": { "type": "object", "properties": { "param": {"type": "string"} }, "required": ["param"], }, } ]
Then handle execution by overriding tool_executor.execute_tool or adding a handler in your own module.
Module Structure
lm_mcp_server/
├── __manifest__.py
├── controllers/
│ ├── mcp_controller.py # POST /mcp, GET/POST /mcp/sse
│ ├── oauth_controller.py # OAuth 2.0 endpoints
│ └── portal_controller.py # /mcp-page/<slug>
├── models/
│ ├── mcp_session.py # mcp.session — audit log
│ ├── mcp_token.py # mcp.token — PAT + OAuth tokens
│ ├── mcp_job.py # mcp.job — async job queue
│ ├── mcp_portal_page.py # mcp.portal.page — shareable dashboards
│ ├── mcp_generated_module.py # mcp.generated.module — AI module builder
│ ├── mcp_tool_registry.py # mcp.tool.registry — tool definitions
│ └── res_config_settings.py # Settings extension
└── services/
├── mcp_protocol.py # JSON-RPC envelope, tools/list, tools/call
├── tool_executor.py # Tool dispatch + scope enforcement
├── schema_cache.py # LRU schema cache
├── rate_limiter.py # In-memory rate limiter
├── redis_rate_limiter.py # Redis sliding-window rate limiter
├── redaction.py # PII redaction for payload capture
├── bi_tools.py # BI reporting tools (7 tools)
├── job_tools.py # Async job tools (4 tools)
├── portal_tools.py # Portal page tools (3 tools)
├── module_tools.py # Module generator tools (4 tools)
└── module_generator.py # ZIP builder + spec validator
Odoo Proprietary License v1.0 This software and associated files (the "Software") may only be used (executed, modified, executed after modifications) if you have purchased a valid license from the authors, typically via Odoo Apps, or if you have received a written agreement from the authors of the Software (see the COPYRIGHT file). You may develop Odoo modules that use the Software as a library (typically by depending on it, importing it and using its resources), but without copying any source code or material from the Software. You may distribute those modules under the license of your choice, provided that this license is compatible with the terms of the Odoo Proprietary License (For example: LGPL, MIT, or proprietary licenses similar to this one). It is forbidden to publish, distribute, sublicense, or sell copies of the Software or modified copies of the Software. The above copyright notice and this permission notice must be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Please log in to comment on this module