# Odoo MCP Server — Agentic Edition

[![PyPI](https://img.shields.io/pypi/v/odoo-mcp-server-conn.svg)](https://pypi.org/project/odoo-mcp-server-conn/)
[![Python](https://img.shields.io/pypi/pyversions/odoo-mcp-server-conn.svg)](https://pypi.org/project/odoo-mcp-server-conn/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![ES](https://img.shields.io/badge/Lang-Español-blue.svg)](README.es.md)

An enterprise-grade **Model Context Protocol (MCP)** server for interacting with Odoo ERP through AI assistants. Unlike a traditional database connector, this server is designed as an **agentic bridge**: it teaches the AI how to navigate Odoo, understand its business logic, and perform complex data analysis.

---

## Why Agentic Edition?

- **Guided Workflows (Prompts)** — Native instructions that teach your AI how to audit inventory, analyse sales, or review security permissions step by step, without writing prompts from scratch.
- **Native BI** — Optimised support for `read_group` and advanced analytical operations, allowing the AI to generate financial reports or KPIs instantly.
- **Deep Introspection** — Tools that grant the AI X-ray vision: discover available action buttons, inspect view XML architectures, evaluate security rules — reducing hallucinations to a minimum.
- **Zero extra dependencies** — Uses only Python stdlib (`urllib`, `json`, `csv`, `xml`) plus the `mcp` package. No `requests`, no `odoorpc`.
- **Built-in Security** — Uses Odoo's own XML-RPC layer; the MCP server cannot bypass permissions the user doesn't already have.

---

## Installation

```bash
# Recommended — isolated and fast
uv tool install odoo-mcp-server-conn

# Standard
pip install odoo-mcp-server-conn
```

---

## Configuration

### Environment variables

| Variable | Required | Description |
|---|---|---|
| `ODOO_URL` | ✅ | Your Odoo URL (e.g. `http://localhost:8069`) |
| `ODOO_DB` | ✅ | Database name |
| `ODOO_USERNAME` | ✅ | User login or email |
| `ODOO_PASSWORD` | ✅ | Password or **API Key** (strongly recommended) |
| `MCP_AUTH_CACHE_TTL` | ❌ | Seconds before re-authenticating (default: `300`) |

> **Tip:** Always prefer an **API Key** over a plain password. Generate one in Odoo under *Settings → Users → Your User → API Keys*.

---

### Claude Code (CLI)

Run this command once — it stores the configuration permanently for the current project:

```bash
claude mcp add odoo-server \
  --env ODOO_URL=http://localhost:8069 \
  --env ODOO_DB=my_database \
  --env ODOO_USERNAME=admin \
  --env ODOO_PASSWORD=my_api_key \
  -- odoo-mcp-server-conn
```

Verify the connection inside Claude Code:

```
/mcp
```

<details>
<summary>Project-scoped config — share with your team via <code>.mcp.json</code></summary>

Add `--scope project` to create a `.mcp.json` at the repository root that your whole team can use. Each developer supplies their own credentials via environment variables or CI secrets.

```bash
claude mcp add odoo-server \
  --scope project \
  --env ODOO_URL=http://localhost:8069 \
  --env ODOO_DB=my_database \
  --env ODOO_USERNAME=admin \
  --env ODOO_PASSWORD=my_api_key \
  -- odoo-mcp-server-conn
```

</details>

---

### Claude Desktop

Locate your config file:

- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`

Add the following block:

```json
{
  "mcpServers": {
    "odoo-server": {
      "command": "odoo-mcp-server-conn",
      "env": {
        "ODOO_URL": "http://localhost:8069",
        "ODOO_DB": "my_database",
        "ODOO_USERNAME": "admin",
        "ODOO_PASSWORD": "my_api_key"
      }
    }
  }
}
```

---

### VS Code (Copilot / Cline / Roo Code)

Add to your `.vscode/mcp.json` (workspace-level) or user MCP settings:

```json
{
  "servers": {
    "odoo-server": {
      "type": "stdio",
      "command": "odoo-mcp-server-conn",
      "env": {
        "ODOO_URL": "http://localhost:8069",
        "ODOO_DB": "my_database",
        "ODOO_USERNAME": "admin",
        "ODOO_PASSWORD": "my_api_key"
      }
    }
  }
}
```

<details>
<summary>Cline / Roo Code — <code>cline_mcp_settings.json</code></summary>

```json
{
  "mcpServers": {
    "odoo-server": {
      "command": "odoo-mcp-server-conn",
      "env": {
        "ODOO_URL": "http://localhost:8069",
        "ODOO_DB": "my_database",
        "ODOO_USERNAME": "admin",
        "ODOO_PASSWORD": "my_api_key"
      }
    }
  }
}
```

</details>

---

### Cursor IDE

1. Go to **Settings → Features → MCP**.
2. Click **Add new server** → type `command`.
3. Command: `odoo-mcp-server-conn`.
4. Add each environment variable in the *Env vars* section.

---

### Windsurf

Add to `~/.codeium/windsurf/mcp_config.json`:

```json
{
  "mcpServers": {
    "odoo-server": {
      "command": "odoo-mcp-server-conn",
      "env": {
        "ODOO_URL": "http://localhost:8069",
        "ODOO_DB": "my_database",
        "ODOO_USERNAME": "admin",
        "ODOO_PASSWORD": "my_api_key"
      }
    }
  }
}
```

---

## Tools

### CRUD — Core operations

| Tool | Odoo method | Description |
|---|---|---|
| `search_records` | `search` | Return IDs matching a domain filter |
| `read_records` | `read` | Read fields from records by ID |
| `search_read_records` | `search_read` | Search + read in one optimised call |
| `create_record` | `create` | Create a new record |
| `update_record` | `write` | Update existing records |
| `delete_record` | `unlink` | Delete records ⚠️ |
| `count_records` | `search_count` | Count without loading records (fast) |

### Introspection — understand the data model in real time

| Tool | Description |
|---|---|
| `get_model_fields` | Live schema of any model (types, relations, required flags) |
| `get_view_architecture` | Final merged XML of a view (form / tree / kanban / search) |
| `get_workflow_states` | States, stages, and transition buttons of a model |
| `get_action_buttons` | All buttons in a view with visibility conditions and groups |
| `get_related_records` | Auto-resolved Many2one / One2many / Many2many relations |
| `get_security_rules` | ACL and `ir.rule` records for a model |
| `explain_domain` | Translates an Odoo domain filter into plain English |

### BI & Analytics

| Tool | Description |
|---|---|
| `read_group` | `GROUP BY` with sums, counts, averages. Supports `:month` / `:year` date grouping |
| `export_to_csv` | Export records to a CSV string (up to 1 000 rows) |
| `get_available_reports` | List PDF / HTML reports available for a model |

### Wildcard

| Tool | Description |
|---|---|
| `execute_method` | Call **any** public Odoo method (e.g. `action_confirm`, `button_validate`) |

---

## Guided Prompts (pre-trained workflows)

Invoke these prompts directly from your AI client to start a structured analysis:

| Prompt | What it does |
|---|---|
| `analyze_sales` | Sales KPIs — revenue trend, top customers, conversion rate |
| `diagnose_inventory` | Low-stock products, stuck transfers, warehouse utilisation |
| `audit_permissions` | Cross-reference security groups with ACL, flag over-privileged users |
| `financial_overview` | Cash flow overview — AR, AP, invoicing by period |

---

## Resources (navigable URIs)

The AI can query these URIs directly as if browsing the ERP:

| URI | Description |
|---|---|
| `odoo://models` | Master list of all models installed in the instance |
| `odoo://fields/{model}` | Data dictionary for a specific model |
| `odoo://record/{model}/{id}` | Complete record sheet |
| `odoo://search/{model}/{domain}` | Instant search, e.g. `odoo://search/res.partner/[["is_company","=",true]]` |

---

## Security

- The server operates entirely through Odoo's XML-RPC layer — it cannot bypass any permission the authenticated user doesn't already have in the ERP.
- No raw SQL, no forced commits, no ORM bypass.
- Credentials are read exclusively from environment variables — never hardcoded.

**License:** MIT
