Skip to main content
Glama
AntonS2042

odoo-mcp

by AntonS2042
README.md
# Odoo 17 – MCP-Server (Proof of Concept)

Ein schlanker **MCP-Server**, der ausgewählte Odoo-17-Geschäftsprozesse als
Tools kapselt. Ein LLM-Agent (z.B. OpenClaw) kann diese Tools auswählen und
ausführen, ohne Odoo selbst zu verändern. Die Anbindung erfolgt entkoppelt
über die externe Odoo-API (XML-RPC)

## Tools

| Bereich    | Tool                       | Zweck                                              |
|------------|----------------------------|----------------------------------------------------|
| Read       | `odoo_search_read`         | Flexibles Lesen beliebiger Odoo-Modelle            |
| Inventory  | `search_products`          | Verkaufsfähige Produkte suchen (inkl. Bestand)     |
| Inventory  | `check_stock_level`        | Verfügbaren Lagerbestand eines Produkts prüfen     |
| Sales      | `find_or_create_customer`  | Kunden über E-Mail finden oder neu anlegen         |
| Sales      | `create_sale_order`        | Verkaufsauftrag (Angebot) anlegen                  |
| Sales      | `confirm_sale_order`       | Angebot bestätigen → Verkaufsauftrag               |

## 1. Odoo lokal starten

```bash
docker compose up -d
```

Dann http://localhost:8069 öffnen und beim ersten Start eine Datenbank
namens `odoo` **mit Demodaten** anlegen (liefert Beispielprodukte/-kunden).
Das Master-Passwort wird in `config/odoo.conf` gesetzt; dazu die Vorlage
kopieren und ein eigenes Passwort eintragen:

```bash
cp config/odoo.conf.example config/odoo.conf   # admin_passwd anpassen
```

> `config/odoo.conf` ist bewusst per `.gitignore` ausgeschlossen und darf nicht
> mit echtem Passwort/Hash veröffentlicht werden.

## 2. MCP-Server einrichten

```bash
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
cp .env.example .env        # ggf. Zugangsdaten anpassen
```

## 3. Server testen

```bash
.venv/bin/python main.py    # startet den MCP-Server über stdio
```

Der Server kommuniziert über stdio (JSON-RPC) und wird normalerweise vom
MCP-Client/Agenten gestartet, nicht direkt im Terminal bedient.

## 4. In einem MCP-Client registrieren

Beispielkonfiguration (z.B. für OpenClaw / kompatible Clients):

```json
{
  "mcpServers": {
    "odoo": {
      "command": "/ABSOLUTER/PFAD/zu/odoo-mcp/.venv/bin/python",
      "args": ["/ABSOLUTER/PFAD/zu/odoo-mcp/main.py"]
    }
  }
}
```

> Pfade an den eigenen Projektordner anpassen (absolute Pfade zum venv-Python
> und zu `main.py`).

## Beispiel-Ablauf (typische Tool-Kette eines Agenten)

1. `search_products("Desk")` → Produkt-ID ermitteln
2. `check_stock_level(product_id)` → Bestand prüfen
3. `find_or_create_customer("Muster GmbH", "info@muster.de")` → Kunden-ID
4. `create_sale_order(customer_id, [{"product_id": 42, "quantity": 2}])` → Angebot
5. `confirm_sale_order(order_id)` → bestätigter Verkaufsauftrag

## Konfiguration

Über Umgebungsvariablen bzw. `.env`:

| Variable        | Default                 | Bedeutung                |
|-----------------|-------------------------|--------------------------|
| `ODOO_URL`      | `http://localhost:8069` | Basis-URL der Instanz    |
| `ODOO_DB`       | `odoo`                  | Datenbankname            |
| `ODOO_USER`     | `admin`                 | Benutzer                 |
| `ODOO_PASSWORD` | `admin`                 | Passwort / API-Key       |

## Governance-Schicht

[policy.yaml](policy.yaml);
[governance.py](governance.py):

| Kontrolle              | Umsetzung                                                        | Policy-Schlüssel       |
|------------------------|------------------------------------------------------------------|------------------------|
| **Capability-Scoping** | Nur freigegebene Tools werden registriert (für den Agenten unsichtbar) | `allowed_tools`  |
| **Eingabevalidierung** | Generisches Read-Tool nur auf erlaubte Modelle beschränkbar      | `allowed_models`       |
| **Audit-Log**          | Jeder Tool-Aufruf als JSON-Zeile (Agent, Parameter, Ergebnis-/Fehler-Referenz, Dauer) | `audit.log_file`, `agent_id` |

Ein leerer/fehlender `allowed_*`-Eintrag bedeutet „keine Einschränkung". Den
Policy-Pfad kann man über die Umgebungsvariable `ODOO_MCP_POLICY` überschreiben.

Beispielzeile aus dem Audit-Log:

```json
{"ts": "2026-06-22T12:55:52Z", "agent_id": "openclaw-poc", "tool": "create_sale_order",
 "params": {"customer_id": 7, "order_lines": [{"product_id": 42, "quantity": 2}]},
 "status": "ok", "result_ref": 15, "duration_ms": 38.4}
```