# Odoo Mcp Server

> MCP server for Odoo ERP — connect any AI agent to your Odoo instance

- **Type:** MCP server
- **Install:** `agentstack add mcp-oconsole-odoo-mcp-server`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [oconsole](https://agentstack.voostack.com/s/oconsole)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [oconsole](https://github.com/oconsole)
- **Source:** https://github.com/oconsole/odoo-mcp-server

## Install

```sh
agentstack add mcp-oconsole-odoo-mcp-server
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Odoo MCP Server

An [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server that connects AI agents to Odoo ERP instances. Works with Claude Code, Cursor, Windsurf, and any MCP-compatible client.

Supports **Odoo 17-18** (JSON-RPC) and **Odoo 19+** (JSON-2 API) — auto-detects the best protocol.

## Quick Start

```bash
# Run directly (uv handles dependencies automatically)
ODOO_URL=https://my.odoo.com ODOO_DB=mydb ODOO_USER=admin ODOO_PASSWORD=secret \
  uv run odoo_mcp_server.py
```

No virtualenv or `pip install` needed — the script has [inline metadata](https://packaging.python.org/en/latest/specifications/inline-script-metadata/) that `uv` resolves automatically.

## Configure in Claude Code

Add to your project's `.mcp.json`:

```json
{
  "mcpServers": {
    "odoo": {
      "type": "stdio",
      "command": "uv",
      "args": ["run", "--python", "3.11", "--script", "/path/to/odoo_mcp_server.py"],
      "env": {
        "ODOO_URL": "https://your-instance.odoo.com",
        "ODOO_DB": "your-database",
        "ODOO_USER": "admin",
        "ODOO_PASSWORD": "your-password"
      }
    }
  }
}
```

Or for Odoo 19+ with API key auth:

```json
{
  "mcpServers": {
    "odoo": {
      "type": "stdio",
      "command": "uv",
      "args": ["run", "--python", "3.11", "--script", "/path/to/odoo_mcp_server.py"],
      "env": {
        "ODOO_URL": "https://your-instance.odoo.com",
        "ODOO_DB": "your-database",
        "ODOO_USER": "admin",
        "ODOO_API_KEY": "your-api-key"
      }
    }
  }
}
```

## Configure in Cursor / Windsurf

Add to `~/.cursor/mcp.json` or equivalent:

```json
{
  "mcpServers": {
    "odoo": {
      "command": "uv",
      "args": ["run", "--python", "3.11", "--script", "/path/to/odoo_mcp_server.py"],
      "env": {
        "ODOO_URL": "https://your-instance.odoo.com",
        "ODOO_DB": "your-database",
        "ODOO_USER": "admin",
        "ODOO_PASSWORD": "your-password"
      }
    }
  }
}
```

## Environment Variables

| Variable | Required | Description |
|---|---|---|
| `ODOO_URL` | Yes | Odoo instance URL |
| `ODOO_DB` | Yes | Database name |
| `ODOO_USER` | Yes | Login username |
| `ODOO_PASSWORD` | One of these | Password (Odoo 17-18) |
| `ODOO_API_KEY` | required | API key (Odoo 19+, preferred) |
| `ODOO_READONLY` | No | Set to `true` to disable all write operations |

### Read-Only Mode

Set `ODOO_READONLY=true` to disable `create`, `update`, `delete`, and `execute` tools. Useful for safe browsing of production instances:

```json
{
  "mcpServers": {
    "odoo": {
      "type": "stdio",
      "command": "uv",
      "args": ["run", "--python", "3.11", "--script", "/path/to/odoo_mcp_server.py"],
      "env": {
        "ODOO_URL": "https://production.odoo.com",
        "ODOO_DB": "prod",
        "ODOO_USER": "readonly-user",
        "ODOO_PASSWORD": "secret",
        "ODOO_READONLY": "true"
      }
    }
  }
}
```

## Available Tools

### Core CRUD

| Tool | Description |
|---|---|
| `odoo_search_read` | Query records with domain filters, field selection, pagination |
| `odoo_search_count` | Count matching records without fetching data |
| `odoo_export` | Bulk export up to 2000 records per call for spreadsheets |
| `odoo_create` | Create new records |
| `odoo_update` | Update existing records by ID |
| `odoo_delete` | Delete records by ID |
| `odoo_execute` | Run any model method (action_confirm, action_post, etc.) |

### Discovery

| Tool | Description |
|---|---|
| `odoo_list_models` | Discover available models with keyword filter |
| `odoo_get_fields` | Inspect field definitions for any model |
| `odoo_doctor` | Health diagnostics (version, modules, users, crons, errors) |
| `odoo_connection_info` | Show current connection details |

### Model Customization

| Tool | Description |
|---|---|
| `odoo_model_info` | Get comprehensive model metadata in one call — fields, views, actions, defaults, sort order |
| `odoo_set_default` | Set, update, or clear a field's default value (handles ir.default + JSON encoding) |
| `odoo_get_view` | Get the fully rendered (merged) form/tree/search view XML |
| `odoo_modify_action` | Change a window action's domain, context, sort order, limit, or view modes |

## Example Usage

Once configured, ask your AI agent:

- "List all sale orders from this month"
- "Show me the fields on res.partner"
- "Create a new contact named Acme Corp"
- "Run a health check on the Odoo instance"
- "Export all products to a spreadsheet"
- "Confirm sale order 42"

### Model Customization Examples

- "What's the default sort order for sale.order?"
- "Change the default invoice policy on products to 'delivery'"
- "Show me the form view for res.partner"
- "What window actions exist for account.move? Change the default sort to date desc"
- "List all custom fields on res.partner"
- "What fields are required on sale.order?"

## Model Customization Tools — Detailed Reference

### odoo_model_info

Returns everything about a model in one call, eliminating the need for multiple exploratory queries.

```
odoo_model_info(model="sale.order")
```

Returns:
- `default_order` — the model's `_order` attribute (e.g. `"date_order desc, id desc"`)
- `rec_name` — the field used for display name in dropdowns
- `field_count` — total number of fields
- `fields_by_type` — field count grouped by type (`many2one: 12, char: 8, ...`)
- `custom_fields` — user-created fields (x_ prefix or state=manual)
- `relational_fields` — all Many2one, One2many, Many2many with their targets
- `required_fields` — fields that must be filled
- `views` — base views (form, tree, search) with IDs and priorities
- `actions` — window actions with their domain, context, and view modes
- `defaults` — current ir.default values set for this model's fields

### odoo_set_default

Manages field defaults via ir.default with proper JSON encoding. The most common source of agent errors when done manually.

```
# Set global default
odoo_set_default(model="product.template", field_name="invoice_policy", value="delivery")

# Set user-specific default
odoo_set_default(model="sale.order", field_name="warehouse_id", value=2, user_id=5)

# Remove a default
odoo_set_default(model="product.template", field_name="invoice_policy", value=null)
```

The tool:
1. Finds the field_id in ir.model.fields (validates the field exists)
2. JSON-encodes the value automatically
3. Creates or updates the ir.default record
4. Returns before/after values for confirmation

### odoo_get_view

Returns the fully rendered view XML after all inheritance is applied — what the user actually sees, not the raw fragments stored in ir.ui.view.

```
odoo_get_view(model="sale.order", view_type="form")
odoo_get_view(model="res.partner", view_type="tree")
odoo_get_view(model="account.move", view_type="search")
```

Returns:
- `arch` — the complete merged XML
- `view_id` — the base view ID
- `fields_in_view` — list of field names present in the view

### odoo_modify_action

Changes how a model appears in the UI by modifying its window action (ir.actions.act_window).

```
# List actions for a model (read-only)
odoo_modify_action(model="sale.order")

# Change default sort order
odoo_modify_action(action_id=42, order="date_order desc")

# Change default filter and page size
odoo_modify_action(action_id=42, domain="[['state','=','sale']]", limit=200)

# Add default grouping via context
odoo_modify_action(action_id=42, context="{'group_by': 'partner_id'}")
```

The tool returns before/after values so you can verify what changed.

## How It Works

```
AI Agent (Claude, Cursor, etc.)
    ↕ MCP Protocol (stdio)
Odoo MCP Server
    ↕ JSON-RPC / JSON-2 API
Odoo Instance
```

The server authenticates once at startup and maintains a persistent connection. All tools use the same authenticated session.

## Requirements

- Python 3.11+
- [uv](https://docs.astral.sh/uv/) (recommended) or `pip install fastmcp httpx`

## License

MIT

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [oconsole](https://github.com/oconsole)
- **Source:** [oconsole/odoo-mcp-server](https://github.com/oconsole/odoo-mcp-server)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-oconsole-odoo-mcp-server
- Seller: https://agentstack.voostack.com/s/oconsole
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
