Skip to main content
Glama
CATS70

NOVA MCP Server

by CATS70
README.md
# NOVA MCP Server

Serveur **Model Context Protocol** en lecture seule exposant les données comptables et
commerciales de la société de démonstration NOVA (Dolibarr 23.0.3), pour investigation
progressive par un assistant IA via **Cowork**. Voir `spec-final.md` pour la spécification
complète.

## Architecture

- **Auth** (`app/auth/`) : validation JWT Keycloak (JWKS via `PyJWKClient`), résolution
  d'identité `(iss, sub)`, `CredentialStore` (YAML local) mappant vers une clé API Dolibarr
  par utilisateur, middleware `credential_gate` (403 si identité non mappée).
- **Dolibarr** (`app/dolibarr/`) : client HTTP centralisé (pool de connexions persistant,
  retries limités, conversion Decimal) pour l'API REST Dolibarr stock (tiers, factures,
  paiements, banque).
- **Module compagnon NOVA** (`dolibarr-module/`) : le plan comptable et le Grand livre ne
  sont pas exposés par l'API Dolibarr standard — voir la section dédiée ci-dessous.
- **Privacy Layer** (`app/privacy/`) : remplace toute identité de tiers par une référence
  technique stable (`THIRDPARTY:<id>`, etc.), appliquée systématiquement par les services.
- **Domain** (`app/domain/`) : règles comptables déterministes (EBITDA, aging, pagination,
  validation) indépendantes de tout framework.
- **Services** (`app/services/`) : logique métier, un module par domaine.
- **MCP** (`app/mcp_server/`) : serveur MCP (SDK officiel Anthropic), tools par domaine,
  décorateur central de traduction d'erreurs + logging (`errors.py`).

## Pourquoi un module compagnon Dolibarr ?

L'API REST stock de Dolibarr 23.0 n'expose aucun endpoint pour le plan comptable ou le Grand
livre (le seul point d'entrée natif, `GET /accountancy/exportdata`, écrit un fichier côté
serveur sans le retourner dans la réponse HTTP). `dolibarr-module/nova/` ajoute deux
endpoints en lecture seule (`GET /nova/accounts`, `GET /nova/bookkeeping`) sous le même
mécanisme REST natif (DOLAPIKEY, permissions applicatives). **Ce module s'installe séparément
sur l'instance Dolibarr NOVA** — voir `dolibarr-module/README.md`.

## Démarrage local

```bash
uv sync --extra dev
cp .env.example .env        # renseigner OIDC_ISSUER, CREDENTIAL_STORE_PATH, DOLIBARR_API_URL
cp credentials/credentials.example.yaml credentials/credentials.yaml   # ne pas versionner
uv run uvicorn app.main:app --reload
```

- `GET /health/live`, `GET /health/ready` : healthchecks (non authentifiés).
- `POST /mcp` : endpoint MCP (Streamable HTTP).

## Tests

```bash
uv run pytest                      # suite complète (couverture terminal + coverage.xml)
uv run pytest --cov=app --cov-report=html
```

Aucune base de données : les tests utilisent un double de test (`tests/fixtures/`) pour
`DolibarrClient`, pas de fixtures PostgreSQL/NullPool.

## Docker

```bash
docker compose up --build
```

Le `CredentialStore` est monté en lecture seule (`./credentials:/app/credentials:ro`) — ne
jamais versionner `credentials/credentials.yaml`.

## Prérequis côté Dolibarr NOVA

1. Installer `dolibarr-module/nova/` (voir son README).
2. Pour chaque auditeur : créer un utilisateur Dolibarr dédié, générer sa `DOLAPIKEY`,
   accorder le droit **Lire le plan comptable et le Grand livre via l'API NOVA**, puis
   ajouter son entrée dans `credentials/credentials.yaml` (avec le `sub` de son token
   Keycloak) — redémarrer le serveur MCP pour la prise en compte (pas de rechargement à
   chaud, H2).
3. Pour `get_company` : renseigner la constante Dolibarr `API_LOGINS_ALLOWED_FOR_GET_COMPANY`
   (ou accorder le droit admin) pour chaque login utilisé — sinon ce tool précis échoue avec
   une erreur upstream 403 (comportement attendu).