mcp-server-odoo
by Julionores
README.md
# mcp-odoo-toolkit
[](https://github.com/Julionores/mcp-odoo-toolkit/actions/workflows/ci.yml)
Une stack Docker et un client Python pour mettre en place et **réellement exploiter** un serveur
[MCP (Model Context Protocol)](https://modelcontextprotocol.io/) devant une instance Odoo, avec le
paquet officiel [`mcp-server-odoo`](https://pypi.org/project/mcp-server-odoo/). Le projet démontre,
avec des sorties réellement capturées, la différence concrète entre un démarrage rapide sans
contrôle d'accès (mode *YOLO*) et un mode sécurisé avec liste blanche de modèles et clés d'API.
> Projet réalisé par **Junior Tsafack Megnekeu** ([blog.jtmcloud.com](https://blog.jtmcloud.com) ·
> [GitHub](https://github.com/Julionores) ·
> [LinkedIn](https://www.linkedin.com/in/junior-tsafack-megnekeu-b673151b9)) — pièce d'un
> portfolio technique orienté ERP/DevOps. Voir aussi
> [`agent-matching-recrutement`](https://github.com/Julionores/agent-matching-recrutement),
> [`gradientforge`](https://github.com/Julionores/gradientforge),
> [`radar-risque-impaye`](https://github.com/Julionores/radar-risque-impaye),
> [`collecte-agricole-planner`](https://github.com/Julionores/collecte-agricole-planner),
> [`ticket-tide`](https://github.com/Julionores/ticket-tide),
> [`inspectline`](https://github.com/Julionores/inspectline),
> [`runbook-rag`](https://github.com/Julionores/runbook-rag), et l'ensemble du portfolio :
> [`devsecops-pipeline-reference`](https://github.com/Julionores/devsecops-pipeline-reference),
> [`securebank-api`](https://github.com/Julionores/securebank-api),
> [`postgresql-ha-repmgr`](https://github.com/Julionores/postgresql-ha-repmgr),
> [`iso27001-isms-toolkit`](https://github.com/Julionores/iso27001-isms-toolkit),
> [`dynamodb-streams-cdc-pipeline`](https://github.com/Julionores/dynamodb-streams-cdc-pipeline),
> [`aws-troubleshooting-challenge`](https://github.com/Julionores/aws-troubleshooting-challenge),
> [`s3-cross-region-replication`](https://github.com/Julionores/s3-cross-region-replication),
> [`aws-alb-deployment-patterns`](https://github.com/Julionores/aws-alb-deployment-patterns) et
> [`aws-vpc-connectivity-patterns`](https://github.com/Julionores/aws-vpc-connectivity-patterns).
> Ce projet accompagne le cours
> [Serveur MCP pour Odoo](https://blog.jtmcloud.com/erp/mcp-odoo/01-fondamentaux-mcp/).
## Le problème
Un assistant IA devient utile quand il peut agir sur de vraies données Odoo (chercher un contact,
lire une facture...). Le protocole MCP standardise cette connexion — mais le paquet
`mcp-server-odoo` propose **deux modes radicalement différents** pour s'y connecter, et le choix
entre les deux n'est pas qu'un détail de configuration.
## Démontré avec de vraies données
### Mode YOLO — rapide, mais sans filet
```bash
docker compose up -d db odoo mcp-server # ODOO_YOLO=true dans .env
python examples/demo.py
```
```text
--- list_models ---
{ "total": 55, "yolo_mode": { "enabled": true, "description": "FULL ACCESS", ... } }
--- search_records: res.partner (limite a 5) ---
{ "records": [ { "id": 14, "name": "Azure Interior", ... } ], "total": 36, ... }
```
**55 modèles Odoo accessibles sans distinction** — tout ce que l'utilisateur configuré peut voir
dans Odoo, y compris `res.users`, `ir.config_parameter`, etc.
### Mode sécurisé — le module Odoo `mcp_server`
Après installation du module Odoo officiel `mcp_server` (non fourni dans ce dépôt — voir
[Licence](#licence)), activation d'un seul modèle en lecture seule, et génération d'une clé d'API :
```bash
# .env : ODOO_YOLO=false, ODOO_API_KEY=<clé générée>
docker compose up -d mcp-server
python examples/demo.py
```
```text
--- list_models ---
{
"models": [{ "model": "res.partner", "name": "Contact",
"operations": { "read": true, "write": false, "create": false, "unlink": false } }],
"yolo_mode": null,
"total": 1
}
```
**1 seul modèle accessible, en lecture seule.** Une tentative d'écriture est immédiatement rejetée :
```bash
python examples/test_hardened_denial.py
```
```text
Error executing tool create_record: Access denied: Operation 'create' not allowed on model 'res.partner'
```
Le parcours complet (installation du module, whitelist, clé d'API, journal d'audit `mcp.log`) est
documenté pas à pas dans le [cours associé](https://blog.jtmcloud.com/erp/mcp-odoo/05-mode-securise/).
## Architecture
```text
mcp-odoo-toolkit/
├── docker/Dockerfile # image du serveur MCP (mcp-server-odoo)
├── docker-compose.yml # Odoo 16 + PostgreSQL 16 + serveur MCP
├── docker-compose.override.example.yml # exemple pour monter le module mcp_server en local
├── .env.example # variables : YOLO vs mode sécurisé
├── src/mcp_odoo_toolkit/ # client Python reutilisable (SDK mcp officiel)
├── examples/ # démos bout en bout, exécutées reellement
└── tests/ # tests unitaires (pytest)
```
Le client (`src/mcp_odoo_toolkit/client.py`) encapsule l'ouverture d'une session MCP en transport
`streamable-http` avec le SDK officiel [`mcp`](https://pypi.org/project/mcp/) :
```python
from mcp_odoo_toolkit import call_tool, list_tool_names, mcp_session
async with mcp_session("http://localhost:8000/mcp") as session:
tools = await list_tool_names(session)
result = await call_tool(session, "search_records", {"model": "res.partner", "limit": 5})
```
## Installation
```bash
git clone https://github.com/Julionores/mcp-odoo-toolkit.git
cd mcp-odoo-toolkit
cp .env.example .env
conda create -n mcp-odoo-toolkit python=3.11
conda activate mcp-odoo-toolkit
pip install -e ".[dev]"
docker compose up -d db odoo
# Créer une base avec données de démo (voir Module 2 du cours pour le détail) :
curl -s -X POST http://localhost:8069/web/database/create \
-F "master_pwd=admin" -F "name=mcp_demo" -F "login=admin" -F "password=admin" -F "demo=true"
docker compose up -d --build mcp-server
python examples/demo.py
```
## Tests
```bash
pytest -v
```
```text
tests/test_client.py::test_list_tool_names_returns_names_in_order PASSED
tests/test_client.py::test_call_tool_returns_first_text_block PASSED
tests/test_client.py::test_call_tool_returns_none_when_no_content PASSED
3 passed in 1.99s
```
Les tests unitaires simulent la `ClientSession` du SDK `mcp` (aucune dépendance à un serveur MCP
réel, pour rester rapides et déterministes en CI) ; les scripts de `examples/` exercent, eux, le
vrai serveur MCP contre une vraie instance Odoo.
## Limites assumées
- Mode YOLO utilisé par défaut (`.env.example`) pour un démarrage immédiat : à ne jamais utiliser
tel quel au-delà d'une démonstration (voir le [Module 7 du cours](https://blog.jtmcloud.com/erp/mcp-odoo/07-securite-bonnes-pratiques/)).
- Le module Odoo `mcp_server` n'est pas fourni ici (licence OPL-1, non redistribuable) : le mode
sécurisé nécessite de l'obtenir séparément depuis [sa source officielle](https://github.com/ivnvxd/mcp-server-odoo).
- L'intégration LibreChat (Module 6 du cours) est documentée par sa configuration, mais non
testée de bout en bout dans ce dépôt (nécessite une clé d'API LLM propre à chaque utilisateur).
## Licence
Le code de ce dépôt (Dockerfile, `docker-compose.yml`, client Python, tests) est sous licence
MIT — voir [`LICENSE`](LICENSE). Il s'appuie sur deux composants tiers **non inclus** dans ce
dépôt :
- [`mcp-server-odoo`](https://pypi.org/project/mcp-server-odoo/) (licence MPL-2.0, par Andrey
Ivanov) — installé comme dépendance depuis PyPI, jamais copié.
- Le module Odoo `mcp_server` (licence **OPL-1**, par much. GmbH) — **volontairement absent** de
ce dépôt, car cette licence interdit sa redistribution. Le [Module 4 du cours](https://blog.jtmcloud.com/erp/mcp-odoo/04-module-mcp-server-odoo/)
documente son fonctionnement ; obtenez-le depuis sa source officielle pour l'utiliser.
Projet à but pédagogique et de démonstration.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues