Newcontext-mode—Save 98% of your AI coding agent's context windowLearn more
MCP Directory
ServersClientsBlog

context-mode

Save 98% of your AI coding agent's context window. Works with Claude Code, Cursor, Copilot, Codex, and more.

Try context-mode
MCP Directory

Model Context Protocol Directory

MKSF LTD
Suite 8805 5 Brayford Square
London, E1 0SG

MCP Directory

  • About
  • Blog
  • Documentation
  • Contact

Menu

  • Servers
  • Clients

© 2026 model-context-protocol.com

The Model Context Protocol (MCP) is an open standard for AI model communication.
Powered by Mert KoseogluSoftware Forge
  1. Home
  2. Servers
  3. odoo-mcp-19

odoo-mcp-19

GitHub

MCP Server for Odoo 19+ with v2 JSON-2 API Support

3
2
   ____      __               __  _____________     _______
  / __ \____/ /___  ____     /  |/  / ____/ __ \   <  / __ \  __
 / / / / __  / __ \/ __ \   / /|_/ / /   / /_/ /   / / /_/ /_/ /_
/ /_/ / /_/ / /_/ / /_/ /  / /  / / /___/ ____/   / /\__, /_  __/
\____/\__,_/\____/\____/  /_/  /_/\____/_/       /_//____/ /_/

Connect Claude and AI assistants to Odoo 19+ via the Model Context Protocol (MCP).

Features

  • 5 tools, full power - execute_method calls ANY method on ANY model. Combined with batch_execute, execute_workflow, configure_odoo, and read_resource, you have complete Odoo API access
  • 27 resources - Dynamic model discovery, compact schemas, workflows, and introspection
  • 13 prompts - Guided workflows for common business operations
  • 30 ORM methods - Complete documentation with examples
  • 13 modules - Special methods including AI module (Enterprise)
  • Safety layer - Pre-execution risk classification, blocked models, cascade warnings
  • DX optimizations - Quick-schema, bundle, session-bootstrap, resolve_json for token-efficient AI operations
  • MCP 2025-11-25 - Background tasks, progress tracking, icons, structured outputs
  • FastMCP 3.2.0+ - Latest stable SDK with security fixes, providers, transforms, OpenTelemetry
  • Input validation - Regex-validated model/method names, URI scheme guards, JSON type checks
  • Thread-safe - Singleton client, locked global caches for concurrent HTTP transport
  • Hardened Docker - Non-root container, --env-file for secrets, mandatory HTTP auth

Installation

Prerequisites

  • Docker Desktop (recommended) OR Python 3.10+
  • An Odoo 19+ instance with API access
  • An API key from your Odoo instance (Settings > Users > API Keys)

Option A: Docker (recommended)

Pull from Docker Hub:

docker pull alanogik/odoo-mcp-19:latest

Or build from source:

git clone https://github.com/AlanOgic/odoo-mcp-19.git
cd odoo-mcp-19
docker build -t odoo-mcp-19:latest .

Quick test (verify it connects):

docker run --rm -i \
  -e ODOO_URL=https://your-instance.odoo.com \
  -e ODOO_DB=your-database \
  -e ODOO_USERNAME=your-username \
  -e ODOO_API_KEY=your-api-key \
  odoo-mcp-19:latest

You should see the server start without errors. Press Ctrl+C to stop.

Option B: From source (Python venv)

# 1. Clone the repository
git clone https://github.com/AlanOgic/odoo-mcp-19.git
cd odoo-mcp-19

# 2. Create a virtual environment
python3 -m venv .venv

# 3. Activate it
source .venv/bin/activate        # macOS / Linux
# .venv\Scripts\activate         # Windows

# 4. Install the package
pip install -e .

# 5. Create your .env file
cp .env.example .env             # Then edit with your Odoo credentials
# Or create manually:
cat > .env << 'EOF'
ODOO_URL=https://your-instance.odoo.com
ODOO_DB=your-database
ODOO_USERNAME=your-username
ODOO_API_KEY=your-api-key
EOF

# 6. Test it
python -m odoo_mcp

Option C: pip install

pip install odoo-mcp-19

Configure Claude Desktop

Edit your Claude Desktop configuration file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Using Docker (recommended)

Method 1: Using run-docker.sh wrapper (simplest)

Create a .env file in the project root with your credentials, then:

{
  "mcpServers": {
    "odoo": {
      "command": "/path/to/odoo-mcp-19/run-docker.sh"
    }
  }
}

Method 2: Inline Docker command

{
  "mcpServers": {
    "odoo": {
      "command": "docker",
      "args": ["run", "--rm", "-i",
        "-e", "ODOO_URL=https://your-instance.odoo.com",
        "-e", "ODOO_DB=your-database",
        "-e", "ODOO_USERNAME=your-username",
        "-e", "ODOO_API_KEY=your-api-key",
        "odoo-mcp-19:latest"
      ]
    }
  }
}

Using Python (venv)

{
  "mcpServers": {
    "odoo": {
      "command": "/path/to/odoo-mcp-19/.venv/bin/python",
      "args": ["-m", "odoo_mcp"],
      "env": {
        "ODOO_URL": "https://your-instance.odoo.com",
        "ODOO_DB": "your-database",
        "ODOO_USERNAME": "your-username",
        "ODOO_API_KEY": "your-api-key"
      }
    }
  }
}

Using pip install

{
  "mcpServers": {
    "odoo": {
      "command": "odoo-mcp-19",
      "env": {
        "ODOO_URL": "https://your-instance.odoo.com",
        "ODOO_DB": "your-database",
        "ODOO_USERNAME": "your-username",
        "ODOO_API_KEY": "your-api-key"
      }
    }
  }
}

Restart Claude Desktop after saving the config file.

Verify it works

Ask Claude: "List the first 5 partners in Odoo"

Quick start examples

# Search partners
execute_method("res.partner", "search_read",
    kwargs_json='{"domain": [["is_company", "=", true]], "fields": ["name", "email"], "limit": 10}')

# Create a partner
execute_method("res.partner", "create",
    args_json='[{"name": "ACME Corp", "is_company": true, "email": "[email protected]"}]')

# Update with auto-resolved Many2one (no need to know user ID)
execute_method("res.partner", "write",
    args_json='[[42], {"name": "ACME Corp Updated"}]',
    resolve_json='{"user_id": {"model": "res.users", "search": "John"}}')

# Confirm a sale order (2-step safety confirmation with token)
# Step 1: triggers safety gate, returns confirmation_token in hint
result = execute_method("sale.order", "action_confirm", args_json='[[15]]')
# Step 2: confirm with the token from step 1
execute_method("sale.order", "action_confirm", args_json='[[15]]',
    confirmed=true, confirmation_token='<token from step 1>')

# Multi-step workflow in one call
execute_workflow("quote_to_cash", '{"order_id": 123}')

Architecture

Tools (5)

ToolPurpose
execute_methodCall any method on any Odoo model
batch_executeMultiple operations with progress tracking
execute_workflowPre-built multi-step workflows
configure_odooInteractive connection setup
read_resourceRead any odoo:// resource by URI

Resources (27)

ResourceDescription
odoo://modelsList all models
odoo://model/{name}Model info with fields
odoo://model/{name}/schemaFull fields and relationships
odoo://model/{name}/fieldsLightweight field list with labels
odoo://model/{name}/quick-schemaUltra-compact schema (~1.5KB, short keys)
odoo://model/{name}/workflowState machine transitions and side effects
odoo://model/{name}/docsRich docs: labels, help text, selections
odoo://bundle/{models}Batch quick-schema for N models (max 10)
odoo://session-bootstrapBootstrap: schemas + workflows for common models
odoo://record/{model}/{id}Get a specific record by ID
odoo://methods/{model}Available methods (enriched with live signatures)
odoo://docs/{model}Documentation URLs
odoo://conceptsBusiness term to model mappings
odoo://find-model/{concept}Natural language to model name
odoo://tools/{query}Search available operations
odoo://actions/{model}Discover model actions
odoo://templatesList all resource templates
odoo://tool-registryPre-built workflows
odoo://module-knowledgeSpecial methods knowledge
odoo://module-knowledge/{name}Knowledge for a specific module
odoo://workflowsBusiness workflows
odoo://server/infoOdoo server information
odoo://domain-syntaxDomain operator reference
odoo://paginationPagination guide
odoo://hierarchicalParent/child tree query patterns
odoo://aggregationAggregation guide (formatted_read_group)
odoo://model-limitationsKnown model issues + runtime problems

Prompts (13)

PromptPurpose
odoo-explorationDiscover instance capabilities
search-recordsSearch for records in a model
odoo-api-referenceQuick API reference card
quote-to-cashComplete sales workflow
ar-aging-reportAccounts receivable aging
inventory-checkStock levels analysis
crm-pipelinePipeline analysis
customer-360Complete customer view
daily-operationsOperations dashboard
domain-builderBuild complex domain filters
hierarchical-queryQuery parent/child trees
paginated-searchPaginate large result sets
aggregation-reportAggregation reports

Safety Layer (v1.10.0)

Pre-execution safety classification gates dangerous operations behind confirmation.

Risk levels

LevelBehaviorConfirm?
SAFEExecute immediatelyNever
MEDIUMGate based on mode/volumeConditional
HIGHAlways require confirmationAlways
BLOCKEDAlways refuseN/A

Blocked models (write always refused)

ir.rule, ir.model.access, ir.module.module, ir.config_parameter, ir.model, ir.model.fields, res.users, res.groups

Sensitive models (write always confirms)

account.move, account.payment, account.bank.statement, hr.payslip, ir.cron

Cascade warnings

Side effects are surfaced for workflow actions:

  • sale.order + action_confirm → creates deliveries
  • account.move + action_post → creates journal entries (irreversible)
  • stock.picking + button_validate → updates stock levels
  • purchase.order + button_confirm → creates incoming receipts
  • account.payment + action_post → creates journal entries + reconciliation

Confirmation flow (token-based, v1.14.0)

  1. Caller sends execute_method(model, method, args_json)
  2. Safety layer classifies the operation
  3. If confirmation needed: returns pending_confirmation=true with safety classification and a confirmation_token in the hint field
  4. Caller reviews, then re-calls with confirmed=true AND confirmation_token='<token>'

Tokens are single-use, expire after 120s, and are bound to the specific model+method. This prevents agents from bypassing the safety gate by always passing confirmed=true.

DX Improvements (v1.11.0)

Quick Schema

odoo://model/{model}/quick-schema — Ultra-compact schema with short keys: t (type), req (required), ro (readonly), rel (relation). ~60-80% smaller than /fields.

Bundle

odoo://bundle/res.partner,sale.order,stock.picking — Batch quick-schema for up to 10 models in one call.

Session Bootstrap

odoo://session-bootstrap — One call to bootstrap a conversation with schemas + workflows for common models. Configure via MCP_BOOTSTRAP_MODELS env var.

Workflow

odoo://model/{model}/workflow — State machine transitions for 6 main models with side effects and irreversibility flags. Dynamic fallback for unmapped models.

Many2one Resolution

Auto-resolve field names to IDs with resolve_json:

execute_method("res.partner", "write",
    args_json='[[1], {"user_id": null}]',
    resolve_json='{"user_id": {"model": "res.users", "search": "John"}}')

Default Context

Set MCP_DEFAULT_CONTEXT to apply context to all operations:

export MCP_DEFAULT_CONTEXT='{"lang": "fr_FR", "tz": "Europe/Paris"}'

Expanded Error Patterns

~25 error patterns with actionable suggestions covering 422, 500, 403, 404 errors and fallback patterns.

HTTP Transport

Run as an HTTP server with Bearer token authentication for remote or multi-client access.

Docker Compose (recommended)

Add to your .env:

MCP_TRANSPORT=streamable-http
MCP_API_KEY=your-secret-bearer-token

Then:

docker compose up -d

The MCP endpoint is available at http://localhost:8080/mcp.

Docker run

docker run -d -p 8080:8080 \
  -e ODOO_URL=https://your.odoo.com \
  -e ODOO_DB=mydb \
  -e ODOO_USERNAME=admin \
  -e ODOO_API_KEY=xxx \
  -e MCP_TRANSPORT=streamable-http \
  -e MCP_API_KEY=your-secret-token \
  odoo-mcp-19:latest

Claude Desktop config (HTTP)

{
  "mcpServers": {
    "odoo": {
      "type": "streamable-http",
      "url": "http://localhost:8080/mcp",
      "headers": {
        "Authorization": "Bearer your-secret-token"
      }
    }
  }
}

Verify it works

# Should succeed (200)
curl -i -X POST http://localhost:8080/mcp \
  -H "Authorization: Bearer your-secret-token" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "method": "initialize", "id": 1}'

# Should fail (401/403) — wrong or missing token
curl -i -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "method": "initialize", "id": 1}'

Configuration

VariableRequiredDefaultDescription
ODOO_URLYes—Odoo server URL
ODOO_DBYes—Database name
ODOO_USERNAMEYes—Username
ODOO_API_KEYYes—API key (Settings > Users > API Keys)
ODOO_PASSWORDNo—Password (fallback if no API key)
ODOO_TIMEOUTNo30Request timeout in seconds
ODOO_VERIFY_SSLNotrueSSL certificate verification
MCP_TRANSPORTNostdioTransport: stdio or streamable-http
MCP_API_KEYYes (HTTP)—Bearer token for HTTP auth (required for streamable-http)
MCP_HOSTNo0.0.0.0HTTP bind address
MCP_PORTNo8080HTTP port
MCP_SAFETY_MODENostrictstrict or permissive
MCP_SAFETY_AUDITNo—true to log safety audit to stderr
MCP_DEFAULT_CONTEXTNo—JSON object merged into all contexts
MCP_BOOTSTRAP_MODELSNores.partner,sale.order,account.move,product.product,stock.pickingModels for session-bootstrap

Documentation

Full documentation in the Wiki:

  • Getting Started
  • Tools
  • Resources
  • ORM Methods
  • Module Knowledge
  • AI Module
  • Domain Syntax
  • Prompts

Security

  • HTTP transport requires MCP_API_KEY — server refuses to start without it
  • Docker runs as non-root user (UID 1001)
  • Input validation — model names (dotted notation regex), method names (identifier regex), URI scheme (odoo:// only)
  • No traceback forwarding — Odoo server tracebacks logged to stderr, never returned to clients
  • Credential files gitignored — .env, .mcp.json, odoo_config.json
  • SSL warning — visible warning on startup when ODOO_VERIFY_SSL=false with HTTPS
  • Thread-safe caches — doc cache (100 entries max, LRU eviction) and runtime issue tracker use locks
  • MCP_DEFAULT_CONTEXT — capped at 4KB, MCP_BOOTSTRAP_MODELS capped at 20 models

Requirements

  • Python 3.10+
  • Odoo 19+
  • FastMCP 3.2.0+ (with tasks extra)
  • requests 2.32.4+

License

MIT

Repository

AL
AlanOgic

AlanOgic/odoo-mcp-19

Created

January 26, 2026

Updated

April 13, 2026

Language

Python

Category

Communication