Sponsored by Deepsite.site

Odoo Mcp Gateway

Created By
parth-unjiya5 days ago
Security-first MCP gateway for Odoo 17/18/19 — 27 tools, YAML-driven security
Overview

odoo-mcp-gateway

Security-first, version-agnostic MCP gateway for Odoo 17/18/19. Works with stock and custom modules via YAML configuration. Zero Odoo-side code required.

Python 3.10+ License: MIT Odoo

Why This Exists

Existing Odoo MCP servers share common problems: hardcoded model lists that miss custom modules, security as an afterthought, mandatory custom Odoo addons, and single-version targets. This gateway solves all of them:

  • Two-layer security — MCP restrictions (YAML) + Odoo's built-in ACLs (ir.model.access + ir.rule)
  • YAML-driven configuration — model restrictions, RBAC, field-level access, rate limiting, audit logging
  • Custom module support — auto-discovers models via ir.model, add YAML config and it works
  • Version-agnostic — Odoo 17, 18, 19 with version-specific adapters
  • Zero Odoo-side codepip install + YAML config = done. No custom addon required
  • Full MCP primitives — 27 Tools + 5 Resources + 7 Prompts (most servers only implement Tools)
  • Plugin architecture — extend with pip-installable domain packs via entry_points

Architecture

MCP Client (Claude Desktop / Claude Code / HTTP)
    |  User calls login tool with Odoo credentials
    v
MCP Server (FastMCP)
    |
    |-- security_gate()    --> Rate limit + RBAC tool access + audit logging
    |-- restrictions       --> Model/method/field block lists (YAML + hardcoded)
    |-- rbac               --> Field-level filtering + write sanitization
    |
    |-- tools/             --> 27 MCP tools (auth + schema + CRUD + plugins)
    |-- resources/         --> 5 MCP resources (odoo:// URIs)
    |-- prompts/           --> 7 reusable prompt templates
    |-- plugins/           --> Entry-point plugin system (HR, Sales, Project, Helpdesk)
    |
    |  JSON-RPC / XML-RPC as authenticated user
    v
Odoo 17/18/19 (security enforced per user via ir.model.access + ir.rule)

Security Pipeline

Every tool and resource call passes through this pipeline:

Request --> Rate Limit --> Authentication Check --> RBAC Tool Access
    --> Model Restriction --> Method Restriction --> Field Validation
    --> Handler Execution --> RBAC Field Filtering --> Audit Log --> Response

Hardcoded safety guardrails that cannot be overridden by YAML:

  • 18 always-blocked models (ir.config_parameter, ir.cron, ir.module.module, ir.rule, ir.mail_server, etc.)
  • 18 always-blocked methods (sudo, with_user, with_env, _sql, _write, _create, etc.)
  • 28 ORM methods blocked in execute_method (prevents bypassing field-level checks)

Quick Start

pip install odoo-mcp-gateway

# Copy and edit config files
cp config/restrictions.yaml.example config/restrictions.yaml
cp config/model_access.yaml.example config/model_access.yaml
cp config/rbac.yaml.example config/rbac.yaml

# Set environment variables
export ODOO_URL=http://localhost:8069
export ODOO_DB=mydb

# Run (stdio mode for Claude Desktop / Claude Code)
python -m odoo_mcp_gateway

# Or HTTP mode for web clients
MCP_TRANSPORT=streamable-http python -m odoo_mcp_gateway

Claude Desktop Configuration

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "odoo": {
      "command": "python",
      "args": ["-m", "odoo_mcp_gateway"],
      "env": {
        "ODOO_URL": "http://localhost:8069",
        "ODOO_DB": "mydb"
      }
    }
  }
}

Claude Code Configuration

# Add as MCP server
claude mcp add odoo -- python -m odoo_mcp_gateway

Environment Variables

VariableDefaultDescription
ODOO_URLhttp://localhost:8069Odoo server URL
ODOO_DB(required)Odoo database name
MCP_TRANSPORTstdioTransport mode (stdio or streamable-http)
MCP_HOST127.0.0.1HTTP host (streamable-http mode)
MCP_PORT8080HTTP port (streamable-http mode)
MCP_LOG_LEVELINFOLogging level

Security

Two-Layer Security Model

  1. MCP gateway restrictions (YAML config + hardcoded guardrails) — blocks sensitive models, dangerous methods, privileged fields before any Odoo call is made
  2. Odoo's built-in ACLs — enforces per-user access on actual records via ir.model.access and ir.rule

Model Restriction Tiers

TierEffectExample
always_blockedNobody can access, including adminsir.config_parameter, res.users.apikeys
admin_onlyOnly admin usersir.model, ir.model.fields
admin_write_onlyRead OK for all, write needs adminres.company, res.currency

Hardcoded Safety Guardrails

These cannot be overridden by YAML configuration:

Blocked models (17): ir.config_parameter, res.users.apikeys, ir.cron, ir.module.module, ir.model.access, ir.rule, ir.mail_server, ir.ui.view, ir.actions.server, res.config.settings, change.password.wizard, change.password.user, base.module.update, base.module.upgrade, base.module.uninstall, fetchmail.server, bus.bus

Blocked methods (18): sudo, with_user, with_company, with_context, with_env, with_prefetch, _auto_init, _sql, _register_hook, _write, _create, _read, _setup_base, _setup_fields, _setup_complete, init, _table_query, _read_group_raw

Additional Security Features

  • Rate limiting — per-session token bucket with separate global and write budgets
  • RBAC — tool-level access control by user group, field-level response filtering
  • Input validation — model names, method names, field names, domain filters, ORDER BY clauses, write values (size/depth/type)
  • IDOR protection — plugin tools scope data access to the authenticated user
  • Audit logging — structured JSON logs for all allowed and denied operations
  • Error sanitization — strips internal URLs, SQL fragments, file paths, stack traces from error messages
  • XXE protection — XML-RPC responses parsed with defusedxml
  • Domain validation — Odoo domain filters validated for operators, field names, value types, nesting depth, and list sizes

Authentication

Three stock Odoo auth methods — no custom addon needed:

MethodProtocolUse Case
api_keyXML-RPCServer-to-server, CI/CD pipelines
passwordJSON-RPCInteractive users, Claude Desktop
sessionJSON-RPCReuse existing browser session (development)
# Example: login via the MCP tool
> login(method="password", username="admin", credential="admin", database="mydb")

MCP Tools (11)

ToolDescription
loginAuthenticate with Odoo (api_key / password / session)
list_modelsList accessible models with metadata and keyword filter
get_model_fieldsGet field definitions for a model with optional filter
search_readSearch records with domain filters, field selection, ordering
get_recordGet a single record by ID
search_countCount matching records
create_recordCreate a new record (validates field names and values)
update_recordUpdate existing record (validates field names and values)
delete_recordDelete a single record by ID
read_groupAggregated grouped reads with aggregate functions
execute_methodCall allowed model methods (validates method name)

MCP Resources (5)

URIDescription
odoo://modelsList all accessible models
odoo://models/{name}Model detail with field definitions
odoo://record/{model}/{id}Single record data with RBAC field filtering
odoo://schema/{model}Field schema with type info and importance ranking
odoo://categoriesModel categories with counts

MCP Prompts (7)

PromptDescription
analyze_modelComprehensive model structure analysis
explore_dataNatural language data exploration guide
create_workflowGuide through model-specific workflows
compare_recordsSide-by-side record comparison
generate_reportAnalytical report generation
discover_custom_modulesFind and understand custom modules
debug_accessTroubleshoot access and permission issues

Built-in Domain Plugins

HR Plugin

ToolDescription
check_inRecord attendance check-in
check_outRecord attendance check-out
get_my_attendanceView attendance records (with month filter)
get_my_leavesView leave requests (with state filter)
request_leaveSubmit a leave request
get_my_profileView employee profile

Sales Plugin

ToolDescription
get_my_quotationsList quotations/orders (with state filter)
get_order_detailsFull order details with line items
confirm_orderConfirm a draft/sent quotation
get_sales_summaryAggregated sales statistics (with period filter)

Project Plugin

ToolDescription
get_my_tasksList assigned tasks (with state/project filter)
get_project_summaryProject stats: task counts by stage, overdue
update_task_stageMove a task to a different stage

Helpdesk Plugin

ToolDescription
get_my_ticketsList assigned tickets (with state/priority filter)
create_ticketCreate a new helpdesk ticket
update_ticket_stageMove a ticket to a different stage

Custom Module Support

Add custom Odoo modules without writing Python code. Edit model_access.yaml:

custom_models:
  full_crud:
    - custom.delivery.route
    - custom.warehouse.zone
  read_only:
    - custom.delivery.log

allowed_methods:
  custom.delivery.route:
    - action_dispatch
    - action_complete
    - action_cancel

Then all CRUD tools (search_read, create_record, update_record, delete_record) and execute_method work on the custom models with full security enforcement.

Plugin System

Extend the gateway with pip-installable plugins:

from odoo_mcp_gateway.plugins.base import OdooPlugin

class ManufacturingPlugin(OdooPlugin):
    @property
    def name(self) -> str:
        return "manufacturing"

    @property
    def required_odoo_modules(self) -> list[str]:
        return ["mrp"]

    @property
    def required_models(self) -> list[str]:
        return ["mrp.production", "mrp.bom"]

    def register(self, server, context):
        @server.tool()
        async def get_production_orders(...):
            ...

Register via pyproject.toml entry points:

[project.entry-points."odoo_mcp_gateway.plugins"]
manufacturing = "my_package:ManufacturingPlugin"

Configuration Files

FilePurpose
config/restrictions.yamlModel/method/field block lists (3 tiers)
config/model_access.yamlPer-model access policies, allowed methods, sensitive fields
config/rbac.yamlRole-based tool access and field filtering by group
config/gateway.yamlServer, connection, auth settings

All files have .example templates with extensive inline documentation. Copy and customize:

cp config/restrictions.yaml.example config/restrictions.yaml
cp config/model_access.yaml.example config/model_access.yaml
cp config/rbac.yaml.example config/rbac.yaml

Example: Restrict a Model

# restrictions.yaml
restrictions:
  always_blocked:
    - my.secret.model
  admin_only:
    - hr.salary.rule
  admin_write_only:
    - res.company
  blocked_write_fields:
    - password_crypt
    - api_key
    - totp_secret

Example: RBAC by Group

# rbac.yaml
rbac:
  tool_group_requirements:
    delete_record:
      - base.group_system
    execute_method:
      - base.group_erp_manager
  sensitive_fields:
    hr.employee:
      salary:
        required_group: hr.group_hr_manager

Docker

cp .env.example .env   # Edit with your Odoo settings
docker compose up

Services:

  • MCP Gateway — port 8080 (streamable-http mode)
  • Odoo 18 — internal only (no host port exposed by default)
  • PostgreSQL — internal only

The gateway runs as a non-root user in a minimal Python image.

CLI Tools

# Test Odoo connectivity
odoo-mcp-tools test-connection --url http://localhost:8069

# Validate all YAML config files
odoo-mcp-tools validate-config --config-dir config

# List configured model access policies
odoo-mcp-tools list-models --config-dir config

Development

git clone https://github.com/parth-unjiya/odoo-mcp-gateway.git
cd odoo-mcp-gateway
pip install -e ".[dev]"

# Run tests
pytest tests/ -v

# Run with coverage
pytest tests/ --cov=odoo_mcp_gateway --cov-report=term-missing

# Lint
ruff check src/ tests/

# Type check (strict mode)
mypy src/

Source Layout

src/odoo_mcp_gateway/
├── __main__.py                  # Entry point (stdio + HTTP)
├── server.py                    # FastMCP server setup, tool registration
├── config.py                    # Pydantic settings (env + .env)
├── client/
│   ├── base.py                  # OdooClientBase ABC, AuthResult
│   ├── jsonrpc.py               # JSON-RPC client (session auth)
│   ├── xmlrpc.py                # XML-RPC client (API key auth, defusedxml)
│   └── exceptions.py            # OdooError hierarchy (7 types)
├── core/
│   ├── auth/manager.py          # 3 auth strategies
│   ├── connection/manager.py    # Circuit breaker + retry
│   ├── version/                 # Odoo 17/18/19 detection + adapters
│   ├── security/
│   │   ├── restrictions.py      # 3-tier model/method restrictions + hardcoded guardrails
│   │   ├── rbac.py              # Tool access + field filtering
│   │   ├── middleware.py        # Security pipeline + security_gate()
│   │   ├── rate_limit.py        # Token bucket rate limiter
│   │   ├── audit.py             # Structured audit logging
│   │   ├── sanitizer.py         # Error message sanitization
│   │   └── config_loader.py     # YAML config → Pydantic models
│   └── discovery/
│       ├── model_registry.py    # ir.model auto-discovery
│       ├── field_inspector.py   # fields_get with TTL cache
│       └── suggestions.py       # Category search + related models
├── tools/
│   ├── auth.py                  # login tool
│   ├── schema.py                # list_models, get_model_fields
│   └── crud.py                  # search_read, create/update/delete, execute_method
├── resources/handlers.py        # 5 MCP resources (odoo:// URIs)
├── prompts/handlers.py          # 7 MCP prompt templates
├── plugins/
│   ├── base.py, registry.py     # Plugin ABC + entry_point discovery
│   └── core/                    # Built-in plugins (HR, Sales, Project, Helpdesk)
├── cli/tools.py                 # CLI: test-connection, validate-config
└── utils/                       # Domain builder, formatting, token budget

Testing

1,043 tests across all layers with 93% code coverage:

tests/unit/
├── client/          # JSON-RPC, XML-RPC, auth manager, XXE protection
├── security/        # Restrictions, RBAC, audit, rate limit, sanitizer, security_gate
├── discovery/       # Model registry, field inspector, suggestions
├── tools/           # All 11 MCP tools + input validation
├── plugins/         # Plugin system + 4 domain plugins + IDOR protection
└── cli/             # CLI utility tools
# Run all tests
pytest tests/ -v

# Run specific area
pytest tests/unit/security/ -v
pytest tests/unit/tools/ -v
pytest tests/unit/plugins/ -v

# Coverage report
pytest tests/ --cov=odoo_mcp_gateway --cov-report=html

Error Handling

All Odoo errors are classified into 7 types:

ErrorCause
OdooConnectionErrorCannot reach Odoo server
OdooAuthErrorInvalid credentials
OdooAccessErrorir.model.access denied
OdooValidationErrorField validation failure
OdooUserErrorBusiness logic error
OdooMissingErrorRecord not found
OdooVersionErrorUnsupported Odoo version

All error messages are sanitized before reaching the MCP client — internal URLs, SQL fragments, file paths, and stack traces are automatically stripped.

Known Limitations

  • Single-user stdio mode: The gateway is designed for single-user stdio transport (Claude Desktop, Claude Code). Multi-user streamable-http mode works but sessions are not fully isolated between concurrent users.
  • XML-RPC credential handling: When using API key authentication (XML-RPC), the credential is sent with every RPC call as required by the protocol. Use HTTPS in production.
  • Admin detection: Admin status is derived from Odoo group membership. Non-English Odoo instances may need configuration adjustments for group name resolution.

Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/my-feature)
  3. Make your changes with tests
  4. Ensure all checks pass: pytest && ruff check src/ tests/ && mypy src/
  5. Submit a pull request

License

MIT

Recommend Servers
TraeBuild with Free GPT-4.1 & Claude 3.7. Fully MCP-Ready.
Tavily Mcp
AiimagemultistyleA Model Context Protocol (MCP) server for image generation and manipulation using fal.ai's Stable Diffusion model.
Amap Maps高德地图官方 MCP Server
Zhipu Web SearchZhipu Web Search MCP Server is a search engine specifically designed for large models. It integrates four search engines, allowing users to flexibly compare and switch between them. Building upon the web crawling and ranking capabilities of traditional search engines, it enhances intent recognition capabilities, returning results more suitable for large model processing (such as webpage titles, URLs, summaries, site names, site icons, etc.). This helps AI applications achieve "dynamic knowledge acquisition" and "precise scenario adaptation" capabilities.
Jina AI MCP ToolsA Model Context Protocol (MCP) server that integrates with Jina AI Search Foundation APIs.
WindsurfThe new purpose-built IDE to harness magic
Baidu Map百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
RedisA Model Context Protocol server that provides access to Redis databases. This server enables LLMs to interact with Redis key-value stores through a set of standardized tools.
Howtocook Mcp基于Anduin2017 / HowToCook (程序员在家做饭指南)的mcp server,帮你推荐菜谱、规划膳食,解决“今天吃什么“的世纪难题; Based on Anduin2017/HowToCook (Programmer's Guide to Cooking at Home), MCP Server helps you recommend recipes, plan meals, and solve the century old problem of "what to eat today"
Playwright McpPlaywright MCP server
Visual Studio Code - Open Source ("Code - OSS")Visual Studio Code
Serper MCP ServerA Serper MCP Server
MiniMax MCPOfficial MiniMax Model Context Protocol (MCP) server that enables interaction with powerful Text to Speech, image generation and video generation APIs.
EdgeOne Pages MCPAn MCP service designed for deploying HTML content to EdgeOne Pages and obtaining an accessible public URL.
Y GuiA web-based graphical interface for AI chat interactions with support for multiple AI models and MCP (Model Context Protocol) servers.
BlenderBlenderMCP connects Blender to Claude AI through the Model Context Protocol (MCP), allowing Claude to directly interact with and control Blender. This integration enables prompt assisted 3D modeling, scene creation, and manipulation.
MCP AdvisorMCP Advisor & Installation - Use the right MCP server for your needs
DeepChatYour AI Partner on Desktop
CursorThe AI Code Editor
ChatWiseThe second fastest AI chatbot™