Skip to main content
Glama
AleemHaider

odoo-mcp

by AleemHaider
README.md
# Odoo MCP Multi (own build)

A from-scratch, open MCP server that turns Claude (or any MCP client) into an
operator of the **Odoo ORM** — exactly the 12 tools described in
[`Odoo_MCP_Tools_Guide.md`](./Odoo_MCP_Tools_Guide.md).

It is a thin, ergonomic wrapper around Odoo's **external API (XML-RPC)**:

```
Claude ──(MCP tool)──► server.py ──(XML-RPC /xmlrpc/2/object)──► Odoo (PostgreSQL)
       ◄──(structured JSON)──               ◄──(ORM data)──
```

Everything ultimately routes through one call:
`models.execute_kw(db, uid, key, model, method, args, kwargs)`.

---

## The 12 tools

| Tool | Group | Risk | Purpose |
|---|---|---|---|
| `list_available_profiles` | Discover | — | See configured environments (call FIRST) |
| `get_version` | Discover | — | Odoo server version |
| `list_models` | Discover | — | Find tables (models) |
| `list_fields` | Discover | — | See a model's schema |
| `search_read` | Read | — | **Query data** (returns pagination envelope) |
| `get_financial_report` | Read | — | Native reports (Odoo 17+) |
| `create` | Write | ⚠️ | Create a record |
| `write` | Write | ⚠️ | Update records |
| `unlink` | Write | ⚠️⚠️ | Delete records |
| `execute_kw` | Write | ⚠️⚠️ | **Run ANY model method** |
| `export_records` | Bulk | — | Export (backup/migration) |
| `import_records` | Bulk | ⚠️ | Import/upsert in bulk |

---

## Quick install — one command, no clone (recommended)

Requires [`uv`](https://docs.astral.sh/uv/) (`pip install uv`). This fetches the
code straight from GitHub, installs it in an isolated env, and registers it with
Claude — credentials are passed inline as env vars, so there's no file to edit:

```bash
claude mcp add odoo -s user \
  -e ODOO_URL=https://your-instance.odoo.com \
  -e ODOO_DB=your-db-name \
  -e ODOO_USER=you@company.com \
  -e ODOO_PASSWORD=your-api-key \
  -- uvx --from git+https://github.com/AleemHaider/odoo-mcp odoo-mcp
```

That's the whole install. Start Claude and ask *"List my Odoo profiles"*.
For multiple Odoo instances, use the `profiles.json` flow below instead.

---

## Setup (manual / multi-profile)

### 1. Install
```bash
pip install -r requirements.txt      # installs fastmcp
```

### 2. Configure profiles
Copy the example and fill in your Odoo credentials:
```bash
cp profiles.example.json profiles.json
```
```json
{
  "default": "Interhi",
  "profiles": {
    "Interhi": {
      "url": "https://your-instance.odoo.com",
      "database": "your-db-name",
      "username": "admin",
      "password": "your-api-key-or-password"
    }
  }
}
```

> **Tip:** In Odoo, generate an **API key** (Settings → Users → API Keys) and use
> it as the `password`. Mark production profiles with `"readonly": true` to block
> all mutations from that profile.

**Alternative (single profile via env vars, no file):**
```bash
export ODOO_URL="https://your-instance.odoo.com"
export ODOO_DB="your-db-name"
export ODOO_USER="admin"
export ODOO_PASSWORD="your-api-key"
```

### 3. Run
```bash
python server.py          # speaks MCP over stdio
```

---

## Connect it to Claude

### Claude Desktop
Add to `claude_desktop_config.json`
(macOS: `~/Library/Application Support/Claude/`, Windows: `%APPDATA%\Claude\`):
```json
{
  "mcpServers": {
    "odoo": {
      "command": "python",
      "args": ["/absolute/path/to/odoo mcp/server.py"]
    }
  }
}
```

### Claude Code (CLI)
```bash
claude mcp add odoo -- python "/absolute/path/to/odoo mcp/server.py"
```

Restart the client; the 12 tools appear automatically.

---

## Key concepts (how to drive it)

- **Domains** use Odoo **prefix (Polish) notation** — never the words `and`/`or`:
  ```
  ["&", ["state","=","posted"], ["move_type","=","out_invoice"]]
  ["|", ["a","=",1], ["b","=",2]]
  ```
- **Every read returns a pagination envelope**:
  ```json
  {"records": [...], "total": 128, "limit": 100, "offset": 0,
   "has_more": true, "next_offset": 100, "format": "json"}
  ```
  If `has_more` is true, call again with `offset = next_offset`.
- **Output `format`**: `json` (process), `compact` (light array-of-arrays),
  `table` (Markdown for users), `html` (paste into Odoo), `csv` (spreadsheet).
- **IDs for methods** always go in a list: `args=[[490749]]`.
- **Relational command tuples**: `[[0,0,{...}]]` (new o2m line),
  `[[6,0,[id1,id2]]]` (set m2m).
- **execute_kw is the swiss-army knife** — any Odoo button = a method behind it:
  `account.move / action_post / [[490749]]` validates an invoice.

## Safety notes
- Always run `list_available_profiles` first to confirm the environment.
- Read-only introspection via `execute_kw` (search/read/fields_get/read_group…)
  is allowed on `readonly` profiles; mutating methods are blocked.
- Errors come back as `{"success": false, "error": "..."}` with the cleaned
  Odoo message (e.g. `Invalid leaf`, `Expected singleton`).

---

*Wraps the Odoo external API. Concept & tool set documented in
`Odoo_MCP_Tools_Guide.md`.*